mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 02:08:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
212
dom/svg/SVGAnimatedLengthList.cpp
Normal file
212
dom/svg/SVGAnimatedLengthList.cpp
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/* -*- 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 "SVGAnimatedLengthList.h"
|
||||
|
||||
#include "DOMSVGAnimatedLengthList.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsSVGAttrTearoffTable.h"
|
||||
#include "nsSMILValue.h"
|
||||
#include "SVGLengthListSMILType.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
nsresult
|
||||
SVGAnimatedLengthList::SetBaseValueString(const nsAString& aValue)
|
||||
{
|
||||
SVGLengthList newBaseValue;
|
||||
nsresult rv = newBaseValue.SetValueFromString(aValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DOMSVGAnimatedLengthList *domWrapper =
|
||||
DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this);
|
||||
if (domWrapper) {
|
||||
// We must send this notification *before* changing mBaseVal! If the length
|
||||
// of our baseVal is being reduced, 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 values *before* we change them.
|
||||
//
|
||||
domWrapper->InternalBaseValListWillChangeTo(newBaseValue);
|
||||
}
|
||||
|
||||
// We don't need to call DidChange* here - we're only called by
|
||||
// nsSVGElement::ParseAttribute under Element::SetAttr,
|
||||
// which takes care of notifying.
|
||||
|
||||
rv = mBaseVal.CopyFrom(newBaseValue);
|
||||
if (NS_FAILED(rv) && domWrapper) {
|
||||
// Attempting to increase mBaseVal's length failed - reduce domWrapper
|
||||
// back to the same length:
|
||||
domWrapper->InternalBaseValListWillChangeTo(mBaseVal);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
SVGAnimatedLengthList::ClearBaseValue(uint32_t aAttrEnum)
|
||||
{
|
||||
DOMSVGAnimatedLengthList *domWrapper =
|
||||
DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this);
|
||||
if (domWrapper) {
|
||||
// We must send this notification *before* changing mBaseVal! (See above.)
|
||||
domWrapper->InternalBaseValListWillChangeTo(SVGLengthList());
|
||||
}
|
||||
mBaseVal.Clear();
|
||||
// Caller notifies
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGAnimatedLengthList::SetAnimValue(const SVGLengthList& aNewAnimValue,
|
||||
nsSVGElement *aElement,
|
||||
uint32_t aAttrEnum)
|
||||
{
|
||||
DOMSVGAnimatedLengthList *domWrapper =
|
||||
DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this);
|
||||
if (domWrapper) {
|
||||
// A new animation may totally change the number of items in the animVal
|
||||
// list, replacing what was essentially a mirror of the baseVal list, or
|
||||
// else replacing and overriding an existing animation. When this happens
|
||||
// we must try and keep our animVal's DOM wrapper in sync (see the comment
|
||||
// in DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo).
|
||||
//
|
||||
// It's 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. Happily it's cheap to just blindly
|
||||
// notify our animVal's DOM wrapper of its internal counterpart's new value
|
||||
// each time this method is called, so that's what we do.
|
||||
//
|
||||
// Note that we must send this notification *before* setting or changing
|
||||
// mAnimVal! (See the comment in SetBaseValueString above.)
|
||||
//
|
||||
domWrapper->InternalAnimValListWillChangeTo(aNewAnimValue);
|
||||
}
|
||||
if (!mAnimVal) {
|
||||
mAnimVal = new SVGLengthList();
|
||||
}
|
||||
nsresult rv = mAnimVal->CopyFrom(aNewAnimValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
// OOM. We clear the animation, and, importantly, ClearAnimValue() ensures
|
||||
// that mAnimVal and its DOM wrapper (if any) will have the same length!
|
||||
ClearAnimValue(aElement, aAttrEnum);
|
||||
return rv;
|
||||
}
|
||||
aElement->DidAnimateLengthList(aAttrEnum);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SVGAnimatedLengthList::ClearAnimValue(nsSVGElement *aElement,
|
||||
uint32_t aAttrEnum)
|
||||
{
|
||||
DOMSVGAnimatedLengthList *domWrapper =
|
||||
DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this);
|
||||
if (domWrapper) {
|
||||
// When all animation ends, animVal simply mirrors baseVal, which may have
|
||||
// a different number of items to the last active animated value. We must
|
||||
// keep the length of our animVal's DOM wrapper list in sync, and again we
|
||||
// must do that before touching mAnimVal. See comments above.
|
||||
//
|
||||
domWrapper->InternalAnimValListWillChangeTo(mBaseVal);
|
||||
}
|
||||
mAnimVal = nullptr;
|
||||
aElement->DidAnimateLengthList(aAttrEnum);
|
||||
}
|
||||
|
||||
nsISMILAttr*
|
||||
SVGAnimatedLengthList::ToSMILAttr(nsSVGElement *aSVGElement,
|
||||
uint8_t aAttrEnum,
|
||||
uint8_t aAxis,
|
||||
bool aCanZeroPadList)
|
||||
{
|
||||
return new SMILAnimatedLengthList(this, aSVGElement, aAttrEnum, aAxis, aCanZeroPadList);
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGAnimatedLengthList::
|
||||
SMILAnimatedLengthList::ValueFromString(const nsAString& aStr,
|
||||
const dom::SVGAnimationElement* /*aSrcElement*/,
|
||||
nsSMILValue& aValue,
|
||||
bool& aPreventCachingOfSandwich) const
|
||||
{
|
||||
nsSMILValue val(&SVGLengthListSMILType::sSingleton);
|
||||
SVGLengthListAndInfo *llai = static_cast<SVGLengthListAndInfo*>(val.mU.mPtr);
|
||||
nsresult rv = llai->SetValueFromString(aStr);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
llai->SetInfo(mElement, mAxis, mCanZeroPadList);
|
||||
aValue = Move(val);
|
||||
|
||||
// If any of the lengths in the list depend on their context, then we must
|
||||
// prevent caching of the entire animation sandwich. This is because the
|
||||
// units of a length at a given index can change from sandwich layer to
|
||||
// layer, and indeed even be different within a single sandwich layer. If
|
||||
// any length in the result of an animation sandwich is the result of the
|
||||
// addition of lengths where one or more of those lengths is context
|
||||
// dependent, then naturally the resultant length is also context
|
||||
// dependent, regardless of whether its actual unit is context dependent or
|
||||
// not. Unfortunately normal invalidation mechanisms won't cause us to
|
||||
// recalculate the result of the sandwich if the context changes, so we
|
||||
// take the (substantial) performance hit of preventing caching of the
|
||||
// sandwich layer, causing the animation sandwich to be recalculated every
|
||||
// single sample.
|
||||
|
||||
aPreventCachingOfSandwich = false;
|
||||
for (uint32_t i = 0; i < llai->Length(); ++i) {
|
||||
uint8_t unit = (*llai)[i].GetUnit();
|
||||
if (unit == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE ||
|
||||
unit == nsIDOMSVGLength::SVG_LENGTHTYPE_EMS ||
|
||||
unit == nsIDOMSVGLength::SVG_LENGTHTYPE_EXS) {
|
||||
aPreventCachingOfSandwich = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsSMILValue
|
||||
SVGAnimatedLengthList::SMILAnimatedLengthList::GetBaseValue() const
|
||||
{
|
||||
// To benefit from Return Value Optimization and avoid copy constructor calls
|
||||
// due to our use of return-by-value, we must return the exact same object
|
||||
// from ALL return points. This function must only return THIS variable:
|
||||
nsSMILValue val;
|
||||
|
||||
nsSMILValue tmp(&SVGLengthListSMILType::sSingleton);
|
||||
SVGLengthListAndInfo *llai = static_cast<SVGLengthListAndInfo*>(tmp.mU.mPtr);
|
||||
nsresult rv = llai->CopyFrom(mVal->mBaseVal);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
llai->SetInfo(mElement, mAxis, mCanZeroPadList);
|
||||
val = Move(tmp);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGAnimatedLengthList::SMILAnimatedLengthList::SetAnimValue(const nsSMILValue& aValue)
|
||||
{
|
||||
NS_ASSERTION(aValue.mType == &SVGLengthListSMILType::sSingleton,
|
||||
"Unexpected type to assign animated value");
|
||||
if (aValue.mType == &SVGLengthListSMILType::sSingleton) {
|
||||
mVal->SetAnimValue(*static_cast<SVGLengthListAndInfo*>(aValue.mU.mPtr),
|
||||
mElement,
|
||||
mAttrEnum);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SVGAnimatedLengthList::SMILAnimatedLengthList::ClearAnimValue()
|
||||
{
|
||||
if (mVal->mAnimVal) {
|
||||
mVal->ClearAnimValue(mElement, mAttrEnum);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
Loading…
Add table
Add a link
Reference in a new issue