зеркало из https://github.com/mozilla/gecko-dev.git
Bug 631436 part 2 - support length animation with different units r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D191515
This commit is contained in:
Родитель
5ec06e8577
Коммит
3352d3d85b
|
@ -116,9 +116,13 @@ DOMSVGLength* DOMSVGLength::Copy() {
|
|||
float value;
|
||||
if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
|
||||
SVGAnimatedLength* length = svg->GetAnimatedLength(mAttrEnum);
|
||||
unit = length->GetSpecifiedUnitType();
|
||||
value = mIsAnimValItem ? length->GetAnimValInSpecifiedUnits()
|
||||
: length->GetBaseValInSpecifiedUnits();
|
||||
if (mIsAnimValItem) {
|
||||
unit = length->GetAnimUnitType();
|
||||
value = length->GetAnimValInSpecifiedUnits();
|
||||
} else {
|
||||
unit = length->GetBaseUnitType();
|
||||
value = length->GetBaseValInSpecifiedUnits();
|
||||
}
|
||||
} else {
|
||||
const SVGLength& length = InternalItem();
|
||||
unit = length.GetUnit();
|
||||
|
@ -134,7 +138,9 @@ uint16_t DOMSVGLength::UnitType() {
|
|||
}
|
||||
uint16_t unitType;
|
||||
if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
|
||||
unitType = svg->GetAnimatedLength(mAttrEnum)->GetSpecifiedUnitType();
|
||||
unitType = mIsAnimValItem
|
||||
? svg->GetAnimatedLength(mAttrEnum)->GetAnimUnitType()
|
||||
: svg->GetAnimatedLength(mAttrEnum)->GetBaseUnitType();
|
||||
} else {
|
||||
unitType = HasOwner() ? InternalItem().GetUnit() : mUnit;
|
||||
}
|
||||
|
@ -415,9 +421,12 @@ void DOMSVGLength::RemovingFromList() {
|
|||
SVGLength DOMSVGLength::ToSVGLength() {
|
||||
if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
|
||||
SVGAnimatedLength* length = svg->GetAnimatedLength(mAttrEnum);
|
||||
return SVGLength(mIsAnimValItem ? length->GetAnimValInSpecifiedUnits()
|
||||
: length->GetBaseValInSpecifiedUnits(),
|
||||
length->GetSpecifiedUnitType());
|
||||
if (mIsAnimValItem) {
|
||||
return SVGLength(length->GetAnimValInSpecifiedUnits(),
|
||||
length->GetAnimUnitType());
|
||||
}
|
||||
return SVGLength(length->GetBaseValInSpecifiedUnits(),
|
||||
length->GetBaseUnitType());
|
||||
}
|
||||
return HasOwner() ? InternalItem() : SVGLength(mValue, mUnit);
|
||||
}
|
||||
|
@ -462,7 +471,11 @@ void DOMSVGLength::FlushIfNeeded() {
|
|||
};
|
||||
|
||||
if (nsCOMPtr<SVGElement> svg = do_QueryInterface(mOwner)) {
|
||||
MaybeFlush(svg->GetAnimatedLength(mAttrEnum)->GetSpecifiedUnitType(), svg);
|
||||
if (mIsAnimValItem) {
|
||||
MaybeFlush(svg->GetAnimatedLength(mAttrEnum)->GetAnimUnitType(), svg);
|
||||
} else {
|
||||
MaybeFlush(svg->GetAnimatedLength(mAttrEnum)->GetBaseUnitType(), svg);
|
||||
}
|
||||
}
|
||||
if (nsCOMPtr<DOMSVGLengthList> lengthList = do_QueryInterface(mOwner)) {
|
||||
MaybeFlush(InternalItem().GetUnit(), lengthList->Element());
|
||||
|
|
|
@ -17,13 +17,12 @@
|
|||
#include "mozilla/dom/SVGViewportElement.h"
|
||||
#include "DOMSVGAnimatedLength.h"
|
||||
#include "DOMSVGLength.h"
|
||||
#include "gfxTextRun.h"
|
||||
#include "LayoutLogging.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "SMILFloatType.h"
|
||||
#include "SVGLengthSMILType.h"
|
||||
#include "SVGAttrTearoffTable.h"
|
||||
#include "SVGGeometryProperty.h"
|
||||
|
||||
|
@ -373,21 +372,21 @@ nsresult SVGAnimatedLength::ConvertToSpecifiedUnits(uint16_t unitType,
|
|||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
if (mIsBaseSet && mSpecifiedUnitType == uint8_t(unitType)) return NS_OK;
|
||||
if (mIsBaseSet && mBaseUnitType == uint8_t(unitType)) return NS_OK;
|
||||
|
||||
float valueInSpecifiedUnits;
|
||||
|
||||
if (SVGLength::IsAbsoluteUnit(unitType) &&
|
||||
SVGLength::IsAbsoluteUnit(mSpecifiedUnitType)) {
|
||||
valueInSpecifiedUnits = mBaseVal * SVGLength::GetAbsUnitsPerAbsUnit(
|
||||
unitType, mSpecifiedUnitType);
|
||||
SVGLength::IsAbsoluteUnit(mBaseUnitType)) {
|
||||
valueInSpecifiedUnits =
|
||||
mBaseVal * SVGLength::GetAbsUnitsPerAbsUnit(unitType, mBaseUnitType);
|
||||
} else {
|
||||
float pixelsPerUnit = GetPixelsPerUnit(aSVGElement, unitType);
|
||||
if (pixelsPerUnit == 0.0f) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
float valueInPixels =
|
||||
mBaseVal * GetPixelsPerUnit(aSVGElement, mSpecifiedUnitType);
|
||||
mBaseVal * GetPixelsPerUnit(aSVGElement, mBaseUnitType);
|
||||
valueInSpecifiedUnits = valueInPixels / pixelsPerUnit;
|
||||
}
|
||||
|
||||
|
@ -401,7 +400,10 @@ nsresult SVGAnimatedLength::ConvertToSpecifiedUnits(uint16_t unitType,
|
|||
// change.
|
||||
AutoChangeLengthNotifier notifier(this, aSVGElement);
|
||||
|
||||
mSpecifiedUnitType = uint8_t(unitType);
|
||||
mBaseUnitType = uint8_t(unitType);
|
||||
if (!mIsAnimated) {
|
||||
mAnimUnitType = mBaseUnitType;
|
||||
}
|
||||
// Setting aDoSetAttr to false here will ensure we don't call
|
||||
// Will/DidChangeAngle a second time (and dispatch duplicate notifications).
|
||||
SetBaseValueInSpecifiedUnits(valueInSpecifiedUnits, aSVGElement, false);
|
||||
|
@ -419,7 +421,7 @@ nsresult SVGAnimatedLength::NewValueSpecifiedUnits(uint16_t aUnitType,
|
|||
}
|
||||
|
||||
if (mIsBaseSet && mBaseVal == aValueInSpecifiedUnits &&
|
||||
mSpecifiedUnitType == uint8_t(aUnitType)) {
|
||||
mBaseUnitType == uint8_t(aUnitType)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -427,9 +429,10 @@ nsresult SVGAnimatedLength::NewValueSpecifiedUnits(uint16_t aUnitType,
|
|||
|
||||
mBaseVal = aValueInSpecifiedUnits;
|
||||
mIsBaseSet = true;
|
||||
mSpecifiedUnitType = uint8_t(aUnitType);
|
||||
mBaseUnitType = uint8_t(aUnitType);
|
||||
if (!mIsAnimated) {
|
||||
mAnimVal = mBaseVal;
|
||||
mAnimUnitType = mBaseUnitType;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -457,7 +460,7 @@ nsresult SVGAnimatedLength::SetBaseValueString(const nsAString& aValueAsString,
|
|||
}
|
||||
|
||||
if (mIsBaseSet && mBaseVal == float(value) &&
|
||||
mSpecifiedUnitType == uint8_t(unitType)) {
|
||||
mBaseUnitType == uint8_t(unitType)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -465,25 +468,26 @@ nsresult SVGAnimatedLength::SetBaseValueString(const nsAString& aValueAsString,
|
|||
|
||||
mBaseVal = value;
|
||||
mIsBaseSet = true;
|
||||
mSpecifiedUnitType = uint8_t(unitType);
|
||||
mBaseUnitType = uint8_t(unitType);
|
||||
if (!mIsAnimated) {
|
||||
mAnimVal = mBaseVal;
|
||||
mAnimUnitType = mBaseUnitType;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void SVGAnimatedLength::GetBaseValueString(nsAString& aValueAsString) const {
|
||||
GetValueString(aValueAsString, mBaseVal, mSpecifiedUnitType);
|
||||
GetValueString(aValueAsString, mBaseVal, mBaseUnitType);
|
||||
}
|
||||
|
||||
void SVGAnimatedLength::GetAnimValueString(nsAString& aValueAsString) const {
|
||||
GetValueString(aValueAsString, mAnimVal, mSpecifiedUnitType);
|
||||
GetValueString(aValueAsString, mAnimVal, mAnimUnitType);
|
||||
}
|
||||
|
||||
nsresult SVGAnimatedLength::SetBaseValue(float aValue, SVGElement* aSVGElement,
|
||||
bool aDoSetAttr) {
|
||||
float pixelsPerUnit = GetPixelsPerUnit(aSVGElement, mSpecifiedUnitType);
|
||||
float pixelsPerUnit = GetPixelsPerUnit(aSVGElement, mBaseUnitType);
|
||||
if (pixelsPerUnit == 0.0f) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
@ -507,16 +511,15 @@ void SVGAnimatedLength::SetAnimValueInSpecifiedUnits(float aValue,
|
|||
aSVGElement->DidAnimateLength(mAttrEnum);
|
||||
}
|
||||
|
||||
nsresult SVGAnimatedLength::SetAnimValue(float aValue,
|
||||
SVGElement* aSVGElement) {
|
||||
float valueInSpecifiedUnits =
|
||||
aValue / GetPixelsPerUnit(aSVGElement, mSpecifiedUnitType);
|
||||
|
||||
if (std::isfinite(valueInSpecifiedUnits)) {
|
||||
SetAnimValueInSpecifiedUnits(valueInSpecifiedUnits, aSVGElement);
|
||||
return NS_OK;
|
||||
void SVGAnimatedLength::SetAnimValue(float aValue, uint16_t aUnitType,
|
||||
SVGElement* aSVGElement) {
|
||||
if (mIsAnimated && mAnimVal == aValue && mAnimUnitType == aUnitType) {
|
||||
return;
|
||||
}
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
mAnimVal = aValue;
|
||||
mAnimUnitType = aUnitType;
|
||||
mIsAnimated = true;
|
||||
aSVGElement->DidAnimateLength(mAttrEnum);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGAnimatedLength> SVGAnimatedLength::ToDOMAnimatedLength(
|
||||
|
@ -549,17 +552,21 @@ nsresult SVGAnimatedLength::SMILLength::ValueFromString(
|
|||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
SMILValue val(SMILFloatType::Singleton());
|
||||
val.mU.mDouble = value * mVal->GetPixelsPerUnit(mSVGElement, unitType);
|
||||
aValue = val;
|
||||
SMILValue val(SVGLengthSMILType::Singleton());
|
||||
SVGLengthAndInfo* lai = static_cast<SVGLengthAndInfo*>(val.mU.mPtr);
|
||||
lai->Set(value, unitType, mVal->GetCtxType());
|
||||
lai->SetInfo(mSVGElement);
|
||||
aValue = std::move(val);
|
||||
aPreventCachingOfSandwich = !SVGLength::IsAbsoluteUnit(unitType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SMILValue SVGAnimatedLength::SMILLength::GetBaseValue() const {
|
||||
SMILValue val(SMILFloatType::Singleton());
|
||||
val.mU.mDouble = mVal->GetBaseValue(mSVGElement);
|
||||
SMILValue val(SVGLengthSMILType::Singleton());
|
||||
auto* lai = static_cast<SVGLengthAndInfo*>(val.mU.mPtr);
|
||||
lai->CopyBaseFrom(*mVal);
|
||||
lai->SetInfo(mSVGElement);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -567,17 +574,76 @@ void SVGAnimatedLength::SMILLength::ClearAnimValue() {
|
|||
if (mVal->mIsAnimated) {
|
||||
mVal->mIsAnimated = false;
|
||||
mVal->mAnimVal = mVal->mBaseVal;
|
||||
mVal->mAnimUnitType = mVal->mBaseUnitType;
|
||||
mSVGElement->DidAnimateLength(mVal->mAttrEnum);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult SVGAnimatedLength::SMILLength::SetAnimValue(const SMILValue& aValue) {
|
||||
NS_ASSERTION(aValue.mType == SMILFloatType::Singleton(),
|
||||
NS_ASSERTION(aValue.mType == SVGLengthSMILType::Singleton(),
|
||||
"Unexpected type to assign animated value");
|
||||
if (aValue.mType == SMILFloatType::Singleton()) {
|
||||
return mVal->SetAnimValue(float(aValue.mU.mDouble), mSVGElement);
|
||||
if (aValue.mType == SVGLengthSMILType::Singleton()) {
|
||||
SVGLengthAndInfo* lai = static_cast<SVGLengthAndInfo*>(aValue.mU.mPtr);
|
||||
mVal->SetAnimValue(lai->Value(), lai->UnitType(), mSVGElement);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
float SVGLengthAndInfo::ConvertUnits(const SVGLengthAndInfo& aTo) const {
|
||||
if (aTo.mUnitType == mUnitType) {
|
||||
return mValue;
|
||||
}
|
||||
return SVGLength(mValue, mUnitType)
|
||||
.GetValueInSpecifiedUnit(aTo.mUnitType, aTo.Element(), aTo.mCtxType);
|
||||
}
|
||||
|
||||
float SVGLengthAndInfo::ValueInPixels(const UserSpaceMetrics& aMetrics) const {
|
||||
return mValue == 0.0f ? 0.0f
|
||||
: mValue * SVGLength::GetPixelsPerUnit(
|
||||
aMetrics, mUnitType, mCtxType);
|
||||
}
|
||||
|
||||
void SVGLengthAndInfo::Add(const SVGLengthAndInfo& aValueToAdd,
|
||||
uint32_t aCount) {
|
||||
mElement = aValueToAdd.mElement;
|
||||
|
||||
SVGElementMetrics metrics(Element());
|
||||
|
||||
// We may be dealing with two different length units, so we normalize to
|
||||
// pixels for the add:
|
||||
|
||||
float currentLength = ValueInPixels(metrics);
|
||||
float lengthToAdd = aValueToAdd.ValueInPixels(metrics) * aCount;
|
||||
|
||||
// And then we give the resulting value the same units as the value
|
||||
// that we're animating to/by (i.e. the same as aValueToAdd):
|
||||
mUnitType = aValueToAdd.mUnitType;
|
||||
mCtxType = aValueToAdd.mCtxType;
|
||||
mValue = (currentLength + lengthToAdd) /
|
||||
SVGLength::GetPixelsPerUnit(metrics, mUnitType, mCtxType);
|
||||
}
|
||||
|
||||
void SVGLengthAndInfo::Interpolate(const SVGLengthAndInfo& aStart,
|
||||
const SVGLengthAndInfo& aEnd,
|
||||
double aUnitDistance,
|
||||
SVGLengthAndInfo& aResult) {
|
||||
MOZ_ASSERT(!aStart.mElement || aStart.mElement == aEnd.mElement,
|
||||
"Should not be interpolating between different elements");
|
||||
|
||||
float startValue, endValue;
|
||||
if (!aStart.mElement || aUnitDistance > 0.5) {
|
||||
aResult.mUnitType = aEnd.mUnitType;
|
||||
aResult.mCtxType = aEnd.mCtxType;
|
||||
startValue = aStart.ConvertUnits(aEnd);
|
||||
endValue = aEnd.mValue;
|
||||
} else {
|
||||
aResult.mUnitType = aStart.mUnitType;
|
||||
aResult.mCtxType = aStart.mCtxType;
|
||||
startValue = aStart.mValue;
|
||||
endValue = aEnd.ConvertUnits(aStart);
|
||||
}
|
||||
aResult.mElement = aEnd.mElement;
|
||||
aResult.mValue = startValue + (endValue - startValue) * aUnitDistance;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -116,7 +116,7 @@ class SVGAnimatedLength {
|
|||
float aValue = 0,
|
||||
uint8_t aUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {
|
||||
mAnimVal = mBaseVal = aValue;
|
||||
mSpecifiedUnitType = aUnitType;
|
||||
mBaseUnitType = mAnimUnitType = aUnitType;
|
||||
mAttrEnum = aAttrEnum;
|
||||
mCtxType = aCtxType;
|
||||
mIsAnimated = false;
|
||||
|
@ -126,7 +126,8 @@ class SVGAnimatedLength {
|
|||
SVGAnimatedLength& operator=(const SVGAnimatedLength& aLength) {
|
||||
mBaseVal = aLength.mBaseVal;
|
||||
mAnimVal = aLength.mAnimVal;
|
||||
mSpecifiedUnitType = aLength.mSpecifiedUnitType;
|
||||
mBaseUnitType = aLength.mBaseUnitType;
|
||||
mAnimUnitType = aLength.mAnimUnitType;
|
||||
mIsAnimated = aLength.mIsAnimated;
|
||||
mIsBaseSet = aLength.mIsBaseSet;
|
||||
return *this;
|
||||
|
@ -138,27 +139,27 @@ class SVGAnimatedLength {
|
|||
void GetAnimValueString(nsAString& aValue) const;
|
||||
|
||||
float GetBaseValue(const SVGElement* aSVGElement) const {
|
||||
return mBaseVal * GetPixelsPerUnit(aSVGElement, mSpecifiedUnitType);
|
||||
return mBaseVal * GetPixelsPerUnit(aSVGElement, mBaseUnitType);
|
||||
}
|
||||
|
||||
float GetAnimValue(const SVGElement* aSVGElement) const {
|
||||
return mAnimVal * GetPixelsPerUnit(aSVGElement, mSpecifiedUnitType);
|
||||
return mAnimVal * GetPixelsPerUnit(aSVGElement, mAnimUnitType);
|
||||
}
|
||||
float GetAnimValue(nsIFrame* aFrame) const {
|
||||
return mAnimVal * GetPixelsPerUnit(aFrame, mSpecifiedUnitType);
|
||||
return mAnimVal * GetPixelsPerUnit(aFrame, mAnimUnitType);
|
||||
}
|
||||
float GetAnimValue(const SVGViewportElement* aCtx) const {
|
||||
return mAnimVal * GetPixelsPerUnit(aCtx, mSpecifiedUnitType);
|
||||
return mAnimVal * GetPixelsPerUnit(aCtx, mAnimUnitType);
|
||||
}
|
||||
float GetAnimValue(const UserSpaceMetrics& aMetrics) const {
|
||||
return mAnimVal * GetPixelsPerUnit(aMetrics, mSpecifiedUnitType);
|
||||
return mAnimVal * GetPixelsPerUnit(aMetrics, mAnimUnitType);
|
||||
}
|
||||
|
||||
uint8_t GetCtxType() const { return mCtxType; }
|
||||
uint8_t GetSpecifiedUnitType() const { return mSpecifiedUnitType; }
|
||||
uint8_t GetBaseUnitType() const { return mBaseUnitType; }
|
||||
uint8_t GetAnimUnitType() const { return mAnimUnitType; }
|
||||
bool IsPercentage() const {
|
||||
return mSpecifiedUnitType ==
|
||||
dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
|
||||
return mAnimUnitType == dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
|
||||
}
|
||||
float GetAnimValInSpecifiedUnits() const { return mAnimVal; }
|
||||
float GetBaseValInSpecifiedUnits() const { return mBaseVal; }
|
||||
|
@ -181,9 +182,10 @@ class SVGAnimatedLength {
|
|||
private:
|
||||
float mAnimVal;
|
||||
float mBaseVal;
|
||||
uint8_t mSpecifiedUnitType;
|
||||
uint8_t mAttrEnum; // element specified tracking for attribute
|
||||
uint8_t mCtxType; // X, Y or Unspecified
|
||||
uint8_t mBaseUnitType;
|
||||
uint8_t mAnimUnitType;
|
||||
uint8_t mAttrEnum : 6; // element specified tracking for attribute
|
||||
uint8_t mCtxType : 2; // X, Y or Unspecified
|
||||
bool mIsAnimated : 1;
|
||||
bool mIsBaseSet : 1;
|
||||
|
||||
|
@ -205,7 +207,7 @@ class SVGAnimatedLength {
|
|||
nsresult SetBaseValue(float aValue, SVGElement* aSVGElement, bool aDoSetAttr);
|
||||
void SetBaseValueInSpecifiedUnits(float aValue, SVGElement* aSVGElement,
|
||||
bool aDoSetAttr);
|
||||
nsresult SetAnimValue(float aValue, SVGElement* aSVGElement);
|
||||
void SetAnimValue(float aValue, uint16_t aUnitType, SVGElement* aSVGElement);
|
||||
void SetAnimValueInSpecifiedUnits(float aValue, SVGElement* aSVGElement);
|
||||
nsresult NewValueSpecifiedUnits(uint16_t aUnitType,
|
||||
float aValueInSpecifiedUnits,
|
||||
|
@ -237,6 +239,83 @@ class SVGAnimatedLength {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is used by the SMIL code when a length is to be stored in a
|
||||
* SMILValue instance. Since SMILValue objects may be cached, it is necessary
|
||||
* for us to hold a strong reference to our element so that it doesn't
|
||||
* disappear out from under us if, say, the element is removed from the DOM
|
||||
* tree.
|
||||
*/
|
||||
class SVGLengthAndInfo {
|
||||
public:
|
||||
SVGLengthAndInfo() = default;
|
||||
|
||||
explicit SVGLengthAndInfo(dom::SVGElement* aElement)
|
||||
: mElement(do_GetWeakReference(aElement->AsNode())) {}
|
||||
|
||||
void SetInfo(dom::SVGElement* aElement) {
|
||||
mElement = do_GetWeakReference(aElement->AsNode());
|
||||
}
|
||||
|
||||
dom::SVGElement* Element() const {
|
||||
nsCOMPtr<nsIContent> e = do_QueryReferent(mElement);
|
||||
return static_cast<dom::SVGElement*>(e.get());
|
||||
}
|
||||
|
||||
bool operator==(const SVGLengthAndInfo& rhs) const {
|
||||
return mValue == rhs.mValue && mUnitType == rhs.mUnitType &&
|
||||
mCtxType == rhs.mCtxType;
|
||||
}
|
||||
|
||||
float Value() const { return mValue; }
|
||||
|
||||
uint8_t UnitType() const { return mUnitType; }
|
||||
|
||||
void CopyFrom(const SVGLengthAndInfo& rhs) {
|
||||
mElement = rhs.mElement;
|
||||
mValue = rhs.mValue;
|
||||
mUnitType = rhs.mUnitType;
|
||||
mCtxType = rhs.mCtxType;
|
||||
}
|
||||
|
||||
float ConvertUnits(const SVGLengthAndInfo& aTo) const;
|
||||
|
||||
float ValueInPixels(const dom::UserSpaceMetrics& aMetrics) const;
|
||||
|
||||
void Add(const SVGLengthAndInfo& aValueToAdd, uint32_t aCount);
|
||||
|
||||
static void Interpolate(const SVGLengthAndInfo& aStart,
|
||||
const SVGLengthAndInfo& aEnd, double aUnitDistance,
|
||||
SVGLengthAndInfo& aResult);
|
||||
|
||||
/**
|
||||
* Enables SVGAnimatedLength values to be copied into SVGLengthAndInfo
|
||||
* objects. Note that callers should also call SetInfo() when using this
|
||||
* method!
|
||||
*/
|
||||
void CopyBaseFrom(const SVGAnimatedLength& rhs) {
|
||||
mValue = rhs.GetBaseValInSpecifiedUnits();
|
||||
mUnitType = rhs.GetBaseUnitType();
|
||||
mCtxType = rhs.GetCtxType();
|
||||
}
|
||||
|
||||
void Set(float aValue, uint8_t aUnitType, uint8_t aCtxType) {
|
||||
mValue = aValue;
|
||||
mUnitType = aUnitType;
|
||||
mCtxType = aCtxType;
|
||||
}
|
||||
|
||||
private:
|
||||
// We must keep a weak reference to our element because we may belong to a
|
||||
// cached baseVal SMILValue. See the comments starting at:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
|
||||
// See also https://bugzilla.mozilla.org/show_bug.cgi?id=653497
|
||||
nsWeakPtr mElement;
|
||||
float mValue = 0.0f;
|
||||
uint8_t mUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER;
|
||||
uint8_t mCtxType = SVGContentUtils::XY;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_SVG_SVGANIMATEDLENGTH_H_
|
||||
|
|
|
@ -1073,11 +1073,14 @@ bool SVGElement::UpdateDeclarationBlockFromLength(
|
|||
StyleLockedDeclarationBlock& aBlock, nsCSSPropertyID aPropId,
|
||||
const SVGAnimatedLength& aLength, ValToUse aValToUse) {
|
||||
float value;
|
||||
uint8_t units;
|
||||
if (aValToUse == ValToUse::Anim) {
|
||||
value = aLength.GetAnimValInSpecifiedUnits();
|
||||
units = aLength.GetAnimUnitType();
|
||||
} else {
|
||||
MOZ_ASSERT(aValToUse == ValToUse::Base);
|
||||
value = aLength.GetBaseValInSpecifiedUnits();
|
||||
units = aLength.GetBaseUnitType();
|
||||
}
|
||||
|
||||
// SVG parser doesn't check non-negativity of some parsed value, we should not
|
||||
|
@ -1087,8 +1090,7 @@ bool SVGElement::UpdateDeclarationBlockFromLength(
|
|||
return false;
|
||||
}
|
||||
|
||||
nsCSSUnit cssUnit =
|
||||
SVGLength::SpecifiedUnitTypeToCSSUnit(aLength.GetSpecifiedUnitType());
|
||||
nsCSSUnit cssUnit = SVGLength::SpecifiedUnitTypeToCSSUnit(units);
|
||||
|
||||
if (cssUnit == eCSSUnit_Percent) {
|
||||
Servo_DeclarationBlock_SetPercentValue(&aBlock, aPropId, value / 100.f);
|
||||
|
|
|
@ -74,8 +74,7 @@ bool SVGGeometryElement::GeometryDependsOnCoordCtx() {
|
|||
LengthAttributesInfo info =
|
||||
const_cast<SVGGeometryElement*>(this)->GetLengthInfo();
|
||||
for (uint32_t i = 0; i < info.mCount; i++) {
|
||||
if (info.mValues[i].GetSpecifiedUnitType() ==
|
||||
SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE) {
|
||||
if (info.mValues[i].IsPercentage()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "SVGLengthSMILType.h"
|
||||
|
||||
#include "mozilla/SMILValue.h"
|
||||
#include "SVGAnimatedLengthList.h"
|
||||
#include "nsDebug.h"
|
||||
#include <math.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom::SVGLength_Binding;
|
||||
|
||||
void SVGLengthSMILType::Init(SMILValue& aValue) const {
|
||||
MOZ_ASSERT(aValue.IsNull(), "Unexpected value type");
|
||||
|
||||
aValue.mU.mPtr = new SVGLengthAndInfo();
|
||||
aValue.mType = this;
|
||||
}
|
||||
|
||||
void SVGLengthSMILType::Destroy(SMILValue& aValue) const {
|
||||
MOZ_ASSERT(aValue.mType == this, "Unexpected SMIL value");
|
||||
delete static_cast<SVGLengthAndInfo*>(aValue.mU.mPtr);
|
||||
aValue.mU.mPtr = nullptr;
|
||||
aValue.mType = SMILNullType::Singleton();
|
||||
}
|
||||
|
||||
nsresult SVGLengthSMILType::Assign(SMILValue& aDest,
|
||||
const SMILValue& aSrc) const {
|
||||
MOZ_ASSERT(aDest.mType == aSrc.mType, "Incompatible SMIL types");
|
||||
MOZ_ASSERT(aDest.mType == this, "Unexpected SMIL value");
|
||||
|
||||
auto* src = static_cast<const SVGLengthAndInfo*>(aSrc.mU.mPtr);
|
||||
auto* dest = static_cast<SVGLengthAndInfo*>(aDest.mU.mPtr);
|
||||
dest->CopyFrom(*src);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool SVGLengthSMILType::IsEqual(const SMILValue& aLeft,
|
||||
const SMILValue& aRight) const {
|
||||
MOZ_ASSERT(aLeft.mType == aRight.mType, "Incompatible SMIL types");
|
||||
MOZ_ASSERT(aLeft.mType == this, "Unexpected type for SMIL value");
|
||||
|
||||
return *static_cast<const SVGLengthAndInfo*>(aLeft.mU.mPtr) ==
|
||||
*static_cast<const SVGLengthAndInfo*>(aRight.mU.mPtr);
|
||||
}
|
||||
|
||||
nsresult SVGLengthSMILType::Add(SMILValue& aDest, const SMILValue& aValueToAdd,
|
||||
uint32_t aCount) const {
|
||||
MOZ_ASSERT(aValueToAdd.mType == aDest.mType, "Trying to add invalid types");
|
||||
MOZ_ASSERT(aValueToAdd.mType == this, "Unexpected source type");
|
||||
|
||||
auto& dest = *static_cast<SVGLengthAndInfo*>(aDest.mU.mPtr);
|
||||
const auto& valueToAdd =
|
||||
*static_cast<const SVGLengthAndInfo*>(aValueToAdd.mU.mPtr);
|
||||
|
||||
dest.Add(valueToAdd, aCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SVGLengthSMILType::ComputeDistance(const SMILValue& aFrom,
|
||||
const SMILValue& aTo,
|
||||
double& aDistance) const {
|
||||
MOZ_ASSERT(aFrom.mType == aTo.mType, "Trying to compare different types");
|
||||
MOZ_ASSERT(aFrom.mType == this, "Unexpected source type");
|
||||
|
||||
const auto& from = *static_cast<SVGLengthAndInfo*>(aFrom.mU.mPtr);
|
||||
const auto& to = *static_cast<const SVGLengthAndInfo*>(aTo.mU.mPtr);
|
||||
|
||||
MOZ_ASSERT(from.Element() == to.Element());
|
||||
|
||||
dom::SVGElementMetrics metrics(from.Element());
|
||||
|
||||
// Normalize both to pixels in case they're different units:
|
||||
aDistance = fabs(to.ValueInPixels(metrics) - from.ValueInPixels(metrics));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SVGLengthSMILType::Interpolate(const SMILValue& aStartVal,
|
||||
const SMILValue& aEndVal,
|
||||
double aUnitDistance,
|
||||
SMILValue& aResult) const {
|
||||
MOZ_ASSERT(aStartVal.mType == aEndVal.mType,
|
||||
"Trying to interpolate different types");
|
||||
MOZ_ASSERT(aStartVal.mType == this, "Unexpected types for interpolation");
|
||||
MOZ_ASSERT(aResult.mType == this, "Unexpected result type");
|
||||
|
||||
const auto& start = *static_cast<SVGLengthAndInfo*>(aStartVal.mU.mPtr);
|
||||
const auto& end = *static_cast<const SVGLengthAndInfo*>(aEndVal.mU.mPtr);
|
||||
auto& result = *static_cast<SVGLengthAndInfo*>(aResult.mU.mPtr);
|
||||
|
||||
SVGLengthAndInfo::Interpolate(start, end, aUnitDistance, result);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 DOM_SVG_SVGLENGTHSMILTYPE_H_
|
||||
#define DOM_SVG_SVGLENGTHSMILTYPE_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/SMILType.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class SVGLengthSMILType final : public SMILType {
|
||||
public:
|
||||
// Singleton for SMILValue objects to hold onto.
|
||||
static SVGLengthSMILType* Singleton() {
|
||||
static SVGLengthSMILType sSingleton;
|
||||
return &sSingleton;
|
||||
}
|
||||
|
||||
protected:
|
||||
// SMILType Methods
|
||||
// -------------------
|
||||
void Init(SMILValue& aValue) const override;
|
||||
void Destroy(SMILValue& aValue) const override;
|
||||
nsresult Assign(SMILValue& aDest, const SMILValue& aSrc) const override;
|
||||
bool IsEqual(const SMILValue& aLeft, const SMILValue& aRight) const override;
|
||||
nsresult Add(SMILValue& aDest, const SMILValue& aValueToAdd,
|
||||
uint32_t aCount) const override;
|
||||
nsresult ComputeDistance(const SMILValue& aFrom, const SMILValue& aTo,
|
||||
double& aDistance) const override;
|
||||
nsresult Interpolate(const SMILValue& aStartVal, const SMILValue& aEndVal,
|
||||
double aUnitDistance, SMILValue& aResult) const override;
|
||||
|
||||
private:
|
||||
// Private constructor: prevent instances beyond my singleton.
|
||||
constexpr SVGLengthSMILType() = default;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_SVG_SVGLENGTHSMILTYPE_H_
|
|
@ -199,6 +199,7 @@ UNIFIED_SOURCES += [
|
|||
"SVGLength.cpp",
|
||||
"SVGLengthList.cpp",
|
||||
"SVGLengthListSMILType.cpp",
|
||||
"SVGLengthSMILType.cpp",
|
||||
"SVGLineElement.cpp",
|
||||
"SVGMarkerElement.cpp",
|
||||
"SVGMaskElement.cpp",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 600">
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 800">
|
||||
<!-- 1. patternUnits -->
|
||||
<defs>
|
||||
<pattern id="patternUnits" width="80" height="80"
|
||||
|
@ -98,6 +98,36 @@
|
|||
<rect width="100" height="100" stroke="black" fill="url(#xlink)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 6. x, y -->
|
||||
<defs>
|
||||
<pattern id="xy" width="1" height="1" x="0.1" y="-0.1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 600)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 7. width, height -->
|
||||
<defs>
|
||||
<pattern id="widthHeight" width="1" height="1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 700)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 3.9 KiB После Ширина: | Высота: | Размер: 5.0 KiB |
|
@ -1,5 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 600">
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 800">
|
||||
<!-- Bug 544809 - nsSVGPatternFrame::GetPatternWithAttr and callers should
|
||||
take account of SMIL animation.
|
||||
|
||||
|
@ -133,6 +133,43 @@
|
|||
<rect width="100" height="100" stroke="black" fill="url(#xlinkRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 6. x, y: defaults to 0 -->
|
||||
<defs>
|
||||
<pattern xlink:href="#xyRef" id="xy"/>
|
||||
<pattern id="xyRef" width="1" height="1">
|
||||
<set attributeName="x" to="0.1"/>
|
||||
<set attributeName="y" to="-0.1"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 600)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xyRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 7. width, height: defaults to 0 (disables rendering) -->
|
||||
<defs>
|
||||
<pattern xlink:href="#widthHeightRef" id="widthHeight"/>
|
||||
<pattern id="widthHeightRef">
|
||||
<set attributeName="width" to="1"/>
|
||||
<set attributeName="height" to="1"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 700)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#widthHeightRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 5.8 KiB После Ширина: | Высота: | Размер: 7.2 KiB |
|
@ -1,35 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
|
||||
<!-- 1. x, y -->
|
||||
<defs>
|
||||
<pattern id="xy" width="1" height="1" x="0.1" y="-0.1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g>
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 2. width, height -->
|
||||
<defs>
|
||||
<pattern id="widthHeight" width="1" height="1">
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 1.3 KiB |
|
@ -1,52 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200">
|
||||
<!-- Bug 544809 - nsSVGPatternFrame::GetPatternWithAttr and callers should
|
||||
take account of SMIL animation.
|
||||
|
||||
This test is a continuation of anim-pattern-attr-presence-01.svg but is
|
||||
separated because it currently fails due to bug 621651. Once that bug is
|
||||
resolved the tests in this file should be merged into
|
||||
anim-pattern-attr-presence-01.svg
|
||||
-->
|
||||
<!-- 1. x, y: defaults to 0 -->
|
||||
<!-- Currently broken by bug 621651 -->
|
||||
<defs>
|
||||
<pattern xlink:href="#xyRef" id="xy"/>
|
||||
<pattern id="xyRef" width="1" height="1">
|
||||
<set attributeName="x" to="0.1"/>
|
||||
<set attributeName="y" to="-0.1"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g>
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xy)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#xyRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- 2. width, height: defaults to 0 (disables rendering) -->
|
||||
<!-- Currently broken by bug 621651 -->
|
||||
<defs>
|
||||
<pattern xlink:href="#widthHeightRef" id="widthHeight"/>
|
||||
<pattern id="widthHeightRef">
|
||||
<set attributeName="width" to="1"/>
|
||||
<set attributeName="height" to="1"/>
|
||||
<rect width="50" height="50" fill="blue"/>
|
||||
<rect x="50" width="50" height="50" fill="red"/>
|
||||
<rect y="50" width="50" height="50" fill="red"/>
|
||||
<rect x="50" y="50" width="50" height="50" fill="blue"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<g transform="translate(0 100)">
|
||||
<rect width="100" height="100" stroke="black" fill="url(#widthHeight)"/>
|
||||
<g transform="translate(100)">
|
||||
<rect width="100" height="100" stroke="black"
|
||||
fill="url(#widthHeightRef)"/>
|
||||
</g>
|
||||
</g>
|
||||
<!-- If adding more tests here, be sure to update the viewBox on the root svg
|
||||
element -->
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 2.1 KiB |
|
@ -237,8 +237,6 @@ skip == anim-text-x-y-dx-dy-01.svg anim-text-x-y-dx-dy-01-ref.svg # bug 579588
|
|||
# Test we don't rely on HasAttr to see if an attribute has been set
|
||||
== anim-rect-rxry-1.svg anim-rect-rxry-1-ref.svg
|
||||
fuzzy(0-1,0-350) == anim-pattern-attr-presence-01.svg anim-pattern-attr-presence-01-ref.svg
|
||||
fails == anim-pattern-attr-presence-02.svg anim-pattern-attr-presence-02-ref.svg
|
||||
# ^ bug 621651
|
||||
fuzzy-if(cocoaWidget&&layersGPUAccelerated,0-1,0-2) == anim-gradient-attr-presence-01.svg anim-gradient-attr-presence-01-ref.svg
|
||||
|
||||
== api-sanity-1.svg lime.svg
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[svglength-animation-unitType.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Test change of unit type for SVGLength animation.]
|
||||
expected: FAIL
|
Загрузка…
Ссылка в новой задаче