Files
palemoon27/dom/svg/DOMSVGPathSeg.cpp
T
roytam1 9af8eeaf15 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1125514 - Use jemalloc's metadata statistics to compute bookkeeping. r=glandium (541dbcfc6f)
- Bug 1201462 - Don't count arena allocated metadata once per bin. r=glandium (57e7c31081)
- back some warnings (377df69d65)
- Bug 1219501. In imagelib, initialize the number of cores to at least 1 in case of error. r=seth (3d7d1635f0)
- Bug 1219501. Limit total number of image decoding threads to 32 regardless of number asked for. r=seth (829a7a623d)
- Bug 1213744 (Part 1) - Support zero-size frame rects and detecting the end of the frame in Downscaler. r=tn (05e29075cc)
- Bug 1213744 (Part 2) - Clamp the GIF frame rect to the visible rect for DDD and don't decode outside it. r=tn (8a25e10a3e)
- Bug 1194837. Don't use the inverse orientation matrix when computing the image space invalidate rect. r=seth (cb5e4c2643)
- Bug 1214054 - Don't fire DECODE_COMPLETE in VectorImage::OnSVGDocumetError(). r=dholbert (bb7c34e46f)
- Bug 1195878 - If we detect animation during a full decode, drop the results of the full decode on the floor. r=tn (a765af2b68)
- Bug 1210553 - Remove the alternate flags arguments from SurfaceCache's Lookup functions. r=dholbert (15c6124f98)
- Bug 1217320 - Remove more XPIDL signature comments in .cpp files. r=froydnj (411ac93047)
- Bug 1186796 - Replace nsBaseHashtable::EnumerateRead() calls in image/ with iterators r=njn (665773ae6d)
- Bug 1186792 - Replace nsBaseHashtable::EnumerateRead() calls in hal/ with iterators. r=dhylands. (d57c6b11da)
- Bug 1187142 - Replace nsBaseHashtable::Enumerate() calls in hal/ with iterators. r=dhylands. (ec05c5b125)
- Bug 1186793 - Replace nsBaseHashtable::EnumerateRead() calls in gfx/ with iterators r=njn (9b3cdd92ce)
- Bug 1215900 - Fix clang's -Wimplicit-fallthrough warnings in gfx/ipc/ GfxMessageUtils.h. r=mstange (f55605f1fe)
- Bug 618898 - Part 1: Add WGL_NV_DX_interop. r=jgilbert (73390398ed)
- Bug 618898 - Add D3D11SharedSurfaceInterop. r=jgilbert (3dde956b85)
- Bug 1208513 - Resurrect SharedSurface_GLTexture for use on iOS r=jgilbert (b0fdc90414)
- Bug 1150760 - Don't call workaround unless necessary. - r=kamidphish (9bdd135931)
- Bug 1151106 - let debugger stop on each iteration of a "for(;;)" loop; r=jimb (b1b921c3a7)
- Bug 1223652 - Remove redundant else block after return statement in CGBlockScopeList::findEnclosingScope. r=arai (f1368bfc73)
- Bug 1219515 - IonMonkey: Fix ThrowIfNotConstructing was not declared. r=evilpie (1d6cedad10)
- Bug 1224044 - Use stable hashing in SavedFramePtrHasher r=terrence (4389cf1b70)
- Bug 1206596: Change js::SavedStacks to use mozilla::FastBernoulliTrial. r=fitzgen (1c4a8d1929)
- Bug 1206357: Add mfbt/FastBernoulliTrial.h, implementing efficient random sampling. r=waldo (7143e53dba)
- No bug: Fix comment in mfbt/FastBernoulliTrial.h. DONTBUILD r=me (e3343f8d9d)
- Bug 1217919 - Separate dynamic module scopes from those of function calls r=shu (521f6826e5)
- Bug 1202568 - Cherry-pick warning fixes from upstream double-conversion. r=Ms2ger (ef738f753b)
- add back some disabled android stuff (0351b0c518)
- Bug 1135261 - return new window from window.open in desktop runtime; r=marco,smaug,junior,wesj (fa4d8f2468)
- Bug 898075 - Remove the mozbrowserasyncscroll event from Gecko. r=botond,kanru,sicking (b1fdcb7630)
- namespace (91374d2db8)
2022-12-30 09:29:16 +08:00

384 lines
13 KiB
C++

/* -*- 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 "nsSVGElement.h"
#include "nsError.h"
// See the architecture comment in DOMSVGPathSegList.h.
namespace mozilla {
// 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_SCRIPT_OBJECTS
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
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DOMSVGPathSeg, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMSVGPathSeg, Release)
//----------------------------------------------------------------------
// Helper class: AutoChangePathSegNotifier
// Stack-based helper class to pair calls to WillChangePathSegList
// and DidChangePathSegList.
class MOZ_RAII AutoChangePathSegNotifier
{
public:
explicit AutoChangePathSegNotifier(DOMSVGPathSeg* aPathSeg MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mPathSeg(aPathSeg)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(mPathSeg, "Expecting non-null pathSeg");
MOZ_ASSERT(mPathSeg->HasOwner(),
"Expecting list to have an owner for notification");
mEmptyOrOldValue =
mPathSeg->Element()->WillChangePathSegList();
}
~AutoChangePathSegNotifier()
{
mPathSeg->Element()->DidChangePathSegList(mEmptyOrOldValue);
if (mPathSeg->mList->AttrIsAnimating()) {
mPathSeg->Element()->AnimationNeedsResample();
}
}
private:
DOMSVGPathSeg* const mPathSeg;
nsAttrValue mEmptyOrOldValue;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
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; \
} \
AutoChangePathSegNotifier 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:
NS_NOTREACHED("Invalid path segment type");
return nullptr;
}
}
} // namespace mozilla