SVGGradientFrame.h (7112B)
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_SVGGRADIENTFRAME_H_ 8 #define LAYOUT_SVG_SVGGRADIENTFRAME_H_ 9 10 #include "gfxMatrix.h" 11 #include "gfxRect.h" 12 #include "mozilla/SVGPaintServerFrame.h" 13 #include "nsCOMPtr.h" 14 #include "nsCSSRenderingGradients.h" 15 #include "nsIFrame.h" 16 #include "nsLiteralString.h" 17 18 class gfxPattern; 19 class nsAtom; 20 class nsIContent; 21 22 namespace mozilla { 23 class PresShell; 24 class SVGAnimatedTransformList; 25 26 namespace dom { 27 class SVGLinearGradientElement; 28 class SVGRadialGradientElement; 29 } // namespace dom 30 } // namespace mozilla 31 32 nsIFrame* NS_NewSVGLinearGradientFrame(mozilla::PresShell* aPresShell, 33 mozilla::ComputedStyle* aStyle); 34 nsIFrame* NS_NewSVGRadialGradientFrame(mozilla::PresShell* aPresShell, 35 mozilla::ComputedStyle* aStyle); 36 37 namespace mozilla { 38 39 class SVGGradientFrame : public SVGPaintServerFrame { 40 using ExtendMode = gfx::ExtendMode; 41 42 protected: 43 SVGGradientFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, 44 ClassID aID); 45 46 public: 47 NS_DECL_ABSTRACT_FRAME(SVGGradientFrame) 48 NS_DECL_QUERYFRAME 49 NS_DECL_QUERYFRAME_TARGET(SVGGradientFrame) 50 51 // SVGPaintServerFrame methods: 52 already_AddRefed<gfxPattern> GetPaintServerPattern( 53 nsIFrame* aSource, const DrawTarget* aDrawTarget, 54 const gfxMatrix& aContextMatrix, 55 StyleSVGPaint nsStyleSVG::* aFillOrStroke, float aGraphicOpacity, 56 imgDrawingParams& aImgParams, const gfxRect* aOverrideBounds) override; 57 58 // nsIFrame interface: 59 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 60 AttrModType aModType) override; 61 62 #ifdef DEBUG_FRAME_DUMP 63 nsresult GetFrameName(nsAString& aResult) const override { 64 return MakeFrameName(u"SVGGradient"_ns, aResult); 65 } 66 #endif // DEBUG 67 68 private: 69 /** 70 * Parses this frame's href and - if it references another gradient - returns 71 * it. It also makes this frame a rendering observer of the specified ID. 72 */ 73 SVGGradientFrame* GetReferencedGradient(); 74 75 void GetStops(nsTArray<ColorStop>* aStops, float aGraphicOpacity); 76 77 SVGGradientFrame* GetGradientTransformFrame(SVGGradientFrame* aDefault); 78 // Will be singular for gradientUnits="objectBoundingBox" with an empty bbox. 79 gfxMatrix GetGradientTransform(nsIFrame* aSource, 80 const gfxRect* aOverrideBounds); 81 82 protected: 83 virtual bool GradientVectorLengthIsZero() = 0; 84 virtual already_AddRefed<gfxPattern> CreateGradient() = 0; 85 86 // Accessors to lookup gradient attributes 87 uint16_t GetEnumValue(uint32_t aIndex, nsIContent* aDefault); 88 uint16_t GetEnumValue(uint32_t aIndex) { 89 return GetEnumValue(aIndex, mContent); 90 } 91 uint16_t GetGradientUnits(); 92 uint16_t GetSpreadMethod(); 93 float GetLengthValue(const SVGAnimatedLength& aLength); 94 95 // Gradient-type-specific lookups since the length values differ between 96 // linear and radial gradients 97 virtual dom::SVGLinearGradientElement* GetLinearGradientWithLength( 98 uint32_t aIndex, dom::SVGLinearGradientElement* aDefault); 99 virtual dom::SVGRadialGradientElement* GetRadialGradientWithLength( 100 uint32_t aIndex, dom::SVGRadialGradientElement* aDefault); 101 102 // The frame our gradient is (currently) being applied to 103 nsIFrame* mSource; 104 105 private: 106 // Flag to mark this frame as "in use" during recursive calls along our 107 // gradient's reference chain so we can detect reference loops. See: 108 // http://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute 109 bool mLoopFlag; 110 // Gradients often don't reference other gradients, so here we cache 111 // the fact that that isn't happening. 112 bool mNoHRefURI; 113 }; 114 115 // ------------------------------------------------------------------------- 116 // Linear Gradients 117 // ------------------------------------------------------------------------- 118 119 class SVGLinearGradientFrame final : public SVGGradientFrame { 120 friend nsIFrame* ::NS_NewSVGLinearGradientFrame( 121 mozilla::PresShell* aPresShell, ComputedStyle* aStyle); 122 123 protected: 124 explicit SVGLinearGradientFrame(ComputedStyle* aStyle, 125 nsPresContext* aPresContext) 126 : SVGGradientFrame(aStyle, aPresContext, kClassID) {} 127 128 public: 129 NS_DECL_QUERYFRAME 130 NS_DECL_FRAMEARENA_HELPERS(SVGLinearGradientFrame) 131 132 // nsIFrame interface: 133 #ifdef DEBUG 134 void Init(nsIContent* aContent, nsContainerFrame* aParent, 135 nsIFrame* aPrevInFlow) override; 136 #endif 137 138 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 139 AttrModType aModType) override; 140 141 #ifdef DEBUG_FRAME_DUMP 142 nsresult GetFrameName(nsAString& aResult) const override { 143 return MakeFrameName(u"SVGLinearGradient"_ns, aResult); 144 } 145 #endif // DEBUG 146 147 protected: 148 using SVGGradientFrame::GetLengthValue; 149 float GetLengthValue(uint32_t aIndex); 150 mozilla::dom::SVGLinearGradientElement* GetLinearGradientWithLength( 151 uint32_t aIndex, 152 mozilla::dom::SVGLinearGradientElement* aDefault) override; 153 bool GradientVectorLengthIsZero() override; 154 already_AddRefed<gfxPattern> CreateGradient() override; 155 }; 156 157 // ------------------------------------------------------------------------- 158 // Radial Gradients 159 // ------------------------------------------------------------------------- 160 161 class SVGRadialGradientFrame final : public SVGGradientFrame { 162 friend nsIFrame* ::NS_NewSVGRadialGradientFrame( 163 mozilla::PresShell* aPresShell, ComputedStyle* aStyle); 164 165 protected: 166 explicit SVGRadialGradientFrame(ComputedStyle* aStyle, 167 nsPresContext* aPresContext) 168 : SVGGradientFrame(aStyle, aPresContext, kClassID) {} 169 170 public: 171 NS_DECL_QUERYFRAME 172 NS_DECL_FRAMEARENA_HELPERS(SVGRadialGradientFrame) 173 174 // nsIFrame interface: 175 #ifdef DEBUG 176 void Init(nsIContent* aContent, nsContainerFrame* aParent, 177 nsIFrame* aPrevInFlow) override; 178 #endif 179 180 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 181 AttrModType aModType) override; 182 183 #ifdef DEBUG_FRAME_DUMP 184 nsresult GetFrameName(nsAString& aResult) const override { 185 return MakeFrameName(u"SVGRadialGradient"_ns, aResult); 186 } 187 #endif // DEBUG 188 189 protected: 190 using SVGGradientFrame::GetLengthValue; 191 float GetLengthValue(uint32_t aIndex, Maybe<float> aDefaultValue = Nothing()); 192 float GetLengthValue(uint32_t aIndex, float aDefaultValue) { 193 return GetLengthValue(aIndex, Some(aDefaultValue)); 194 } 195 mozilla::dom::SVGRadialGradientElement* GetRadialGradientWithLength( 196 uint32_t aIndex, 197 mozilla::dom::SVGRadialGradientElement* aDefault) override; 198 bool GradientVectorLengthIsZero() override; 199 already_AddRefed<gfxPattern> CreateGradient() override; 200 }; 201 202 } // namespace mozilla 203 204 #endif // LAYOUT_SVG_SVGGRADIENTFRAME_H_