1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef LAYOUT_SVG_SVGOUTERSVGFRAME_H_
8 #define LAYOUT_SVG_SVGOUTERSVGFRAME_H_
10 #include "mozilla/Attributes.h"
11 #include "mozilla/ISVGSVGFrame.h"
12 #include "mozilla/SVGContainerFrame.h"
13 #include "mozilla/UniquePtr.h"
19 class AutoSVGViewHandler
;
20 class SVGForeignObjectFrame
;
21 class SVGFragmentIdentifier
;
23 } // namespace mozilla
25 nsContainerFrame
* NS_NewSVGOuterSVGFrame(mozilla::PresShell
* aPresShell
,
26 mozilla::ComputedStyle
* aStyle
);
27 nsContainerFrame
* NS_NewSVGOuterSVGAnonChildFrame(
28 mozilla::PresShell
* aPresShell
, mozilla::ComputedStyle
* aStyle
);
32 ////////////////////////////////////////////////////////////////////////
33 // SVGOuterSVGFrame class
35 class SVGOuterSVGFrame final
: public SVGDisplayContainerFrame
,
37 using imgDrawingParams
= image::imgDrawingParams
;
39 friend nsContainerFrame
* ::NS_NewSVGOuterSVGFrame(
40 mozilla::PresShell
* aPresShell
, ComputedStyle
* aStyle
);
41 friend class AutoSVGViewHandler
;
42 friend class SVGFragmentIdentifier
;
45 explicit SVGOuterSVGFrame(ComputedStyle
* aStyle
, nsPresContext
* aPresContext
);
49 NS_DECL_FRAMEARENA_HELPERS(SVGOuterSVGFrame
)
53 NS_ASSERTION(!mForeignObjectHash
|| mForeignObjectHash
->Count() == 0,
54 "foreignObject(s) still registered!");
59 virtual nscoord
GetMinISize(gfxContext
* aRenderingContext
) override
;
60 virtual nscoord
GetPrefISize(gfxContext
* aRenderingContext
) override
;
62 virtual IntrinsicSize
GetIntrinsicSize() override
;
63 AspectRatio
GetIntrinsicRatio() const override
;
65 SizeComputationResult
ComputeSize(
66 gfxContext
* aRenderingContext
, WritingMode aWritingMode
,
67 const LogicalSize
& aCBSize
, nscoord aAvailableISize
,
68 const LogicalSize
& aMargin
, const LogicalSize
& aBorderPadding
,
69 const mozilla::StyleSizeOverrides
& aSizeOverrides
,
70 ComputeSizeFlags aFlags
) override
;
72 virtual void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
73 const ReflowInput
& aReflowInput
,
74 nsReflowStatus
& aStatus
) override
;
76 virtual void DidReflow(nsPresContext
* aPresContext
,
77 const ReflowInput
* aReflowInput
) override
;
79 void UnionChildOverflow(mozilla::OverflowAreas
& aOverflowAreas
) override
;
81 virtual void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
82 const nsDisplayListSet
& aLists
) override
;
84 virtual void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
85 nsIFrame
* aPrevInFlow
) override
;
87 bool IsFrameOfType(uint32_t aFlags
) const override
{
88 return SVGDisplayContainerFrame::IsFrameOfType(
90 ~(eSupportsContainLayoutAndPaint
| eReplaced
| eReplacedSizing
));
93 #ifdef DEBUG_FRAME_DUMP
94 virtual nsresult
GetFrameName(nsAString
& aResult
) const override
{
95 return MakeFrameName(u
"SVGOuterSVG"_ns
, aResult
);
99 void DidSetComputedStyle(ComputedStyle
* aOldComputedStyle
) override
;
101 void DestroyFrom(nsIFrame
* aDestructRoot
,
102 PostDestroyData
& aPostDestroyData
) override
;
104 virtual nsresult
AttributeChanged(int32_t aNameSpaceID
, nsAtom
* aAttribute
,
105 int32_t aModType
) override
;
107 virtual nsContainerFrame
* GetContentInsertionFrame() override
{
108 // Any children must be added to our single anonymous inner frame kid.
110 PrincipalChildList().FirstChild() &&
111 PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame(),
112 "Where is our anonymous child?");
113 return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
116 bool IsSVGTransformed(Matrix
* aOwnTransform
,
117 Matrix
* aFromParentTransform
) const override
;
119 // Return our anonymous box child.
120 void AppendDirectlyOwnedAnonBoxes(nsTArray
<OwnedAnonBox
>& aResult
) override
;
122 // ISVGSVGFrame interface:
123 virtual void NotifyViewportOrTransformChanged(uint32_t aFlags
) override
;
125 // ISVGDisplayableFrame methods:
126 virtual void PaintSVG(gfxContext
& aContext
, const gfxMatrix
& aTransform
,
127 imgDrawingParams
& aImgParams
,
128 const nsIntRect
* aDirtyRect
= nullptr) override
;
129 virtual SVGBBox
GetBBoxContribution(const Matrix
& aToBBoxUserspace
,
130 uint32_t aFlags
) override
;
132 // SVGContainerFrame methods:
133 virtual gfxMatrix
GetCanvasTM() override
;
135 /* Methods to allow descendant SVGForeignObjectFrame frames to register and
136 * unregister themselves with their nearest SVGOuterSVGFrame ancestor. This
137 * is temporary until display list based invalidation is impleented for SVG.
138 * Maintaining a list of our foreignObject descendants allows us to search
139 * them for areas that need to be invalidated, without having to also search
140 * the SVG frame tree for foreignObjects. This is important so that bug 539356
141 * does not slow down SVG in general (only foreignObjects, until bug 614732 is
144 void RegisterForeignObject(SVGForeignObjectFrame
* aFrame
);
145 void UnregisterForeignObject(SVGForeignObjectFrame
* aFrame
);
147 virtual bool HasChildrenOnlyTransform(Matrix
* aTransform
) const override
{
148 // Our anonymous wrapper child must claim our children-only transforms as
149 // its own so that our real children (the frames it wraps) are transformed
150 // by them, and we must pretend we don't have any children-only transforms
151 // so that our anonymous child is _not_ transformed by them.
156 * Return true only if the height is unspecified (defaulting to 100%) or else
157 * the height is explicitly set to a percentage value no greater than 100%.
159 bool VerticalScrollbarNotNeeded() const;
161 bool IsCallingReflowSVG() const { return mCallingReflowSVG
; }
163 void InvalidateSVG(const nsRegion
& aRegion
) {
164 if (!aRegion
.IsEmpty()) {
165 mInvalidRegion
.Or(mInvalidRegion
, aRegion
);
170 void ClearInvalidRegion() { mInvalidRegion
.SetEmpty(); }
172 const nsRegion
& GetInvalidRegion() {
174 if (!IsInvalid(rect
)) {
175 mInvalidRegion
.SetEmpty();
177 return mInvalidRegion
;
180 nsRegion
FindInvalidatedForeignObjectFrameChildren(nsIFrame
* aFrame
);
183 bool mCallingReflowSVG
;
185 /* Returns true if our content is the document element and our document is
186 * being used as an image.
188 bool IsRootOfImage();
190 void MaybeSendIntrinsicSizeAndRatioToEmbedder();
191 void MaybeSendIntrinsicSizeAndRatioToEmbedder(Maybe
<IntrinsicSize
>,
194 // This is temporary until display list based invalidation is implemented for
196 // A hash-set containing our SVGForeignObjectFrame descendants. Note we use
197 // a hash-set to avoid the O(N^2) behavior we'd get tearing down an SVG frame
198 // subtree if we were to use a list (see bug 381285 comment 20).
199 UniquePtr
<nsTHashtable
<nsPtrHashKey
<SVGForeignObjectFrame
>>>
202 nsRegion mInvalidRegion
;
206 bool mViewportInitialized
;
208 bool mIsInObjectOrEmbed
;
212 ////////////////////////////////////////////////////////////////////////
213 // SVGOuterSVGAnonChildFrame class
216 * SVGOuterSVGFrames have a single direct child that is an instance of this
217 * class, and which is used to wrap their real child frames. Such anonymous
218 * wrapper frames created from this class exist because SVG frames need their
219 * GetPosition() offset to be their offset relative to "user space" (in app
220 * units) so that they can play nicely with nsDisplayTransform. This is fine
221 * for all SVG frames except for direct children of an SVGOuterSVGFrame,
222 * since an SVGOuterSVGFrame can have CSS border and padding (unlike other
223 * SVG frames). The direct children can't include the offsets due to any such
224 * border/padding in their mRects since that would break nsDisplayTransform,
225 * but not including these offsets would break other parts of the Mozilla code
226 * that assume a frame's mRect contains its border-box-to-parent-border-box
227 * offset, in particular nsIFrame::GetOffsetTo and the functions that depend on
228 * it. Wrapping an SVGOuterSVGFrame's children in an instance of this class
229 * with its GetPosition() set to its SVGOuterSVGFrame's border/padding offset
230 * keeps both nsDisplayTransform and nsIFrame::GetOffsetTo happy.
232 * The reason that this class inherit from SVGDisplayContainerFrame rather
233 * than simply from nsContainerFrame is so that we can avoid having special
234 * handling for these inner wrappers in multiple parts of the SVG code. For
235 * example, the implementations of IsSVGTransformed and GetCanvasTM assume
236 * SVGContainerFrame instances all the way up to the SVGOuterSVGFrame.
238 class SVGOuterSVGAnonChildFrame final
: public SVGDisplayContainerFrame
{
239 friend nsContainerFrame
* ::NS_NewSVGOuterSVGAnonChildFrame(
240 mozilla::PresShell
* aPresShell
, ComputedStyle
* aStyle
);
242 explicit SVGOuterSVGAnonChildFrame(ComputedStyle
* aStyle
,
243 nsPresContext
* aPresContext
)
244 : SVGDisplayContainerFrame(aStyle
, aPresContext
, kClassID
) {}
247 NS_DECL_FRAMEARENA_HELPERS(SVGOuterSVGAnonChildFrame
)
250 virtual void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
251 nsIFrame
* aPrevInFlow
) override
;
254 virtual void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
255 const nsDisplayListSet
& aLists
) override
;
257 #ifdef DEBUG_FRAME_DUMP
258 virtual nsresult
GetFrameName(nsAString
& aResult
) const override
{
259 return MakeFrameName(u
"SVGOuterSVGAnonChild"_ns
, aResult
);
263 bool IsSVGTransformed(Matrix
* aOwnTransform
,
264 Matrix
* aFromParentTransform
) const override
;
266 // SVGContainerFrame methods:
267 virtual gfxMatrix
GetCanvasTM() override
{
268 // GetCanvasTM returns the transform from an SVG frame to the frame's
269 // SVGOuterSVGFrame's content box, so we do not include any x/y offset
270 // set on us for any CSS border or padding on our SVGOuterSVGFrame.
271 return static_cast<SVGOuterSVGFrame
*>(GetParent())->GetCanvasTM();
275 } // namespace mozilla
277 #endif // LAYOUT_SVG_SVGOUTERSVGFRAME_H_