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