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:
Robert Longson 2023-11-21 03:37:35 +00:00
Родитель 5ec06e8577
Коммит 3352d3d85b
14 изменённых файлов: 434 добавлений и 154 удалений

Просмотреть файл

@ -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