Bug 816778 Part 1: Convert SVGPoint to WebIDL r=bz

This commit is contained in:
David Zbarsky 2012-12-22 23:54:19 -05:00
parent 6550289df6
commit 91171c07f6
9 changed files with 191 additions and 85 deletions

View File

@ -13,6 +13,7 @@
#include "nsIDOMSVGMatrix.h"
#include "nsContentUtils.h" // NS_ENSURE_FINITE
#include "DOMSVGMatrix.h"
#include "mozilla/dom/SVGPointBinding.h"
// See the architecture comment in DOMSVGPointList.h.
@ -29,46 +30,70 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
tmp->mList->mItems[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(DOMSVGPoint)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPoint)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPoint)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPoint)
DOMCI_DATA(SVGPoint, DOMSVGPoint)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPoint)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(DOMSVGPoint) // pseudo-interface
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGPoint)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPoint)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
DOMSVGPoint::GetX(float* aX)
float
DOMSVGPoint::X()
{
if (mIsAnimValItem && HasOwner()) {
Element()->FlushAnimations(); // May make HasOwner() == false
}
*aX = HasOwner() ? InternalItem().mX : mPt.mX;
return HasOwner() ? InternalItem().mX : mPt.mX;
}
NS_IMETHODIMP
DOMSVGPoint::GetX(float* aX)
{
*aX = X();
return NS_OK;
}
NS_IMETHODIMP
DOMSVGPoint::SetX(float aX)
{
if (mIsAnimValItem || mIsReadonly) {
return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
if (!NS_finite(aX)) {
return NS_ERROR_ILLEGAL_VALUE;
}
NS_ENSURE_FINITE(aX, NS_ERROR_ILLEGAL_VALUE);
ErrorResult rv;
SetX(aX, rv);
return rv.ErrorCode();
}
void
DOMSVGPoint::SetX(float aX, ErrorResult& rv)
{
if (mIsAnimValItem || mIsReadonly) {
rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
}
if (HasOwner()) {
if (InternalItem().mX == aX) {
return NS_OK;
return;
}
nsAttrValue emptyOrOldValue = Element()->WillChangePointList();
InternalItem().mX = aX;
@ -76,34 +101,50 @@ DOMSVGPoint::SetX(float aX)
if (mList->AttrIsAnimating()) {
Element()->AnimationNeedsResample();
}
return NS_OK;
return;
}
mPt.mX = aX;
return NS_OK;
}
float
DOMSVGPoint::Y()
{
if (mIsAnimValItem && HasOwner()) {
Element()->FlushAnimations(); // May make HasOwner() == false
}
return HasOwner() ? InternalItem().mY : mPt.mY;
}
NS_IMETHODIMP
DOMSVGPoint::GetY(float* aY)
{
if (mIsAnimValItem && HasOwner()) {
Element()->FlushAnimations(); // May make HasOwner() == false
}
*aY = HasOwner() ? InternalItem().mY : mPt.mY;
*aY = Y();
return NS_OK;
}
NS_IMETHODIMP
DOMSVGPoint::SetY(float aY)
{
if (mIsAnimValItem || mIsReadonly) {
return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
if (!NS_finite(aY)) {
return NS_ERROR_ILLEGAL_VALUE;
}
NS_ENSURE_FINITE(aY, NS_ERROR_ILLEGAL_VALUE);
ErrorResult rv;
SetY(aY, rv);
return rv.ErrorCode();
}
void
DOMSVGPoint::SetY(float aY, ErrorResult& rv)
{
if (mIsAnimValItem || mIsReadonly) {
rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
}
if (HasOwner()) {
if (InternalItem().mY == aY) {
return NS_OK;
return;
}
nsAttrValue emptyOrOldValue = Element()->WillChangePointList();
InternalItem().mY = aY;
@ -111,27 +152,36 @@ DOMSVGPoint::SetY(float aY)
if (mList->AttrIsAnimating()) {
Element()->AnimationNeedsResample();
}
return NS_OK;
return;
}
mPt.mY = aY;
return NS_OK;
}
NS_IMETHODIMP
DOMSVGPoint::MatrixTransform(nsIDOMSVGMatrix *matrix,
nsIDOMSVGPoint **_retval)
{
*_retval = MatrixTransform(matrix).get();
return NS_OK;
}
already_AddRefed<DOMSVGPoint>
DOMSVGPoint::MatrixTransform(nsIDOMSVGMatrix* matrix)
{
nsCOMPtr<DOMSVGMatrix> domMatrix = do_QueryInterface(matrix);
if (!domMatrix)
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
float x = HasOwner() ? InternalItem().mX : mPt.mX;
float y = HasOwner() ? InternalItem().mY : mPt.mY;
gfxPoint pt = domMatrix->Matrix().Transform(gfxPoint(x, y));
NS_ADDREF(*_retval = new DOMSVGPoint(pt));
nsRefPtr<DOMSVGPoint> newPoint = new DOMSVGPoint(pt);
return newPoint.forget();
}
return NS_OK;
JSObject*
DOMSVGPoint::WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap)
{
return mozilla::dom::SVGPointBinding::Wrap(cx, scope, this, triedToWrap);
}
void

View File

@ -14,6 +14,7 @@
#include "nsIDOMSVGPoint.h"
#include "nsTArray.h"
#include "SVGPoint.h"
#include "nsWrapperCache.h"
#include "mozilla/Attributes.h"
class nsSVGElement;
@ -45,12 +46,13 @@ namespace mozilla {
* See the architecture comment in DOMSVGLength.h (yes, LENGTH) for an overview
* of the important points regarding how this specific class works.
*/
class DOMSVGPoint MOZ_FINAL : public nsIDOMSVGPoint
class DOMSVGPoint MOZ_FINAL : public nsIDOMSVGPoint,
public nsWrapperCache
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGPOINT_IID)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPoint)
NS_DECL_NSIDOMSVGPOINT
/**
@ -64,6 +66,7 @@ public:
, mIsReadonly(false)
, mIsAnimValItem(aIsAnimValItem)
{
SetIsDOMBinding();
// These shifts are in sync with the members.
NS_ABORT_IF_FALSE(aList &&
aListIndex <= MaxListIndex(), "bad arg");
@ -71,12 +74,13 @@ public:
NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGPoint!");
}
DOMSVGPoint(const DOMSVGPoint *aPt = nullptr)
explicit DOMSVGPoint(const DOMSVGPoint *aPt = nullptr)
: mList(nullptr)
, mListIndex(0)
, mIsReadonly(false)
, mIsAnimValItem(false)
{
SetIsDOMBinding();
if (aPt) {
mPt = aPt->ToSVGPoint();
}
@ -88,16 +92,18 @@ public:
, mIsReadonly(false)
, mIsAnimValItem(false)
{
SetIsDOMBinding();
mPt.mX = aX;
mPt.mY = aY;
}
DOMSVGPoint(const gfxPoint &aPt)
explicit DOMSVGPoint(const gfxPoint &aPt)
: mList(nullptr)
, mListIndex(0)
, mIsReadonly(false)
, mIsAnimValItem(false)
{
SetIsDOMBinding();
mPt.mX = float(aPt.x);
mPt.mY = float(aPt.y);
NS_ASSERTION(NS_finite(mPt.mX) && NS_finite(mPt.mX),
@ -114,6 +120,19 @@ public:
}
}
// WebIDL
float X();
void SetX(float aX, ErrorResult& rv);
float Y();
void SetY(float aY, ErrorResult& rv);
already_AddRefed<DOMSVGPoint> MatrixTransform(nsIDOMSVGMatrix* matrix);
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
bool *triedToWrap);
nsISupports* GetParentObject() {
return mList;
}
/**
* Create an unowned copy of this object. The caller is responsible for the
* first AddRef()!

View File

@ -219,8 +219,8 @@ DOMSVGPointList::Clear()
return rv.ErrorCode();
}
already_AddRefed<nsIDOMSVGPoint>
DOMSVGPointList::Initialize(nsIDOMSVGPoint *aNewItem, ErrorResult& aError)
already_AddRefed<DOMSVGPoint>
DOMSVGPointList::Initialize(DOMSVGPoint& aNewItem, ErrorResult& aError)
{
if (IsAnimValList()) {
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
@ -235,29 +235,30 @@ DOMSVGPointList::Initialize(nsIDOMSVGPoint *aNewItem, ErrorResult& aError)
// clone of aNewItem, it would actually insert aNewItem. To prevent that
// from happening we have to do the clone here, if necessary.
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
return nullptr;
}
if (domItem->HasOwner() || domItem->IsReadonly()) {
aNewItem = domItem->Clone();
nsRefPtr<DOMSVGPoint> newItem = &aNewItem;
if (aNewItem.HasOwner() || aNewItem.IsReadonly()) {
newItem = aNewItem.Clone();
}
Clear();
return InsertItemBefore(aNewItem, 0, aError);
return InsertItemBefore(*newItem, 0, aError);
}
NS_IMETHODIMP
DOMSVGPointList::Initialize(nsIDOMSVGPoint *aNewItem,
nsIDOMSVGPoint **_retval)
{
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
*_retval = nullptr;
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
}
ErrorResult rv;
*_retval = Initialize(aNewItem, rv).get();
*_retval = Initialize(*domItem, rv).get();
return rv.ErrorCode();
}
nsIDOMSVGPoint*
DOMSVGPoint*
DOMSVGPointList::IndexedGetter(uint32_t aIndex, bool& aFound,
ErrorResult& aError)
{
@ -281,8 +282,8 @@ DOMSVGPointList::GetItem(uint32_t aIndex,
return rv.ErrorCode();
}
already_AddRefed<nsIDOMSVGPoint>
DOMSVGPointList::InsertItemBefore(nsIDOMSVGPoint *aNewItem, uint32_t aIndex,
already_AddRefed<DOMSVGPoint>
DOMSVGPointList::InsertItemBefore(DOMSVGPoint& aNewItem, uint32_t aIndex,
ErrorResult& aError)
{
if (IsAnimValList()) {
@ -296,13 +297,9 @@ DOMSVGPointList::InsertItemBefore(nsIDOMSVGPoint *aNewItem, uint32_t aIndex,
return nullptr;
}
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
return nullptr;
}
if (domItem->HasOwner() || domItem->IsReadonly()) {
domItem = domItem->Clone(); // must do this before changing anything!
nsRefPtr<DOMSVGPoint> domItem = &aNewItem;
if (aNewItem.HasOwner() || aNewItem.IsReadonly()) {
domItem = aNewItem.Clone(); // must do this before changing anything!
}
// Ensure we have enough memory so we can avoid complex error handling below:
@ -317,7 +314,7 @@ DOMSVGPointList::InsertItemBefore(nsIDOMSVGPoint *aNewItem, uint32_t aIndex,
MaybeInsertNullInAnimValListAt(aIndex);
InternalList().InsertItem(aIndex, domItem->ToSVGPoint());
mItems.InsertElementAt(aIndex, domItem.get());
mItems.InsertElementAt(aIndex, domItem);
// This MUST come after the insertion into InternalList(), or else under the
// insertion into InternalList() the values read from domItem would be bad
@ -338,13 +335,18 @@ DOMSVGPointList::InsertItemBefore(nsIDOMSVGPoint *aNewItem,
uint32_t aIndex,
nsIDOMSVGPoint **_retval)
{
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
*_retval = nullptr;
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
}
ErrorResult rv;
*_retval = InsertItemBefore(aNewItem, aIndex, rv).get();
*_retval = InsertItemBefore(*domItem, aIndex, rv).get();
return rv.ErrorCode();
}
already_AddRefed<nsIDOMSVGPoint>
DOMSVGPointList::ReplaceItem(nsIDOMSVGPoint *aNewItem, uint32_t aIndex,
already_AddRefed<DOMSVGPoint>
DOMSVGPointList::ReplaceItem(DOMSVGPoint& aNewItem, uint32_t aIndex,
ErrorResult& aError)
{
if (IsAnimValList()) {
@ -352,17 +354,14 @@ DOMSVGPointList::ReplaceItem(nsIDOMSVGPoint *aNewItem, uint32_t aIndex,
return nullptr;
}
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
return nullptr;
}
if (aIndex >= LengthNoFlush()) {
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr;
}
if (domItem->HasOwner() || domItem->IsReadonly()) {
domItem = domItem->Clone(); // must do this before changing anything!
nsRefPtr<DOMSVGPoint> domItem = &aNewItem;
if (aNewItem.HasOwner() || aNewItem.IsReadonly()) {
domItem = aNewItem.Clone(); // must do this before changing anything!
}
nsAttrValue emptyOrOldValue = Element()->WillChangePointList();
@ -391,12 +390,17 @@ DOMSVGPointList::ReplaceItem(nsIDOMSVGPoint *aNewItem,
uint32_t aIndex,
nsIDOMSVGPoint **_retval)
{
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
*_retval = nullptr;
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
}
ErrorResult rv;
*_retval = ReplaceItem(aNewItem, aIndex, rv).get();
*_retval = ReplaceItem(*domItem, aIndex, rv).get();
return rv.ErrorCode();
}
already_AddRefed<nsIDOMSVGPoint>
already_AddRefed<DOMSVGPoint>
DOMSVGPointList::RemoveItem(uint32_t aIndex, ErrorResult& aError)
{
if (IsAnimValList()) {
@ -421,7 +425,7 @@ DOMSVGPointList::RemoveItem(uint32_t aIndex, ErrorResult& aError)
// Notify the DOM item of removal *before* modifying the lists so that the
// DOM item can copy its *old* value:
mItems[aIndex]->RemovingFromList();
nsCOMPtr<nsIDOMSVGPoint> result = mItems[aIndex];
nsCOMPtr<DOMSVGPoint> result = mItems[aIndex];
InternalList().RemoveItem(aIndex);
mItems.RemoveElementAt(aIndex);
@ -448,8 +452,13 @@ NS_IMETHODIMP
DOMSVGPointList::AppendItem(nsIDOMSVGPoint *aNewItem,
nsIDOMSVGPoint **_retval)
{
nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem);
if (!domItem) {
*_retval = nullptr;
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
}
ErrorResult rv;
*_retval = AppendItem(aNewItem, rv).get();
*_retval = AppendItem(*domItem, rv).get();
return rv.ErrorCode();
}

View File

@ -140,29 +140,29 @@ public:
return LengthNoFlush();
}
void Clear(ErrorResult& aError);
already_AddRefed<nsIDOMSVGPoint> Initialize(nsIDOMSVGPoint *aNewItem,
ErrorResult& aError);
nsIDOMSVGPoint* GetItem(uint32_t aIndex, ErrorResult& aError)
already_AddRefed<DOMSVGPoint> Initialize(DOMSVGPoint& aNewItem,
ErrorResult& aError);
DOMSVGPoint* GetItem(uint32_t aIndex, ErrorResult& aError)
{
bool found;
nsIDOMSVGPoint* item = IndexedGetter(aIndex, found, aError);
DOMSVGPoint* item = IndexedGetter(aIndex, found, aError);
if (!found) {
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
}
return item;
}
nsIDOMSVGPoint* IndexedGetter(uint32_t aIndex, bool& aFound,
ErrorResult& aError);
already_AddRefed<nsIDOMSVGPoint> InsertItemBefore(nsIDOMSVGPoint *aNewItem,
uint32_t aIndex,
ErrorResult& aError);
already_AddRefed<nsIDOMSVGPoint> ReplaceItem(nsIDOMSVGPoint *aNewItem,
uint32_t aIndex,
ErrorResult& aError);
already_AddRefed<nsIDOMSVGPoint> RemoveItem(uint32_t aIndex,
ErrorResult& aError);
already_AddRefed<nsIDOMSVGPoint> AppendItem(nsIDOMSVGPoint *aNewItem,
ErrorResult& aError)
DOMSVGPoint* IndexedGetter(uint32_t aIndex, bool& aFound,
ErrorResult& aError);
already_AddRefed<DOMSVGPoint> InsertItemBefore(DOMSVGPoint& aNewItem,
uint32_t aIndex,
ErrorResult& aError);
already_AddRefed<DOMSVGPoint> ReplaceItem(DOMSVGPoint& aNewItem,
uint32_t aIndex,
ErrorResult& aError);
already_AddRefed<DOMSVGPoint> RemoveItem(uint32_t aIndex,
ErrorResult& aError);
already_AddRefed<DOMSVGPoint> AppendItem(DOMSVGPoint& aNewItem,
ErrorResult& aError)
{
return InsertItemBefore(aNewItem, LengthNoFlush(), aError);
}

View File

@ -459,6 +459,11 @@ DOMInterfaces = {
'resultNotAddRefed': [ 'getItem' ]
},
'SVGPoint': {
'nativeType': 'mozilla::DOMSVGPoint',
'headerFile': 'DOMSVGPoint.h'
},
'SVGPointList': {
'nativeType': 'mozilla::DOMSVGPointList',
'headerFile': 'DOMSVGPointList.h',
@ -860,7 +865,6 @@ addExternalIface('SVGLength')
addExternalIface('SVGMatrix')
addExternalIface('SVGNumber')
addExternalIface('SVGPathSeg')
addExternalIface('SVGPoint')
addExternalIface('SVGTransform')
addExternalIface('Text', nativeType='nsTextNode')
addExternalIface('TextMetrics', headerFile='nsIDOMCanvasRenderingContext2D.h')

View File

@ -5,9 +5,9 @@
#include "domstubs.idl"
[scriptable, uuid(ec2da3ef-5a99-49ed-aaef-b5af916c14ac)]
[scriptable, builtinclass, uuid(ec2da3ef-5a99-49ed-aaef-b5af916c14ac)]
interface nsIDOMSVGMatrix : nsISupports
{
{
attribute float a;
// raises DOMException on setting
attribute float b;

View File

@ -0,0 +1,25 @@
/* -*- 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 SVGMatrix;
interface SVGPoint {
[SetterThrows]
attribute float x;
[SetterThrows]
attribute float y;
[Creator]
SVGPoint matrixTransform(SVGMatrix matrix);
};

View File

@ -10,8 +10,6 @@
* liability, trademark and document use rules apply.
*/
interface SVGPoint;
interface SVGPointList {
readonly attribute unsigned long numberOfItems;
[Throws]

View File

@ -71,6 +71,7 @@ webidl_files = \
SVGLengthList.webidl \
SVGNumberList.webidl \
SVGPathSegList.webidl \
SVGPoint.webidl \
SVGPointList.webidl \
SVGTransformList.webidl \
TextDecoder.webidl \