michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef __NS_SVGGRADIENTFRAME_H__ michael@0: #define __NS_SVGGRADIENTFRAME_H__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "gfxMatrix.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsFrame.h" michael@0: #include "nsLiteralString.h" michael@0: #include "nsSVGPaintServerFrame.h" michael@0: michael@0: class gfxPattern; michael@0: class nsIAtom; michael@0: class nsIContent; michael@0: class nsIFrame; michael@0: class nsIPresShell; michael@0: class nsStyleContext; michael@0: michael@0: struct gfxRect; michael@0: michael@0: namespace mozilla { michael@0: class nsSVGAnimatedTransformList; michael@0: michael@0: namespace dom { michael@0: class SVGLinearGradientElement; michael@0: class SVGRadialGradientElement; michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: typedef nsSVGPaintServerFrame nsSVGGradientFrameBase; michael@0: michael@0: /** michael@0: * Gradients can refer to other gradients. We create an nsSVGPaintingProperty michael@0: * with property type nsGkAtoms::href to track the referenced gradient. michael@0: */ michael@0: class nsSVGGradientFrame : public nsSVGGradientFrameBase michael@0: { michael@0: protected: michael@0: nsSVGGradientFrame(nsStyleContext* aContext); michael@0: michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: // nsSVGPaintServerFrame methods: michael@0: virtual already_AddRefed michael@0: GetPaintServerPattern(nsIFrame *aSource, michael@0: const gfxMatrix& aContextMatrix, michael@0: nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, michael@0: float aGraphicOpacity, michael@0: const gfxRect *aOverrideBounds) MOZ_OVERRIDE; michael@0: michael@0: // nsIFrame interface: michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("SVGGradient"), aResult); michael@0: } michael@0: #endif // DEBUG michael@0: michael@0: private: michael@0: michael@0: // Parse our xlink:href and set up our nsSVGPaintingProperty if we michael@0: // reference another gradient and we don't have a property. Return michael@0: // the referenced gradient's frame if available, null otherwise. michael@0: nsSVGGradientFrame* GetReferencedGradient(); michael@0: michael@0: // Optionally get a stop frame (returns stop index/count) michael@0: void GetStopFrames(nsTArray* aStopFrames); michael@0: michael@0: const mozilla::nsSVGAnimatedTransformList* GetGradientTransformList( michael@0: nsIContent* aDefault); michael@0: // Will be singular for gradientUnits="objectBoundingBox" with an empty bbox. michael@0: gfxMatrix GetGradientTransform(nsIFrame *aSource, michael@0: const gfxRect *aOverrideBounds); michael@0: michael@0: protected: michael@0: virtual bool GradientVectorLengthIsZero() = 0; michael@0: virtual already_AddRefed CreateGradient() = 0; michael@0: michael@0: // Internal methods for handling referenced gradients michael@0: class AutoGradientReferencer; michael@0: nsSVGGradientFrame* GetReferencedGradientIfNotInUse(); michael@0: michael@0: // Accessors to lookup gradient attributes michael@0: uint16_t GetEnumValue(uint32_t aIndex, nsIContent *aDefault); michael@0: uint16_t GetEnumValue(uint32_t aIndex) michael@0: { michael@0: return GetEnumValue(aIndex, mContent); michael@0: } michael@0: uint16_t GetGradientUnits(); michael@0: uint16_t GetSpreadMethod(); michael@0: michael@0: // Gradient-type-specific lookups since the length values differ between michael@0: // linear and radial gradients michael@0: virtual mozilla::dom::SVGLinearGradientElement * GetLinearGradientWithLength( michael@0: uint32_t aIndex, mozilla::dom::SVGLinearGradientElement* aDefault); michael@0: virtual mozilla::dom::SVGRadialGradientElement * GetRadialGradientWithLength( michael@0: uint32_t aIndex, mozilla::dom::SVGRadialGradientElement* aDefault); michael@0: michael@0: // The frame our gradient is (currently) being applied to michael@0: nsIFrame* mSource; michael@0: michael@0: private: michael@0: // Flag to mark this frame as "in use" during recursive calls along our michael@0: // gradient's reference chain so we can detect reference loops. See: michael@0: // http://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute michael@0: bool mLoopFlag; michael@0: // Gradients often don't reference other gradients, so here we cache michael@0: // the fact that that isn't happening. michael@0: bool mNoHRefURI; michael@0: }; michael@0: michael@0: michael@0: // ------------------------------------------------------------------------- michael@0: // Linear Gradients michael@0: // ------------------------------------------------------------------------- michael@0: michael@0: typedef nsSVGGradientFrame nsSVGLinearGradientFrameBase; michael@0: michael@0: class nsSVGLinearGradientFrame : public nsSVGLinearGradientFrameBase michael@0: { michael@0: friend nsIFrame* NS_NewSVGLinearGradientFrame(nsIPresShell* aPresShell, michael@0: nsStyleContext* aContext); michael@0: protected: michael@0: nsSVGLinearGradientFrame(nsStyleContext* aContext) : michael@0: nsSVGLinearGradientFrameBase(aContext) {} michael@0: michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: // nsIFrame interface: michael@0: #ifdef DEBUG michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; // frame type: nsGkAtoms::svgLinearGradientFrame michael@0: michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("SVGLinearGradient"), aResult); michael@0: } michael@0: #endif // DEBUG michael@0: michael@0: protected: michael@0: float GetLengthValue(uint32_t aIndex); michael@0: virtual mozilla::dom::SVGLinearGradientElement* GetLinearGradientWithLength( michael@0: uint32_t aIndex, mozilla::dom::SVGLinearGradientElement* aDefault) MOZ_OVERRIDE; michael@0: virtual bool GradientVectorLengthIsZero() MOZ_OVERRIDE; michael@0: virtual already_AddRefed CreateGradient() MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: // ------------------------------------------------------------------------- michael@0: // Radial Gradients michael@0: // ------------------------------------------------------------------------- michael@0: michael@0: typedef nsSVGGradientFrame nsSVGRadialGradientFrameBase; michael@0: michael@0: class nsSVGRadialGradientFrame : public nsSVGRadialGradientFrameBase michael@0: { michael@0: friend nsIFrame* NS_NewSVGRadialGradientFrame(nsIPresShell* aPresShell, michael@0: nsStyleContext* aContext); michael@0: protected: michael@0: nsSVGRadialGradientFrame(nsStyleContext* aContext) : michael@0: nsSVGRadialGradientFrameBase(aContext) {} michael@0: michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: // nsIFrame interface: michael@0: #ifdef DEBUG michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; // frame type: nsGkAtoms::svgRadialGradientFrame michael@0: michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE michael@0: { michael@0: return MakeFrameName(NS_LITERAL_STRING("SVGRadialGradient"), aResult); michael@0: } michael@0: #endif // DEBUG michael@0: michael@0: protected: michael@0: float GetLengthValue(uint32_t aIndex); michael@0: float GetLengthValue(uint32_t aIndex, float aDefaultValue); michael@0: float GetLengthValueFromElement(uint32_t aIndex, michael@0: mozilla::dom::SVGRadialGradientElement& aElement); michael@0: virtual mozilla::dom::SVGRadialGradientElement* GetRadialGradientWithLength( michael@0: uint32_t aIndex, mozilla::dom::SVGRadialGradientElement* aDefault) MOZ_OVERRIDE; michael@0: virtual bool GradientVectorLengthIsZero() MOZ_OVERRIDE; michael@0: virtual already_AddRefed CreateGradient() MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: #endif // __NS_SVGGRADIENTFRAME_H__ michael@0: