Bug 1339690 - Part 3: Drop spacing mode. r=birtles,smaug

MozReview-Commit-ID: 1c7jpzWQjVP

--HG--
extra : rebase_source : 7850e290abb5fd87684c99710666c881eb777eb4
This commit is contained in:
Boris Chiou 2017-06-13 15:09:19 +08:00
Родитель 0946a7bd73
Коммит f8dbd6bb32
13 изменённых файлов: 22 добавлений и 651 удалений

Просмотреть файл

@ -10,9 +10,7 @@
// For UnrestrictedDoubleOrKeyframeAnimationOptions
#include "mozilla/dom/AnimationEffectTiming.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/KeyframeUtils.h"
#include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
#include "nsIScriptError.h"
namespace mozilla {
namespace dom {
@ -113,8 +111,6 @@ KeyframeEffect::SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget)
RefPtr<nsStyleContext> styleContext = GetTargetStyleContext();
if (styleContext) {
UpdateProperties(styleContext);
} else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
}
MaybeUpdateFrameForCompositor();
@ -125,9 +121,6 @@ KeyframeEffect::SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget)
if (mAnimation) {
nsNodeUtils::AnimationAdded(mAnimation);
}
} else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
// New target is null, so fall back to distribute spacing.
KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
}
// If the new target frame is also oversized we should probably record that
@ -181,61 +174,5 @@ KeyframeEffect::SetComposite(const CompositeOperation& aComposite)
}
}
void
KeyframeEffect::SetSpacing(JSContext* aCx,
const nsAString& aSpacing,
CallerType aCallerType,
ErrorResult& aRv)
{
SpacingMode spacingMode = SpacingMode::distribute;
nsCSSPropertyID pacedProperty = eCSSProperty_UNKNOWN;
nsAutoString invalidPacedProperty;
KeyframeEffectParams::ParseSpacing(aSpacing,
spacingMode,
pacedProperty,
invalidPacedProperty,
aCallerType,
aRv);
if (aRv.Failed()) {
return;
}
if (!invalidPacedProperty.IsEmpty()) {
const char16_t* params[] = { invalidPacedProperty.get() };
nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aCx);
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Animation"),
doc,
nsContentUtils::eDOM_PROPERTIES,
"UnanimatablePacedProperty",
params, ArrayLength(params));
}
if (mEffectOptions.mSpacingMode == spacingMode &&
mEffectOptions.mPacedProperty == pacedProperty) {
return;
}
mEffectOptions.mSpacingMode = spacingMode;
mEffectOptions.mPacedProperty = pacedProperty;
// Apply spacing. We apply distribute here. If the new spacing is paced,
// UpdateProperties() will apply it.
if (mEffectOptions.mSpacingMode == SpacingMode::distribute) {
KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
}
if (mAnimation && mAnimation->IsRelevant()) {
nsNodeUtils::AnimationChanged(mAnimation);
}
if (mTarget) {
RefPtr<nsStyleContext> styleContext = GetTargetStyleContext();
if (styleContext) {
UpdateProperties(styleContext);
}
}
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -72,12 +72,6 @@ public:
// GetStyleContext.
void SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget);
void GetSpacing(nsString& aRetVal, CallerType aCallerType)
{
KeyframeEffectReadOnly::GetSpacing(aRetVal);
}
void SetSpacing(JSContext* aCx, const nsAString& aSpacing,
CallerType aCallerType, ErrorResult& aRv);
IterationCompositeOperation IterationComposite(CallerType aCallerType)
{
return KeyframeEffectReadOnly::IterationComposite();

Просмотреть файл

@ -1,174 +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 "mozilla/KeyframeEffectParams.h"
#include "mozilla/AnimationUtils.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/KeyframeUtils.h"
#include "mozilla/RangedPtr.h"
#include "nsReadableUtils.h"
namespace mozilla {
static inline bool
IsLetter(char16_t aCh)
{
return (0x41 <= aCh && aCh <= 0x5A) || (0x61 <= aCh && aCh <= 0x7A);
}
static inline bool
IsDigit(char16_t aCh)
{
return 0x30 <= aCh && aCh <= 0x39;
}
static inline bool
IsNameStartCode(char16_t aCh)
{
return IsLetter(aCh) || aCh >= 0x80 || aCh == '_';
}
static inline bool
IsNameCode(char16_t aCh)
{
return IsNameStartCode(aCh) || IsDigit(aCh) || aCh == '-';
}
static inline bool
IsNewLine(char16_t aCh)
{
// 0x0A (LF), 0x0C (FF), 0x0D (CR), or pairs of CR followed by LF are
// replaced by LF.
return aCh == 0x0A || aCh == 0x0C || aCh == 0x0D;
}
static inline bool
IsValidEscape(char16_t aFirst, char16_t aSecond)
{
return aFirst == '\\' && !IsNewLine(aSecond);
}
static bool
IsIdentStart(RangedPtr<const char16_t> aIter,
const char16_t* const aEnd)
{
if (aIter == aEnd) {
return false;
}
if (*aIter == '-') {
if (aIter + 1 == aEnd) {
return false;
}
char16_t second = *(aIter + 1);
return IsNameStartCode(second) ||
second == '-' ||
(aIter + 2 != aEnd && IsValidEscape(second, *(aIter + 2)));
}
return IsNameStartCode(*aIter) ||
(aIter + 1 != aEnd && IsValidEscape(*aIter, *(aIter + 1)));
}
static void
ConsumeIdentToken(RangedPtr<const char16_t>& aIter,
const char16_t* const aEnd,
nsAString& aResult)
{
aResult.Truncate();
// Check if it starts with an identifier.
if (!IsIdentStart(aIter, aEnd)) {
return;
}
// Start to consume.
while (aIter != aEnd) {
if (IsNameCode(*aIter)) {
aResult.Append(*aIter);
} else if (*aIter == '\\') {
const RangedPtr<const char16_t> secondChar = aIter + 1;
if (secondChar == aEnd || !IsValidEscape(*aIter, *secondChar)) {
break;
}
// Consume '\\' and append the character following this '\\'.
++aIter;
aResult.Append(*aIter);
} else {
break;
}
++aIter;
}
}
/* static */ void
KeyframeEffectParams::ParseSpacing(const nsAString& aSpacing,
SpacingMode& aSpacingMode,
nsCSSPropertyID& aPacedProperty,
nsAString& aInvalidPacedProperty,
dom::CallerType aCallerType,
ErrorResult& aRv)
{
aInvalidPacedProperty.Truncate();
// Ignore spacing if the core API is not enabled since it is not yet ready to
// ship.
if (!AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
aSpacingMode = SpacingMode::distribute;
return;
}
// Parse spacing.
// distribute | paced({ident})
// https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-spacing
// 1. distribute spacing.
if (aSpacing.EqualsLiteral("distribute")) {
aSpacingMode = SpacingMode::distribute;
return;
}
// 2. paced spacing.
static const nsLiteralString kPacedPrefix = NS_LITERAL_STRING("paced(");
if (!StringBeginsWith(aSpacing, kPacedPrefix)) {
aRv.ThrowTypeError<dom::MSG_INVALID_SPACING_MODE_ERROR>(aSpacing);
return;
}
RangedPtr<const char16_t> iter(aSpacing.Data() + kPacedPrefix.Length(),
aSpacing.Data(), aSpacing.Length());
const char16_t* const end = aSpacing.EndReading();
nsAutoString identToken;
ConsumeIdentToken(iter, end, identToken);
if (identToken.IsEmpty()) {
aRv.ThrowTypeError<dom::MSG_INVALID_SPACING_MODE_ERROR>(aSpacing);
return;
}
aPacedProperty =
nsCSSProps::LookupProperty(identToken, CSSEnabledState::eForAllContent);
if (aPacedProperty == eCSSProperty_UNKNOWN ||
aPacedProperty == eCSSPropertyExtra_variable ||
// We just unconditionally pass Gecko as the backend type here since
// Servo doesn't support paced timing and this feature will soon be
// removed (bug 1339690).
!KeyframeUtils::IsAnimatableProperty(aPacedProperty,
StyleBackendType::Gecko)) {
aPacedProperty = eCSSProperty_UNKNOWN;
aInvalidPacedProperty = identToken;
}
if (end - iter.get() != 1 || *iter != ')') {
aRv.ThrowTypeError<dom::MSG_INVALID_SPACING_MODE_ERROR>(aSpacing);
return;
}
aSpacingMode = aPacedProperty == eCSSProperty_UNKNOWN
? SpacingMode::distribute
: SpacingMode::paced;
}
} // namespace mozilla

Просмотреть файл

@ -7,62 +7,19 @@
#ifndef mozilla_KeyframeEffectParams_h
#define mozilla_KeyframeEffectParams_h
#include "nsCSSProps.h"
#include "nsString.h"
// X11 has a #define for None
#ifdef None
#undef None
#endif
#include "mozilla/dom/KeyframeEffectBinding.h" // IterationCompositeOperation
#include "mozilla/dom/BindingDeclarations.h" // CallerType
namespace mozilla {
class ErrorResult;
enum class SpacingMode
{
distribute,
paced
};
struct KeyframeEffectParams
{
void GetSpacingAsString(nsAString& aSpacing) const
{
if (mSpacingMode == SpacingMode::distribute) {
aSpacing.AssignLiteral("distribute");
} else {
aSpacing.AssignLiteral("paced(");
aSpacing.AppendASCII(nsCSSProps::GetStringValue(mPacedProperty).get());
aSpacing.AppendLiteral(")");
}
}
/**
* Parse spacing string.
*
* @param aSpacing The input spacing string.
* @param [out] aSpacingMode The parsed spacing mode.
* @param [out] aPacedProperty The parsed CSS property if using paced spacing.
* @param [out] aInvalidPacedProperty A string that, if we parsed a string of
* the form 'paced(<ident>)' where <ident>
* is not a recognized animatable property,
* will be set to <ident>.
* @param [out] aRv The error result.
*/
static void ParseSpacing(const nsAString& aSpacing,
SpacingMode& aSpacingMode,
nsCSSPropertyID& aPacedProperty,
nsAString& aInvalidPacedProperty,
dom::CallerType aCallerType,
ErrorResult& aRv);
dom::IterationCompositeOperation mIterationComposite =
dom::IterationCompositeOperation::Replace;
dom::CompositeOperation mComposite = dom::CompositeOperation::Replace;
SpacingMode mSpacingMode = SpacingMode::distribute;
nsCSSPropertyID mPacedProperty = eCSSProperty_UNKNOWN;
};
} // namespace mozilla

Просмотреть файл

@ -23,7 +23,6 @@
#include "mozilla/TypeTraits.h"
#include "Layers.h" // For Layer
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetStyleContext
#include "nsContentUtils.h" // nsContentUtils::ReportToConsole
#include "nsCSSPropertyIDSet.h"
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
#include "nsCSSPseudoElements.h" // For CSSPseudoElementType
@ -218,10 +217,6 @@ KeyframeEffectReadOnly::DoSetKeyframes(nsTArray<Keyframe>&& aKeyframes,
}
mKeyframes = Move(aKeyframes);
// Apply distribute spacing irrespective of the spacing mode. We will apply
// the specified spacing mode when we generate computed animation property
// values from the keyframes since both operations require a style context
// and need to be performed whenever the style context changes.
KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
if (mAnimation && mAnimation->IsRelevant()) {
@ -788,27 +783,20 @@ KeyframeEffectOptionsFromUnion(
template <class OptionsType>
static KeyframeEffectParams
KeyframeEffectParamsFromUnion(const OptionsType& aOptions,
nsAString& aInvalidPacedProperty,
CallerType aCallerType,
ErrorResult& aRv)
CallerType aCallerType)
{
KeyframeEffectParams result;
if (!aOptions.IsUnrestrictedDouble()) {
const KeyframeEffectOptions& options =
KeyframeEffectOptionsFromUnion(aOptions);
KeyframeEffectParams::ParseSpacing(options.mSpacing,
result.mSpacingMode,
result.mPacedProperty,
aInvalidPacedProperty,
aCallerType,
aRv);
// Ignore iterationComposite if the Web Animations API is not enabled,
// then the default value 'Replace' will be used.
if (AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
result.mIterationComposite = options.mIterationComposite;
result.mComposite = options.mComposite;
}
if (aOptions.IsUnrestrictedDouble() ||
// Ignore iterationComposite if the Web Animations API is not enabled,
// then the default value 'Replace' will be used.
!AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
return result;
}
const KeyframeEffectOptions& options =
KeyframeEffectOptionsFromUnion(aOptions);
result.mIterationComposite = options.mIterationComposite;
result.mComposite = options.mComposite;
return result;
}
@ -857,23 +845,8 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(
return nullptr;
}
nsAutoString invalidPacedProperty;
KeyframeEffectParams effectOptions =
KeyframeEffectParamsFromUnion(aOptions, invalidPacedProperty,
aGlobal.CallerType(), aRv);
if (aRv.Failed()) {
return nullptr;
}
if (!invalidPacedProperty.IsEmpty()) {
const char16_t* params[] = { invalidPacedProperty.get() };
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Animation"),
doc,
nsContentUtils::eDOM_PROPERTIES,
"UnanimatablePacedProperty",
params, ArrayLength(params));
}
KeyframeEffectParamsFromUnion(aOptions, aGlobal.CallerType());
Maybe<OwningAnimationTarget> target = ConvertTarget(aTarget);
RefPtr<KeyframeEffectType> effect =
@ -954,15 +927,6 @@ KeyframeEffectReadOnly::BuildProperties(StyleType* aStyle)
mTarget->mElement,
aStyle);
// FIXME: Bug 1332633: we have to implement ComputeDistance for
// RawServoAnimationValue.
if (mEffectOptions.mSpacingMode == SpacingMode::paced &&
!mDocument->IsStyledByServo()) {
KeyframeUtils::ApplySpacing(keyframesCopy, SpacingMode::paced,
mEffectOptions.mPacedProperty,
computedValues, aStyle);
}
result =
KeyframeUtils::GetAnimationPropertiesFromKeyframes(
keyframesCopy,

Просмотреть файл

@ -158,10 +158,6 @@ public:
IterationCompositeOperation IterationComposite() const;
CompositeOperation Composite() const;
void GetSpacing(nsString& aRetVal) const
{
mEffectOptions.GetSpacingAsString(aRetVal);
}
void NotifyAnimationTimingUpdated();
void RequestRestyle(EffectCompositor::RestyleType aRestyleType);
void SetAnimation(Animation* aAnimation) override;

Просмотреть файл

@ -36,10 +36,6 @@ namespace mozilla {
//
// ------------------------------------------------------------------
// This is used while calculating paced spacing. If the keyframe is not pacable,
// we set its cumulative distance to kNotPaceable, so we can use this to check.
const double kNotPaceable = -1.0;
// For the aAllowList parameter of AppendStringOrStringSequence and
// GetPropertyValuesPairs.
enum class ListAllowance { eDisallow, eAllow };
@ -412,22 +408,9 @@ static bool
RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes,
nsIDocument* aDocument);
static void
DistributeRange(const Range<Keyframe>& aSpacingRange,
const Range<Keyframe>& aRangeToAdjust);
static void
DistributeRange(const Range<Keyframe>& aSpacingRange);
static void
PaceRange(const Range<Keyframe>& aKeyframes,
const Range<double>& aCumulativeDistances);
static nsTArray<double>
GetCumulativeDistances(const nsTArray<ComputedKeyframeValues>& aValues,
nsCSSPropertyID aProperty,
nsStyleContext* aStyleContext);
// ------------------------------------------------------------------
//
// Public API
@ -482,32 +465,12 @@ KeyframeUtils::GetKeyframesFromObject(JSContext* aCx,
}
/* static */ void
KeyframeUtils::ApplySpacing(nsTArray<Keyframe>& aKeyframes,
SpacingMode aSpacingMode,
nsCSSPropertyID aProperty,
nsTArray<ComputedKeyframeValues>& aComputedValues,
nsStyleContext* aStyleContext)
KeyframeUtils::ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes)
{
if (aKeyframes.IsEmpty()) {
return;
}
nsTArray<double> cumulativeDistances;
if (aSpacingMode == SpacingMode::paced) {
// We just unconditionally pass Gecko as the backend type here since
// Servo doesn't support paced timing and this feature will soon be removed
// (bug 1339690).
MOZ_ASSERT(IsAnimatableProperty(aProperty, StyleBackendType::Gecko),
"Paced property should be animatable");
cumulativeDistances = GetCumulativeDistances(aComputedValues, aProperty,
aStyleContext);
// Reset the computed offsets if using paced spacing.
for (Keyframe& keyframe : aKeyframes) {
keyframe.mComputedOffset = Keyframe::kComputedOffsetNotSet;
}
}
// If the first keyframe has an unspecified offset, fill it in with 0%.
// If there is only a single keyframe, then it gets 100%.
if (aKeyframes.Length() > 1) {
@ -532,70 +495,11 @@ KeyframeUtils::ApplySpacing(nsTArray<Keyframe>& aKeyframes,
keyframeB->mComputedOffset = keyframeB->mOffset.valueOr(1.0);
// Fill computed offsets in (keyframe A, keyframe B).
if (aSpacingMode == SpacingMode::distribute) {
DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1));
} else {
// a) Find Paced A (first paceable keyframe) and
// Paced B (last paceable keyframe) in [keyframe A, keyframe B].
RangedPtr<Keyframe> pacedA = keyframeA;
while (pacedA < keyframeB &&
cumulativeDistances[pacedA - begin] == kNotPaceable) {
++pacedA;
}
RangedPtr<Keyframe> pacedB = keyframeB;
while (pacedB > keyframeA &&
cumulativeDistances[pacedB - begin] == kNotPaceable) {
--pacedB;
}
// As spec says, if there is no paceable keyframe
// in [keyframe A, keyframe B], we let Paced A and Paced B refer to
// keyframe B.
if (pacedA > pacedB) {
pacedA = pacedB = keyframeB;
}
// b) Apply distributing offsets in (keyframe A, Paced A] and
// [Paced B, keyframe B).
DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1),
Range<Keyframe>(keyframeA + 1, pacedA + 1));
DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1),
Range<Keyframe>(pacedB, keyframeB));
// c) Apply paced offsets to each paceable keyframe in (Paced A, Paced B).
// We pass the range [Paced A, Paced B] since PaceRange needs the end
// points of the range in order to calculate the correct offset.
PaceRange(Range<Keyframe>(pacedA, pacedB + 1),
Range<double>(&cumulativeDistances[pacedA - begin],
pacedB - pacedA + 1));
// d) Fill in any computed offsets in (Paced A, Paced B) that are still
// not set (e.g. because the keyframe was not paceable, or because the
// cumulative distance between paceable properties was zero).
for (RangedPtr<Keyframe> frame = pacedA + 1; frame < pacedB; ++frame) {
if (frame->mComputedOffset != Keyframe::kComputedOffsetNotSet) {
continue;
}
RangedPtr<Keyframe> start = frame - 1;
RangedPtr<Keyframe> end = frame + 1;
while (end < pacedB &&
end->mComputedOffset == Keyframe::kComputedOffsetNotSet) {
++end;
}
DistributeRange(Range<Keyframe>(start, end + 1));
frame = end;
}
}
DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1));
keyframeA = keyframeB;
}
}
/* static */ void
KeyframeUtils::ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes)
{
nsTArray<ComputedKeyframeValues> emptyArray;
// FIXME: Bug 1339690: below static_cast should be dropped.
ApplySpacing(aKeyframes, SpacingMode::distribute, eCSSProperty_UNKNOWN,
emptyArray, static_cast<nsStyleContext*>(nullptr));
}
/* static */ nsTArray<ComputedKeyframeValues>
KeyframeUtils::GetComputedKeyframeValues(
const nsTArray<Keyframe>& aKeyframes,
@ -1567,7 +1471,7 @@ RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes,
for (size_t i = 0, len = aKeyframes.Length(); i < len; i++) {
const Keyframe& frame = aKeyframes[i];
// We won't have called ApplySpacing when this is called so
// We won't have called ApplyDistributeSpacing when this is called so
// we can't use frame.mComputedOffset. Instead we do a rough version
// of that algorithm that substitutes null offsets with 0.0 for the first
// frame, 1.0 for the last frame, and 0.5 for everything else.
@ -1620,7 +1524,7 @@ RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes,
* the range of aSpacingRange.
*
* @param aSpacingRange The sequence of keyframes between whose endpoints we
* should apply distribute spacing.
* should apply distribute offsets.
* @param aRangeToAdjust The range of keyframes we want to apply to.
*/
static void
@ -1657,170 +1561,4 @@ DistributeRange(const Range<Keyframe>& aSpacingRange)
aSpacingRange.end() - 1));
}
/**
* Apply paced spacing to all paceable keyframes in between the endpoints of the
* given range.
*
* @param aKeyframes The range of keyframes between whose endpoints we should
* apply paced spacing. Both endpoints should be paceable, i.e. the
* corresponding elements in |aCumulativeDist| should not be kNotPaceable.
* Within this function, we refer to the start and end points of this range
* as Paced A and Paced B respectively in keeping with the notation used in
* the spec.
* @param aCumulativeDistances The sequence of cumulative distances of the paced
* property as returned by GetCumulativeDistances(). This acts as a
* parallel range to |aKeyframes|.
*/
static void
PaceRange(const Range<Keyframe>& aKeyframes,
const Range<double>& aCumulativeDistances)
{
MOZ_ASSERT(aKeyframes.length() == aCumulativeDistances.length(),
"Range length mismatch");
const size_t len = aKeyframes.length();
// If there is nothing between the end points, there is nothing to space.
if (len < 3) {
return;
}
const double distA = *(aCumulativeDistances.begin());
const double distB = *(aCumulativeDistances.end() - 1);
MOZ_ASSERT(distA != kNotPaceable && distB != kNotPaceable,
"Both Paced A and Paced B should be paceable");
// If the total distance is zero, we should fall back to distribute spacing.
// The caller will fill-in any keyframes without a computed offset using
// distribute spacing so we can just return here.
if (distA == distB) {
return;
}
const RangedPtr<Keyframe> pacedA = aKeyframes.begin();
const RangedPtr<Keyframe> pacedB = aKeyframes.end() - 1;
MOZ_ASSERT(pacedA->mComputedOffset != Keyframe::kComputedOffsetNotSet &&
pacedB->mComputedOffset != Keyframe::kComputedOffsetNotSet,
"Both Paced A and Paced B should have valid computed offsets");
// Apply computed offset.
const double offsetA = pacedA->mComputedOffset;
const double diffOffset = pacedB->mComputedOffset - offsetA;
const double initialDist = distA;
const double totalDist = distB - initialDist;
for (auto iter = pacedA + 1; iter != pacedB; ++iter) {
size_t k = iter - aKeyframes.begin();
if (aCumulativeDistances[k] == kNotPaceable) {
continue;
}
double dist = aCumulativeDistances[k] - initialDist;
iter->mComputedOffset = offsetA + diffOffset * dist / totalDist;
}
}
/**
* Get cumulative distances for the paced property.
*
* @param aValues The computed values returned by GetComputedKeyframeValues.
* @param aPacedProperty The paced property.
* @param aStyleContext The style context for computing distance on transform.
* @return The cumulative distances for the paced property. The length will be
* the same as aValues.
*/
static nsTArray<double>
GetCumulativeDistances(const nsTArray<ComputedKeyframeValues>& aValues,
nsCSSPropertyID aPacedProperty,
nsStyleContext* aStyleContext)
{
// a) If aPacedProperty is a shorthand property, get its components.
// Otherwise, just add the longhand property into the set.
size_t pacedPropertyCount = 0;
nsCSSPropertyIDSet pacedPropertySet;
bool isShorthand = nsCSSProps::IsShorthand(aPacedProperty);
if (isShorthand) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPacedProperty,
CSSEnabledState::eForAllContent) {
pacedPropertySet.AddProperty(*p);
++pacedPropertyCount;
}
} else {
pacedPropertySet.AddProperty(aPacedProperty);
pacedPropertyCount = 1;
}
// b) Search each component (shorthand) or the longhand property, and
// calculate the cumulative distances of paceable keyframe pairs.
const size_t len = aValues.Length();
nsTArray<double> cumulativeDistances(len);
// cumulativeDistances is a parallel array to |aValues|, so set its length to
// the length of |aValues|.
cumulativeDistances.SetLength(len);
ComputedKeyframeValues prevPacedValues;
size_t preIdx = 0;
for (size_t i = 0; i < len; ++i) {
// Find computed values of the paced property.
ComputedKeyframeValues pacedValues;
for (const PropertyStyleAnimationValuePair& pair : aValues[i]) {
if (pacedPropertySet.HasProperty(pair.mProperty)) {
pacedValues.AppendElement(pair);
}
}
// Check we have values for all the paceable longhand components.
if (pacedValues.Length() != pacedPropertyCount) {
// This keyframe is not paceable, assign kNotPaceable and skip it.
cumulativeDistances[i] = kNotPaceable;
continue;
}
// Sort the pacedValues first, so the order of subproperties of
// pacedValues is always the same as that of prevPacedValues.
if (isShorthand) {
pacedValues.Sort(
TPropertyPriorityComparator<PropertyStyleAnimationValuePair>());
}
if (prevPacedValues.IsEmpty()) {
// This is the first paceable keyframe so its cumulative distance is 0.0.
cumulativeDistances[i] = 0.0;
} else {
double dist = 0.0;
if (isShorthand) {
// Apply the distance by the square root of the sum of squares of
// longhand component distances.
for (size_t propIdx = 0; propIdx < pacedPropertyCount; ++propIdx) {
nsCSSPropertyID prop = prevPacedValues[propIdx].mProperty;
MOZ_ASSERT(pacedValues[propIdx].mProperty == prop,
"Property mismatch");
double componentDistance = 0.0;
if (StyleAnimationValue::ComputeDistance(
prop,
prevPacedValues[propIdx].mValue.mGecko,
pacedValues[propIdx].mValue.mGecko,
aStyleContext,
componentDistance)) {
dist += componentDistance * componentDistance;
}
}
dist = sqrt(dist);
} else {
// If the property is longhand, we just use the 1st value.
// If ComputeDistance() fails, |dist| will remain zero so there will be
// no distance between the previous paced value and this value.
Unused <<
StyleAnimationValue::ComputeDistance(aPacedProperty,
prevPacedValues[0].mValue.mGecko,
pacedValues[0].mValue.mGecko,
aStyleContext,
dist);
}
cumulativeDistances[i] = cumulativeDistances[preIdx] + dist;
}
prevPacedValues.SwapElements(pacedValues);
preIdx = i;
}
return cumulativeDistances;
}
} // namespace mozilla

Просмотреть файл

@ -7,9 +7,10 @@
#ifndef mozilla_KeyframeUtils_h
#define mozilla_KeyframeUtils_h
#include "mozilla/KeyframeEffectParams.h" // For CompositeOperation
#include "nsCSSPropertyID.h"
#include "nsTArrayForwardDeclare.h" // For nsTArray
#include "js/RootingAPI.h" // For JS::Handle
#include "mozilla/KeyframeEffectParams.h" // SpacingMode
struct JSContext;
class JSObject;
@ -91,39 +92,10 @@ public:
const ServoComputedValues* aComputedValues);
/**
* Fills in the mComputedOffset member of each keyframe in the given array
* using the specified spacing mode.
* Calculate the computed offset of keyframes by evenly distributing keyframes
* with a missing offset.
*
* https://w3c.github.io/web-animations/#spacing-keyframes
*
* @param aKeyframes The set of keyframes to adjust.
* @param aSpacingMode The spacing mode to apply.
* @param aProperty The paced property. Only used when |aSpacingMode| is
* SpacingMode::paced. In all other cases it is ignored and hence may be
* any value, e.g. eCSSProperty_UNKNOWN.
* @param aComputedValues The set of computed keyframe values as returned by
* GetComputedKeyframeValues. Only used when |aSpacingMode| is
* SpacingMode::paced. In all other cases this parameter is unused and may
* be any value including an empty array.
* @param aStyleContext The style context used for calculating paced spacing
* on transform.
*/
static void ApplySpacing(nsTArray<Keyframe>& aKeyframes,
SpacingMode aSpacingMode,
nsCSSPropertyID aProperty,
nsTArray<ComputedKeyframeValues>& aComputedValues,
nsStyleContext* aStyleContext);
static void ApplySpacing(nsTArray<Keyframe>& aKeyframes,
SpacingMode aSpacingMode,
nsCSSPropertyID aProperty,
nsTArray<ComputedKeyframeValues>& aComputedValues,
const ServoComputedValues* aServoValues)
{
NS_WARNING("stylo: ApplySpacing not implemented yet");
}
/**
* Wrapper for ApplySpacing to simplify using distribute spacing.
* @see https://w3c.github.io/web-animations/#calculating-computed-keyframes
*
* @param aKeyframes The set of keyframes to adjust.
*/
@ -140,8 +112,7 @@ public:
* GetComputedKeyframeValues) used to fill in the individual
* AnimationPropertySegment objects. Although these values could be
* calculated from |aKeyframes|, passing them in as a separate parameter
* allows the result of GetComputedKeyframeValues to be re-used both
* here and in ApplySpacing.
* allows the result of GetComputedKeyframeValues to be re-used here.
* @param aEffectComposite The composite operation specified on the effect.
* For any keyframes in |aKeyframes| that do not specify a composite
* operation, this value will be used.

Просмотреть файл

@ -56,7 +56,6 @@ UNIFIED_SOURCES += [
'EffectCompositor.cpp',
'EffectSet.cpp',
'KeyframeEffect.cpp',
'KeyframeEffectParams.cpp',
'KeyframeEffectReadOnly.cpp',
'KeyframeUtils.cpp',
'PendingAnimationTracker.cpp',

Просмотреть файл

@ -558,10 +558,6 @@ DOMInterfaces = {
'concrete': False
},
'KeyframeEffect': {
'implicitJSContext': { 'setterOnly': [ 'spacing' ] }
},
'LegacyMozTCPSocket': {
'headerFile': 'TCPSocket.h',
'wrapperCache': False,

Просмотреть файл

@ -94,7 +94,6 @@ MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0} because the registration has been {1} since the update was scheduled.")
MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
MSG_DEF(MSG_INVALID_SPACING_MODE_ERROR, 1, JSEXN_TYPEERR, "Invalid spacing '{0}'.")
MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")

Просмотреть файл

@ -309,8 +309,6 @@ ImageBitmapRenderingContext_TransferImageBitmap=ImageBitmapRenderingContext.tran
ChromeScriptedDOMParserWithoutPrincipal=Creating DOMParser without a principal is deprecated.
IIRFilterChannelCountChangeWarning=IIRFilterNode channel count changes may produce audio glitches.
BiquadFilterChannelCountChangeWarning=BiquadFilterNode channel count changes may produce audio glitches.
# LOCALIZATION NOTE: %1$S is the unanimatable paced property.
UnanimatablePacedProperty=Paced property %1$S is not an animatable property.
# LOCALIZATION NOTE: Do not translate ".jpeg"
GenericImageNameJPEG=image.jpeg
# LOCALIZATION NOTE: Do not translate ".gif"

Просмотреть файл

@ -18,7 +18,6 @@ enum IterationCompositeOperation {
dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
IterationCompositeOperation iterationComposite = "replace";
CompositeOperation composite = "replace";
DOMString spacing = "distribute";
};
[Func="nsDocument::IsWebAnimationsEnabled",
@ -30,7 +29,6 @@ interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
readonly attribute (Element or CSSPseudoElement)? target;
readonly attribute IterationCompositeOperation iterationComposite;
readonly attribute CompositeOperation composite;
readonly attribute DOMString spacing;
// We use object instead of ComputedKeyframe so that we can put the
// property-value pairs on the object.
@ -66,8 +64,6 @@ interface KeyframeEffect : KeyframeEffectReadOnly {
[NeedsCallerType]
inherit attribute IterationCompositeOperation iterationComposite;
inherit attribute CompositeOperation composite;
[SetterThrows, NeedsCallerType]
inherit attribute DOMString spacing;
[Throws]
void setKeyframes (object? keyframes);
};