mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 436418, patch F: SVG/SMIL animateMotion - add support for keyPoints attribute. r=roc
This commit is contained in:
parent
49730afb12
commit
c240503b49
@ -1287,6 +1287,7 @@ GK_ATOM(by, "by")
|
||||
GK_ATOM(calcMode, "calcMode")
|
||||
GK_ATOM(css, "CSS")
|
||||
GK_ATOM(dur, "dur")
|
||||
GK_ATOM(keyPoints, "keyPoints")
|
||||
GK_ATOM(keySplines, "keySplines")
|
||||
GK_ATOM(keyTimes, "keyTimes")
|
||||
GK_ATOM(mozAnimateMotionDummyAttr, "_mozAnimateMotionDummyAttr")
|
||||
|
@ -234,7 +234,8 @@ nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr,
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
// GetValues may update the error state
|
||||
// Check that we have the right number of keySplines and keyTimes
|
||||
CheckValueListDependentAttrs(values.Length());
|
||||
if (mErrorFlags != 0)
|
||||
return;
|
||||
|
||||
@ -801,15 +802,18 @@ nsSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we have the right number of keySplines and keyTimes
|
||||
CheckKeyTimes(result.Length());
|
||||
CheckKeySplines(result.Length());
|
||||
|
||||
result.SwapElements(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILAnimationFunction::CheckValueListDependentAttrs(PRUint32 aNumValues)
|
||||
{
|
||||
CheckKeyTimes(aNumValues);
|
||||
CheckKeySplines(aNumValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs checks for the keyTimes attribute required by the SMIL spec but
|
||||
* which depend on other attributes and therefore needs to be updated as
|
||||
@ -1031,7 +1035,9 @@ nsSMILAnimationFunction::SetKeyTimes(const nsAString& aKeyTimes,
|
||||
mKeyTimes.Clear();
|
||||
aResult.SetTo(aKeyTimes);
|
||||
|
||||
nsresult rv = nsSMILParserUtils::ParseKeyTimes(aKeyTimes, mKeyTimes);
|
||||
nsresult rv =
|
||||
nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyTimes, PR_TRUE,
|
||||
mKeyTimes);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && mKeyTimes.Length() < 1)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
@ -326,8 +326,9 @@ protected:
|
||||
virtual nsresult GetValues(const nsISMILAttr& aSMILAttr,
|
||||
nsSMILValueArray& aResult);
|
||||
|
||||
void CheckKeyTimes(PRUint32 aNumValues);
|
||||
void CheckKeySplines(PRUint32 aNumValues);
|
||||
virtual void CheckValueListDependentAttrs(PRUint32 aNumValues);
|
||||
void CheckKeyTimes(PRUint32 aNumValues);
|
||||
void CheckKeySplines(PRUint32 aNumValues);
|
||||
|
||||
// When GetValues() returns a single-value array, this method indicates
|
||||
// whether that single value can be understood to be a static value, to be
|
||||
|
@ -494,8 +494,9 @@ nsSMILParserUtils::ParseKeySplines(const nsAString& aSpec,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSMILParserUtils::ParseKeyTimes(const nsAString& aSpec,
|
||||
nsTArray<double>& aTimeArray)
|
||||
nsSMILParserUtils::ParseSemicolonDelimitedProgressList(const nsAString& aSpec,
|
||||
PRBool aNonDecreasing,
|
||||
nsTArray<double>& aArray)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
@ -512,12 +513,13 @@ nsSMILParserUtils::ParseKeyTimes(const nsAString& aSpec,
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
if (value > 1.0 || value < 0.0 || value < previousValue) {
|
||||
if (value > 1.0 || value < 0.0 ||
|
||||
(aNonDecreasing && value < previousValue)) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!aTimeArray.AppendElement(value)) {
|
||||
if (!aArray.AppendElement(value)) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
@ -66,8 +66,10 @@ public:
|
||||
static nsresult ParseKeySplines(const nsAString& aSpec,
|
||||
nsTArray<double>& aSplineArray);
|
||||
|
||||
static nsresult ParseKeyTimes(const nsAString& aSpec,
|
||||
nsTArray<double>& aTimesArray);
|
||||
// Used for parsing the |keyTimes| and |keyPoints| attributes.
|
||||
static nsresult ParseSemicolonDelimitedProgressList(const nsAString& aSpec,
|
||||
PRBool aNonDecreasing,
|
||||
nsTArray<double>& aArray);
|
||||
|
||||
static nsresult ParseValues(const nsAString& aSpec,
|
||||
const nsISMILAnimationElement* aSrcElement,
|
||||
|
@ -81,7 +81,13 @@ SVGMotionSMILAnimationFunction::SetAttr(nsIAtom* aAttribute,
|
||||
nsAttrValue& aResult,
|
||||
nsresult* aParseResult)
|
||||
{
|
||||
if (aAttribute == nsGkAtoms::rotate) {
|
||||
// Handle motion-specific attrs
|
||||
if (aAttribute == nsGkAtoms::keyPoints) {
|
||||
nsresult rv = SetKeyPoints(aValue, aResult);
|
||||
if (aParseResult) {
|
||||
*aParseResult = rv;
|
||||
}
|
||||
} else if (aAttribute == nsGkAtoms::rotate) {
|
||||
nsresult rv = SetRotate(aValue, aResult);
|
||||
if (aParseResult) {
|
||||
*aParseResult = rv;
|
||||
@ -103,7 +109,9 @@ SVGMotionSMILAnimationFunction::SetAttr(nsIAtom* aAttribute,
|
||||
PRBool
|
||||
SVGMotionSMILAnimationFunction::UnsetAttr(nsIAtom* aAttribute)
|
||||
{
|
||||
if (aAttribute == nsGkAtoms::rotate) {
|
||||
if (aAttribute == nsGkAtoms::keyPoints) {
|
||||
UnsetKeyPoints();
|
||||
} else if (aAttribute == nsGkAtoms::rotate) {
|
||||
UnsetRotate();
|
||||
} else if (aAttribute == nsGkAtoms::by ||
|
||||
aAttribute == nsGkAtoms::from ||
|
||||
@ -234,14 +242,18 @@ SVGMotionSMILAnimationFunction::
|
||||
PRBool
|
||||
SVGMotionSMILAnimationFunction::
|
||||
GenerateValuesForPathAndPoints(gfxFlattenedPath* aPath,
|
||||
PRBool aIsKeyPoints,
|
||||
nsTArray<double>& aPointDistances,
|
||||
nsTArray<nsSMILValue>& aResult)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aResult.IsEmpty(), "outparam is non-empty");
|
||||
|
||||
// If we're using "keyPoints" as our list of input distances, then we need
|
||||
// to de-normalize from the [0, 1] scale to the [0, totalPathLen] scale.
|
||||
double distanceMultiplier = aIsKeyPoints ? aPath->GetLength() : 1.0;
|
||||
const PRUint32 numPoints = aPointDistances.Length();
|
||||
for (PRUint32 i = 0; i < numPoints; ++i) {
|
||||
double curDist = aPointDistances[i];
|
||||
double curDist = aPointDistances[i] * distanceMultiplier;
|
||||
if (!aResult.AppendElement(
|
||||
SVGMotionSMILType::ConstructSMILValue(aPath, curDist,
|
||||
mRotateType, mRotateAngle))) {
|
||||
@ -267,8 +279,11 @@ SVGMotionSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
|
||||
}
|
||||
NS_ABORT_IF_FALSE(!mPathVertices.IsEmpty(), "have a path but no vertices");
|
||||
|
||||
// Now: Make the actual list of nsSMILValues
|
||||
PRBool success = GenerateValuesForPathAndPoints(mPath, mPathVertices,
|
||||
// Now: Make the actual list of nsSMILValues (using keyPoints, if set)
|
||||
PRBool isUsingKeyPoints = !mKeyPoints.IsEmpty();
|
||||
PRBool success = GenerateValuesForPathAndPoints(mPath, isUsingKeyPoints,
|
||||
isUsingKeyPoints ?
|
||||
mKeyPoints : mPathVertices,
|
||||
aResult);
|
||||
if (!success) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -277,6 +292,75 @@ SVGMotionSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SVGMotionSMILAnimationFunction::
|
||||
CheckValueListDependentAttrs(PRUint32 aNumValues)
|
||||
{
|
||||
// Call superclass method.
|
||||
nsSMILAnimationFunction::CheckValueListDependentAttrs(aNumValues);
|
||||
|
||||
// Added behavior: Do checks specific to keyPoints.
|
||||
CheckKeyPoints();
|
||||
}
|
||||
|
||||
void
|
||||
SVGMotionSMILAnimationFunction::CheckKeyPoints()
|
||||
{
|
||||
if (!HasAttr(nsGkAtoms::keyPoints))
|
||||
return;
|
||||
|
||||
// attribute is ignored for calcMode="paced" (even if it's got errors)
|
||||
if (GetCalcMode() == CALC_PACED) {
|
||||
SetKeyPointsErrorFlag(PR_FALSE);
|
||||
}
|
||||
|
||||
if (mKeyPoints.IsEmpty()) {
|
||||
// keyPoints attr is set, but array is empty => it failed preliminary checks
|
||||
SetKeyPointsErrorFlag(PR_TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing else to check -- we can catch all keyPoints errors elsewhere.
|
||||
// - Formatting & range issues will be caught in SetKeyPoints, and will
|
||||
// result in an empty mKeyPoints array, which will drop us into the error
|
||||
// case above.
|
||||
// - Number-of-entries issues will be caught in CheckKeyTimes (and flagged
|
||||
// as a problem with |keyTimes|), since we use our keyPoints entries to
|
||||
// populate the "values" list, and that list's count gets passed to
|
||||
// CheckKeyTimes.
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGMotionSMILAnimationFunction::SetKeyPoints(const nsAString& aKeyPoints,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
mKeyPoints.Clear();
|
||||
aResult.SetTo(aKeyPoints);
|
||||
|
||||
nsresult rv =
|
||||
nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyPoints, PR_FALSE,
|
||||
mKeyPoints);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && mKeyPoints.Length() < 1)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mKeyPoints.Clear();
|
||||
}
|
||||
|
||||
mHasChanged = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SVGMotionSMILAnimationFunction::UnsetKeyPoints()
|
||||
{
|
||||
mKeyTimes.Clear();
|
||||
SetKeyPointsErrorFlag(PR_FALSE);
|
||||
mHasChanged = PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGMotionSMILAnimationFunction::SetRotate(const nsAString& aRotate,
|
||||
nsAttrValue& aResult)
|
||||
|
@ -75,8 +75,12 @@ protected:
|
||||
NS_OVERRIDE virtual nsSMILCalcMode GetCalcMode() const;
|
||||
NS_OVERRIDE virtual nsresult GetValues(const nsISMILAttr& aSMILAttr,
|
||||
nsSMILValueArray& aResult);
|
||||
NS_OVERRIDE virtual void CheckValueListDependentAttrs(PRUint32 aNumValues);
|
||||
NS_OVERRIDE virtual PRBool TreatSingleValueAsStatic() const;
|
||||
|
||||
void CheckKeyPoints();
|
||||
nsresult SetKeyPoints(const nsAString& aKeyPoints, nsAttrValue& aResult);
|
||||
void UnsetKeyPoints();
|
||||
nsresult SetRotate(const nsAString& aRotate, nsAttrValue& aResult);
|
||||
void UnsetRotate();
|
||||
|
||||
@ -86,11 +90,14 @@ protected:
|
||||
void RebuildPathAndVertices(const nsIContent* aContextElem);
|
||||
void RebuildPathAndVerticesFromBasicAttrs(const nsIContent* aContextElem);
|
||||
PRBool GenerateValuesForPathAndPoints(gfxFlattenedPath* aPath,
|
||||
PRBool aIsKeyPoints,
|
||||
nsTArray<double>& aPointDistances,
|
||||
nsTArray<nsSMILValue>& aResult);
|
||||
|
||||
// Members
|
||||
// -------
|
||||
nsTArray<double> mKeyPoints; // parsed from "keyPoints" attribute.
|
||||
|
||||
RotateType mRotateType; // auto, auto-reverse, or explicit.
|
||||
float mRotateAngle; // the angle value, if explicit.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user