Bug 1748835 [wpt PR 32273] - Avoid reftest-wait timeout if ::target-text is unsupport...
[gecko.git] / layout / svg / SVGOuterSVGFrame.h
blob4fc68f8fc958322d6f3a4f84ca2c1a80c47b645c
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"
14 #include "nsRegion.h"
15 #include "nsTHashSet.h"
17 class gfxContext;
19 namespace mozilla {
20 class AutoSVGViewHandler;
21 class SVGForeignObjectFrame;
22 class SVGFragmentIdentifier;
23 class PresShell;
24 } // namespace mozilla
26 nsContainerFrame* NS_NewSVGOuterSVGFrame(mozilla::PresShell* aPresShell,
27 mozilla::ComputedStyle* aStyle);
28 nsContainerFrame* NS_NewSVGOuterSVGAnonChildFrame(
29 mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle);
31 namespace mozilla {
33 ////////////////////////////////////////////////////////////////////////
34 // SVGOuterSVGFrame class
36 class SVGOuterSVGFrame final : public SVGDisplayContainerFrame,
37 public ISVGSVGFrame {
38 using imgDrawingParams = image::imgDrawingParams;
40 friend nsContainerFrame* ::NS_NewSVGOuterSVGFrame(
41 mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
42 friend class AutoSVGViewHandler;
43 friend class SVGFragmentIdentifier;
45 protected:
46 explicit SVGOuterSVGFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
48 public:
49 NS_DECL_QUERYFRAME
50 NS_DECL_FRAMEARENA_HELPERS(SVGOuterSVGFrame)
52 #ifdef DEBUG
53 ~SVGOuterSVGFrame() {
54 NS_ASSERTION(!mForeignObjectHash || mForeignObjectHash->Count() == 0,
55 "foreignObject(s) still registered!");
57 #endif
59 // nsIFrame:
60 virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
61 virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
63 virtual IntrinsicSize GetIntrinsicSize() override;
64 AspectRatio GetIntrinsicRatio() const override;
66 SizeComputationResult ComputeSize(
67 gfxContext* aRenderingContext, WritingMode aWritingMode,
68 const LogicalSize& aCBSize, nscoord aAvailableISize,
69 const LogicalSize& aMargin, const LogicalSize& aBorderPadding,
70 const mozilla::StyleSizeOverrides& aSizeOverrides,
71 ComputeSizeFlags aFlags) override;
73 virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
74 const ReflowInput& aReflowInput,
75 nsReflowStatus& aStatus) override;
77 virtual void DidReflow(nsPresContext* aPresContext,
78 const ReflowInput* aReflowInput) override;
80 void UnionChildOverflow(mozilla::OverflowAreas& aOverflowAreas) override;
82 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
83 const nsDisplayListSet& aLists) override;
85 virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
86 nsIFrame* aPrevInFlow) override;
88 bool IsFrameOfType(uint32_t aFlags) const override {
89 return SVGDisplayContainerFrame::IsFrameOfType(
90 aFlags &
91 ~(eSupportsContainLayoutAndPaint | eReplaced | eReplacedSizing));
94 #ifdef DEBUG_FRAME_DUMP
95 virtual nsresult GetFrameName(nsAString& aResult) const override {
96 return MakeFrameName(u"SVGOuterSVG"_ns, aResult);
98 #endif
100 void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
102 void DestroyFrom(nsIFrame* aDestructRoot,
103 PostDestroyData& aPostDestroyData) override;
105 virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
106 int32_t aModType) override;
108 virtual nsContainerFrame* GetContentInsertionFrame() override {
109 // Any children must be added to our single anonymous inner frame kid.
110 MOZ_ASSERT(
111 PrincipalChildList().FirstChild() &&
112 PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame(),
113 "Where is our anonymous child?");
114 return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
117 bool IsSVGTransformed(Matrix* aOwnTransform,
118 Matrix* aFromParentTransform) const override;
120 // Return our anonymous box child.
121 void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
123 // ISVGSVGFrame interface:
124 virtual void NotifyViewportOrTransformChanged(uint32_t aFlags) override;
126 // ISVGDisplayableFrame methods:
127 virtual void PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
128 imgDrawingParams& aImgParams,
129 const nsIntRect* aDirtyRect = nullptr) override;
130 virtual SVGBBox GetBBoxContribution(const Matrix& aToBBoxUserspace,
131 uint32_t aFlags) override;
133 // SVGContainerFrame methods:
134 virtual gfxMatrix GetCanvasTM() override;
136 /* Methods to allow descendant SVGForeignObjectFrame frames to register and
137 * unregister themselves with their nearest SVGOuterSVGFrame ancestor. This
138 * is temporary until display list based invalidation is impleented for SVG.
139 * Maintaining a list of our foreignObject descendants allows us to search
140 * them for areas that need to be invalidated, without having to also search
141 * the SVG frame tree for foreignObjects. This is important so that bug 539356
142 * does not slow down SVG in general (only foreignObjects, until bug 614732 is
143 * fixed).
145 void RegisterForeignObject(SVGForeignObjectFrame* aFrame);
146 void UnregisterForeignObject(SVGForeignObjectFrame* aFrame);
148 virtual bool HasChildrenOnlyTransform(Matrix* aTransform) const override {
149 // Our anonymous wrapper child must claim our children-only transforms as
150 // its own so that our real children (the frames it wraps) are transformed
151 // by them, and we must pretend we don't have any children-only transforms
152 // so that our anonymous child is _not_ transformed by them.
153 return false;
157 * Return true only if the height is unspecified (defaulting to 100%) or else
158 * the height is explicitly set to a percentage value no greater than 100%.
160 bool VerticalScrollbarNotNeeded() const;
162 bool IsCallingReflowSVG() const { return mCallingReflowSVG; }
164 void InvalidateSVG(const nsRegion& aRegion) {
165 if (!aRegion.IsEmpty()) {
166 mInvalidRegion.Or(mInvalidRegion, aRegion);
167 InvalidateFrame();
171 void ClearInvalidRegion() { mInvalidRegion.SetEmpty(); }
173 const nsRegion& GetInvalidRegion() {
174 nsRect rect;
175 if (!IsInvalid(rect)) {
176 mInvalidRegion.SetEmpty();
178 return mInvalidRegion;
181 nsRegion FindInvalidatedForeignObjectFrameChildren(nsIFrame* aFrame);
183 protected:
184 bool mCallingReflowSVG;
186 /* Returns true if our content is the document element and our document is
187 * being used as an image.
189 bool IsRootOfImage();
191 void MaybeSendIntrinsicSizeAndRatioToEmbedder();
192 void MaybeSendIntrinsicSizeAndRatioToEmbedder(Maybe<IntrinsicSize>,
193 Maybe<AspectRatio>);
195 // This is temporary until display list based invalidation is implemented for
196 // SVG.
197 // A hash-set containing our SVGForeignObjectFrame descendants. Note we use
198 // a hash-set to avoid the O(N^2) behavior we'd get tearing down an SVG frame
199 // subtree if we were to use a list (see bug 381285 comment 20).
200 UniquePtr<nsTHashSet<SVGForeignObjectFrame*>> mForeignObjectHash;
202 nsRegion mInvalidRegion;
204 float mFullZoom;
206 bool mViewportInitialized;
207 bool mIsRootContent;
208 bool mIsInObjectOrEmbed;
209 bool mIsInIframe;
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) {}
246 public:
247 NS_DECL_FRAMEARENA_HELPERS(SVGOuterSVGAnonChildFrame)
249 #ifdef DEBUG
250 virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
251 nsIFrame* aPrevInFlow) override;
252 #endif
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);
261 #endif
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_