mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Bug 629200 part 21 - Remove unnecessary serialisation from setting SVGPathSegList; r=jwatt
This commit is contained in:
parent
e378090f95
commit
3066580868
@ -59,6 +59,7 @@
|
|||||||
#include "SVGAnimatedPreserveAspectRatio.h"
|
#include "SVGAnimatedPreserveAspectRatio.h"
|
||||||
#include "SVGLengthList.h"
|
#include "SVGLengthList.h"
|
||||||
#include "SVGNumberList.h"
|
#include "SVGNumberList.h"
|
||||||
|
#include "SVGPathData.h"
|
||||||
#include "SVGPointList.h"
|
#include "SVGPointList.h"
|
||||||
|
|
||||||
namespace css = mozilla::css;
|
namespace css = mozilla::css;
|
||||||
@ -303,6 +304,11 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
|
|||||||
cont->mSVGNumberPair = otherCont->mSVGNumberPair;
|
cont->mSVGNumberPair = otherCont->mSVGNumberPair;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case eSVGPathData:
|
||||||
|
{
|
||||||
|
cont->mSVGPathData = otherCont->mSVGPathData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case eSVGPointList:
|
case eSVGPointList:
|
||||||
{
|
{
|
||||||
cont->mSVGPointList = otherCont->mSVGPointList;
|
cont->mSVGPointList = otherCont->mSVGPointList;
|
||||||
@ -487,6 +493,20 @@ nsAttrValue::SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::SetTo(const mozilla::SVGPathData& aValue,
|
||||||
|
const nsAString* aSerialized)
|
||||||
|
{
|
||||||
|
if (EnsureEmptyMiscContainer()) {
|
||||||
|
MiscContainer* cont = GetMiscContainer();
|
||||||
|
cont->mSVGPathData = &aValue;
|
||||||
|
cont->mType = eSVGPathData;
|
||||||
|
if (aSerialized && aSerialized->Length()) {
|
||||||
|
SetMiscAtomOrString(aSerialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsAttrValue::SetTo(const mozilla::SVGPointList& aValue,
|
nsAttrValue::SetTo(const mozilla::SVGPointList& aValue,
|
||||||
const nsAString* aSerialized)
|
const nsAString* aSerialized)
|
||||||
@ -651,6 +671,11 @@ nsAttrValue::ToString(nsAString& aResult) const
|
|||||||
GetMiscContainer()->mSVGNumberPair->GetBaseValueString(aResult);
|
GetMiscContainer()->mSVGNumberPair->GetBaseValueString(aResult);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case eSVGPathData:
|
||||||
|
{
|
||||||
|
GetMiscContainer()->mSVGPathData->GetValueAsString(aResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case eSVGPointList:
|
case eSVGPointList:
|
||||||
{
|
{
|
||||||
GetMiscContainer()->mSVGPointList->GetValueAsString(aResult);
|
GetMiscContainer()->mSVGPointList->GetValueAsString(aResult);
|
||||||
@ -874,6 +899,10 @@ nsAttrValue::HashValue() const
|
|||||||
{
|
{
|
||||||
return NS_PTR_TO_INT32(cont->mSVGNumberPair);
|
return NS_PTR_TO_INT32(cont->mSVGNumberPair);
|
||||||
}
|
}
|
||||||
|
case eSVGPathData:
|
||||||
|
{
|
||||||
|
return NS_PTR_TO_INT32(cont->mSVGPathData);
|
||||||
|
}
|
||||||
case eSVGPointList:
|
case eSVGPointList:
|
||||||
{
|
{
|
||||||
return NS_PTR_TO_INT32(cont->mSVGPointList);
|
return NS_PTR_TO_INT32(cont->mSVGPointList);
|
||||||
@ -1002,6 +1031,10 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
|
|||||||
{
|
{
|
||||||
return thisCont->mSVGNumberPair == otherCont->mSVGNumberPair;
|
return thisCont->mSVGNumberPair == otherCont->mSVGNumberPair;
|
||||||
}
|
}
|
||||||
|
case eSVGPathData:
|
||||||
|
{
|
||||||
|
return thisCont->mSVGPathData == otherCont->mSVGPathData;
|
||||||
|
}
|
||||||
case eSVGPointList:
|
case eSVGPointList:
|
||||||
{
|
{
|
||||||
return thisCont->mSVGPointList == otherCont->mSVGPointList;
|
return thisCont->mSVGPointList == otherCont->mSVGPointList;
|
||||||
|
@ -71,6 +71,7 @@ class StyleRule;
|
|||||||
class SVGAnimatedPreserveAspectRatio;
|
class SVGAnimatedPreserveAspectRatio;
|
||||||
class SVGLengthList;
|
class SVGLengthList;
|
||||||
class SVGNumberList;
|
class SVGNumberList;
|
||||||
|
class SVGPathData;
|
||||||
class SVGPointList;
|
class SVGPointList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +143,10 @@ public:
|
|||||||
,eSVGLengthList = 0x17
|
,eSVGLengthList = 0x17
|
||||||
,eSVGNumberList = 0x18
|
,eSVGNumberList = 0x18
|
||||||
,eSVGNumberPair = 0x19
|
,eSVGNumberPair = 0x19
|
||||||
,eSVGPointList = 0x20
|
,eSVGPathData = 0x20
|
||||||
,eSVGPreserveAspectRatio = 0x21
|
,eSVGPointList = 0x21
|
||||||
,eSVGViewBox = 0x22
|
,eSVGPreserveAspectRatio = 0x22
|
||||||
|
,eSVGViewBox = 0x23
|
||||||
};
|
};
|
||||||
|
|
||||||
ValueType Type() const;
|
ValueType Type() const;
|
||||||
@ -167,6 +169,7 @@ public:
|
|||||||
void SetTo(const mozilla::SVGNumberList& aValue,
|
void SetTo(const mozilla::SVGNumberList& aValue,
|
||||||
const nsAString* aSerialized);
|
const nsAString* aSerialized);
|
||||||
void SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized);
|
void SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized);
|
||||||
|
void SetTo(const mozilla::SVGPathData& aValue, const nsAString* aSerialized);
|
||||||
void SetTo(const mozilla::SVGPointList& aValue, const nsAString* aSerialized);
|
void SetTo(const mozilla::SVGPointList& aValue, const nsAString* aSerialized);
|
||||||
void SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue,
|
void SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue,
|
||||||
const nsAString* aSerialized);
|
const nsAString* aSerialized);
|
||||||
@ -408,6 +411,7 @@ private:
|
|||||||
const mozilla::SVGLengthList* mSVGLengthList;
|
const mozilla::SVGLengthList* mSVGLengthList;
|
||||||
const mozilla::SVGNumberList* mSVGNumberList;
|
const mozilla::SVGNumberList* mSVGNumberList;
|
||||||
const nsSVGNumberPair* mSVGNumberPair;
|
const nsSVGNumberPair* mSVGNumberPair;
|
||||||
|
const mozilla::SVGPathData* mSVGPathData;
|
||||||
const mozilla::SVGPointList* mSVGPointList;
|
const mozilla::SVGPointList* mSVGPointList;
|
||||||
const mozilla::SVGAnimatedPreserveAspectRatio* mSVGPreserveAspectRatio;
|
const mozilla::SVGAnimatedPreserveAspectRatio* mSVGPreserveAspectRatio;
|
||||||
const nsSVGViewBox* mSVGViewBox;
|
const nsSVGViewBox* mSVGViewBox;
|
||||||
|
@ -245,9 +245,13 @@ DOMSVGPathSeg::IndexIsValid()
|
|||||||
} \
|
} \
|
||||||
NS_ENSURE_FINITE(float(a##propName), NS_ERROR_ILLEGAL_VALUE); \
|
NS_ENSURE_FINITE(float(a##propName), NS_ERROR_ILLEGAL_VALUE); \
|
||||||
if (HasOwner()) { \
|
if (HasOwner()) { \
|
||||||
|
if (InternalItem()[1+index] == float(a##propName)) { \
|
||||||
|
return NS_OK; \
|
||||||
|
} \
|
||||||
|
NS_ABORT_IF_FALSE(IsInList(), "Will/DidChangePathSegList() is wrong"); \
|
||||||
|
nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList(); \
|
||||||
InternalItem()[1+index] = float(a##propName); \
|
InternalItem()[1+index] = float(a##propName); \
|
||||||
NS_ABORT_IF_FALSE(IsInList(), "DidChangePathSegList() is wrong"); \
|
Element()->DidChangePathSegList(emptyOrOldValue); \
|
||||||
Element()->DidChangePathSegList(true); \
|
|
||||||
if (mList->AttrIsAnimating()) { \
|
if (mList->AttrIsAnimating()) { \
|
||||||
Element()->AnimationNeedsResample(); \
|
Element()->AnimationNeedsResample(); \
|
||||||
} \
|
} \
|
||||||
|
@ -269,6 +269,7 @@ DOMSVGPathSegList::Clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Length() > 0) {
|
if (Length() > 0) {
|
||||||
|
nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList();
|
||||||
// DOM list items that are to be removed must be removed before we change
|
// DOM list items that are to be removed must be removed before we change
|
||||||
// the internal list, otherwise they wouldn't be able to copy their
|
// the internal list, otherwise they wouldn't be able to copy their
|
||||||
// internal counterparts' values!
|
// internal counterparts' values!
|
||||||
@ -285,7 +286,7 @@ DOMSVGPathSegList::Clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
InternalList().Clear();
|
InternalList().Clear();
|
||||||
Element()->DidChangePathSegList(true);
|
Element()->DidChangePathSegList(emptyOrOldValue);
|
||||||
if (AttrIsAnimating()) {
|
if (AttrIsAnimating()) {
|
||||||
Element()->AnimationNeedsResample();
|
Element()->AnimationNeedsResample();
|
||||||
}
|
}
|
||||||
@ -371,6 +372,7 @@ DOMSVGPathSegList::InsertItemBefore(nsIDOMSVGPathSeg *aNewItem,
|
|||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList();
|
||||||
// Now that we know we're inserting, keep animVal list in sync as necessary.
|
// Now that we know we're inserting, keep animVal list in sync as necessary.
|
||||||
MaybeInsertNullInAnimValListAt(aIndex, internalIndex, argCount);
|
MaybeInsertNullInAnimValListAt(aIndex, internalIndex, argCount);
|
||||||
|
|
||||||
@ -387,7 +389,7 @@ DOMSVGPathSegList::InsertItemBefore(nsIDOMSVGPathSeg *aNewItem,
|
|||||||
|
|
||||||
UpdateListIndicesFromIndex(aIndex + 1, argCount + 1);
|
UpdateListIndicesFromIndex(aIndex + 1, argCount + 1);
|
||||||
|
|
||||||
Element()->DidChangePathSegList(true);
|
Element()->DidChangePathSegList(emptyOrOldValue);
|
||||||
if (AttrIsAnimating()) {
|
if (AttrIsAnimating()) {
|
||||||
Element()->AnimationNeedsResample();
|
Element()->AnimationNeedsResample();
|
||||||
}
|
}
|
||||||
@ -416,6 +418,7 @@ DOMSVGPathSegList::ReplaceItem(nsIDOMSVGPathSeg *aNewItem,
|
|||||||
domItem = domItem->Clone(); // must do this before changing anything!
|
domItem = domItem->Clone(); // must do this before changing anything!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList();
|
||||||
if (ItemAt(aIndex)) {
|
if (ItemAt(aIndex)) {
|
||||||
// Notify any existing DOM item of removal *before* modifying the lists so
|
// Notify any existing DOM item of removal *before* modifying the lists so
|
||||||
// that the DOM item can copy the *old* value at its index:
|
// that the DOM item can copy the *old* value at its index:
|
||||||
@ -451,7 +454,7 @@ DOMSVGPathSegList::ReplaceItem(nsIDOMSVGPathSeg *aNewItem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Element()->DidChangePathSegList(true);
|
Element()->DidChangePathSegList(emptyOrOldValue);
|
||||||
if (AttrIsAnimating()) {
|
if (AttrIsAnimating()) {
|
||||||
Element()->AnimationNeedsResample();
|
Element()->AnimationNeedsResample();
|
||||||
}
|
}
|
||||||
@ -474,6 +477,7 @@ DOMSVGPathSegList::RemoveItem(PRUint32 aIndex,
|
|||||||
// We have to return the removed item, so make sure it exists:
|
// We have to return the removed item, so make sure it exists:
|
||||||
EnsureItemAt(aIndex);
|
EnsureItemAt(aIndex);
|
||||||
|
|
||||||
|
nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList();
|
||||||
// Notify the DOM item of removal *before* modifying the lists so that the
|
// Notify the DOM item of removal *before* modifying the lists so that the
|
||||||
// DOM item can copy its *old* value:
|
// DOM item can copy its *old* value:
|
||||||
ItemAt(aIndex)->RemovingFromList();
|
ItemAt(aIndex)->RemovingFromList();
|
||||||
@ -493,7 +497,7 @@ DOMSVGPathSegList::RemoveItem(PRUint32 aIndex,
|
|||||||
|
|
||||||
UpdateListIndicesFromIndex(aIndex, -(argCount + 1));
|
UpdateListIndicesFromIndex(aIndex, -(argCount + 1));
|
||||||
|
|
||||||
Element()->DidChangePathSegList(true);
|
Element()->DidChangePathSegList(emptyOrOldValue);
|
||||||
if (AttrIsAnimating()) {
|
if (AttrIsAnimating()) {
|
||||||
Element()->AnimationNeedsResample();
|
Element()->AnimationNeedsResample();
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,8 @@ EXPORTS = \
|
|||||||
SVGLength.h \
|
SVGLength.h \
|
||||||
SVGLengthList.h \
|
SVGLengthList.h \
|
||||||
SVGNumberList.h \
|
SVGNumberList.h \
|
||||||
|
SVGPathData.h \
|
||||||
|
SVGPathSegUtils.h \
|
||||||
SVGPoint.h \
|
SVGPoint.h \
|
||||||
SVGPointList.h \
|
SVGPointList.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -381,11 +381,12 @@ nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||||||
if (GetPathDataAttrName() == aAttribute) {
|
if (GetPathDataAttrName() == aAttribute) {
|
||||||
SVGAnimatedPathSegList* segList = GetAnimPathSegList();
|
SVGAnimatedPathSegList* segList = GetAnimPathSegList();
|
||||||
if (segList) {
|
if (segList) {
|
||||||
rv = segList->SetBaseValueString(aValue);
|
segList->SetBaseValueString(aValue);
|
||||||
if (NS_FAILED(rv)) {
|
// The spec says we parse everything up to the failure, so we DON'T
|
||||||
// The spec says we parse everything up to the failure, so we don't
|
// need to check the result of SetBaseValueString or call
|
||||||
// call segList->ClearBaseValue()
|
// segList->ClearBaseValue() if it fails
|
||||||
}
|
aResult.SetTo(segList->GetBaseValue(), &aValue);
|
||||||
|
didSetResult = true;
|
||||||
foundMatch = true;
|
foundMatch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -682,8 +683,8 @@ nsSVGElement::UnsetAttrInternal(PRInt32 aNamespaceID, nsIAtom* aName,
|
|||||||
if (GetPathDataAttrName() == aName) {
|
if (GetPathDataAttrName() == aName) {
|
||||||
SVGAnimatedPathSegList *segList = GetAnimPathSegList();
|
SVGAnimatedPathSegList *segList = GetAnimPathSegList();
|
||||||
if (segList) {
|
if (segList) {
|
||||||
|
MaybeSerializeAttrBeforeRemoval(aName, aNotify);
|
||||||
segList->ClearBaseValue();
|
segList->ClearBaseValue();
|
||||||
DidChangePathSegList(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1791,18 +1792,24 @@ nsSVGElement::DidAnimatePointList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
nsAttrValue
|
||||||
nsSVGElement::DidChangePathSegList(bool aDoSetAttr)
|
nsSVGElement::WillChangePathSegList()
|
||||||
{
|
{
|
||||||
if (!aDoSetAttr)
|
NS_ABORT_IF_FALSE(GetPathDataAttrName(),
|
||||||
return;
|
"Changing non-existent path seg list?");
|
||||||
|
return WillChangeValue(GetPathDataAttrName());
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoString serializedValue;
|
void
|
||||||
GetAnimPathSegList()->GetBaseValue().GetValueAsString(serializedValue);
|
nsSVGElement::DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue)
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(GetPathDataAttrName(),
|
||||||
|
"Changing non-existent path seg list?");
|
||||||
|
|
||||||
nsAttrValue attrValue(serializedValue);
|
nsAttrValue newValue;
|
||||||
SetParsedAttr(kNameSpaceID_None, GetPathDataAttrName(), nsnull,
|
newValue.SetTo(GetAnimPathSegList()->GetBaseValue(), nsnull);
|
||||||
attrValue, true);
|
|
||||||
|
DidChangeValue(GetPathDataAttrName(), aEmptyOrOldValue, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -179,6 +179,7 @@ public:
|
|||||||
nsAttrValue WillChangeNumberList(PRUint8 aAttrEnum);
|
nsAttrValue WillChangeNumberList(PRUint8 aAttrEnum);
|
||||||
nsAttrValue WillChangeLengthList(PRUint8 aAttrEnum);
|
nsAttrValue WillChangeLengthList(PRUint8 aAttrEnum);
|
||||||
nsAttrValue WillChangePointList();
|
nsAttrValue WillChangePointList();
|
||||||
|
nsAttrValue WillChangePathSegList();
|
||||||
|
|
||||||
void DidChangeLength(PRUint8 aAttrEnum, const nsAttrValue& aEmptyOrOldValue);
|
void DidChangeLength(PRUint8 aAttrEnum, const nsAttrValue& aEmptyOrOldValue);
|
||||||
void DidChangeNumber(PRUint8 aAttrEnum);
|
void DidChangeNumber(PRUint8 aAttrEnum);
|
||||||
@ -197,7 +198,7 @@ public:
|
|||||||
void DidChangeLengthList(PRUint8 aAttrEnum,
|
void DidChangeLengthList(PRUint8 aAttrEnum,
|
||||||
const nsAttrValue& aEmptyOrOldValue);
|
const nsAttrValue& aEmptyOrOldValue);
|
||||||
void DidChangePointList(const nsAttrValue& aEmptyOrOldValue);
|
void DidChangePointList(const nsAttrValue& aEmptyOrOldValue);
|
||||||
virtual void DidChangePathSegList(bool aDoSetAttr);
|
void DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue);
|
||||||
virtual void DidChangeTransformList(bool aDoSetAttr);
|
virtual void DidChangeTransformList(bool aDoSetAttr);
|
||||||
void DidChangeString(PRUint8 aAttrEnum) {}
|
void DidChangeString(PRUint8 aAttrEnum) {}
|
||||||
void DidChangeStringList(bool aIsConditionalProcessingAttribute,
|
void DidChangeStringList(bool aIsConditionalProcessingAttribute,
|
||||||
|
@ -5,6 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=611138
|
|||||||
<head>
|
<head>
|
||||||
<title>Generic tests for SVG animated length lists</title>
|
<title>Generic tests for SVG animated length lists</title>
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript" src="MutationEventChecker.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -86,17 +87,25 @@ function run_tests()
|
|||||||
ok(list.numberOfItems == 1 && list.getItem(0) == seg,
|
ok(list.numberOfItems == 1 && list.getItem(0) == seg,
|
||||||
'initialize should be able initialize an invalid path with a non-moveto item');
|
'initialize should be able initialize an invalid path with a non-moveto item');
|
||||||
|
|
||||||
|
// Test mutation events
|
||||||
|
|
||||||
|
eventChecker = new MutationEventChecker;
|
||||||
d = 'M0,0 L12,34'
|
d = 'M0,0 L12,34'
|
||||||
path.setAttribute('d', d);
|
path.setAttribute('d', d);
|
||||||
function check_old_value(e) {
|
eventChecker.watchAttr(path, "d");
|
||||||
is(e.target, path, 'check mutation event is for expected node');
|
|
||||||
is(e.attrName, 'd', 'check mutation event is for expected attribute');
|
// -- Actual changes
|
||||||
is(e.prevValue, d, 'check old attribute value is correctly reported');
|
eventChecker.expect("modify modify modify");
|
||||||
isnot(e.newValue, d, 'check attribute value has changed');
|
list[0].x = 10;
|
||||||
}
|
list[0].y = 5;
|
||||||
path.addEventListener('DOMAttrModified', check_old_value, false);
|
path.setAttribute("d", "M20,5 L12,34");
|
||||||
list.getItem(1).y = 35;
|
|
||||||
path.removeEventListener('DOMAttrModified', check_old_value, false);
|
// -- Redundant changes
|
||||||
|
eventChecker.expect("");
|
||||||
|
list[0].x = 20;
|
||||||
|
list[1].y = 34;
|
||||||
|
path.setAttribute("d", "M20,5 L12,34");
|
||||||
|
eventChecker.finish();
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user