SVGOuterSVGFrame.h (7977B)
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/. */ 6 7 #ifndef LAYOUT_SVG_SVGOUTERSVGFRAME_H_ 8 #define LAYOUT_SVG_SVGOUTERSVGFRAME_H_ 9 10 #include "mozilla/ISVGSVGFrame.h" 11 #include "mozilla/SVGContainerFrame.h" 12 13 class gfxContext; 14 15 namespace mozilla { 16 class AutoSVGViewHandler; 17 class SVGFragmentIdentifier; 18 class PresShell; 19 } // namespace mozilla 20 21 nsContainerFrame* NS_NewSVGOuterSVGFrame(mozilla::PresShell* aPresShell, 22 mozilla::ComputedStyle* aStyle); 23 nsContainerFrame* NS_NewSVGOuterSVGAnonChildFrame( 24 mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle); 25 26 namespace mozilla { 27 28 //////////////////////////////////////////////////////////////////////// 29 // SVGOuterSVGFrame class 30 31 class SVGOuterSVGFrame final : public SVGDisplayContainerFrame, 32 public ISVGSVGFrame { 33 using imgDrawingParams = image::imgDrawingParams; 34 35 friend nsContainerFrame* ::NS_NewSVGOuterSVGFrame( 36 mozilla::PresShell* aPresShell, ComputedStyle* aStyle); 37 friend class AsyncSendIntrinsicSizeAndRatioToEmbedder; 38 friend class AutoSVGViewHandler; 39 friend class SVGFragmentIdentifier; 40 41 protected: 42 explicit SVGOuterSVGFrame(ComputedStyle* aStyle, nsPresContext* aPresContext); 43 44 public: 45 NS_DECL_QUERYFRAME 46 NS_DECL_FRAMEARENA_HELPERS(SVGOuterSVGFrame) 47 48 nscoord IntrinsicISize(const IntrinsicSizeInput& aInput, 49 IntrinsicISizeType aType) override; 50 51 IntrinsicSize GetIntrinsicSize() override; 52 AspectRatio GetIntrinsicRatio() const override; 53 54 SizeComputationResult ComputeSize( 55 const SizeComputationInput& aSizingInput, WritingMode aWritingMode, 56 const LogicalSize& aCBSize, nscoord aAvailableISize, 57 const LogicalSize& aMargin, const LogicalSize& aBorderPadding, 58 const mozilla::StyleSizeOverrides& aSizeOverrides, 59 ComputeSizeFlags aFlags) override; 60 61 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, 62 const ReflowInput& aReflowInput, 63 nsReflowStatus& aStatus) override; 64 65 void UnionChildOverflow(mozilla::OverflowAreas& aOverflowAreas, 66 bool aAsIfScrolled) override; 67 68 void BuildDisplayList(nsDisplayListBuilder* aBuilder, 69 const nsDisplayListSet& aLists) override; 70 71 void Init(nsIContent* aContent, nsContainerFrame* aParent, 72 nsIFrame* aPrevInFlow) override; 73 74 #ifdef DEBUG_FRAME_DUMP 75 nsresult GetFrameName(nsAString& aResult) const override { 76 return MakeFrameName(u"SVGOuterSVG"_ns, aResult); 77 } 78 #endif 79 80 void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override; 81 82 void Destroy(DestroyContext&) override; 83 84 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 85 AttrModType aModType) override; 86 87 nsContainerFrame* GetContentInsertionFrame() override { 88 // Any children must be added to our single anonymous inner frame kid. 89 MOZ_ASSERT( 90 PrincipalChildList().FirstChild() && 91 PrincipalChildList().FirstChild()->IsSVGOuterSVGAnonChildFrame(), 92 "Where is our anonymous child?"); 93 return PrincipalChildList().FirstChild()->GetContentInsertionFrame(); 94 } 95 96 bool DoGetParentSVGTransforms(Matrix*) const override { return false; }; 97 98 // Return our anonymous box child. 99 void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override; 100 101 // ISVGSVGFrame interface: 102 void NotifyViewportOrTransformChanged(ChangeFlags aFlags) override; 103 104 // ISVGDisplayableFrame methods: 105 void PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform, 106 imgDrawingParams& aImgParams) override; 107 SVGBBox GetBBoxContribution(const Matrix& aToBBoxUserspace, 108 uint32_t aFlags) override; 109 110 // SVGContainerFrame methods: 111 gfxMatrix GetCanvasTM() override; 112 113 bool HasChildrenOnlyTransform(Matrix* aTransform) const override; 114 115 /** 116 * Return true only if the height is unspecified (defaulting to 100%) or else 117 * the height is explicitly set to a percentage value no greater than 100%. 118 */ 119 bool VerticalScrollbarNotNeeded() const; 120 121 bool IsCallingReflowSVG() const { return mCallingReflowSVG; } 122 123 protected: 124 /* Returns true if our content is the document element and our document is 125 * being used as an image. 126 */ 127 bool IsRootOfImage(); 128 float ComputeFullZoom() const; 129 130 void MaybeSendIntrinsicSizeAndRatioToEmbedder(); 131 void MaybeSendIntrinsicSizeAndRatioToEmbedder(Maybe<IntrinsicSize>, 132 Maybe<AspectRatio>); 133 134 float mFullZoom = 1.0f; 135 136 bool mCallingReflowSVG = false; 137 bool mIsRootContent = false; 138 bool mIsInObjectOrEmbed = false; 139 bool mIsInIframe = false; 140 }; 141 142 //////////////////////////////////////////////////////////////////////// 143 // SVGOuterSVGAnonChildFrame class 144 145 /** 146 * SVGOuterSVGFrames have a single direct child that is an instance of this 147 * class, and which is used to wrap their real child frames. Such anonymous 148 * wrapper frames created from this class exist because SVG frames need their 149 * GetPosition() offset to be their offset relative to "user space" (in app 150 * units) so that they can play nicely with nsDisplayTransform. This is fine 151 * for all SVG frames except for direct children of an SVGOuterSVGFrame, 152 * since an SVGOuterSVGFrame can have CSS border and padding (unlike other 153 * SVG frames). The direct children can't include the offsets due to any such 154 * border/padding in their mRects since that would break nsDisplayTransform, 155 * but not including these offsets would break other parts of the Mozilla code 156 * that assume a frame's mRect contains its border-box-to-parent-border-box 157 * offset, in particular nsIFrame::GetOffsetTo and the functions that depend on 158 * it. Wrapping an SVGOuterSVGFrame's children in an instance of this class 159 * with its GetPosition() set to its SVGOuterSVGFrame's border/padding offset 160 * keeps both nsDisplayTransform and nsIFrame::GetOffsetTo happy. 161 * 162 * The reason that this class inherit from SVGDisplayContainerFrame rather 163 * than simply from nsContainerFrame is so that we can avoid having special 164 * handling for these inner wrappers in multiple parts of the SVG code. For 165 * example, the implementations of IsSVGTransformed and GetCanvasTM assume 166 * SVGContainerFrame instances all the way up to the SVGOuterSVGFrame. 167 */ 168 class SVGOuterSVGAnonChildFrame final : public SVGDisplayContainerFrame { 169 friend nsContainerFrame* ::NS_NewSVGOuterSVGAnonChildFrame( 170 mozilla::PresShell* aPresShell, ComputedStyle* aStyle); 171 172 explicit SVGOuterSVGAnonChildFrame(ComputedStyle* aStyle, 173 nsPresContext* aPresContext) 174 : SVGDisplayContainerFrame(aStyle, aPresContext, kClassID) {} 175 176 public: 177 NS_DECL_FRAMEARENA_HELPERS(SVGOuterSVGAnonChildFrame) 178 179 #ifdef DEBUG 180 void Init(nsIContent* aContent, nsContainerFrame* aParent, 181 nsIFrame* aPrevInFlow) override; 182 #endif 183 184 void BuildDisplayList(nsDisplayListBuilder* aBuilder, 185 const nsDisplayListSet& aLists) override; 186 187 #ifdef DEBUG_FRAME_DUMP 188 nsresult GetFrameName(nsAString& aResult) const override { 189 return MakeFrameName(u"SVGOuterSVGAnonChild"_ns, aResult); 190 } 191 #endif 192 193 bool DoGetParentSVGTransforms(Matrix*) const override; 194 195 // SVGContainerFrame methods: 196 gfxMatrix GetCanvasTM() override { 197 // GetCanvasTM returns the transform from an SVG frame to the frame's 198 // SVGOuterSVGFrame's content box, so we do not include any x/y offset 199 // set on us for any CSS border or padding on our SVGOuterSVGFrame. 200 return static_cast<SVGOuterSVGFrame*>(GetParent())->GetCanvasTM(); 201 } 202 }; 203 204 } // namespace mozilla 205 206 #endif // LAYOUT_SVG_SVGOUTERSVGFRAME_H_