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