зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1745149 - Remove SVGPathSeg APIs and related code. r=longsonr,boris,webidl,devtools-reviewers,smaug,nchevobbe
These were unshipped a long time ago... Differential Revision: https://phabricator.services.mozilla.com/D214278
This commit is contained in:
Родитель
2c6909e66f
Коммит
597601a294
|
@ -1,6 +1,5 @@
|
|||
[DEFAULT]
|
||||
prefs = [
|
||||
"dom.svg.pathSeg.enabled=true",
|
||||
"layout.css.properties-and-values.enabled=true"
|
||||
]
|
||||
tags = "devtools"
|
||||
|
|
|
@ -779,65 +779,13 @@ function assertPathSegments(pathEl, hasClosePath, expectedValues) {
|
|||
);
|
||||
}
|
||||
|
||||
function isExpectedPath(pathEl, hasClosePath, expectedValues) {
|
||||
const pathSegList = pathEl.pathSegList;
|
||||
if (!pathSegList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!expectedValues.every(value =>
|
||||
isPassingThrough(pathSegList, value.x, value.y)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasClosePath) {
|
||||
const closePathSeg = pathSegList.getItem(pathSegList.numberOfItems - 1);
|
||||
if (closePathSeg.pathSegType !== closePathSeg.PATHSEG_CLOSEPATH) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isExpectedPath(_pathEl, _hasClosePath, _expectedValues) {
|
||||
// FIXME(bug 1903594): Probably re-implement with some other API, or manually parse it:
|
||||
// * https://github.com/progers/pathseg
|
||||
// * https://www.w3.org/TR/svg-paths/#InterfaceSVGPathData
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given vertex is passing throug on the path.
|
||||
*
|
||||
* @param {pathSegList} pathSegList - pathSegList of <path> element.
|
||||
* @param {float} x - x of vertex.
|
||||
* @param {float} y - y of vertex.
|
||||
* @return {boolean} true: passing through, false: no on the path.
|
||||
*/
|
||||
function isPassingThrough(pathSegList, x, y) {
|
||||
let previousPathSeg = pathSegList.getItem(0);
|
||||
for (let i = 0; i < pathSegList.numberOfItems; i++) {
|
||||
const pathSeg = pathSegList.getItem(i);
|
||||
if (pathSeg.x === undefined) {
|
||||
continue;
|
||||
}
|
||||
const currentX = parseFloat(pathSeg.x.toFixed(3));
|
||||
const currentY = parseFloat(pathSeg.y.toFixed(3));
|
||||
if (currentX === x && currentY === y) {
|
||||
return true;
|
||||
}
|
||||
const previousX = parseFloat(previousPathSeg.x.toFixed(3));
|
||||
const previousY = parseFloat(previousPathSeg.y.toFixed(3));
|
||||
if (
|
||||
previousX <= x &&
|
||||
x <= currentX &&
|
||||
Math.min(previousY, currentY) <= y &&
|
||||
y <= Math.max(previousY, currentY)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
previousPathSeg = pathSeg;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return animation item element by the index.
|
||||
*
|
||||
|
|
|
@ -816,111 +816,6 @@ DOMInterfaces = {
|
|||
'headerFile': 'DOMSVGNumberList.h'
|
||||
},
|
||||
|
||||
'SVGPathSeg': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSeg',
|
||||
'headerFile': 'DOMSVGPathSeg.h',
|
||||
},
|
||||
|
||||
'SVGPathSegClosePath': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegClosePath',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegMovetoAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegMovetoAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegMovetoRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegMovetoRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegArcAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegArcAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegArcRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegArcRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoHorizontalAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoHorizontalAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoHorizontalRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoHorizontalRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoVerticalAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoVerticalAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoVerticalRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoVerticalRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicSmoothAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicSmoothAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicSmoothRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicSmoothRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticSmoothAbs': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticSmoothAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticSmoothRel': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticSmoothRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegList': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegList',
|
||||
'headerFile': 'DOMSVGPathSegList.h'
|
||||
},
|
||||
|
||||
'SVGPoint': {
|
||||
'nativeType': 'mozilla::dom::DOMSVGPoint',
|
||||
'headerFile': 'DOMSVGPoint.h'
|
||||
|
|
|
@ -1,314 +0,0 @@
|
|||
/* -*- 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 "DOMSVGPathSeg.h"
|
||||
#include "DOMSVGPathSegList.h"
|
||||
#include "SVGAnimatedPathSegList.h"
|
||||
#include "SVGElement.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsError.h"
|
||||
|
||||
// See the architecture comment in DOMSVGPathSegList.h.
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
using namespace dom::SVGPathSeg_Binding;
|
||||
|
||||
// We could use NS_IMPL_CYCLE_COLLECTION(, except that in Unlink() we need to
|
||||
// clear our list's weak ref to us to be safe. (The other option would be to
|
||||
// not unlink and rely on the breaking of the other edges in the cycle, as
|
||||
// NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSeg)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSeg)
|
||||
// We may not belong to a list, so we must null check tmp->mList.
|
||||
if (tmp->mList) {
|
||||
tmp->mList->ItemAt(tmp->mListIndex) = nullptr;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSeg)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSeg)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
DOMSVGPathSeg::DOMSVGPathSeg(DOMSVGPathSegList* aList, uint32_t aListIndex,
|
||||
bool aIsAnimValItem)
|
||||
: mList(aList), mListIndex(aListIndex), mIsAnimValItem(aIsAnimValItem) {
|
||||
// These shifts are in sync with the members in the header.
|
||||
MOZ_ASSERT(aList && aListIndex <= MaxListIndex(), "bad arg");
|
||||
|
||||
MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
|
||||
}
|
||||
|
||||
DOMSVGPathSeg::DOMSVGPathSeg()
|
||||
: mList(nullptr), mListIndex(0), mIsAnimValItem(false) {}
|
||||
|
||||
void DOMSVGPathSeg::InsertingIntoList(DOMSVGPathSegList* aList,
|
||||
uint32_t aListIndex,
|
||||
bool aIsAnimValItem) {
|
||||
MOZ_ASSERT(!HasOwner(), "Inserting item that is already in a list");
|
||||
|
||||
mList = aList;
|
||||
mListIndex = aListIndex;
|
||||
mIsAnimValItem = aIsAnimValItem;
|
||||
|
||||
MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
|
||||
}
|
||||
|
||||
void DOMSVGPathSeg::RemovingFromList() {
|
||||
uint32_t argCount = SVGPathSegUtils::ArgCountForType(Type());
|
||||
// InternalItem() + 1, because the args come after the encoded seg type
|
||||
memcpy(PtrToMemberArgs(), InternalItem() + 1, argCount * sizeof(float));
|
||||
mList = nullptr;
|
||||
mIsAnimValItem = false;
|
||||
}
|
||||
|
||||
void DOMSVGPathSeg::ToSVGPathSegEncodedData(float* aRaw) {
|
||||
MOZ_ASSERT(aRaw, "null pointer");
|
||||
uint32_t argCount = SVGPathSegUtils::ArgCountForType(Type());
|
||||
if (IsInList()) {
|
||||
// 1 + argCount, because we're copying the encoded seg type and args
|
||||
memcpy(aRaw, InternalItem(), (1 + argCount) * sizeof(float));
|
||||
} else {
|
||||
aRaw[0] = SVGPathSegUtils::EncodeType(Type());
|
||||
// aRaw + 1, because the args go after the encoded seg type
|
||||
memcpy(aRaw + 1, PtrToMemberArgs(), argCount * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
float* DOMSVGPathSeg::InternalItem() {
|
||||
uint32_t dataIndex = mList->mItems[mListIndex].mInternalDataIndex;
|
||||
return &(mList->InternalList().mData[dataIndex]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool DOMSVGPathSeg::IndexIsValid() {
|
||||
SVGAnimatedPathSegList* alist = Element()->GetAnimPathSegList();
|
||||
return (mIsAnimValItem && mListIndex < alist->GetAnimValue().CountItems()) ||
|
||||
(!mIsAnimValItem && mListIndex < alist->GetBaseValue().CountItems());
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of DOMSVGPathSeg sub-classes below this point
|
||||
|
||||
#define IMPL_PROP_WITH_TYPE(segName, propName, index, type) \
|
||||
type DOMSVGPathSeg##segName::propName() { \
|
||||
if (mIsAnimValItem && HasOwner()) { \
|
||||
Element()->FlushAnimations(); /* May make HasOwner() == false */ \
|
||||
} \
|
||||
return type(HasOwner() ? InternalItem()[1 + index] : mArgs[index]); \
|
||||
} \
|
||||
void DOMSVGPathSeg##segName::Set##propName(type a##propName, \
|
||||
ErrorResult& rv) { \
|
||||
if (mIsAnimValItem) { \
|
||||
rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); \
|
||||
return; \
|
||||
} \
|
||||
if (HasOwner()) { \
|
||||
if (InternalItem()[1 + index] == float(a##propName)) { \
|
||||
return; \
|
||||
} \
|
||||
AutoChangePathSegListNotifier notifier(this); \
|
||||
InternalItem()[1 + index] = float(a##propName); \
|
||||
} else { \
|
||||
mArgs[index] = float(a##propName); \
|
||||
} \
|
||||
}
|
||||
|
||||
// For float, the normal type of arguments
|
||||
#define IMPL_FLOAT_PROP(segName, propName, index) \
|
||||
IMPL_PROP_WITH_TYPE(segName, propName, index, float)
|
||||
|
||||
// For the boolean flags in arc commands
|
||||
#define IMPL_BOOL_PROP(segName, propName, index) \
|
||||
IMPL_PROP_WITH_TYPE(segName, propName, index, bool)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(MovetoAbs, X, 0)
|
||||
IMPL_FLOAT_PROP(MovetoAbs, Y, 1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(MovetoRel, X, 0)
|
||||
IMPL_FLOAT_PROP(MovetoRel, Y, 1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(LinetoAbs, X, 0)
|
||||
IMPL_FLOAT_PROP(LinetoAbs, Y, 1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(LinetoRel, X, 0)
|
||||
IMPL_FLOAT_PROP(LinetoRel, Y, 1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoCubicAbs, X1, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicAbs, Y1, 1)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicAbs, X2, 2)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicAbs, Y2, 3)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicAbs, X, 4)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicAbs, Y, 5)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoCubicRel, X1, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicRel, Y1, 1)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicRel, X2, 2)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicRel, Y2, 3)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicRel, X, 4)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicRel, Y, 5)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticAbs, X1, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticAbs, Y1, 1)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticAbs, X, 2)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticAbs, Y, 3)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticRel, X1, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticRel, Y1, 1)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticRel, X, 2)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticRel, Y, 3)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(ArcAbs, R1, 0)
|
||||
IMPL_FLOAT_PROP(ArcAbs, R2, 1)
|
||||
IMPL_FLOAT_PROP(ArcAbs, Angle, 2)
|
||||
IMPL_BOOL_PROP(ArcAbs, LargeArcFlag, 3)
|
||||
IMPL_BOOL_PROP(ArcAbs, SweepFlag, 4)
|
||||
IMPL_FLOAT_PROP(ArcAbs, X, 5)
|
||||
IMPL_FLOAT_PROP(ArcAbs, Y, 6)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(ArcRel, R1, 0)
|
||||
IMPL_FLOAT_PROP(ArcRel, R2, 1)
|
||||
IMPL_FLOAT_PROP(ArcRel, Angle, 2)
|
||||
IMPL_BOOL_PROP(ArcRel, LargeArcFlag, 3)
|
||||
IMPL_BOOL_PROP(ArcRel, SweepFlag, 4)
|
||||
IMPL_FLOAT_PROP(ArcRel, X, 5)
|
||||
IMPL_FLOAT_PROP(ArcRel, Y, 6)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(LinetoHorizontalAbs, X, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(LinetoHorizontalRel, X, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(LinetoVerticalAbs, Y, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(LinetoVerticalRel, Y, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, X2, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, Y2, 1)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, X, 2)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothAbs, Y, 3)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, X2, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, Y2, 1)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, X, 2)
|
||||
IMPL_FLOAT_PROP(CurvetoCubicSmoothRel, Y, 3)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticSmoothAbs, X, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticSmoothAbs, Y, 1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticSmoothRel, X, 0)
|
||||
IMPL_FLOAT_PROP(CurvetoQuadraticSmoothRel, Y, 1)
|
||||
|
||||
// This must come after DOMSVGPathSegClosePath et. al. have been declared.
|
||||
/* static */
|
||||
DOMSVGPathSeg* DOMSVGPathSeg::CreateFor(DOMSVGPathSegList* aList,
|
||||
uint32_t aListIndex,
|
||||
bool aIsAnimValItem) {
|
||||
uint32_t dataIndex = aList->mItems[aListIndex].mInternalDataIndex;
|
||||
float* data = &aList->InternalList().mData[dataIndex];
|
||||
uint32_t type = SVGPathSegUtils::DecodeType(data[0]);
|
||||
|
||||
switch (type) {
|
||||
case PATHSEG_CLOSEPATH:
|
||||
return new DOMSVGPathSegClosePath(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_MOVETO_ABS:
|
||||
return new DOMSVGPathSegMovetoAbs(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_MOVETO_REL:
|
||||
return new DOMSVGPathSegMovetoRel(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_LINETO_ABS:
|
||||
return new DOMSVGPathSegLinetoAbs(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_LINETO_REL:
|
||||
return new DOMSVGPathSegLinetoRel(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_CUBIC_ABS:
|
||||
return new DOMSVGPathSegCurvetoCubicAbs(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_CUBIC_REL:
|
||||
return new DOMSVGPathSegCurvetoCubicRel(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_QUADRATIC_ABS:
|
||||
return new DOMSVGPathSegCurvetoQuadraticAbs(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_QUADRATIC_REL:
|
||||
return new DOMSVGPathSegCurvetoQuadraticRel(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_ARC_ABS:
|
||||
return new DOMSVGPathSegArcAbs(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_ARC_REL:
|
||||
return new DOMSVGPathSegArcRel(aList, aListIndex, aIsAnimValItem);
|
||||
case PATHSEG_LINETO_HORIZONTAL_ABS:
|
||||
return new DOMSVGPathSegLinetoHorizontalAbs(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_LINETO_HORIZONTAL_REL:
|
||||
return new DOMSVGPathSegLinetoHorizontalRel(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_LINETO_VERTICAL_ABS:
|
||||
return new DOMSVGPathSegLinetoVerticalAbs(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_LINETO_VERTICAL_REL:
|
||||
return new DOMSVGPathSegLinetoVerticalRel(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
|
||||
return new DOMSVGPathSegCurvetoCubicSmoothAbs(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
|
||||
return new DOMSVGPathSegCurvetoCubicSmoothRel(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
|
||||
return new DOMSVGPathSegCurvetoQuadraticSmoothAbs(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
|
||||
return new DOMSVGPathSegCurvetoQuadraticSmoothRel(aList, aListIndex,
|
||||
aIsAnimValItem);
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid path segment type");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -1,639 +0,0 @@
|
|||
/* -*- 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_DOMSVGPATHSEG_H_
|
||||
#define DOM_SVG_DOMSVGPATHSEG_H_
|
||||
|
||||
#include "DOMSVGPathSegList.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "SVGPathSegUtils.h"
|
||||
#include "mozilla/dom/SVGPathSegBinding.h"
|
||||
|
||||
#define MOZ_SVG_LIST_INDEX_BIT_COUNT 31
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class SVGElement;
|
||||
|
||||
#define CHECK_ARG_COUNT_IN_SYNC(segType) \
|
||||
MOZ_ASSERT( \
|
||||
ArrayLength(mArgs) == \
|
||||
SVGPathSegUtils::ArgCountForType(uint32_t(segType)) || \
|
||||
uint32_t(segType) == dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH, \
|
||||
"Arg count/array size out of sync")
|
||||
|
||||
#define IMPL_SVGPATHSEG_SUBCLASS_COMMON(segName, segType) \
|
||||
explicit DOMSVGPathSeg##segName(const float* aArgs) : DOMSVGPathSeg() { \
|
||||
CHECK_ARG_COUNT_IN_SYNC(segType); \
|
||||
memcpy( \
|
||||
mArgs, aArgs, \
|
||||
SVGPathSegUtils::ArgCountForType(uint32_t(segType)) * sizeof(float)); \
|
||||
} \
|
||||
DOMSVGPathSeg##segName(DOMSVGPathSegList* aList, uint32_t aListIndex, \
|
||||
bool aIsAnimValItem) \
|
||||
: DOMSVGPathSeg(aList, aListIndex, aIsAnimValItem) { \
|
||||
CHECK_ARG_COUNT_IN_SYNC(segType); \
|
||||
} \
|
||||
/* From DOMSVGPathSeg: */ \
|
||||
uint32_t Type() const override { return segType; } \
|
||||
DOMSVGPathSeg* Clone() override { \
|
||||
/* InternalItem() + 1, because we're skipping the encoded seg type */ \
|
||||
float* args = IsInList() ? InternalItem() + 1 : mArgs; \
|
||||
return new DOMSVGPathSeg##segName(args); \
|
||||
} \
|
||||
float* PtrToMemberArgs() override { return mArgs; } \
|
||||
\
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) \
|
||||
override { \
|
||||
return dom::SVGPathSeg##segName##_Binding::Wrap(aCx, this, aGivenProto); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Class DOMSVGPathSeg
|
||||
*
|
||||
* This class is the base class of the classes that create the DOM objects that
|
||||
* wrap the internal path segments that are encoded in an SVGPathData. Its
|
||||
* sub-classes are also used to create the objects returned by
|
||||
* SVGPathElement.createSVGPathSegXxx().
|
||||
*
|
||||
* See the architecture comment in DOMSVGPathSegList.h for an overview of the
|
||||
* important points regarding these DOM wrapper structures.
|
||||
*
|
||||
* See the architecture comment in DOMSVGLength.h (yes, LENGTH) for an overview
|
||||
* of the important points regarding how this specific class works.
|
||||
*
|
||||
* The main differences between this class and DOMSVGLength is that we have
|
||||
* sub-classes (it does not), and the "internal counterpart" that we provide a
|
||||
* DOM wrapper for is a list of floats, not an instance of an internal class.
|
||||
*/
|
||||
class DOMSVGPathSeg : public nsWrapperCache {
|
||||
template <class T>
|
||||
friend class AutoChangePathSegListNotifier;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMSVGPathSeg)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMSVGPathSeg)
|
||||
|
||||
/**
|
||||
* Unlike the other list classes, we hide our ctor (because no one should be
|
||||
* creating instances of this class directly). This factory method in exposed
|
||||
* instead to take care of creating instances of the correct sub-class.
|
||||
*/
|
||||
static DOMSVGPathSeg* CreateFor(DOMSVGPathSegList* aList, uint32_t aListIndex,
|
||||
bool aIsAnimValItem);
|
||||
|
||||
/**
|
||||
* Create an unowned copy of this object. The caller is responsible for the
|
||||
* first AddRef()!
|
||||
*/
|
||||
virtual DOMSVGPathSeg* Clone() = 0;
|
||||
|
||||
bool IsInList() const { return !!mList; }
|
||||
|
||||
/**
|
||||
* Returns true if our attribute is animating (in which case our animVal is
|
||||
* not simply a mirror of our baseVal).
|
||||
*/
|
||||
bool AttrIsAnimating() const { return mList && mList->AttrIsAnimating(); }
|
||||
|
||||
/**
|
||||
* In future, if this class is used for non-list segments, this will be
|
||||
* different to IsInList().
|
||||
*/
|
||||
bool HasOwner() const { return !!mList; }
|
||||
|
||||
/**
|
||||
* This method is called to notify this DOM object that it is being inserted
|
||||
* into a list, and give it the information it needs as a result.
|
||||
*
|
||||
* This object MUST NOT already belong to a list when this method is called.
|
||||
* That's not to say that script can't move these DOM objects between
|
||||
* lists - it can - it's just that the logic to handle that (and send out
|
||||
* the necessary notifications) is located elsewhere (in DOMSVGPathSegList).)
|
||||
*/
|
||||
void InsertingIntoList(DOMSVGPathSegList* aList, uint32_t aListIndex,
|
||||
bool aIsAnimValItem);
|
||||
|
||||
static uint32_t MaxListIndex() {
|
||||
return (1U << MOZ_SVG_LIST_INDEX_BIT_COUNT) - 1;
|
||||
}
|
||||
|
||||
/// This method is called to notify this object that its list index changed.
|
||||
void UpdateListIndex(uint32_t aListIndex) { mListIndex = aListIndex; }
|
||||
|
||||
/**
|
||||
* This method is called to notify this DOM object that it is about to be
|
||||
* removed from its current DOM list so that it can first make a copy of its
|
||||
* internal counterpart's values. (If it didn't do this, then it would
|
||||
* "lose" its value on being removed.)
|
||||
*/
|
||||
void RemovingFromList();
|
||||
|
||||
/**
|
||||
* This method converts the segment to a string of floats as found in
|
||||
* SVGPathData (i.e. the first float contains the type of the segment,
|
||||
* encoded into a float, followed by its arguments in the same order as they
|
||||
* are given in the <path> element's 'd' attribute).
|
||||
*/
|
||||
void ToSVGPathSegEncodedData(float* aRaw);
|
||||
|
||||
/**
|
||||
* The type of this path segment.
|
||||
*/
|
||||
virtual uint32_t Type() const = 0;
|
||||
|
||||
// WebIDL
|
||||
DOMSVGPathSegList* GetParentObject() { return mList; }
|
||||
uint16_t PathSegType() const { return Type(); }
|
||||
void GetPathSegTypeAsLetter(nsAString& aPathSegTypeAsLetter) {
|
||||
aPathSegTypeAsLetter = SVGPathSegUtils::GetPathSegTypeAsLetter(Type());
|
||||
}
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Generic ctor for DOMSVGPathSeg objects that are created for an attribute.
|
||||
*/
|
||||
DOMSVGPathSeg(DOMSVGPathSegList* aList, uint32_t aListIndex,
|
||||
bool aIsAnimValItem);
|
||||
|
||||
/**
|
||||
* Ctor for creating the objects returned by
|
||||
* SVGPathElement.createSVGPathSegXxx(), which do not initially belong to an
|
||||
* attribute.
|
||||
*/
|
||||
DOMSVGPathSeg();
|
||||
|
||||
virtual ~DOMSVGPathSeg() {
|
||||
// Our mList's weak ref to us must be nulled out when we die. If GC has
|
||||
// unlinked us using the cycle collector code, then that has already
|
||||
// happened, and mList is null.
|
||||
if (mList) {
|
||||
mList->ItemAt(mListIndex) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
dom::SVGElement* Element() { return mList->Element(); }
|
||||
|
||||
/**
|
||||
* Get a reference to the internal SVGPathSeg list item that this DOM wrapper
|
||||
* object currently wraps.
|
||||
*
|
||||
* To simplify the code we just have this one method for obtaining both
|
||||
* baseVal and animVal internal items. This means that animVal items don't
|
||||
* get const protection, but then our setter methods guard against changing
|
||||
* animVal items.
|
||||
*/
|
||||
float* InternalItem();
|
||||
|
||||
virtual float* PtrToMemberArgs() = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool IndexIsValid();
|
||||
#endif
|
||||
|
||||
RefPtr<DOMSVGPathSegList> mList;
|
||||
|
||||
// Bounds for the following are checked in the ctor, so be sure to update
|
||||
// that if you change the capacity of any of the following.
|
||||
|
||||
uint32_t mListIndex : MOZ_SVG_LIST_INDEX_BIT_COUNT;
|
||||
uint32_t mIsAnimValItem : 1; // uint32_t because MSVC won't pack otherwise
|
||||
};
|
||||
|
||||
class DOMSVGPathSegClosePath : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegClosePath() {}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(ClosePath,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH)
|
||||
|
||||
protected:
|
||||
// To allow IMPL_SVGPATHSEG_SUBCLASS_COMMON above to compile we need an
|
||||
// mArgs, but since C++ doesn't allow zero-sized arrays we need to give it
|
||||
// one (unused) element.
|
||||
float mArgs[1];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegMovetoAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegMovetoAbs(float x, float y) {
|
||||
mArgs[0] = x;
|
||||
mArgs[1] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_MOVETO_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[2];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegMovetoRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegMovetoRel(float x, float y) {
|
||||
mArgs[0] = x;
|
||||
mArgs[1] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(MovetoRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_MOVETO_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[2];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegLinetoAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegLinetoAbs(float x, float y) {
|
||||
mArgs[0] = x;
|
||||
mArgs[1] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_LINETO_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[2];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegLinetoRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegLinetoRel(float x, float y) {
|
||||
mArgs[0] = x;
|
||||
mArgs[1] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(LinetoRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_LINETO_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[2];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoCubicAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoCubicAbs(float x1, float y1, float x2, float y2, float x,
|
||||
float y) {
|
||||
mArgs[0] = x1;
|
||||
mArgs[1] = y1;
|
||||
mArgs[2] = x2;
|
||||
mArgs[3] = y2;
|
||||
mArgs[4] = x;
|
||||
mArgs[5] = y;
|
||||
}
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float X1();
|
||||
void SetX1(float aX1, ErrorResult& rv);
|
||||
float Y1();
|
||||
void SetY1(float aY1, ErrorResult& rv);
|
||||
float X2();
|
||||
void SetX2(float aX2, ErrorResult& rv);
|
||||
float Y2();
|
||||
void SetY2(float aY2, ErrorResult& rv);
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoCubicAbs, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_ABS)
|
||||
|
||||
protected:
|
||||
float mArgs[6];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoCubicRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoCubicRel(float x1, float y1, float x2, float y2, float x,
|
||||
float y) {
|
||||
mArgs[0] = x1;
|
||||
mArgs[1] = y1;
|
||||
mArgs[2] = x2;
|
||||
mArgs[3] = y2;
|
||||
mArgs[4] = x;
|
||||
mArgs[5] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoCubicRel, dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float X1();
|
||||
void SetX1(float aX1, ErrorResult& rv);
|
||||
float Y1();
|
||||
void SetY1(float aY1, ErrorResult& rv);
|
||||
float X2();
|
||||
void SetX2(float aX2, ErrorResult& rv);
|
||||
float Y2();
|
||||
void SetY2(float aY2, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[6];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoQuadraticAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoQuadraticAbs(float x1, float y1, float x, float y) {
|
||||
mArgs[0] = x1;
|
||||
mArgs[1] = y1;
|
||||
mArgs[2] = x;
|
||||
mArgs[3] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoQuadraticAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float X1();
|
||||
void SetX1(float aX1, ErrorResult& rv);
|
||||
float Y1();
|
||||
void SetY1(float aY1, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[4];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoQuadraticRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoQuadraticRel(float x1, float y1, float x, float y) {
|
||||
mArgs[0] = x1;
|
||||
mArgs[1] = y1;
|
||||
mArgs[2] = x;
|
||||
mArgs[3] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoQuadraticRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float X1();
|
||||
void SetX1(float aX1, ErrorResult& rv);
|
||||
float Y1();
|
||||
void SetY1(float aY1, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[4];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegArcAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegArcAbs(float r1, float r2, float angle, bool largeArcFlag,
|
||||
bool sweepFlag, float x, float y) {
|
||||
mArgs[0] = r1;
|
||||
mArgs[1] = r2;
|
||||
mArgs[2] = angle;
|
||||
mArgs[3] = largeArcFlag;
|
||||
mArgs[4] = sweepFlag;
|
||||
mArgs[5] = x;
|
||||
mArgs[6] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_ARC_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float R1();
|
||||
void SetR1(float aR1, ErrorResult& rv);
|
||||
float R2();
|
||||
void SetR2(float aR2, ErrorResult& rv);
|
||||
float Angle();
|
||||
void SetAngle(float aAngle, ErrorResult& rv);
|
||||
bool LargeArcFlag();
|
||||
void SetLargeArcFlag(bool aLargeArcFlag, ErrorResult& rv);
|
||||
bool SweepFlag();
|
||||
void SetSweepFlag(bool aSweepFlag, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[7];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegArcRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegArcRel(float r1, float r2, float angle, bool largeArcFlag,
|
||||
bool sweepFlag, float x, float y) {
|
||||
mArgs[0] = r1;
|
||||
mArgs[1] = r2;
|
||||
mArgs[2] = angle;
|
||||
mArgs[3] = largeArcFlag;
|
||||
mArgs[4] = sweepFlag;
|
||||
mArgs[5] = x;
|
||||
mArgs[6] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(ArcRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_ARC_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float R1();
|
||||
void SetR1(float aR1, ErrorResult& rv);
|
||||
float R2();
|
||||
void SetR2(float aR2, ErrorResult& rv);
|
||||
float Angle();
|
||||
void SetAngle(float aAngle, ErrorResult& rv);
|
||||
bool LargeArcFlag();
|
||||
void SetLargeArcFlag(bool aLargeArcFlag, ErrorResult& rv);
|
||||
bool SweepFlag();
|
||||
void SetSweepFlag(bool aSweepFlag, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[7];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegLinetoHorizontalAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
explicit DOMSVGPathSegLinetoHorizontalAbs(float x) { mArgs[0] = x; }
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
LinetoHorizontalAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[1];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegLinetoHorizontalRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
explicit DOMSVGPathSegLinetoHorizontalRel(float x) { mArgs[0] = x; }
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
LinetoHorizontalRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_LINETO_HORIZONTAL_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[1];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegLinetoVerticalAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
explicit DOMSVGPathSegLinetoVerticalAbs(float y) { mArgs[0] = y; }
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
LinetoVerticalAbs, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_ABS)
|
||||
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[1];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegLinetoVerticalRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
explicit DOMSVGPathSegLinetoVerticalRel(float y) { mArgs[0] = y; }
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
LinetoVerticalRel, dom::SVGPathSeg_Binding::PATHSEG_LINETO_VERTICAL_REL)
|
||||
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[1];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoCubicSmoothAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoCubicSmoothAbs(float x2, float y2, float x, float y) {
|
||||
mArgs[0] = x2;
|
||||
mArgs[1] = y2;
|
||||
mArgs[2] = x;
|
||||
mArgs[3] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoCubicSmoothAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float X2();
|
||||
void SetX2(float aX2, ErrorResult& rv);
|
||||
float Y2();
|
||||
void SetY2(float aY2, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[4];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoCubicSmoothRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoCubicSmoothRel(float x2, float y2, float x, float y) {
|
||||
mArgs[0] = x2;
|
||||
mArgs[1] = y2;
|
||||
mArgs[2] = x;
|
||||
mArgs[3] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoCubicSmoothRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
float X2();
|
||||
void SetX2(float aX2, ErrorResult& rv);
|
||||
float Y2();
|
||||
void SetY2(float aY2, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[4];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoQuadraticSmoothAbs : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y) {
|
||||
mArgs[0] = x;
|
||||
mArgs[1] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoQuadraticSmoothAbs,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[2];
|
||||
};
|
||||
|
||||
class DOMSVGPathSegCurvetoQuadraticSmoothRel : public DOMSVGPathSeg {
|
||||
public:
|
||||
DOMSVGPathSegCurvetoQuadraticSmoothRel(float x, float y) {
|
||||
mArgs[0] = x;
|
||||
mArgs[1] = y;
|
||||
}
|
||||
|
||||
IMPL_SVGPATHSEG_SUBCLASS_COMMON(
|
||||
CurvetoQuadraticSmoothRel,
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL)
|
||||
|
||||
float X();
|
||||
void SetX(float aX, ErrorResult& rv);
|
||||
float Y();
|
||||
void SetY(float aY, ErrorResult& rv);
|
||||
|
||||
protected:
|
||||
float mArgs[2];
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#undef MOZ_SVG_LIST_INDEX_BIT_COUNT
|
||||
|
||||
#endif // DOM_SVG_DOMSVGPATHSEG_H_
|
|
@ -1,537 +0,0 @@
|
|||
/* -*- 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 "DOMSVGPathSegList.h"
|
||||
|
||||
#include "DOMSVGPathSeg.h"
|
||||
#include "nsError.h"
|
||||
#include "SVGAnimatedPathSegList.h"
|
||||
#include "SVGAttrTearoffTable.h"
|
||||
#include "SVGPathSegUtils.h"
|
||||
#include "mozilla/dom/SVGElement.h"
|
||||
#include "mozilla/dom/SVGPathElement.h"
|
||||
#include "mozilla/dom/SVGPathSegListBinding.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
// See the comment in this file's header.
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
static inline SVGAttrTearoffTable<void, DOMSVGPathSegList>&
|
||||
SVGPathSegListTearoffTable() {
|
||||
static SVGAttrTearoffTable<void, DOMSVGPathSegList>
|
||||
sSVGPathSegListTearoffTable;
|
||||
return sSVGPathSegListTearoffTable;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList)
|
||||
// No unlinking of mElement, we'd need to null out the value pointer (the
|
||||
// object it points to is held by the element) and null-check it everywhere.
|
||||
tmp->RemoveFromTearoffTable();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPathSegList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPathSegList)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPathSegList)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPathSegList)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
/* static */
|
||||
already_AddRefed<DOMSVGPathSegList> DOMSVGPathSegList::GetDOMWrapper(
|
||||
void* aList, SVGPathElement* aElement) {
|
||||
RefPtr<DOMSVGPathSegList> wrapper =
|
||||
SVGPathSegListTearoffTable().GetTearoff(aList);
|
||||
if (!wrapper) {
|
||||
wrapper = new DOMSVGPathSegList(
|
||||
aElement, aElement->GetAnimPathSegList()->GetAnimValKey() == aList);
|
||||
SVGPathSegListTearoffTable().AddTearoff(aList, wrapper);
|
||||
}
|
||||
return wrapper.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
DOMSVGPathSegList* DOMSVGPathSegList::GetDOMWrapperIfExists(void* aList) {
|
||||
return SVGPathSegListTearoffTable().GetTearoff(aList);
|
||||
}
|
||||
|
||||
void DOMSVGPathSegList::RemoveFromTearoffTable() {
|
||||
// There are now no longer any references to us held by script or list items.
|
||||
// Note we must use GetAnimValKey/GetBaseValKey here, NOT InternalList()!
|
||||
void* key = mIsAnimValList ? InternalAList().GetAnimValKey()
|
||||
: InternalAList().GetBaseValKey();
|
||||
SVGPathSegListTearoffTable().RemoveTearoff(key);
|
||||
}
|
||||
|
||||
DOMSVGPathSegList::~DOMSVGPathSegList() { RemoveFromTearoffTable(); }
|
||||
|
||||
JSObject* DOMSVGPathSegList::WrapObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
return mozilla::dom::SVGPathSegList_Binding::Wrap(cx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void DOMSVGPathSegList::InternalListWillChangeTo(const SVGPathData& aNewValue) {
|
||||
// When the number of items in our internal counterpart changes, we MUST stay
|
||||
// in sync. Everything in the scary comment in
|
||||
// DOMSVGLengthList::InternalBaseValListWillChangeTo applies here just as
|
||||
// much, but we have the additional issue that failing to stay in sync would
|
||||
// mean that - assuming we aren't reading bad memory - we would likely end up
|
||||
// decoding command types from argument floats when looking in our
|
||||
// SVGPathData's data array! Either way, we'll likely then go down
|
||||
// MOZ_ASSERT_UNREACHABLE code paths, or end up reading/setting more bad
|
||||
// memory!!
|
||||
|
||||
// The only time that our other DOM list type implementations remove items is
|
||||
// if those items become surplus items due to an attribute change or SMIL
|
||||
// animation sample shortening the list. In general though, they try to keep
|
||||
// their existing DOM items, even when things change. To be consistent, we'd
|
||||
// really like to do the same thing. However, because different types of path
|
||||
// segment correspond to different DOMSVGPathSeg subclasses, the type of
|
||||
// items in our list are generally not the same, which makes this harder for
|
||||
// us. We have to remove DOM segments if their type is not the same as the
|
||||
// type of the new internal segment at their index.
|
||||
//
|
||||
// We also need to sync up mInternalDataIndex, but since we need to loop over
|
||||
// all the items in the new list checking types anyway, that's almost
|
||||
// insignificant in terms of overhead.
|
||||
//
|
||||
// Note that this method is called on every single SMIL animation resample
|
||||
// and we have no way to short circuit the overhead since we don't have a
|
||||
// way to tell if the call is due to a new animation, or a resample of an
|
||||
// existing animation (when the number and type of items would be the same).
|
||||
// (Note that a new animation could start overriding an existing animation at
|
||||
// any time, so checking IsAnimating() wouldn't work.) Because we get called
|
||||
// on every sample, it would not be acceptable alternative to throw away all
|
||||
// our items and let them be recreated lazily, since that would break what
|
||||
// script sees!
|
||||
|
||||
uint32_t length = mItems.Length();
|
||||
uint32_t index = 0;
|
||||
|
||||
uint32_t dataLength = aNewValue.mData.Length();
|
||||
uint32_t dataIndex = 0; // index into aNewValue's raw data array
|
||||
|
||||
uint32_t newSegType;
|
||||
|
||||
RefPtr<DOMSVGPathSegList> kungFuDeathGrip;
|
||||
if (length) {
|
||||
// RemovingFromList() might clear last reference to |this|.
|
||||
// Retain a temporary reference to keep from dying before returning.
|
||||
//
|
||||
// NOTE: For path-seg lists (unlike other list types), we have to do this
|
||||
// *whenever our list is nonempty* (even if we're growing in length).
|
||||
// That's because the path-seg-type of any segment could differ between old
|
||||
// list vs. new list, which will make us destroy & recreate that segment,
|
||||
// which could remove the last reference to us.
|
||||
//
|
||||
// (We explicitly *don't* want to create a kungFuDeathGrip in the length=0
|
||||
// case, though, because we do hit this code inside our constructor before
|
||||
// any other owning references have been added, and at that point, the
|
||||
// deathgrip-removal would make us die before we exit our constructor.)
|
||||
kungFuDeathGrip = this;
|
||||
}
|
||||
|
||||
while (index < length && dataIndex < dataLength) {
|
||||
newSegType = SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]);
|
||||
if (ItemAt(index) && ItemAt(index)->Type() != newSegType) {
|
||||
ItemAt(index)->RemovingFromList();
|
||||
ItemAt(index) = nullptr;
|
||||
}
|
||||
// Only after the RemovingFromList() can we touch mInternalDataIndex!
|
||||
mItems[index].mInternalDataIndex = dataIndex;
|
||||
++index;
|
||||
dataIndex += 1 + SVGPathSegUtils::ArgCountForType(newSegType);
|
||||
}
|
||||
|
||||
MOZ_ASSERT((index == length && dataIndex <= dataLength) ||
|
||||
(index <= length && dataIndex == dataLength),
|
||||
"very bad - list corruption?");
|
||||
|
||||
if (index < length) {
|
||||
// aNewValue has fewer items than our previous internal counterpart
|
||||
|
||||
uint32_t newLength = index;
|
||||
|
||||
// Remove excess items from the list:
|
||||
for (; index < length; ++index) {
|
||||
if (ItemAt(index)) {
|
||||
ItemAt(index)->RemovingFromList();
|
||||
ItemAt(index) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Only now may we truncate mItems
|
||||
mItems.TruncateLength(newLength);
|
||||
} else if (dataIndex < dataLength) {
|
||||
// aNewValue has more items than our previous internal counterpart
|
||||
|
||||
// Sync mItems:
|
||||
while (dataIndex < dataLength) {
|
||||
if (mItems.Length() &&
|
||||
mItems.Length() - 1 > DOMSVGPathSeg::MaxListIndex()) {
|
||||
// It's safe to get out of sync with our internal list as long as we
|
||||
// have FEWER items than it does.
|
||||
return;
|
||||
}
|
||||
if (!mItems.AppendElement(ItemProxy(nullptr, dataIndex), fallible)) {
|
||||
// OOM
|
||||
ErrorResult rv;
|
||||
Clear(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
return;
|
||||
}
|
||||
dataIndex +=
|
||||
1 + SVGPathSegUtils::ArgCountForType(
|
||||
SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]));
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(dataIndex == dataLength, "Serious processing error");
|
||||
MOZ_ASSERT(index == length, "Serious counting error");
|
||||
}
|
||||
|
||||
bool DOMSVGPathSegList::AttrIsAnimating() const {
|
||||
return InternalAList().IsAnimating();
|
||||
}
|
||||
|
||||
bool DOMSVGPathSegList::AnimListMirrorsBaseList() const {
|
||||
return GetDOMWrapperIfExists(InternalAList().GetAnimValKey()) &&
|
||||
!AttrIsAnimating();
|
||||
}
|
||||
|
||||
SVGPathData& DOMSVGPathSegList::InternalList() const {
|
||||
SVGAnimatedPathSegList* alist = mElement->GetAnimPathSegList();
|
||||
return mIsAnimValList && alist->IsAnimating() ? *alist->mAnimVal
|
||||
: alist->mBaseVal;
|
||||
}
|
||||
|
||||
SVGAnimatedPathSegList& DOMSVGPathSegList::InternalAList() const {
|
||||
MOZ_ASSERT(mElement->GetAnimPathSegList(), "Internal error");
|
||||
return *mElement->GetAnimPathSegList();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// nsIDOMSVGPathSegList implementation:
|
||||
|
||||
void DOMSVGPathSegList::Clear(ErrorResult& aError) {
|
||||
if (IsAnimValList()) {
|
||||
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LengthNoFlush() > 0) {
|
||||
AutoChangePathSegListNotifier notifier(this);
|
||||
// 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
|
||||
// internal counterparts' values!
|
||||
|
||||
InternalListWillChangeTo(SVGPathData()); // clears mItems
|
||||
|
||||
if (!AttrIsAnimating()) {
|
||||
// The anim val list is in sync with the base val list
|
||||
DOMSVGPathSegList* animList =
|
||||
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
|
||||
if (animList) {
|
||||
animList->InternalListWillChangeTo(SVGPathData()); // clears its mItems
|
||||
}
|
||||
}
|
||||
|
||||
InternalList().Clear();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::Initialize(
|
||||
DOMSVGPathSeg& aNewItem, ErrorResult& aError) {
|
||||
if (IsAnimValList()) {
|
||||
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If aNewItem is already in a list we should insert a clone of aNewItem,
|
||||
// and for consistency, this should happen even if *this* is the list that
|
||||
// aNewItem is currently in. Note that in the case of aNewItem being in this
|
||||
// list, the Clear() call before the InsertItemBefore() call would remove it
|
||||
// from this list, and so the InsertItemBefore() call would not insert a
|
||||
// clone of aNewItem, it would actually insert aNewItem. To prevent that
|
||||
// from happening we have to do the clone here, if necessary.
|
||||
|
||||
RefPtr<DOMSVGPathSeg> domItem = &aNewItem;
|
||||
if (aNewItem.HasOwner()) {
|
||||
domItem = aNewItem.Clone();
|
||||
}
|
||||
|
||||
Clear(aError);
|
||||
MOZ_ASSERT(!aError.Failed(), "How could this fail?");
|
||||
return InsertItemBefore(*domItem, 0, aError);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::GetItem(uint32_t index,
|
||||
ErrorResult& error) {
|
||||
bool found;
|
||||
RefPtr<DOMSVGPathSeg> item = IndexedGetter(index, found, error);
|
||||
if (!found) {
|
||||
error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
}
|
||||
return item.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::IndexedGetter(
|
||||
uint32_t aIndex, bool& aFound, ErrorResult& aError) {
|
||||
if (IsAnimValList()) {
|
||||
Element()->FlushAnimations();
|
||||
}
|
||||
aFound = aIndex < LengthNoFlush();
|
||||
if (aFound) {
|
||||
return GetItemAt(aIndex);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::InsertItemBefore(
|
||||
DOMSVGPathSeg& aNewItem, uint32_t aIndex, ErrorResult& aError) {
|
||||
if (IsAnimValList()) {
|
||||
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t internalIndex;
|
||||
if (aIndex < LengthNoFlush()) {
|
||||
internalIndex = mItems[aIndex].mInternalDataIndex;
|
||||
} else {
|
||||
aIndex = LengthNoFlush();
|
||||
internalIndex = InternalList().mData.Length();
|
||||
}
|
||||
if (aIndex >= DOMSVGPathSeg::MaxListIndex()) {
|
||||
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DOMSVGPathSeg> domItem = &aNewItem;
|
||||
if (domItem->HasOwner()) {
|
||||
domItem = domItem->Clone(); // must do this before changing anything!
|
||||
}
|
||||
|
||||
uint32_t argCount = SVGPathSegUtils::ArgCountForType(domItem->Type());
|
||||
|
||||
// Ensure we have enough memory so we can avoid complex error handling below:
|
||||
if (!mItems.SetCapacity(mItems.Length() + 1, fallible) ||
|
||||
!InternalList().mData.SetCapacity(
|
||||
InternalList().mData.Length() + 1 + argCount, fallible)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
if (AnimListMirrorsBaseList()) {
|
||||
DOMSVGPathSegList* animVal =
|
||||
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
|
||||
MOZ_ASSERT(animVal, "animVal should be a valid pointer");
|
||||
if (!animVal->mItems.SetCapacity(animVal->mItems.Length() + 1, fallible)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AutoChangePathSegListNotifier notifier(this);
|
||||
// Now that we know we're inserting, keep animVal list in sync as necessary.
|
||||
MaybeInsertNullInAnimValListAt(aIndex, internalIndex, argCount);
|
||||
|
||||
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
|
||||
domItem->ToSVGPathSegEncodedData(segAsRaw);
|
||||
|
||||
MOZ_ALWAYS_TRUE(InternalList().mData.InsertElementsAt(
|
||||
internalIndex, segAsRaw, 1 + argCount, fallible));
|
||||
MOZ_ALWAYS_TRUE(mItems.InsertElementAt(
|
||||
aIndex, ItemProxy(domItem.get(), internalIndex), fallible));
|
||||
|
||||
// This MUST come after the insertion into InternalList(), or else under the
|
||||
// insertion into InternalList() the values read from domItem would be bad
|
||||
// data from InternalList() itself!:
|
||||
domItem->InsertingIntoList(this, aIndex, IsAnimValList());
|
||||
|
||||
UpdateListIndicesFromIndex(aIndex + 1, argCount + 1);
|
||||
|
||||
return domItem.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::ReplaceItem(
|
||||
DOMSVGPathSeg& aNewItem, uint32_t aIndex, ErrorResult& aError) {
|
||||
if (IsAnimValList()) {
|
||||
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aIndex >= LengthNoFlush()) {
|
||||
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DOMSVGPathSeg> domItem = &aNewItem;
|
||||
if (domItem->HasOwner()) {
|
||||
domItem = domItem->Clone(); // must do this before changing anything!
|
||||
}
|
||||
|
||||
AutoChangePathSegListNotifier notifier(this);
|
||||
if (ItemAt(aIndex)) {
|
||||
// Notify any existing DOM item of removal *before* modifying the lists so
|
||||
// that the DOM item can copy the *old* value at its index:
|
||||
ItemAt(aIndex)->RemovingFromList();
|
||||
}
|
||||
|
||||
uint32_t internalIndex = mItems[aIndex].mInternalDataIndex;
|
||||
// We use InternalList() to get oldArgCount since we may not have a DOM
|
||||
// wrapper at the index being replaced.
|
||||
uint32_t oldType =
|
||||
SVGPathSegUtils::DecodeType(InternalList().mData[internalIndex]);
|
||||
|
||||
// NOTE: ArgCountForType returns a (small) unsigned value, but we're
|
||||
// intentionally putting it in a signed variable, because we're going to
|
||||
// subtract these values and might produce something negative.
|
||||
int32_t oldArgCount = SVGPathSegUtils::ArgCountForType(oldType);
|
||||
int32_t newArgCount = SVGPathSegUtils::ArgCountForType(domItem->Type());
|
||||
|
||||
float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS];
|
||||
domItem->ToSVGPathSegEncodedData(segAsRaw);
|
||||
|
||||
if (!InternalList().mData.ReplaceElementsAt(internalIndex, 1 + oldArgCount,
|
||||
segAsRaw, 1 + newArgCount,
|
||||
fallible)) {
|
||||
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
ItemAt(aIndex) = domItem;
|
||||
|
||||
// This MUST come after the ToSVGPathSegEncodedData call, otherwise that call
|
||||
// would end up reading bad data from InternalList()!
|
||||
domItem->InsertingIntoList(this, aIndex, IsAnimValList());
|
||||
|
||||
int32_t delta = newArgCount - oldArgCount;
|
||||
if (delta != 0) {
|
||||
for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) {
|
||||
mItems[i].mInternalDataIndex += delta;
|
||||
}
|
||||
}
|
||||
|
||||
return domItem.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::RemoveItem(
|
||||
uint32_t aIndex, ErrorResult& aError) {
|
||||
if (IsAnimValList()) {
|
||||
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aIndex >= LengthNoFlush()) {
|
||||
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
// We have to return the removed item, so get it, creating it if necessary:
|
||||
RefPtr<DOMSVGPathSeg> result = GetItemAt(aIndex);
|
||||
|
||||
AutoChangePathSegListNotifier notifier(this);
|
||||
// Notify the DOM item of removal *before* modifying the lists so that the
|
||||
// DOM item can copy its *old* value:
|
||||
ItemAt(aIndex)->RemovingFromList();
|
||||
|
||||
uint32_t internalIndex = mItems[aIndex].mInternalDataIndex;
|
||||
uint32_t segType =
|
||||
SVGPathSegUtils::DecodeType(InternalList().mData[internalIndex]);
|
||||
// NOTE: ArgCountForType returns a (small) unsigned value, but we're
|
||||
// intentionally putting it in a signed value, because we're going to
|
||||
// negate it, and you can't negate an unsigned value.
|
||||
int32_t argCount = SVGPathSegUtils::ArgCountForType(segType);
|
||||
|
||||
// Now that we know we're removing, keep animVal list in sync as necessary.
|
||||
// Do this *before* touching InternalList() so the removed item can get its
|
||||
// internal value.
|
||||
MaybeRemoveItemFromAnimValListAt(aIndex, argCount);
|
||||
|
||||
InternalList().mData.RemoveElementsAt(internalIndex, 1 + argCount);
|
||||
mItems.RemoveElementAt(aIndex);
|
||||
|
||||
UpdateListIndicesFromIndex(aIndex, -(argCount + 1));
|
||||
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::GetItemAt(uint32_t aIndex) {
|
||||
MOZ_ASSERT(aIndex < mItems.Length());
|
||||
|
||||
if (!ItemAt(aIndex)) {
|
||||
ItemAt(aIndex) = DOMSVGPathSeg::CreateFor(this, aIndex, IsAnimValList());
|
||||
}
|
||||
RefPtr<DOMSVGPathSeg> result = ItemAt(aIndex);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void DOMSVGPathSegList::MaybeInsertNullInAnimValListAt(
|
||||
uint32_t aIndex, uint32_t aInternalIndex, uint32_t aArgCountForItem) {
|
||||
MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
|
||||
|
||||
if (!AnimListMirrorsBaseList()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The anim val list is in sync with the base val list
|
||||
DOMSVGPathSegList* animVal =
|
||||
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
|
||||
|
||||
MOZ_ASSERT(animVal, "AnimListMirrorsBaseList() promised a non-null animVal");
|
||||
MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
|
||||
"animVal list not in sync!");
|
||||
MOZ_ALWAYS_TRUE(animVal->mItems.InsertElementAt(
|
||||
aIndex, ItemProxy(nullptr, aInternalIndex), fallible));
|
||||
|
||||
animVal->UpdateListIndicesFromIndex(aIndex + 1, 1 + aArgCountForItem);
|
||||
}
|
||||
|
||||
void DOMSVGPathSegList::MaybeRemoveItemFromAnimValListAt(
|
||||
uint32_t aIndex, int32_t aArgCountForItem) {
|
||||
MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
|
||||
|
||||
if (!AnimListMirrorsBaseList()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This needs to be a strong reference; otherwise, the RemovingFromList call
|
||||
// below might drop the last reference to animVal before we're done with it.
|
||||
RefPtr<DOMSVGPathSegList> animVal =
|
||||
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
|
||||
|
||||
MOZ_ASSERT(animVal, "AnimListMirrorsBaseList() promised a non-null animVal");
|
||||
MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
|
||||
"animVal list not in sync!");
|
||||
|
||||
if (animVal->ItemAt(aIndex)) {
|
||||
animVal->ItemAt(aIndex)->RemovingFromList();
|
||||
}
|
||||
animVal->mItems.RemoveElementAt(aIndex);
|
||||
|
||||
animVal->UpdateListIndicesFromIndex(aIndex, -(1 + aArgCountForItem));
|
||||
}
|
||||
|
||||
void DOMSVGPathSegList::UpdateListIndicesFromIndex(
|
||||
uint32_t aStartingIndex, int32_t aInternalDataIndexDelta) {
|
||||
uint32_t length = mItems.Length();
|
||||
|
||||
for (uint32_t i = aStartingIndex; i < length; ++i) {
|
||||
mItems[i].mInternalDataIndex += aInternalDataIndexDelta;
|
||||
if (ItemAt(i)) {
|
||||
ItemAt(i)->UpdateListIndex(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -1,266 +0,0 @@
|
|||
/* -*- 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_DOMSVGPATHSEGLIST_H_
|
||||
#define DOM_SVG_DOMSVGPATHSEGLIST_H_
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsTArray.h"
|
||||
#include "SVGPathData.h" // IWYU pragma: keep
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/SVGElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
class SVGAnimatedPathSegList;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class DOMSVGPathSeg;
|
||||
class SVGPathElement;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper class: AutoChangePathSegListNotifier
|
||||
// Stack-based helper class to pair calls to WillChangePathSegList and
|
||||
// DidChangePathSegList. Used by DOMSVGPathSeg and DOMSVGPathSegList.
|
||||
template <class T>
|
||||
class MOZ_RAII AutoChangePathSegListNotifier : public mozAutoDocUpdate {
|
||||
public:
|
||||
explicit AutoChangePathSegListNotifier(T* aValue)
|
||||
: mozAutoDocUpdate(aValue->Element()->GetComposedDoc(), true),
|
||||
mValue(aValue) {
|
||||
MOZ_ASSERT(mValue, "Expecting non-null value");
|
||||
mEmptyOrOldValue = mValue->Element()->WillChangePathSegList(*this);
|
||||
}
|
||||
|
||||
~AutoChangePathSegListNotifier() {
|
||||
mValue->Element()->DidChangePathSegList(mEmptyOrOldValue, *this);
|
||||
if (mValue->AttrIsAnimating()) {
|
||||
mValue->Element()->AnimationNeedsResample();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T* const mValue;
|
||||
nsAttrValue mEmptyOrOldValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class DOMSVGPathSegList
|
||||
*
|
||||
* This class is used to create the DOM tearoff objects that wrap internal
|
||||
* SVGPathData objects.
|
||||
*
|
||||
* See the architecture comment in DOMSVGAnimatedLengthList.h first (that's
|
||||
* LENGTH list), then continue reading the remainder of this comment.
|
||||
*
|
||||
* The architecture of this class is very similar to that of DOMSVGLengthList
|
||||
* except that, since there is no nsIDOMSVGAnimatedPathSegList interface
|
||||
* in SVG, we have no parent DOMSVGAnimatedPathSegList (unlike DOMSVGLengthList
|
||||
* which has a parent DOMSVGAnimatedLengthList class). (There is an
|
||||
* SVGAnimatedPathData interface, but that is quite different to
|
||||
* DOMSVGAnimatedLengthList, since it is inherited by elements rather than
|
||||
* elements having members of that type.) As a consequence, much of the logic
|
||||
* that would otherwise be in DOMSVGAnimatedPathSegList (and is in
|
||||
* DOMSVGAnimatedLengthList) is contained in this class.
|
||||
*
|
||||
* This class is strongly intertwined with DOMSVGPathSeg. Our DOMSVGPathSeg
|
||||
* items are friends of us and responsible for nulling out our pointers to
|
||||
* them when they die.
|
||||
*
|
||||
* Our DOM items are created lazily on demand as and when script requests them.
|
||||
*/
|
||||
class DOMSVGPathSegList final : public nsISupports, public nsWrapperCache {
|
||||
template <class T>
|
||||
friend class AutoChangePathSegListNotifier;
|
||||
friend class DOMSVGPathSeg;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPathSegList)
|
||||
|
||||
JSObject* WrapObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
nsISupports* GetParentObject() { return static_cast<nsIContent*>(mElement); }
|
||||
|
||||
/**
|
||||
* Factory method to create and return a DOMSVGPathSegList wrapper
|
||||
* for a given internal SVGPathData object. The factory takes care
|
||||
* of caching the object that it returns so that the same object can be
|
||||
* returned for the given SVGPathData each time it is requested.
|
||||
* The cached object is only removed from the cache when it is destroyed due
|
||||
* to there being no more references to it or to any of its descendant
|
||||
* objects. If that happens, any subsequent call requesting the DOM wrapper
|
||||
* for the SVGPathData will naturally result in a new
|
||||
* DOMSVGPathSegList being returned.
|
||||
*
|
||||
* It's unfortunate that aList is a void* instead of a typed argument. This
|
||||
* is because the mBaseVal and mAnimVal members of SVGAnimatedPathSegList are
|
||||
* of different types - a plain SVGPathData, and a SVGPathData*. We
|
||||
* use the addresses of these members as the key for the hash table, and
|
||||
* clearly SVGPathData* and a SVGPathData** are not the same type.
|
||||
*/
|
||||
static already_AddRefed<DOMSVGPathSegList> GetDOMWrapper(
|
||||
void* aList, dom::SVGPathElement* aElement);
|
||||
|
||||
/**
|
||||
* This method returns the DOMSVGPathSegList wrapper for an internal
|
||||
* SVGPathData object if it currently has a wrapper. If it does
|
||||
* not, then nullptr is returned.
|
||||
*/
|
||||
static DOMSVGPathSegList* GetDOMWrapperIfExists(void* aList);
|
||||
|
||||
/**
|
||||
* This will normally be the same as InternalList().CountItems(), except if
|
||||
* we've hit OOM, in which case our length will be zero.
|
||||
*/
|
||||
uint32_t LengthNoFlush() const {
|
||||
MOZ_ASSERT(
|
||||
mItems.Length() == 0 || mItems.Length() == InternalList().CountItems(),
|
||||
"DOM wrapper's list length is out of sync");
|
||||
return mItems.Length();
|
||||
}
|
||||
|
||||
/**
|
||||
* WATCH OUT! If you add code to call this on a baseVal wrapper, then you
|
||||
* must also call it on the animVal wrapper too if necessary!! See other
|
||||
* callers!
|
||||
*
|
||||
* Called by internal code to notify us when we need to sync the length of
|
||||
* this DOM list with its internal list. This is called immediately prior to
|
||||
* the length of the internal list being changed so that any DOM list items
|
||||
* that need to be removed from the DOM list can first copy their values from
|
||||
* their internal counterpart.
|
||||
*
|
||||
* The only time this method could fail is on OOM when trying to increase the
|
||||
* length of the DOM list. If that happens then this method simply clears the
|
||||
* list and returns. Callers just proceed as normal, and we simply accept
|
||||
* that the DOM list will be empty (until successfully set to a new value).
|
||||
*/
|
||||
void InternalListWillChangeTo(const SVGPathData& aNewValue);
|
||||
|
||||
/**
|
||||
* Returns true if our attribute is animating (in which case our animVal is
|
||||
* not simply a mirror of our baseVal).
|
||||
*/
|
||||
bool AttrIsAnimating() const;
|
||||
/**
|
||||
* Returns true if there is an animated list mirroring the base list.
|
||||
*/
|
||||
bool AnimListMirrorsBaseList() const;
|
||||
|
||||
uint32_t NumberOfItems() const {
|
||||
if (IsAnimValList()) {
|
||||
Element()->FlushAnimations();
|
||||
}
|
||||
return LengthNoFlush();
|
||||
}
|
||||
void Clear(ErrorResult& aError);
|
||||
already_AddRefed<DOMSVGPathSeg> Initialize(DOMSVGPathSeg& aNewItem,
|
||||
ErrorResult& aError);
|
||||
already_AddRefed<DOMSVGPathSeg> GetItem(uint32_t index, ErrorResult& error);
|
||||
already_AddRefed<DOMSVGPathSeg> IndexedGetter(uint32_t index, bool& found,
|
||||
ErrorResult& error);
|
||||
already_AddRefed<DOMSVGPathSeg> InsertItemBefore(DOMSVGPathSeg& aNewItem,
|
||||
uint32_t aIndex,
|
||||
ErrorResult& aError);
|
||||
already_AddRefed<DOMSVGPathSeg> ReplaceItem(DOMSVGPathSeg& aNewItem,
|
||||
uint32_t aIndex,
|
||||
ErrorResult& aError);
|
||||
already_AddRefed<DOMSVGPathSeg> RemoveItem(uint32_t aIndex,
|
||||
ErrorResult& aError);
|
||||
already_AddRefed<DOMSVGPathSeg> AppendItem(DOMSVGPathSeg& aNewItem,
|
||||
ErrorResult& aError) {
|
||||
return InsertItemBefore(aNewItem, LengthNoFlush(), aError);
|
||||
}
|
||||
uint32_t Length() const { return NumberOfItems(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Only our static GetDOMWrapper() factory method may create objects of our
|
||||
* type.
|
||||
*/
|
||||
DOMSVGPathSegList(dom::SVGElement* aElement, bool aIsAnimValList)
|
||||
: mElement(aElement), mIsAnimValList(aIsAnimValList) {
|
||||
InternalListWillChangeTo(InternalList()); // Sync mItems
|
||||
}
|
||||
|
||||
~DOMSVGPathSegList();
|
||||
|
||||
dom::SVGElement* Element() const { return mElement.get(); }
|
||||
|
||||
/// Used to determine if this list is the baseVal or animVal list.
|
||||
bool IsAnimValList() const { return mIsAnimValList; }
|
||||
|
||||
/**
|
||||
* Get a reference to this object's corresponding internal SVGPathData.
|
||||
*
|
||||
* To simplify the code we just have this one method for obtaining both
|
||||
* base val and anim val internal lists. This means that anim val lists don't
|
||||
* get const protection, but our setter methods guard against changing
|
||||
* anim val lists.
|
||||
*/
|
||||
SVGPathData& InternalList() const;
|
||||
|
||||
SVGAnimatedPathSegList& InternalAList() const;
|
||||
|
||||
/// Creates an instance of the appropriate DOMSVGPathSeg sub-class for
|
||||
// aIndex, if it doesn't already exist, and then returns it.
|
||||
already_AddRefed<DOMSVGPathSeg> GetItemAt(uint32_t aIndex);
|
||||
|
||||
void MaybeInsertNullInAnimValListAt(uint32_t aIndex, uint32_t aInternalIndex,
|
||||
uint32_t aArgCountForItem);
|
||||
void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex,
|
||||
int32_t aArgCountForItem);
|
||||
|
||||
// Calls UpdateListIndex on all elements in |mItems| that satisfy ItemAt(),
|
||||
// from |aStartingIndex| to the end of |mItems|. Also adjusts
|
||||
// |mItems.mInternalDataIndex| by the requested amount.
|
||||
void UpdateListIndicesFromIndex(uint32_t aStartingIndex,
|
||||
int32_t aInternalDataIndexDelta);
|
||||
|
||||
DOMSVGPathSeg*& ItemAt(uint32_t aIndex) { return mItems[aIndex].mItem; }
|
||||
|
||||
void RemoveFromTearoffTable();
|
||||
|
||||
/**
|
||||
* This struct is used in our array of mItems to provide us with somewhere to
|
||||
* store the indexes into the internal SVGPathData of the internal seg data
|
||||
* that our DOMSVGPathSeg items wrap (the internal segment data is or varying
|
||||
* length, so we can't just use the index of our DOMSVGPathSeg items
|
||||
* themselves). The reason that we have this separate struct rather than
|
||||
* just storing the internal indexes in the DOMSVGPathSeg items is because we
|
||||
* want to create the DOMSVGPathSeg items lazily on demand.
|
||||
*/
|
||||
struct ItemProxy {
|
||||
ItemProxy() : mItem(nullptr), mInternalDataIndex(0) {}
|
||||
ItemProxy(DOMSVGPathSeg* aItem, uint32_t aInternalDataIndex)
|
||||
: mItem(aItem), mInternalDataIndex(aInternalDataIndex) {}
|
||||
|
||||
DOMSVGPathSeg* mItem;
|
||||
uint32_t mInternalDataIndex;
|
||||
};
|
||||
|
||||
// Weak refs to our DOMSVGPathSeg items. The items are friends and take care
|
||||
// of clearing our pointer to them when they die.
|
||||
FallibleTArray<ItemProxy> mItems;
|
||||
|
||||
// Strong ref to our element to keep it alive. We hold this not only for
|
||||
// ourself, but also for our DOMSVGPathSeg items too.
|
||||
RefPtr<dom::SVGElement> mElement;
|
||||
|
||||
bool mIsAnimValList;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // DOM_SVG_DOMSVGPATHSEGLIST_H_
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "DOMSVGPathSegList.h"
|
||||
#include "SVGPathSegListSMILType.h"
|
||||
#include "mozilla/SMILValue.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
|
@ -28,57 +27,14 @@ nsresult SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue) {
|
|||
// we do want to throw any error code from setAttribute if there's a problem.
|
||||
nsresult rv = newBaseValue.SetValueFromString(aValue);
|
||||
|
||||
// We must send these notifications *before* changing mBaseVal! Our baseVal's
|
||||
// DOM wrapper list may have to remove DOM items from itself, and any removed
|
||||
// DOM items need to copy their internal counterpart's values *before* we
|
||||
// change them. See the comments in
|
||||
// DOMSVGPathSegList::InternalListWillChangeTo().
|
||||
DOMSVGPathSegList* baseValWrapper = nullptr;
|
||||
DOMSVGPathSegList* animValWrapper = nullptr;
|
||||
if (StaticPrefs::dom_svg_pathSeg_enabled()) {
|
||||
baseValWrapper = DOMSVGPathSegList::GetDOMWrapperIfExists(GetBaseValKey());
|
||||
if (baseValWrapper) {
|
||||
baseValWrapper->InternalListWillChangeTo(newBaseValue);
|
||||
}
|
||||
|
||||
if (!IsAnimating()) { // DOM anim val wraps our base val too!
|
||||
animValWrapper =
|
||||
DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
|
||||
if (animValWrapper) {
|
||||
animValWrapper->InternalListWillChangeTo(newBaseValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only now may we modify mBaseVal!
|
||||
|
||||
// We don't need to call DidChange* here - we're only called by
|
||||
// SVGElement::ParseAttribute under Element::SetAttr,
|
||||
// which takes care of notifying.
|
||||
|
||||
mBaseVal.SwapWith(newBaseValue);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void SVGAnimatedPathSegList::ClearBaseValue() {
|
||||
if (StaticPrefs::dom_svg_pathSeg_enabled()) {
|
||||
// We must send these notifications *before* changing mBaseVal! (See above.)
|
||||
|
||||
DOMSVGPathSegList* baseValWrapper =
|
||||
DOMSVGPathSegList::GetDOMWrapperIfExists(GetBaseValKey());
|
||||
if (baseValWrapper) {
|
||||
baseValWrapper->InternalListWillChangeTo(SVGPathData());
|
||||
}
|
||||
|
||||
if (!IsAnimating()) { // DOM anim val wraps our base val too!
|
||||
DOMSVGPathSegList* animValWrapper =
|
||||
DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
|
||||
if (animValWrapper) {
|
||||
animValWrapper->InternalListWillChangeTo(SVGPathData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBaseVal.Clear();
|
||||
// Caller notifies
|
||||
}
|
||||
|
@ -91,20 +47,8 @@ nsresult SVGAnimatedPathSegList::SetAnimValue(const SVGPathData& aNewAnimValue,
|
|||
// Unfortunately it is not possible for us to reliably distinguish between
|
||||
// calls to this method that are setting a new sample for an existing
|
||||
// animation, and calls that are setting the first sample of an animation
|
||||
// that will override an existing animation. In the case of DOMSVGPathSegList
|
||||
// the InternalListWillChangeTo method is not virtually free as it is for the
|
||||
// other DOM list classes, so this is a shame. We'd quite like to be able to
|
||||
// skip the call if possible.
|
||||
// that will override an existing animation.
|
||||
|
||||
if (StaticPrefs::dom_svg_pathSeg_enabled()) {
|
||||
// We must send these notifications *before* changing mAnimVal! (See above.)
|
||||
|
||||
DOMSVGPathSegList* domWrapper =
|
||||
DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
|
||||
if (domWrapper) {
|
||||
domWrapper->InternalListWillChangeTo(aNewAnimValue);
|
||||
}
|
||||
}
|
||||
if (!mAnimVal) {
|
||||
mAnimVal = MakeUnique<SVGPathData>();
|
||||
}
|
||||
|
@ -119,18 +63,6 @@ nsresult SVGAnimatedPathSegList::SetAnimValue(const SVGPathData& aNewAnimValue,
|
|||
}
|
||||
|
||||
void SVGAnimatedPathSegList::ClearAnimValue(SVGElement* aElement) {
|
||||
if (StaticPrefs::dom_svg_pathSeg_enabled()) {
|
||||
// We must send these notifications *before* changing mAnimVal! (See above.)
|
||||
|
||||
DOMSVGPathSegList* domWrapper =
|
||||
DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
|
||||
if (domWrapper) {
|
||||
// When all animation ends, animVal simply mirrors baseVal, which may have
|
||||
// a different number of items to the last active animated value.
|
||||
//
|
||||
domWrapper->InternalListWillChangeTo(mBaseVal);
|
||||
}
|
||||
}
|
||||
mAnimVal = nullptr;
|
||||
aElement->DidAnimatePathSegList();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "SVGPathSegUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::dom::SVGPathSeg_Binding;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "SVGPathData.h"
|
||||
#include "SVGPathSegUtils.h"
|
||||
|
||||
using namespace mozilla::dom::SVGPathSeg_Binding;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "DOMSVGPathSeg.h"
|
||||
#include "DOMSVGPathSegList.h"
|
||||
#include "SVGGeometryProperty.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
@ -21,7 +19,7 @@
|
|||
#include "mozilla/dom/SVGPathElementBinding.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "SVGPathSegUtils.h"
|
||||
#include "mozilla/SVGContentUtils.h"
|
||||
|
||||
NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
|
||||
|
@ -56,152 +54,6 @@ void SVGPathElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
|
|||
|
||||
NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPathElement)
|
||||
|
||||
uint32_t SVGPathElement::GetPathSegAtLength(float distance) {
|
||||
uint32_t seg = 0;
|
||||
auto callback = [&](const ComputedStyle* s) {
|
||||
const nsStyleSVGReset* styleSVGReset = s->StyleSVGReset();
|
||||
if (styleSVGReset->mD.IsPath()) {
|
||||
seg = SVGPathData::GetPathSegAtLength(
|
||||
styleSVGReset->mD.AsPath()._0.AsSpan(), distance);
|
||||
}
|
||||
};
|
||||
|
||||
FlushStyleIfNeeded();
|
||||
if (SVGGeometryProperty::DoForComputedStyle(this, callback)) {
|
||||
return seg;
|
||||
}
|
||||
return mD.GetAnimValue().GetPathSegAtLength(distance);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegClosePath>
|
||||
SVGPathElement::CreateSVGPathSegClosePath() {
|
||||
return do_AddRef(new DOMSVGPathSegClosePath());
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegMovetoAbs>
|
||||
SVGPathElement::CreateSVGPathSegMovetoAbs(float x, float y) {
|
||||
return do_AddRef(new DOMSVGPathSegMovetoAbs(x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegMovetoRel>
|
||||
SVGPathElement::CreateSVGPathSegMovetoRel(float x, float y) {
|
||||
return do_AddRef(new DOMSVGPathSegMovetoRel(x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegLinetoAbs>
|
||||
SVGPathElement::CreateSVGPathSegLinetoAbs(float x, float y) {
|
||||
return do_AddRef(new DOMSVGPathSegLinetoAbs(x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegLinetoRel>
|
||||
SVGPathElement::CreateSVGPathSegLinetoRel(float x, float y) {
|
||||
return do_AddRef(new DOMSVGPathSegLinetoRel(x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicAbs>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1,
|
||||
float y1, float x2, float y2) {
|
||||
// Note that we swap from DOM API argument order to the argument order used
|
||||
// in the <path> element's 'd' attribute (i.e. we put the arguments for the
|
||||
// end point of the segment last instead of first).
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoCubicAbs(x1, y1, x2, y2, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicRel>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1,
|
||||
float y1, float x2, float y2) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoCubicRel(x1, y1, x2, y2, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticAbs>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1,
|
||||
float y1) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoQuadraticAbs(x1, y1, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticRel>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1,
|
||||
float y1) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoQuadraticRel(x1, y1, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegArcAbs> SVGPathElement::CreateSVGPathSegArcAbs(
|
||||
float x, float y, float r1, float r2, float angle, bool largeArcFlag,
|
||||
bool sweepFlag) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(
|
||||
new DOMSVGPathSegArcAbs(r1, r2, angle, largeArcFlag, sweepFlag, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegArcRel> SVGPathElement::CreateSVGPathSegArcRel(
|
||||
float x, float y, float r1, float r2, float angle, bool largeArcFlag,
|
||||
bool sweepFlag) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(
|
||||
new DOMSVGPathSegArcRel(r1, r2, angle, largeArcFlag, sweepFlag, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegLinetoHorizontalAbs>
|
||||
SVGPathElement::CreateSVGPathSegLinetoHorizontalAbs(float x) {
|
||||
return do_AddRef(new DOMSVGPathSegLinetoHorizontalAbs(x));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegLinetoHorizontalRel>
|
||||
SVGPathElement::CreateSVGPathSegLinetoHorizontalRel(float x) {
|
||||
return do_AddRef(new DOMSVGPathSegLinetoHorizontalRel(x));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegLinetoVerticalAbs>
|
||||
SVGPathElement::CreateSVGPathSegLinetoVerticalAbs(float y) {
|
||||
return do_AddRef(new DOMSVGPathSegLinetoVerticalAbs(y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegLinetoVerticalRel>
|
||||
SVGPathElement::CreateSVGPathSegLinetoVerticalRel(float y) {
|
||||
return do_AddRef(new DOMSVGPathSegLinetoVerticalRel(y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothAbs>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y,
|
||||
float x2, float y2) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoCubicSmoothAbs(x2, y2, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothRel>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y,
|
||||
float x2, float y2) {
|
||||
// See comment in CreateSVGPathSegCurvetoCubicAbs
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoCubicSmoothRel(x2, y2, x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothAbs>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y) {
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoQuadraticSmoothAbs(x, y));
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothRel>
|
||||
SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y) {
|
||||
return do_AddRef(new DOMSVGPathSegCurvetoQuadraticSmoothRel(x, y));
|
||||
}
|
||||
|
||||
// FIXME: This API is enabled only if dom.svg.pathSeg.enabled is true. This
|
||||
// preference is off by default in Bug 1388931, and will be dropped later.
|
||||
// So we are not planning to map d property for this API.
|
||||
already_AddRefed<DOMSVGPathSegList> SVGPathElement::PathSegList() {
|
||||
return DOMSVGPathSegList::GetDOMWrapper(mD.GetBaseValKey(), this);
|
||||
}
|
||||
|
||||
// FIXME: This API is enabled only if dom.svg.pathSeg.enabled is true. This
|
||||
// preference is off by default in Bug 1388931, and will be dropped later.
|
||||
// So we are not planning to map d property for this API.
|
||||
already_AddRefed<DOMSVGPathSegList> SVGPathElement::AnimatedPathSegList() {
|
||||
return DOMSVGPathSegList::GetDOMWrapper(mD.GetAnimValKey(), this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// SVGElement methods
|
||||
|
||||
|
@ -364,12 +216,12 @@ bool SVGPathElement::IsClosedLoop() const {
|
|||
// FIXME: Bug 1847621, we can cache this value, instead of walking through the
|
||||
// entire path again and again.
|
||||
uint32_t i = 0;
|
||||
uint32_t segType = SVGPathSeg_Binding::PATHSEG_UNKNOWN;
|
||||
uint32_t segType = PATHSEG_UNKNOWN;
|
||||
while (i < data.Length()) {
|
||||
segType = SVGPathSegUtils::DecodeType(data[i++]);
|
||||
i += SVGPathSegUtils::ArgCountForType(segType);
|
||||
}
|
||||
return segType == SVGPathSeg_Binding::PATHSEG_CLOSEPATH;
|
||||
return segType == PATHSEG_CLOSEPATH;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "mozilla/RefPtr.h"
|
||||
#include "SVGAnimatedPathSegList.h"
|
||||
#include "SVGGeometryElement.h"
|
||||
#include "DOMSVGPathSeg.h"
|
||||
|
||||
nsresult NS_NewSVGPathElement(
|
||||
nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
@ -77,52 +76,6 @@ class SVGPathElement final : public SVGPathElementBase {
|
|||
|
||||
nsStaticAtom* GetPathDataAttrName() const override { return nsGkAtoms::d; }
|
||||
|
||||
// WebIDL
|
||||
MOZ_CAN_RUN_SCRIPT uint32_t GetPathSegAtLength(float distance);
|
||||
already_AddRefed<DOMSVGPathSegClosePath> CreateSVGPathSegClosePath();
|
||||
already_AddRefed<DOMSVGPathSegMovetoAbs> CreateSVGPathSegMovetoAbs(float x,
|
||||
float y);
|
||||
already_AddRefed<DOMSVGPathSegMovetoRel> CreateSVGPathSegMovetoRel(float x,
|
||||
float y);
|
||||
already_AddRefed<DOMSVGPathSegLinetoAbs> CreateSVGPathSegLinetoAbs(float x,
|
||||
float y);
|
||||
already_AddRefed<DOMSVGPathSegLinetoRel> CreateSVGPathSegLinetoRel(float x,
|
||||
float y);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicAbs>
|
||||
CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1,
|
||||
float x2, float y2);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicRel>
|
||||
CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1,
|
||||
float x2, float y2);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticAbs>
|
||||
CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticRel>
|
||||
CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1);
|
||||
already_AddRefed<DOMSVGPathSegArcAbs> CreateSVGPathSegArcAbs(
|
||||
float x, float y, float r1, float r2, float angle, bool largeArcFlag,
|
||||
bool sweepFlag);
|
||||
already_AddRefed<DOMSVGPathSegArcRel> CreateSVGPathSegArcRel(
|
||||
float x, float y, float r1, float r2, float angle, bool largeArcFlag,
|
||||
bool sweepFlag);
|
||||
already_AddRefed<DOMSVGPathSegLinetoHorizontalAbs>
|
||||
CreateSVGPathSegLinetoHorizontalAbs(float x);
|
||||
already_AddRefed<DOMSVGPathSegLinetoHorizontalRel>
|
||||
CreateSVGPathSegLinetoHorizontalRel(float x);
|
||||
already_AddRefed<DOMSVGPathSegLinetoVerticalAbs>
|
||||
CreateSVGPathSegLinetoVerticalAbs(float y);
|
||||
already_AddRefed<DOMSVGPathSegLinetoVerticalRel>
|
||||
CreateSVGPathSegLinetoVerticalRel(float y);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothAbs>
|
||||
CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothRel>
|
||||
CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothAbs>
|
||||
CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y);
|
||||
already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothRel>
|
||||
CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y);
|
||||
already_AddRefed<DOMSVGPathSegList> PathSegList();
|
||||
already_AddRefed<DOMSVGPathSegList> AnimatedPathSegList();
|
||||
|
||||
static bool IsDPropertyChangedViaCSS(const ComputedStyle& aNewStyle,
|
||||
const ComputedStyle& aOldStyle);
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#include "SVGPathData.h"
|
||||
#include "SVGPathSegUtils.h"
|
||||
|
||||
using namespace mozilla::dom::SVGPathSeg_Binding;
|
||||
|
||||
// Indices of boolean flags within 'arc' segment chunks in path-data arrays
|
||||
// (where '0' would correspond to the index of the encoded segment type):
|
||||
#define LARGE_ARC_FLAG_IDX 4
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "nsMathUtils.h"
|
||||
#include "nsTextFormatter.h"
|
||||
|
||||
using namespace mozilla::dom::SVGPathSeg_Binding;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -8,20 +8,39 @@
|
|||
#define DOM_SVG_SVGPATHSEGUTILS_H_
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/dom/SVGPathSegBinding.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "nsDebug.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
namespace mozilla {
|
||||
template <typename Angle, typename LP>
|
||||
struct StyleGenericShapeCommand;
|
||||
|
||||
constexpr uint16_t PATHSEG_UNKNOWN = 0;
|
||||
constexpr uint16_t PATHSEG_CLOSEPATH = 1;
|
||||
constexpr uint16_t PATHSEG_MOVETO_ABS = 2;
|
||||
constexpr uint16_t PATHSEG_MOVETO_REL = 3;
|
||||
constexpr uint16_t PATHSEG_LINETO_ABS = 4;
|
||||
constexpr uint16_t PATHSEG_LINETO_REL = 5;
|
||||
constexpr uint16_t PATHSEG_CURVETO_CUBIC_ABS = 6;
|
||||
constexpr uint16_t PATHSEG_CURVETO_CUBIC_REL = 7;
|
||||
constexpr uint16_t PATHSEG_CURVETO_QUADRATIC_ABS = 8;
|
||||
constexpr uint16_t PATHSEG_CURVETO_QUADRATIC_REL = 9;
|
||||
constexpr uint16_t PATHSEG_ARC_ABS = 10;
|
||||
constexpr uint16_t PATHSEG_ARC_REL = 11;
|
||||
constexpr uint16_t PATHSEG_LINETO_HORIZONTAL_ABS = 12;
|
||||
constexpr uint16_t PATHSEG_LINETO_HORIZONTAL_REL = 13;
|
||||
constexpr uint16_t PATHSEG_LINETO_VERTICAL_ABS = 14;
|
||||
constexpr uint16_t PATHSEG_LINETO_VERTICAL_REL = 15;
|
||||
constexpr uint16_t PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
|
||||
constexpr uint16_t PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
|
||||
constexpr uint16_t PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
|
||||
constexpr uint16_t PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
|
||||
|
||||
#define NS_SVG_PATH_SEG_MAX_ARGS 7
|
||||
#define NS_SVG_PATH_SEG_FIRST_VALID_TYPE \
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CLOSEPATH
|
||||
#define NS_SVG_PATH_SEG_LAST_VALID_TYPE \
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
|
||||
#define NS_SVG_PATH_SEG_FIRST_VALID_TYPE PATHSEG_CLOSEPATH
|
||||
#define NS_SVG_PATH_SEG_LAST_VALID_TYPE PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
|
||||
#define NS_SVG_PATH_SEG_TYPE_COUNT (NS_SVG_PATH_SEG_LAST_VALID_TYPE + 1)
|
||||
|
||||
/**
|
||||
|
@ -181,24 +200,21 @@ class SVGPathSegUtils {
|
|||
}
|
||||
|
||||
static bool IsCubicType(uint32_t aType) {
|
||||
return aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_REL ||
|
||||
aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_ABS ||
|
||||
aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
|
||||
aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
|
||||
return aType == PATHSEG_CURVETO_CUBIC_REL ||
|
||||
aType == PATHSEG_CURVETO_CUBIC_ABS ||
|
||||
aType == PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
|
||||
aType == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
|
||||
}
|
||||
|
||||
static bool IsQuadraticType(uint32_t aType) {
|
||||
return aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_REL ||
|
||||
aType == dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_ABS ||
|
||||
aType ==
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
|
||||
aType ==
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
|
||||
return aType == PATHSEG_CURVETO_QUADRATIC_REL ||
|
||||
aType == PATHSEG_CURVETO_QUADRATIC_ABS ||
|
||||
aType == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
|
||||
aType == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
|
||||
}
|
||||
|
||||
static bool IsArcType(uint32_t aType) {
|
||||
return aType == dom::SVGPathSeg_Binding::PATHSEG_ARC_ABS ||
|
||||
aType == dom::SVGPathSeg_Binding::PATHSEG_ARC_REL;
|
||||
return aType == PATHSEG_ARC_ABS || aType == PATHSEG_ARC_REL;
|
||||
}
|
||||
|
||||
static bool IsRelativeOrAbsoluteType(uint32_t aType) {
|
||||
|
@ -207,11 +223,10 @@ class SVGPathSegUtils {
|
|||
// When adding a new path segment type, ensure that the returned condition
|
||||
// below is still correct.
|
||||
static_assert(
|
||||
NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
|
||||
NS_SVG_PATH_SEG_LAST_VALID_TYPE == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
|
||||
"Unexpected type");
|
||||
|
||||
return aType >= dom::SVGPathSeg_Binding::PATHSEG_MOVETO_ABS;
|
||||
return aType >= PATHSEG_MOVETO_ABS;
|
||||
}
|
||||
|
||||
static bool IsRelativeType(uint32_t aType) {
|
||||
|
@ -222,8 +237,7 @@ class SVGPathSegUtils {
|
|||
// When adding a new path segment type, ensure that the returned condition
|
||||
// below is still correct.
|
||||
static_assert(
|
||||
NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
|
||||
NS_SVG_PATH_SEG_LAST_VALID_TYPE == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
|
||||
"Unexpected type");
|
||||
|
||||
return aType & 1;
|
||||
|
@ -237,8 +251,7 @@ class SVGPathSegUtils {
|
|||
// When adding a new path segment type, ensure that the returned condition
|
||||
// below is still correct.
|
||||
static_assert(
|
||||
NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
|
||||
dom::SVGPathSeg_Binding::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
|
||||
NS_SVG_PATH_SEG_LAST_VALID_TYPE == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
|
||||
"Unexpected type");
|
||||
|
||||
return aType | 1;
|
||||
|
|
|
@ -96,7 +96,7 @@ load 1555795.html
|
|||
load 1560179.html
|
||||
load 1572904.html
|
||||
load 1683907.html
|
||||
pref(dom.svg.pathSeg.enabled,true) load 1715387.html
|
||||
load 1715387.html
|
||||
load 1837487.html
|
||||
load 1858792.html
|
||||
load 1858806.html
|
||||
|
|
|
@ -79,6 +79,7 @@ EXPORTS.mozilla.dom += [
|
|||
"SVGMPathElement.h",
|
||||
"SVGPathData.h",
|
||||
"SVGPathElement.h",
|
||||
"SVGPathSegUtils.h",
|
||||
"SVGPatternElement.h",
|
||||
"SVGPolygonElement.h",
|
||||
"SVGPolylineElement.h",
|
||||
|
@ -122,8 +123,6 @@ UNIFIED_SOURCES += [
|
|||
"DOMSVGLengthList.cpp",
|
||||
"DOMSVGNumber.cpp",
|
||||
"DOMSVGNumberList.cpp",
|
||||
"DOMSVGPathSeg.cpp",
|
||||
"DOMSVGPathSegList.cpp",
|
||||
"DOMSVGPoint.cpp",
|
||||
"DOMSVGPointList.cpp",
|
||||
"DOMSVGStringList.cpp",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
prefs = ["dom.svg.pathSeg.enabled=true"]
|
||||
support-files = [
|
||||
"MutationEventChecker.js",
|
||||
"a_href_destination.svg",
|
||||
|
@ -88,7 +87,6 @@ support-files = [
|
|||
|
||||
["test_getElementById.xhtml"]
|
||||
|
||||
["test_getPathSegListAtLength_with_d_property.html"]
|
||||
|
||||
["test_getSubStringLength.xhtml"]
|
||||
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test for getPathSegAtLength for d property</title>
|
||||
<meta charset=utf-8>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<style>
|
||||
svg {
|
||||
width: 10%;
|
||||
height: 10%;
|
||||
background: #eee;
|
||||
}
|
||||
svg path {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="log"></div>
|
||||
|
||||
<svg viewBox="0 0 20 10">
|
||||
<path id='target1' d="M2,2 L8,8 L12,4"/>
|
||||
</svg>
|
||||
<svg viewBox="0 0 20 10">
|
||||
<path id='target2' style='d: path("M2,2 L8,8 L12,4")' />
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
/* global test, assert_equals */
|
||||
|
||||
'use strict';
|
||||
|
||||
test(function() {
|
||||
let target1 = document.getElementById('target1');
|
||||
let target2 = document.getElementById('target2');
|
||||
assert_equals(target1.getPathSegAtLength(5), 1);
|
||||
assert_equals(target2.getPathSegAtLength(5), 1);
|
||||
|
||||
assert_equals(target1.getPathSegAtLength(10), 2);
|
||||
assert_equals(target2.getPathSegAtLength(10), 2);
|
||||
}, "getPathSegAtLength works properly on both d attribute and d property");
|
||||
|
||||
test(function() {
|
||||
let target = document.getElementById('target1');
|
||||
// Note: in order to make sure we flush style properly, we call
|
||||
// getComputedStyle after setting an initial value first, so if
|
||||
// getPathSegAtLength(5) doesn't flush style, it returns 0.
|
||||
target.style.d = 'none';
|
||||
assert_equals(getComputedStyle(target).d, "none");
|
||||
|
||||
target.style.d = 'path("M2,2 h3 v5")';
|
||||
assert_equals(target.getPathSegAtLength(5), 2);
|
||||
}, "getPathSegAtLength works properly after updating d property");
|
||||
|
||||
</script>
|
|
@ -1,5 +1,4 @@
|
|||
[DEFAULT]
|
||||
prefs = ["dom.svg.pathSeg.enabled=false"]
|
||||
support-files = [
|
||||
"497633.html",
|
||||
"fail.png",
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.w3.org/TR/SVG2/
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
interface mixin SVGAnimatedPathData {
|
||||
[Pref="dom.svg.pathSeg.enabled"]
|
||||
readonly attribute SVGPathSegList pathSegList;
|
||||
[Pref="dom.svg.pathSeg.enabled"]
|
||||
readonly attribute SVGPathSegList animatedPathSegList;
|
||||
};
|
|
@ -11,8 +11,6 @@
|
|||
*/
|
||||
[Exposed=Window]
|
||||
interface SVGPathElement : SVGGeometryElement {
|
||||
[Pref="dom.svg.pathSeg.enabled"]
|
||||
unsigned long getPathSegAtLength(float distance);
|
||||
};
|
||||
|
||||
SVGPathElement includes SVGAnimatedPathData;
|
||||
// TODO: Implement https://www.w3.org/TR/svg-paths/#InterfaceSVGPathData
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.w3.org/TR/SVG2/
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSeg {
|
||||
|
||||
// Path Segment Types
|
||||
const unsigned short PATHSEG_UNKNOWN = 0;
|
||||
const unsigned short PATHSEG_CLOSEPATH = 1;
|
||||
const unsigned short PATHSEG_MOVETO_ABS = 2;
|
||||
const unsigned short PATHSEG_MOVETO_REL = 3;
|
||||
const unsigned short PATHSEG_LINETO_ABS = 4;
|
||||
const unsigned short PATHSEG_LINETO_REL = 5;
|
||||
const unsigned short PATHSEG_CURVETO_CUBIC_ABS = 6;
|
||||
const unsigned short PATHSEG_CURVETO_CUBIC_REL = 7;
|
||||
const unsigned short PATHSEG_CURVETO_QUADRATIC_ABS = 8;
|
||||
const unsigned short PATHSEG_CURVETO_QUADRATIC_REL = 9;
|
||||
const unsigned short PATHSEG_ARC_ABS = 10;
|
||||
const unsigned short PATHSEG_ARC_REL = 11;
|
||||
const unsigned short PATHSEG_LINETO_HORIZONTAL_ABS = 12;
|
||||
const unsigned short PATHSEG_LINETO_HORIZONTAL_REL = 13;
|
||||
const unsigned short PATHSEG_LINETO_VERTICAL_ABS = 14;
|
||||
const unsigned short PATHSEG_LINETO_VERTICAL_REL = 15;
|
||||
const unsigned short PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
|
||||
const unsigned short PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
|
||||
const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
|
||||
const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
|
||||
|
||||
[Pure]
|
||||
readonly attribute unsigned short pathSegType;
|
||||
[Pure]
|
||||
readonly attribute DOMString pathSegTypeAsLetter;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegClosePath : SVGPathSeg {
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegMovetoAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegMovetoRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegLinetoAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegLinetoRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoCubicAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float x1;
|
||||
[SetterThrows]
|
||||
attribute float y1;
|
||||
[SetterThrows]
|
||||
attribute float x2;
|
||||
[SetterThrows]
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoCubicRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float x1;
|
||||
[SetterThrows]
|
||||
attribute float y1;
|
||||
[SetterThrows]
|
||||
attribute float x2;
|
||||
[SetterThrows]
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoQuadraticAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float x1;
|
||||
[SetterThrows]
|
||||
attribute float y1;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoQuadraticRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float x1;
|
||||
[SetterThrows]
|
||||
attribute float y1;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegArcAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float r1;
|
||||
[SetterThrows]
|
||||
attribute float r2;
|
||||
[SetterThrows]
|
||||
attribute float angle;
|
||||
[SetterThrows]
|
||||
attribute boolean largeArcFlag;
|
||||
[SetterThrows]
|
||||
attribute boolean sweepFlag;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegArcRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float r1;
|
||||
[SetterThrows]
|
||||
attribute float r2;
|
||||
[SetterThrows]
|
||||
attribute float angle;
|
||||
[SetterThrows]
|
||||
attribute boolean largeArcFlag;
|
||||
[SetterThrows]
|
||||
attribute boolean sweepFlag;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegLinetoHorizontalAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegLinetoHorizontalRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegLinetoVerticalAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegLinetoVerticalRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoCubicSmoothAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float x2;
|
||||
[SetterThrows]
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoCubicSmoothRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
[SetterThrows]
|
||||
attribute float x2;
|
||||
[SetterThrows]
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoQuadraticSmoothAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[LegacyNoInterfaceObject,
|
||||
Exposed=Window]
|
||||
interface SVGPathSegCurvetoQuadraticSmoothRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.w3.org/TR/SVG11/
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Exposed=Window,
|
||||
Pref="dom.svg.pathSeg.enabled"]
|
||||
interface SVGPathSegList {
|
||||
readonly attribute unsigned long numberOfItems;
|
||||
[Throws]
|
||||
getter SVGPathSeg getItem(unsigned long index);
|
||||
|
||||
// Mozilla-specific stuff
|
||||
readonly attribute unsigned long length; // synonym for numberOfItems
|
||||
};
|
|
@ -866,7 +866,6 @@ WEBIDL_FILES = [
|
|||
"SVGAnimatedLengthList.webidl",
|
||||
"SVGAnimatedNumber.webidl",
|
||||
"SVGAnimatedNumberList.webidl",
|
||||
"SVGAnimatedPathData.webidl",
|
||||
"SVGAnimatedPoints.webidl",
|
||||
"SVGAnimatedPreserveAspectRatio.webidl",
|
||||
"SVGAnimatedRect.webidl",
|
||||
|
@ -929,8 +928,6 @@ WEBIDL_FILES = [
|
|||
"SVGNumber.webidl",
|
||||
"SVGNumberList.webidl",
|
||||
"SVGPathElement.webidl",
|
||||
"SVGPathSeg.webidl",
|
||||
"SVGPathSegList.webidl",
|
||||
"SVGPatternElement.webidl",
|
||||
"SVGPoint.webidl",
|
||||
"SVGPointList.webidl",
|
||||
|
|
|
@ -9,6 +9,7 @@ headers = [
|
|||
"mozilla/css/Loader.h",
|
||||
"mozilla/AnimatedPropertyID.h",
|
||||
"mozilla/css/SheetLoadData.h",
|
||||
"mozilla/dom/SVGPathSegUtils.h",
|
||||
"mozilla/DeclarationBlock.h",
|
||||
"mozilla/dom/AnimationEffectBinding.h",
|
||||
"mozilla/dom/HTMLSlotElement.h",
|
||||
|
@ -16,7 +17,6 @@ headers = [
|
|||
"mozilla/dom/MediaList.h",
|
||||
"mozilla/dom/ScreenBinding.h",
|
||||
"mozilla/dom/ShadowRoot.h",
|
||||
"mozilla/dom/SVGPathSegBinding.h",
|
||||
"mozilla/ipc/ByteBuf.h",
|
||||
"mozilla/AnimationPropertySegment.h",
|
||||
"mozilla/ComputedTiming.h",
|
||||
|
@ -195,7 +195,7 @@ allowlist-vars = [
|
|||
"GECKO_IS_NIGHTLY",
|
||||
"NS_SAME_AS_FOREGROUND_COLOR",
|
||||
"mozilla::detail::gGkAtoms",
|
||||
"mozilla::dom::SVGPathSeg_Binding::PATHSEG_.*",
|
||||
"mozilla::PATHSEG_.*",
|
||||
]
|
||||
# TODO(emilio): A bunch of types here can go away once we generate bindings and
|
||||
# structs together.
|
||||
|
|
|
@ -3353,12 +3353,6 @@
|
|||
value: true
|
||||
mirror: always
|
||||
|
||||
# This enables the SVGPathSeg APIs
|
||||
- name: dom.svg.pathSeg.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Preference that is primarily used for testing of problematic file paths.
|
||||
# It can also be used for switching between different storage directories, but
|
||||
# such feature is not officially supported.
|
||||
|
|
|
@ -72,7 +72,7 @@ impl SVGPathData {
|
|||
/// Decode the svg path raw data from Gecko.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn decode_from_f32_array(path: &[f32]) -> Result<Self, ()> {
|
||||
use crate::gecko_bindings::structs::dom::SVGPathSeg_Binding::*;
|
||||
use crate::gecko_bindings::structs::*;
|
||||
use crate::values::generics::basic_shape::GenericShapeCommand::*;
|
||||
|
||||
let mut result: Vec<PathCommand> = Vec::new();
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
prefs: [dom.svg.pathSeg.enabled:false]
|
|
@ -1,2 +0,0 @@
|
|||
[SVGAnimatedPathData-removed.svg]
|
||||
prefs: [dom.svg.pathSeg.enabled:false]
|
Загрузка…
Ссылка в новой задаче