/* -*- Mode: C++; tab-width: 8; 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_SVGLENGTH2_H__ #define __NS_SVGLENGTH2_H__ #include "mozilla/Attributes.h" #include "nsCoord.h" #include "nsCycleCollectionParticipant.h" #include "nsError.h" #include "nsIDOMSVGLength.h" #include "nsISMILAttr.h" #include "nsMathUtils.h" #include "nsSVGElement.h" #include "SVGContentUtils.h" #include "mozilla/gfx/Rect.h" class nsIFrame; class nsSMILValue; namespace mozilla { class DOMSVGLength; namespace dom { class SVGAnimatedLength; class SVGAnimationElement; class SVGSVGElement; } // namespace dom } // namespace mozilla namespace mozilla { namespace dom { class UserSpaceMetrics { public: virtual ~UserSpaceMetrics() {} virtual float GetEmLength() const = 0; virtual float GetExLength() const = 0; virtual float GetAxisLength(uint8_t aCtxType) const = 0; }; class UserSpaceMetricsWithSize : public UserSpaceMetrics { public: virtual gfx::Size GetSize() const = 0; virtual float GetAxisLength(uint8_t aCtxType) const override; }; class SVGElementMetrics : public UserSpaceMetrics { public: explicit SVGElementMetrics(nsSVGElement* aSVGElement, mozilla::dom::SVGSVGElement* aCtx = nullptr); virtual float GetEmLength() const override; virtual float GetExLength() const override; virtual float GetAxisLength(uint8_t aCtxType) const override; private: bool EnsureCtx() const; nsSVGElement* mSVGElement; mutable mozilla::dom::SVGSVGElement* mCtx; }; class NonSVGFrameUserSpaceMetrics : public UserSpaceMetricsWithSize { public: explicit NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame); virtual float GetEmLength() const override; virtual float GetExLength() const override; virtual gfx::Size GetSize() const override; private: nsIFrame* mFrame; }; } // namespace dom } // namespace mozilla class nsSVGLength2 { friend class mozilla::dom::SVGAnimatedLength; friend class mozilla::DOMSVGLength; typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics; public: void Init(uint8_t aCtxType = SVGContentUtils::XY, uint8_t aAttrEnum = 0xff, float aValue = 0, uint8_t aUnitType = nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER) { mAnimVal = mBaseVal = aValue; mSpecifiedUnitType = aUnitType; mAttrEnum = aAttrEnum; mCtxType = aCtxType; mIsAnimated = false; mIsBaseSet = false; } nsSVGLength2& operator=(const nsSVGLength2& aLength) { mBaseVal = aLength.mBaseVal; mAnimVal = aLength.mAnimVal; mSpecifiedUnitType = aLength.mSpecifiedUnitType; mIsAnimated = aLength.mIsAnimated; mIsBaseSet = aLength.mIsBaseSet; return *this; } nsresult SetBaseValueString(const nsAString& aValue, nsSVGElement *aSVGElement, bool aDoSetAttr); void GetBaseValueString(nsAString& aValue) const; void GetAnimValueString(nsAString& aValue) const; float GetBaseValue(nsSVGElement* aSVGElement) const { return mBaseVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType); } float GetAnimValue(nsSVGElement* aSVGElement) const { return mAnimVal / GetUnitScaleFactor(aSVGElement, mSpecifiedUnitType); } float GetAnimValue(nsIFrame* aFrame) const { return mAnimVal / GetUnitScaleFactor(aFrame, mSpecifiedUnitType); } float GetAnimValue(mozilla::dom::SVGSVGElement* aCtx) const { return mAnimVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); } float GetAnimValue(const UserSpaceMetrics& aMetrics) const { return mAnimVal / GetUnitScaleFactor(aMetrics, mSpecifiedUnitType); } uint8_t GetCtxType() const { return mCtxType; } uint8_t GetSpecifiedUnitType() const { return mSpecifiedUnitType; } bool IsPercentage() const { return mSpecifiedUnitType == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE; } float GetAnimValInSpecifiedUnits() const { return mAnimVal; } float GetBaseValInSpecifiedUnits() const { return mBaseVal; } float GetBaseValue(mozilla::dom::SVGSVGElement* aCtx) const { return mBaseVal / GetUnitScaleFactor(aCtx, mSpecifiedUnitType); } bool HasBaseVal() const { return mIsBaseSet; } // Returns true if the animated value of this length has been explicitly // set (either by animation, or by taking on the base value which has been // explicitly set by markup or a DOM call), false otherwise. // If this returns false, the animated value is still valid, that is, // useable, and represents the default base value of the attribute. bool IsExplicitlySet() const { return mIsAnimated || mIsBaseSet; } already_AddRefed ToDOMAnimatedLength(nsSVGElement* aSVGElement); // Returns a new nsISMILAttr object that the caller must delete nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement); private: float mAnimVal; float mBaseVal; uint8_t mSpecifiedUnitType; uint8_t mAttrEnum; // element specified tracking for attribute uint8_t mCtxType; // X, Y or Unspecified bool mIsAnimated:1; bool mIsBaseSet:1; float GetUnitScaleFactor(nsIFrame *aFrame, uint8_t aUnitType) const; float GetUnitScaleFactor(const UserSpaceMetrics& aMetrics, uint8_t aUnitType) const; float GetUnitScaleFactor(nsSVGElement *aSVGElement, uint8_t aUnitType) const; float GetUnitScaleFactor(mozilla::dom::SVGSVGElement *aCtx, uint8_t aUnitType) const; // SetBaseValue and SetAnimValue set the value in user units void SetBaseValue(float aValue, nsSVGElement *aSVGElement, bool aDoSetAttr); void SetBaseValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement, bool aDoSetAttr); void SetAnimValue(float aValue, nsSVGElement *aSVGElement); void SetAnimValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement); nsresult NewValueSpecifiedUnits(uint16_t aUnitType, float aValue, nsSVGElement *aSVGElement); nsresult ConvertToSpecifiedUnits(uint16_t aUnitType, nsSVGElement *aSVGElement); nsresult ToDOMBaseVal(mozilla::DOMSVGLength **aResult, nsSVGElement* aSVGElement); nsresult ToDOMAnimVal(mozilla::DOMSVGLength **aResult, nsSVGElement* aSVGElement); public: struct SMILLength : public nsISMILAttr { public: SMILLength(nsSVGLength2* aVal, nsSVGElement *aSVGElement) : mVal(aVal), mSVGElement(aSVGElement) {} // These will stay alive because a nsISMILAttr only lives as long // as the Compositing step, and DOM elements don't get a chance to // die during that. nsSVGLength2* mVal; nsSVGElement* mSVGElement; // nsISMILAttr methods virtual nsresult ValueFromString(const nsAString& aStr, const mozilla::dom::SVGAnimationElement* aSrcElement, nsSMILValue &aValue, bool& aPreventCachingOfSandwich) const override; virtual nsSMILValue GetBaseValue() const override; virtual void ClearAnimValue() override; virtual nsresult SetAnimValue(const nsSMILValue& aValue) override; }; }; #endif // __NS_SVGLENGTH2_H__