Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef __NS_SVGOUTERSVGFRAME_H__
7 : #define __NS_SVGOUTERSVGFRAME_H__
8 :
9 : #include "mozilla/Attributes.h"
10 : #include "nsAutoPtr.h"
11 : #include "nsISVGSVGFrame.h"
12 : #include "nsSVGContainerFrame.h"
13 : #include "nsRegion.h"
14 :
15 : class gfxContext;
16 : class nsSVGForeignObjectFrame;
17 :
18 : ////////////////////////////////////////////////////////////////////////
19 : // nsSVGOuterSVGFrame class
20 :
21 : class nsSVGOuterSVGFrame final : public nsSVGDisplayContainerFrame
22 : , public nsISVGSVGFrame
23 : {
24 : typedef mozilla::image::imgDrawingParams imgDrawingParams;
25 :
26 : friend nsContainerFrame*
27 : NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
28 : protected:
29 : explicit nsSVGOuterSVGFrame(nsStyleContext* aContext);
30 :
31 : public:
32 : NS_DECL_QUERYFRAME
33 115 : NS_DECL_FRAMEARENA_HELPERS(nsSVGOuterSVGFrame)
34 :
35 : #ifdef DEBUG
36 0 : ~nsSVGOuterSVGFrame() {
37 0 : NS_ASSERTION(!mForeignObjectHash || mForeignObjectHash->Count() == 0,
38 : "foreignObject(s) still registered!");
39 0 : }
40 : #endif
41 :
42 : // nsIFrame:
43 : virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
44 : virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
45 :
46 : virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
47 : virtual nsSize GetIntrinsicRatio() override;
48 :
49 : virtual mozilla::LogicalSize
50 : ComputeSize(gfxContext *aRenderingContext,
51 : mozilla::WritingMode aWritingMode,
52 : const mozilla::LogicalSize& aCBSize,
53 : nscoord aAvailableISize,
54 : const mozilla::LogicalSize& aMargin,
55 : const mozilla::LogicalSize& aBorder,
56 : const mozilla::LogicalSize& aPadding,
57 : ComputeSizeFlags aFlags) override;
58 :
59 : virtual void Reflow(nsPresContext* aPresContext,
60 : ReflowOutput& aDesiredSize,
61 : const ReflowInput& aReflowInput,
62 : nsReflowStatus& aStatus) override;
63 :
64 : virtual void DidReflow(nsPresContext* aPresContext,
65 : const ReflowInput* aReflowInput,
66 : nsDidReflowStatus aStatus) override;
67 :
68 : virtual void UnionChildOverflow(nsOverflowAreas& aOverflowAreas) override;
69 :
70 : virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
71 : const nsRect& aDirtyRect,
72 : const nsDisplayListSet& aLists) override;
73 :
74 : virtual void Init(nsIContent* aContent,
75 : nsContainerFrame* aParent,
76 : nsIFrame* aPrevInFlow) override;
77 :
78 : virtual nsSplittableType GetSplittableType() const override;
79 :
80 : #ifdef DEBUG_FRAME_DUMP
81 0 : virtual nsresult GetFrameName(nsAString& aResult) const override
82 : {
83 0 : return MakeFrameName(NS_LITERAL_STRING("SVGOuterSVG"), aResult);
84 : }
85 : #endif
86 :
87 : virtual nsresult AttributeChanged(int32_t aNameSpaceID,
88 : nsIAtom* aAttribute,
89 : int32_t aModType) override;
90 :
91 81 : virtual nsContainerFrame* GetContentInsertionFrame() override {
92 : // Any children must be added to our single anonymous inner frame kid.
93 81 : MOZ_ASSERT(PrincipalChildList().FirstChild() &&
94 : PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame(),
95 : "Where is our anonymous child?");
96 81 : return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
97 : }
98 :
99 : bool IsSVGTransformed(Matrix* aOwnTransform,
100 : Matrix* aFromParentTransform) const override;
101 :
102 : // Return our anonymous box child.
103 : void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
104 :
105 : // nsISVGSVGFrame interface:
106 : virtual void NotifyViewportOrTransformChanged(uint32_t aFlags) override;
107 :
108 : // nsSVGDisplayableFrame methods:
109 : virtual void PaintSVG(gfxContext& aContext,
110 : const gfxMatrix& aTransform,
111 : imgDrawingParams& aImgParams,
112 : const nsIntRect* aDirtyRect = nullptr) override;
113 : virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
114 : uint32_t aFlags) override;
115 :
116 : // nsSVGContainerFrame methods:
117 : virtual gfxMatrix GetCanvasTM() override;
118 :
119 : /* Methods to allow descendant nsSVGForeignObjectFrame frames to register and
120 : * unregister themselves with their nearest nsSVGOuterSVGFrame ancestor. This
121 : * is temporary until display list based invalidation is impleented for SVG.
122 : * Maintaining a list of our foreignObject descendants allows us to search
123 : * them for areas that need to be invalidated, without having to also search
124 : * the SVG frame tree for foreignObjects. This is important so that bug 539356
125 : * does not slow down SVG in general (only foreignObjects, until bug 614732 is
126 : * fixed).
127 : */
128 : void RegisterForeignObject(nsSVGForeignObjectFrame* aFrame);
129 : void UnregisterForeignObject(nsSVGForeignObjectFrame* aFrame);
130 :
131 0 : virtual bool HasChildrenOnlyTransform(Matrix *aTransform) const override {
132 : // Our anonymous wrapper child must claim our children-only transforms as
133 : // its own so that our real children (the frames it wraps) are transformed
134 : // by them, and we must pretend we don't have any children-only transforms
135 : // so that our anonymous child is _not_ transformed by them.
136 0 : return false;
137 : }
138 :
139 : /**
140 : * Return true only if the height is unspecified (defaulting to 100%) or else
141 : * the height is explicitly set to a percentage value no greater than 100%.
142 : */
143 : bool VerticalScrollbarNotNeeded() const;
144 :
145 182 : bool IsCallingReflowSVG() const {
146 182 : return mCallingReflowSVG;
147 : }
148 :
149 0 : void InvalidateSVG(const nsRegion& aRegion)
150 : {
151 0 : if (!aRegion.IsEmpty()) {
152 0 : mInvalidRegion.Or(mInvalidRegion, aRegion);
153 0 : InvalidateFrame();
154 : }
155 0 : }
156 :
157 0 : void ClearInvalidRegion() { mInvalidRegion.SetEmpty(); }
158 :
159 0 : const nsRegion& GetInvalidRegion() {
160 0 : nsRect rect;
161 0 : if (!IsInvalid(rect)) {
162 0 : mInvalidRegion.SetEmpty();
163 : }
164 0 : return mInvalidRegion;
165 : }
166 :
167 : nsRegion FindInvalidatedForeignObjectFrameChildren(nsIFrame* aFrame);
168 :
169 : protected:
170 :
171 : bool mCallingReflowSVG;
172 :
173 : /* Returns true if our content is the document element and our document is
174 : * embedded in an HTML 'object', 'embed' or 'applet' element. Set
175 : * aEmbeddingFrame to obtain the nsIFrame for the embedding HTML element.
176 : */
177 : bool IsRootOfReplacedElementSubDoc(nsIFrame **aEmbeddingFrame = nullptr);
178 :
179 : /* Returns true if our content is the document element and our document is
180 : * being used as an image.
181 : */
182 : bool IsRootOfImage();
183 :
184 : // This is temporary until display list based invalidation is implemented for
185 : // SVG.
186 : // A hash-set containing our nsSVGForeignObjectFrame descendants. Note we use
187 : // a hash-set to avoid the O(N^2) behavior we'd get tearing down an SVG frame
188 : // subtree if we were to use a list (see bug 381285 comment 20).
189 : nsAutoPtr<nsTHashtable<nsPtrHashKey<nsSVGForeignObjectFrame> > > mForeignObjectHash;
190 :
191 : nsAutoPtr<gfxMatrix> mCanvasTM;
192 :
193 : nsRegion mInvalidRegion;
194 :
195 : float mFullZoom;
196 :
197 : bool mViewportInitialized;
198 : bool mIsRootContent;
199 : };
200 :
201 : ////////////////////////////////////////////////////////////////////////
202 : // nsSVGOuterSVGAnonChildFrame class
203 :
204 : /**
205 : * nsSVGOuterSVGFrames have a single direct child that is an instance of this
206 : * class, and which is used to wrap their real child frames. Such anonymous
207 : * wrapper frames created from this class exist because SVG frames need their
208 : * GetPosition() offset to be their offset relative to "user space" (in app
209 : * units) so that they can play nicely with nsDisplayTransform. This is fine
210 : * for all SVG frames except for direct children of an nsSVGOuterSVGFrame,
211 : * since an nsSVGOuterSVGFrame can have CSS border and padding (unlike other
212 : * SVG frames). The direct children can't include the offsets due to any such
213 : * border/padding in their mRects since that would break nsDisplayTransform,
214 : * but not including these offsets would break other parts of the Mozilla code
215 : * that assume a frame's mRect contains its border-box-to-parent-border-box
216 : * offset, in particular nsIFrame::GetOffsetTo and the functions that depend on
217 : * it. Wrapping an nsSVGOuterSVGFrame's children in an instance of this class
218 : * with its GetPosition() set to its nsSVGOuterSVGFrame's border/padding offset
219 : * keeps both nsDisplayTransform and nsIFrame::GetOffsetTo happy.
220 : *
221 : * The reason that this class inherit from nsSVGDisplayContainerFrame rather
222 : * than simply from nsContainerFrame is so that we can avoid having special
223 : * handling for these inner wrappers in multiple parts of the SVG code. For
224 : * example, the implementations of IsSVGTransformed and GetCanvasTM assume
225 : * nsSVGContainerFrame instances all the way up to the nsSVGOuterSVGFrame.
226 : */
227 0 : class nsSVGOuterSVGAnonChildFrame final : public nsSVGDisplayContainerFrame
228 : {
229 : friend nsContainerFrame*
230 : NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell,
231 : nsStyleContext* aContext);
232 :
233 22 : explicit nsSVGOuterSVGAnonChildFrame(nsStyleContext* aContext)
234 22 : : nsSVGDisplayContainerFrame(aContext, kClassID)
235 22 : {}
236 :
237 : public:
238 106 : NS_DECL_FRAMEARENA_HELPERS(nsSVGOuterSVGAnonChildFrame)
239 :
240 : #ifdef DEBUG
241 : virtual void Init(nsIContent* aContent,
242 : nsContainerFrame* aParent,
243 : nsIFrame* aPrevInFlow) override;
244 : #endif
245 :
246 : #ifdef DEBUG_FRAME_DUMP
247 0 : virtual nsresult GetFrameName(nsAString& aResult) const override {
248 0 : return MakeFrameName(NS_LITERAL_STRING("SVGOuterSVGAnonChild"), aResult);
249 : }
250 : #endif
251 :
252 : bool IsSVGTransformed(Matrix *aOwnTransform,
253 : Matrix *aFromParentTransform) const override;
254 :
255 : // nsSVGContainerFrame methods:
256 0 : virtual gfxMatrix GetCanvasTM() override {
257 : // GetCanvasTM returns the transform from an SVG frame to the frame's
258 : // nsSVGOuterSVGFrame's content box, so we do not include any x/y offset
259 : // set on us for any CSS border or padding on our nsSVGOuterSVGFrame.
260 0 : return static_cast<nsSVGOuterSVGFrame*>(GetParent())->GetCanvasTM();
261 : }
262 : };
263 :
264 : #endif
|