зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1339690 - Part 3: Drop spacing mode. r=birtles,smaug
MozReview-Commit-ID: 1c7jpzWQjVP --HG-- extra : rebase_source : 7850e290abb5fd87684c99710666c881eb777eb4
This commit is contained in:
Родитель
0946a7bd73
Коммит
f8dbd6bb32
|
@ -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);
|
||||
if (aOptions.IsUnrestrictedDouble() ||
|
||||
// Ignore iterationComposite if the Web Animations API is not enabled,
|
||||
// then the default value 'Replace' will be used.
|
||||
if (AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
|
||||
!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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче