summaryrefslogtreecommitdiffstats
path: root/layout/svg/SVGContainerFrame.h
blob: 9df6f6b0c7493d2845369d5bd46f739b915e5ee1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef LAYOUT_SVG_SVGCONTAINERFRAME_H_
#define LAYOUT_SVG_SVGCONTAINERFRAME_H_

#include "mozilla/Attributes.h"
#include "mozilla/ISVGDisplayableFrame.h"
#include "mozilla/UniquePtr.h"
#include "nsContainerFrame.h"
#include "nsIFrame.h"
#include "nsQueryFrame.h"
#include "nsRect.h"

class gfxContext;
class nsFrameList;
class nsIContent;

struct nsRect;

namespace mozilla {
class PresShell;
}  // namespace mozilla

nsIFrame* NS_NewSVGContainerFrame(mozilla::PresShell* aPresShell,
                                  mozilla::ComputedStyle* aStyle);

namespace mozilla {

/**
 * Base class for SVG container frames. Frame sub-classes that do not
 * display their contents directly (such as the frames for <marker> or
 * <pattern>) just inherit this class. Frame sub-classes that do or can
 * display their contents directly (such as the frames for inner-<svg> or
 * <g>) inherit our SVGDisplayContainerFrame sub-class.
 *
 *                               *** WARNING ***
 *
 * Do *not* blindly cast to SVG element types in this class's methods (see the
 * warning comment for SVGDisplayContainerFrame below).
 */
class SVGContainerFrame : public nsContainerFrame {
  friend nsIFrame* ::NS_NewSVGContainerFrame(mozilla::PresShell* aPresShell,
                                             ComputedStyle* aStyle);

 protected:
  SVGContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
                    ClassID aID)
      : nsContainerFrame(aStyle, aPresContext, aID) {
    AddStateBits(NS_FRAME_SVG_LAYOUT);
  }

 public:
  NS_DECL_QUERYFRAME
  NS_DECL_FRAMEARENA_HELPERS(SVGContainerFrame)

  // Returns the transform to our gfxContext (to device pixels, not CSS px)
  virtual gfxMatrix GetCanvasTM() { return gfxMatrix(); }

  /**
   * Returns true if the frame's content has a transform that applies only to
   * its children, and not to the frame itself. For example, an implicit
   * transform introduced by a 'viewBox' attribute, or an explicit transform
   * due to a root-<svg> having its currentScale/currentTransform properties
   * set. If aTransform is non-null, then it will be set to the transform.
   */
  virtual bool HasChildrenOnlyTransform(Matrix* aTransform) const {
    return false;
  }

  // nsIFrame:
  void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
  void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
                    const nsLineList::iterator* aPrevFrameLine,
                    nsFrameList&& aFrameList) override;
  void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override;

  bool IsFrameOfType(uint32_t aFlags) const override {
    if (aFlags & eSupportsContainLayoutAndPaint) {
      return false;
    }

    return nsContainerFrame::IsFrameOfType(
        aFlags & ~(nsIFrame::eSVG | nsIFrame::eSVGContainer));
  }

  void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                        const nsDisplayListSet& aLists) override {}

  bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas) override;

 protected:
  /**
   * Traverses a frame tree, marking any SVGTextFrame frames as dirty
   * and calling InvalidateRenderingObservers() on it.
   */
  static void ReflowSVGNonDisplayText(nsIFrame* aContainer);
};

/**
 * Frame class or base-class for SVG containers that can or do display their
 * contents directly.
 *
 *                               *** WARNING ***
 *
 * This class's methods can *not* assume that mContent points to an instance of
 * an SVG element class since this class is inherited by
 * SVGGenericContainerFrame which is used for unrecognized elements in the
 * SVG namespace. Do *not* blindly cast to SVG element types.
 */
class SVGDisplayContainerFrame : public SVGContainerFrame,
                                 public ISVGDisplayableFrame {
 protected:
  SVGDisplayContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
                           nsIFrame::ClassID aID)
      : SVGContainerFrame(aStyle, aPresContext, aID) {
    AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
  }

 public:
  NS_DECL_QUERYFRAME
  NS_DECL_QUERYFRAME_TARGET(SVGDisplayContainerFrame)
  NS_DECL_ABSTRACT_FRAME(SVGDisplayContainerFrame)

  // nsIFrame:
  void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
                    const nsLineList::iterator* aPrevFrameLine,
                    nsFrameList&& aFrameList) override;
  void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) override;
  void Init(nsIContent* aContent, nsContainerFrame* aParent,
            nsIFrame* aPrevInFlow) override;

  void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                        const nsDisplayListSet& aLists) override;

  bool IsSVGTransformed(Matrix* aOwnTransform = nullptr,
                        Matrix* aFromParentTransform = nullptr) const override;

  // ISVGDisplayableFrame interface:
  void PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
                imgDrawingParams& aImgParams) override;
  nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
  void ReflowSVG() override;
  void NotifySVGChanged(uint32_t aFlags) override;
  SVGBBox GetBBoxContribution(const Matrix& aToBBoxUserspace,
                              uint32_t aFlags) override;
  bool IsDisplayContainer() override { return true; }
  gfxMatrix GetCanvasTM() override;

 protected:
  /**
   * Cached canvasTM value.
   */
  UniquePtr<gfxMatrix> mCanvasTM;
};

}  // namespace mozilla

#endif  // LAYOUT_SVG_SVGCONTAINERFRAME_H_