mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
Bug 1216843 - Part 2: Implement effect iteration composition. r=birtles, r=smaug
MozReview-Commit-ID: 6u7WtXwL3y3
This commit is contained in:
parent
acded2cbb2
commit
f98523cf02
@ -126,6 +126,22 @@ KeyframeEffect::SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffect::SetIterationComposite(
|
||||
const IterationCompositeOperation& aIterationComposite)
|
||||
{
|
||||
if (mEffectOptions.mIterationComposite == aIterationComposite) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAnimation && mAnimation->IsRelevant()) {
|
||||
nsNodeUtils::AnimationChanged(mAnimation);
|
||||
}
|
||||
|
||||
mEffectOptions.mIterationComposite = aIterationComposite;
|
||||
RequestRestyle(EffectCompositor::RestyleType::Layer);
|
||||
}
|
||||
|
||||
void
|
||||
KeyframeEffect::SetSpacing(JSContext* aCx,
|
||||
const nsAString& aSpacing,
|
||||
|
@ -67,6 +67,8 @@ public:
|
||||
void SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget);
|
||||
|
||||
void SetSpacing(JSContext* aCx, const nsAString& aSpacing, ErrorResult& aRv);
|
||||
void SetIterationComposite(
|
||||
const IterationCompositeOperation& aIterationComposite);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -9,6 +9,11 @@
|
||||
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsString.h"
|
||||
// X11 has a #define for None
|
||||
#ifdef None
|
||||
#undef None
|
||||
#endif
|
||||
#include "mozilla/dom/KeyframeEffectBinding.h" // IterationCompositeOperation
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -51,8 +56,9 @@ struct KeyframeEffectParams
|
||||
nsAString& aInvalidPacedProperty,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// FIXME: Bug 1216843: Add IterationCompositeOperations and
|
||||
// Bug 1216844: Add CompositeOperation
|
||||
dom::IterationCompositeOperation mIterationComposite =
|
||||
dom::IterationCompositeOperation::Replace;
|
||||
// FIXME: Bug 1216844: Add CompositeOperation
|
||||
SpacingMode mSpacingMode = SpacingMode::distribute;
|
||||
nsCSSPropertyID mPacedProperty = eCSSProperty_UNKNOWN;
|
||||
};
|
||||
|
@ -77,7 +77,7 @@ KeyframeEffectReadOnly::WrapObject(JSContext* aCx,
|
||||
IterationCompositeOperation
|
||||
KeyframeEffectReadOnly::IterationComposite() const
|
||||
{
|
||||
return IterationCompositeOperation::Replace;
|
||||
return mEffectOptions.mIterationComposite;
|
||||
}
|
||||
|
||||
CompositeOperation
|
||||
@ -373,12 +373,42 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
aStyleRule = new AnimValuesStyleRule();
|
||||
}
|
||||
|
||||
StyleAnimationValue fromValue = segment->mFromValue;
|
||||
StyleAnimationValue toValue = segment->mToValue;
|
||||
// Iteration composition for accumulate
|
||||
if (mEffectOptions.mIterationComposite ==
|
||||
IterationCompositeOperation::Accumulate &&
|
||||
computedTiming.mCurrentIteration > 0) {
|
||||
const AnimationPropertySegment& lastSegment =
|
||||
prop.mSegments.LastElement();
|
||||
// FIXME: Bug 1293492: Add a utility function to calculate both of
|
||||
// below StyleAnimationValues.
|
||||
DebugOnly<bool> accumulateResult =
|
||||
StyleAnimationValue::Accumulate(prop.mProperty,
|
||||
fromValue,
|
||||
lastSegment.mToValue,
|
||||
computedTiming.mCurrentIteration);
|
||||
// We can't check the accumulation result in case of filter property.
|
||||
// That's because some filter property can't accumulate,
|
||||
// e.g. 'contrast(2) brightness(2)' onto 'brightness(1) contrast(1)'
|
||||
// because of mismatch of the order.
|
||||
MOZ_ASSERT(accumulateResult || prop.mProperty == eCSSProperty_filter,
|
||||
"could not accumulate value");
|
||||
accumulateResult =
|
||||
StyleAnimationValue::Accumulate(prop.mProperty,
|
||||
toValue,
|
||||
lastSegment.mToValue,
|
||||
computedTiming.mCurrentIteration);
|
||||
MOZ_ASSERT(accumulateResult || prop.mProperty == eCSSProperty_filter,
|
||||
"could not accumulate value");
|
||||
}
|
||||
|
||||
// Special handling for zero-length segments
|
||||
if (segment->mToKey == segment->mFromKey) {
|
||||
if (computedTiming.mProgress.Value() < 0) {
|
||||
aStyleRule->AddValue(prop.mProperty, segment->mFromValue);
|
||||
aStyleRule->AddValue(prop.mProperty, Move(fromValue));
|
||||
} else {
|
||||
aStyleRule->AddValue(prop.mProperty, segment->mToValue);
|
||||
aStyleRule->AddValue(prop.mProperty, Move(toValue));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -394,14 +424,14 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
|
||||
StyleAnimationValue val;
|
||||
if (StyleAnimationValue::Interpolate(prop.mProperty,
|
||||
segment->mFromValue,
|
||||
segment->mToValue,
|
||||
fromValue,
|
||||
toValue,
|
||||
valuePosition, val)) {
|
||||
aStyleRule->AddValue(prop.mProperty, Move(val));
|
||||
} else if (valuePosition < 0.5) {
|
||||
aStyleRule->AddValue(prop.mProperty, segment->mFromValue);
|
||||
aStyleRule->AddValue(prop.mProperty, Move(fromValue));
|
||||
} else {
|
||||
aStyleRule->AddValue(prop.mProperty, segment->mToValue);
|
||||
aStyleRule->AddValue(prop.mProperty, Move(toValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -482,6 +512,7 @@ KeyframeEffectParamsFromUnion(const OptionsType& aOptions,
|
||||
result.mPacedProperty,
|
||||
aInvalidPacedProperty,
|
||||
aRv);
|
||||
result.mIterationComposite = options.mIterationComposite;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -69,8 +69,7 @@ partial interface KeyframeEffectReadOnly {
|
||||
optional (unrestricted double or KeyframeEffectOptions) options)]
|
||||
interface KeyframeEffect : KeyframeEffectReadOnly {
|
||||
inherit attribute (Element or CSSPseudoElement)? target;
|
||||
// Bug 1216843 - implement animation composition
|
||||
// inherit attribute IterationCompositeOperation iterationComposite;
|
||||
inherit attribute IterationCompositeOperation iterationComposite;
|
||||
// Bug 1216844 - implement additive animation
|
||||
// inherit attribute CompositeOperation composite;
|
||||
[SetterThrows]
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "mozilla/WidgetUtils.h" // for ComputeTransformForRotation
|
||||
#include "mozilla/dom/KeyframeEffectReadOnly.h"
|
||||
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for dom::FillMode
|
||||
#include "mozilla/dom/KeyframeEffectBinding.h" // for dom::IterationComposite
|
||||
#include "mozilla/gfx/BaseRect.h" // for BaseRect
|
||||
#include "mozilla/gfx/Point.h" // for RoundedToInt, PointTyped
|
||||
#include "mozilla/gfx/Rect.h" // for RoundedToInt, RectTyped
|
||||
@ -553,18 +554,45 @@ AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aTransformedSubtreeRoo
|
||||
}
|
||||
|
||||
static void
|
||||
SampleValue(float aPortion, Animation& aAnimation, StyleAnimationValue& aStart,
|
||||
StyleAnimationValue& aEnd, Animatable* aValue, Layer* aLayer)
|
||||
SampleValue(float aPortion, Animation& aAnimation,
|
||||
const StyleAnimationValue& aStart, const StyleAnimationValue& aEnd,
|
||||
const StyleAnimationValue& aLastValue, uint64_t aCurrentIteration,
|
||||
Animatable* aValue, Layer* aLayer)
|
||||
{
|
||||
StyleAnimationValue interpolatedValue;
|
||||
NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
|
||||
aStart.GetUnit() == StyleAnimationValue::eUnit_None ||
|
||||
aEnd.GetUnit() == StyleAnimationValue::eUnit_None,
|
||||
"Must have same unit");
|
||||
|
||||
StyleAnimationValue startValue = aStart;
|
||||
StyleAnimationValue endValue = aEnd;
|
||||
// Iteration composition for accumulate
|
||||
if (static_cast<dom::IterationCompositeOperation>
|
||||
(aAnimation.iterationComposite()) ==
|
||||
dom::IterationCompositeOperation::Accumulate &&
|
||||
aCurrentIteration > 0) {
|
||||
// FIXME: Bug 1293492: Add a utility function to calculate both of
|
||||
// below StyleAnimationValues.
|
||||
DebugOnly<bool> accumulateResult =
|
||||
StyleAnimationValue::Accumulate(aAnimation.property(),
|
||||
startValue,
|
||||
aLastValue,
|
||||
aCurrentIteration);
|
||||
MOZ_ASSERT(accumulateResult, "could not accumulate value");
|
||||
accumulateResult =
|
||||
StyleAnimationValue::Accumulate(aAnimation.property(),
|
||||
endValue,
|
||||
aLastValue,
|
||||
aCurrentIteration);
|
||||
MOZ_ASSERT(accumulateResult, "could not accumulate value");
|
||||
}
|
||||
|
||||
StyleAnimationValue interpolatedValue;
|
||||
// This should never fail because we only pass transform and opacity values
|
||||
// to the compositor and they should never fail to interpolate.
|
||||
DebugOnly<bool> uncomputeResult =
|
||||
StyleAnimationValue::Interpolate(aAnimation.property(), aStart, aEnd,
|
||||
StyleAnimationValue::Interpolate(aAnimation.property(),
|
||||
startValue, endValue,
|
||||
aPortion, interpolatedValue);
|
||||
MOZ_ASSERT(uncomputeResult, "could not uncompute value");
|
||||
|
||||
@ -683,8 +711,12 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint)
|
||||
|
||||
// interpolate the property
|
||||
Animatable interpolatedValue;
|
||||
SampleValue(portion, animation, animData.mStartValues[segmentIndex],
|
||||
animData.mEndValues[segmentIndex], &interpolatedValue, layer);
|
||||
SampleValue(portion, animation,
|
||||
animData.mStartValues[segmentIndex],
|
||||
animData.mEndValues[segmentIndex],
|
||||
animData.mEndValues.LastElement(),
|
||||
computedTiming.mCurrentIteration,
|
||||
&interpolatedValue, layer);
|
||||
LayerComposite* layerComposite = layer->AsLayerComposite();
|
||||
switch (animation.property()) {
|
||||
case eCSSProperty_opacity:
|
||||
|
@ -204,6 +204,7 @@ struct Animation {
|
||||
float playbackRate;
|
||||
// This is used in the transformed progress calculation.
|
||||
TimingFunction easingFunction;
|
||||
uint8_t iterationComposite;
|
||||
};
|
||||
|
||||
// Change a layer's attributes
|
||||
|
@ -430,6 +430,9 @@ AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty,
|
||||
animation->playbackRate() = aAnimation->PlaybackRate();
|
||||
animation->data() = aData;
|
||||
animation->easingFunction() = ToTimingFunction(timing.mFunction);
|
||||
animation->iterationComposite() =
|
||||
static_cast<uint8_t>(aAnimation->GetEffect()->
|
||||
AsKeyframeEffect()->IterationComposite());
|
||||
|
||||
for (uint32_t segIdx = 0; segIdx < aProperty.mSegments.Length(); segIdx++) {
|
||||
const AnimationPropertySegment& segment = aProperty.mSegments[segIdx];
|
||||
|
@ -2801,6 +2801,26 @@ StyleAnimationValue::AddWeighted(nsCSSPropertyID aProperty,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
StyleAnimationValue::Accumulate(nsCSSPropertyID aProperty,
|
||||
StyleAnimationValue& aDest,
|
||||
const StyleAnimationValue& aValueToAccumulate,
|
||||
uint64_t aCount)
|
||||
{
|
||||
Unit commonUnit =
|
||||
GetCommonUnit(aProperty, aDest.GetUnit(), aValueToAccumulate.GetUnit());
|
||||
switch (commonUnit) {
|
||||
// FIXME: implement them!
|
||||
//case eUnit_Color:
|
||||
//case eUnit_Shadow:
|
||||
//case eUnit_Filter:
|
||||
default:
|
||||
return Add(aProperty, aDest, aValueToAccumulate, aCount);
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Can't accumulate using the given common unit");
|
||||
return false;
|
||||
}
|
||||
|
||||
already_AddRefed<css::StyleRule>
|
||||
BuildStyleRule(nsCSSPropertyID aProperty,
|
||||
dom::Element* aTargetElement,
|
||||
|
@ -129,6 +129,27 @@ public:
|
||||
double aCoeff2, const StyleAnimationValue& aValue2,
|
||||
StyleAnimationValue& aResultValue);
|
||||
|
||||
/**
|
||||
* Accumulates |aValueToAccumulate| onto |aDest| |aCount| times.
|
||||
* The result is stored in |aDest| on success.
|
||||
*
|
||||
* @param aDest The base value to be accumulated.
|
||||
* @param aValueToAccumulate The value to accumulate.
|
||||
* @param aCount The number of times to accumulate
|
||||
* aValueToAccumulate.
|
||||
* @return true on success, false on failure.
|
||||
*
|
||||
* NOTE: This function will work as a wrapper of StyleAnimationValue::Add()
|
||||
* if |aProperty| isn't color or shadow or filter. For these properties,
|
||||
* this function may return a color value that at least one of its components
|
||||
* has a value which is outside the range [0, 1] so that we can calculate
|
||||
* plausible values as interpolation with the return value.
|
||||
*/
|
||||
static MOZ_MUST_USE bool
|
||||
Accumulate(nsCSSPropertyID aProperty, StyleAnimationValue& aDest,
|
||||
const StyleAnimationValue& aValueToAccumulate,
|
||||
uint64_t aCount);
|
||||
|
||||
// Type-conversion methods
|
||||
// -----------------------
|
||||
/**
|
||||
|
@ -1,74 +1,11 @@
|
||||
[iterationComposite.html]
|
||||
type: testharness
|
||||
[iterationComposite of <length> type animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <percentage> type animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <color> type animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <number> type animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <shape> type animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <calc()> value animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of opacity animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of filter blur animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of filter brightness for different unit animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of filter drop-shadow animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of same filter list animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of discrete filter list because of mismatch of the order]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of different length filter list animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of transform: [ scale(1), scale(2) \] animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of transform: scale(2) animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of transform list animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite starts with non-zero value animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite with negative final value animation]
|
||||
expected: FAIL
|
||||
|
||||
[interationComposite changes]
|
||||
expected: FAIL
|
||||
|
||||
[duration changes with iterationComposite(accumulate)]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of box-shadow animation]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <color> type animation that green component is decreasing]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of <calc()> value animation that the values can'tbe reduced]
|
||||
expected: FAIL
|
||||
|
||||
[iterationComposite of transform list animation whose order is mismatched]
|
||||
expected: FAIL
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user