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 "mozilla/Attributes.h" 11 #include "mozilla/SVGPaintServerFrame.h" 12 #include "gfxMatrix.h" 13 #include "gfxRect.h" 14 #include "nsCOMPtr.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 virtual already_AddRefed<gfxPattern> GetPaintServerPattern( 53 nsIFrame* aSource, const DrawTarget* aDrawTarget, 54 const gfxMatrix& aContextMatrix, StyleSVGPaint nsStyleSVG::*aFillOrStroke, 55 float aGraphicOpacity, imgDrawingParams& aImgParams, 56 const gfxRect* aOverrideBounds) override; 57 58 // nsIFrame interface: 59 virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 60 int32_t aModType) override; 61 62 #ifdef DEBUG_FRAME_DUMP GetFrameName(nsAString & aResult)63 virtual 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 // Optionally get a stop frame (returns stop index/count) 76 void GetStopFrames(nsTArray<nsIFrame*>* aStopFrames); 77 78 const SVGAnimatedTransformList* GetGradientTransformList( 79 nsIContent* aDefault); 80 // Will be singular for gradientUnits="objectBoundingBox" with an empty bbox. 81 gfxMatrix GetGradientTransform(nsIFrame* aSource, 82 const gfxRect* aOverrideBounds); 83 84 protected: 85 virtual bool GradientVectorLengthIsZero() = 0; 86 virtual already_AddRefed<gfxPattern> CreateGradient() = 0; 87 88 // Accessors to lookup gradient attributes 89 uint16_t GetEnumValue(uint32_t aIndex, nsIContent* aDefault); GetEnumValue(uint32_t aIndex)90 uint16_t GetEnumValue(uint32_t aIndex) { 91 return GetEnumValue(aIndex, mContent); 92 } 93 uint16_t GetGradientUnits(); 94 uint16_t GetSpreadMethod(); 95 96 // Gradient-type-specific lookups since the length values differ between 97 // linear and radial gradients 98 virtual dom::SVGLinearGradientElement* GetLinearGradientWithLength( 99 uint32_t aIndex, dom::SVGLinearGradientElement* aDefault); 100 virtual dom::SVGRadialGradientElement* GetRadialGradientWithLength( 101 uint32_t aIndex, dom::SVGRadialGradientElement* aDefault); 102 103 // The frame our gradient is (currently) being applied to 104 nsIFrame* mSource; 105 106 private: 107 // Flag to mark this frame as "in use" during recursive calls along our 108 // gradient's reference chain so we can detect reference loops. See: 109 // http://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute 110 bool mLoopFlag; 111 // Gradients often don't reference other gradients, so here we cache 112 // the fact that that isn't happening. 113 bool mNoHRefURI; 114 }; 115 116 // ------------------------------------------------------------------------- 117 // Linear Gradients 118 // ------------------------------------------------------------------------- 119 120 class SVGLinearGradientFrame final : public SVGGradientFrame { 121 friend nsIFrame* ::NS_NewSVGLinearGradientFrame( 122 mozilla::PresShell* aPresShell, ComputedStyle* aStyle); 123 124 protected: SVGLinearGradientFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)125 explicit SVGLinearGradientFrame(ComputedStyle* aStyle, 126 nsPresContext* aPresContext) 127 : SVGGradientFrame(aStyle, aPresContext, kClassID) {} 128 129 public: 130 NS_DECL_QUERYFRAME 131 NS_DECL_FRAMEARENA_HELPERS(SVGLinearGradientFrame) 132 133 // nsIFrame interface: 134 #ifdef DEBUG 135 virtual void Init(nsIContent* aContent, nsContainerFrame* aParent, 136 nsIFrame* aPrevInFlow) override; 137 #endif 138 139 virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 140 int32_t aModType) override; 141 142 #ifdef DEBUG_FRAME_DUMP GetFrameName(nsAString & aResult)143 virtual nsresult GetFrameName(nsAString& aResult) const override { 144 return MakeFrameName(u"SVGLinearGradient"_ns, aResult); 145 } 146 #endif // DEBUG 147 148 protected: 149 float GetLengthValue(uint32_t aIndex); 150 virtual mozilla::dom::SVGLinearGradientElement* GetLinearGradientWithLength( 151 uint32_t aIndex, 152 mozilla::dom::SVGLinearGradientElement* aDefault) override; 153 virtual bool GradientVectorLengthIsZero() override; 154 virtual 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: SVGRadialGradientFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)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 virtual void Init(nsIContent* aContent, nsContainerFrame* aParent, 177 nsIFrame* aPrevInFlow) override; 178 #endif 179 180 virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 181 int32_t aModType) override; 182 183 #ifdef DEBUG_FRAME_DUMP GetFrameName(nsAString & aResult)184 virtual nsresult GetFrameName(nsAString& aResult) const override { 185 return MakeFrameName(u"SVGRadialGradient"_ns, aResult); 186 } 187 #endif // DEBUG 188 189 protected: 190 float GetLengthValue(uint32_t aIndex); 191 float GetLengthValue(uint32_t aIndex, float aDefaultValue); 192 float GetLengthValueFromElement( 193 uint32_t aIndex, mozilla::dom::SVGRadialGradientElement& aElement); 194 virtual mozilla::dom::SVGRadialGradientElement* GetRadialGradientWithLength( 195 uint32_t aIndex, 196 mozilla::dom::SVGRadialGradientElement* aDefault) override; 197 virtual bool GradientVectorLengthIsZero() override; 198 virtual already_AddRefed<gfxPattern> CreateGradient() override; 199 }; 200 201 } // namespace mozilla 202 203 #endif // LAYOUT_SVG_SVGGRADIENTFRAME_H_ 204