--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -320,38 +320,255 @@ KeyframeEffectReadOnly::UpdateProperties
void
KeyframeEffectReadOnly::UpdateProperties(
const ServoComputedValuesWithParent& aServoValues)
{
DoUpdateProperties(aServoValues);
}
-static void
-PhysicalizeLogicalProperties(nsTArray<AnimationProperty>& aProperties,
- nsStyleContext* aStyleContext)
+static void WritingModeStyles(uint8_t& aWritingMode,
+ uint8_t& aTextOrientation,
+ uint8_t& aDirection,
+ nsStyleContext* aStyleContext)
{
- uint8_t writingMode = aStyleContext->StyleVisibility()->mWritingMode;
- uint8_t textOrientation = aStyleContext->StyleVisibility()->mTextOrientation;
- uint8_t direction = aStyleContext->StyleVisibility()->mDirection;
+ aWritingMode = aStyleContext->StyleVisibility()->mWritingMode;
+ aTextOrientation = aStyleContext->StyleVisibility()->mTextOrientation;
+ aDirection = aStyleContext->StyleVisibility()->mDirection;
+}
+
+static void WritingModeStyles(uint8_t& aWritingMode,
+ uint8_t& aTextOrientation,
+ uint8_t& aDirection,
+ const ServoComputedValuesWithParent& aServoValues)
+{
+ MOZ_ASSERT(false,
+ "WritingModeStyles does not support for stylo yet");
+}
+
+static void
+FindAnimationProperty(const nsCSSPropertyID aProperty,
+ nsTArray<AnimationProperty>& aProperties,
+ AnimationProperty*& aResult)
+{
for (AnimationProperty& property : aProperties) {
- if (nsCSSProps::PropHasFlags(property.mProperty, CSS_PROPERTY_LOGICAL)) {
- property.mProperty =
- nsCSSProps::PhysicalProperty(property.mProperty, writingMode,
- textOrientation, direction);
+ if (property.mProperty == aProperty) {
+ aResult = &property;
+ return;
}
}
}
static void
-PhysicalizeLogicalProperties(nsTArray<AnimationProperty>& aProperties,
- const ServoComputedValuesWithParent& aServoValues)
+HoldLogicalProperties(nsTArray<AnimationProperty>& aProperties,
+ nsTArray<nsCSSPropertyID>& aLogicalProperties)
+{
+ aLogicalProperties.Clear();
+ for (const AnimationProperty& property : aProperties) {
+ if (nsCSSProps::PropHasFlags(property.mProperty, CSS_PROPERTY_LOGICAL)) {
+ aLogicalProperties.AppendElement(property.mProperty);
+ }
+ }
+}
+
+static void GetSegmentAt(const AnimationProperty& aProperty,
+ const ComputedTiming& aComputedTiming,
+ AnimationPropertySegment& aResult)
+{
+ // FIXME: Maybe cache the current segment?
+ const AnimationPropertySegment *segment = aProperty.mSegments.Elements(),
+ *segmentEnd = segment + aProperty.mSegments.Length();
+ while (segment->mToKey <= aComputedTiming.mProgress.Value()) {
+ MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
+ if ((segment+1) == segmentEnd) {
+ break;
+ }
+ ++segment;
+ MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys");
+ }
+
+ MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
+ MOZ_ASSERT(segment >= aProperty.mSegments.Elements() &&
+ size_t(segment - aProperty.mSegments.Elements()) <
+ aProperty.mSegments.Length(),
+ "out of array bounds");
+ aResult = *segment;
+}
+
+void
+KeyframeEffectReadOnly::WritingModeStyleAt(
+ const AnimationProperty& aProp,
+ const ComputedTiming& aComputedTiming,
+ uint8_t& aResult)
+{
+ MOZ_ASSERT(aProp.mProperty == eCSSProperty_writing_mode ||
+ aProp.mProperty == eCSSProperty_text_orientation ||
+ aProp.mProperty == eCSSProperty_direction,
+ "aProp.mProperty should be writing-mode or "
+ "text-orientation or direction");
+
+ AnimationPropertySegment segment;
+ GetSegmentAt(aProp, aComputedTiming, segment);
+ StyleAnimationValue value;
+ CalculateAnimationValue(nullptr, aProp, segment, aComputedTiming, value);
+ aResult = value.GetCSSValueValue()->GetIntValue();
+}
+
+void
+KeyframeEffectReadOnly::WritingModeStylesAt(
+ const ComputedTiming& aComputedTiming,
+ uint8_t& aWritingMode,
+ uint8_t& aTextOrientation,
+ uint8_t& aDirection)
+{
+ aWritingMode = mCurrentWritingMode;
+ aTextOrientation = mCurrentTextOrientation;
+ aDirection = mCurrentDirection;
+ for (const AnimationProperty& prop : mProperties) {
+ if (prop.mProperty == eCSSProperty_writing_mode) {
+ WritingModeStyleAt(prop, aComputedTiming, aWritingMode);
+ } else if (prop.mProperty == eCSSProperty_text_orientation) {
+ WritingModeStyleAt(prop, aComputedTiming, aTextOrientation);
+ } else if (prop.mProperty == eCSSProperty_direction) {
+ WritingModeStyleAt(prop, aComputedTiming, aDirection);
+ }
+ }
+}
+
+nsCSSPropertyID
+KeyframeEffectReadOnly::PhysicalPropertyAt(
+ const nsCSSPropertyID aLogicalProperty,
+ const ComputedTiming& aComputedTiming)
+{
+ MOZ_ASSERT(nsCSSProps::PropHasFlags(aLogicalProperty, CSS_PROPERTY_LOGICAL),
+ "aLogicalProperty should be a logical longhand property");
+ uint8_t writingMode, textOrientation, direction;
+ WritingModeStylesAt(aComputedTiming, writingMode, textOrientation, direction);
+ return nsCSSProps::PhysicalProperty(aLogicalProperty, writingMode,
+ textOrientation, direction);
+}
+
+void
+KeyframeEffectReadOnly::CalculateAnimationValue(
+ const RefPtr<AnimValuesStyleRule> aStyleRule,
+ const AnimationProperty& aProperty,
+ const AnimationPropertySegment& aSegment,
+ const ComputedTiming& aComputedTiming,
+ StyleAnimationValue& aResult)
{
- MOZ_ASSERT(false,
- "PhysicalizeLogicalProperties does not support for stylo yet");
+ StyleAnimationValue fromValue =
+ CompositeValue(aProperty.mProperty, aStyleRule,
+ aSegment.mFromValue.mGecko,
+ aSegment.mFromComposite);
+ StyleAnimationValue toValue =
+ CompositeValue(aProperty.mProperty, aStyleRule,
+ aSegment.mToValue.mGecko,
+ aSegment.mToComposite);
+ if (fromValue.IsNull() || toValue.IsNull()) {
+ return;
+ }
+
+ // Iteration composition for accumulate
+ if (mEffectOptions.mIterationComposite ==
+ IterationCompositeOperation::Accumulate &&
+ aComputedTiming.mCurrentIteration > 0) {
+ const AnimationPropertySegment& lastSegment =
+ aProperty.mSegments.LastElement();
+ // FIXME: Bug 1293492: Add a utility function to calculate both of
+ // below StyleAnimationValues.
+ StyleAnimationValue lastValue = lastSegment.mToValue.mGecko.IsNull()
+ ? GetUnderlyingStyle(aProperty.mProperty, aStyleRule)
+ : lastSegment.mToValue.mGecko;
+ fromValue =
+ StyleAnimationValue::Accumulate(aProperty.mProperty,
+ lastValue,
+ Move(fromValue),
+ aComputedTiming.mCurrentIteration);
+ toValue =
+ StyleAnimationValue::Accumulate(aProperty.mProperty,
+ lastValue,
+ Move(toValue),
+ aComputedTiming.mCurrentIteration);
+ }
+
+ // Special handling for zero-length segments
+ if (aSegment.mToKey == aSegment.mFromKey) {
+ aResult =
+ aComputedTiming.mProgress.Value() < 0 ? Move(fromValue) : Move(toValue);
+ return;
+ }
+
+ double positionInSegment =
+ (aComputedTiming.mProgress.Value() - aSegment.mFromKey) /
+ (aSegment.mToKey - aSegment.mFromKey);
+ double valuePosition =
+ ComputedTimingFunction::GetPortion(aSegment.mTimingFunction,
+ positionInSegment,
+ aComputedTiming.mBeforeFlag);
+
+ MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
+
+ if (!StyleAnimationValue::Interpolate(aProperty.mProperty,
+ fromValue, toValue,
+ valuePosition, aResult)) {
+ aResult = valuePosition < 0.5 ? Move(fromValue) : Move(toValue);
+ }
+}
+
+void
+KeyframeEffectReadOnly::UpdateLogicalProperties(
+ nsTArray<AnimationProperty>& aProperties)
+{
+ ComputedTiming computedTiming = GetComputedTiming();
+ uint8_t currentWritingMode, currentTextOrientation, currentDirection;
+ WritingModeStylesAt(computedTiming, currentWritingMode,
+ currentTextOrientation, currentDirection);
+
+ for (const nsCSSPropertyID logicalID : mLogicalProperties) {
+ AnimationProperty* currentProperty = nullptr;
+ FindAnimationProperty(logicalID, aProperties, currentProperty);
+ if (!currentProperty) {
+ nsCSSPropertyID previousID =
+ nsCSSProps::PhysicalProperty(logicalID,
+ mCurrentWritingMode,
+ mCurrentTextOrientation,
+ mCurrentDirection);
+ FindAnimationProperty(previousID, aProperties, currentProperty);
+ }
+ MOZ_ASSERT(currentProperty, "currentProperty should exist in aProperties");
+
+ currentProperty->mProperty =
+ nsCSSProps::PhysicalProperty(logicalID,
+ mCurrentWritingMode,
+ mCurrentTextOrientation,
+ mCurrentDirection);
+ for (AnimationPropertySegment& segment : currentProperty->mSegments) {
+ ComputedTiming timing(computedTiming);
+ timing.mProgress.SetValue(segment.mFromKey);
+ nsCSSPropertyID fromID =
+ PhysicalPropertyAt(logicalID, timing);
+
+ timing.mProgress.SetValue(segment.mToKey);
+ nsCSSPropertyID toID =
+ PhysicalPropertyAt(logicalID, timing);
+
+ if (fromID != currentProperty->mProperty) {
+ AnimationValue neutral;
+ segment.mFromValue = neutral;
+ }
+ if (toID != currentProperty->mProperty) {
+ AnimationValue neutral;
+ segment.mToValue = neutral;
+ }
+ }
+ }
+
+ mCurrentWritingMode = currentWritingMode;
+ mCurrentTextOrientation = currentTextOrientation;
+ mCurrentDirection = currentDirection;
}
template<typename StyleType>
void
KeyframeEffectReadOnly::DoUpdateProperties(StyleType&& aStyle)
{
MOZ_ASSERT_IF(IsPointer<StyleType>::value, aStyle);
@@ -362,17 +579,20 @@ KeyframeEffectReadOnly::DoUpdateProperti
"Should not be called while processing ComposeStyle()");
if (mIsComposingStyle) {
return;
}
nsTArray<AnimationProperty> properties =
BuildProperties(Forward<StyleType>(aStyle));
- PhysicalizeLogicalProperties(properties, aStyle);
+ HoldLogicalProperties(properties, mLogicalProperties);
+ WritingModeStyles(mCurrentWritingMode, mCurrentTextOrientation,
+ mCurrentDirection, aStyle);
+ UpdateLogicalProperties(properties);
// We need to update base styles even if any properties are not changed at all
// since base styles might have been changed due to parent style changes, etc.
EnsureBaseStyles(aStyle, properties);
if (mProperties == properties) {
return;
}
@@ -525,16 +745,33 @@ KeyframeEffectReadOnly::EnsureBaseStyle(
DebugOnly<bool> success =
StyleAnimationValue::ExtractComputedValue(aProperty,
aCachedBaseStyleContext,
result);
MOZ_ASSERT(success, "Should be able to extract computed animation value");
MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue");
+ // Special handling for writnig-mode, text-orientation and direction.
+ // We need valid value for those to calculate logical properties.
+ // However, ExtractComputedValue might return 'unset' value,
+ // if the keyframe is misisng.
+ // Therefor, get and set the valid value from nsStyleContext directory.
+ if (aProperty == eCSSProperty_writing_mode) {
+ uint8_t value = aCachedBaseStyleContext->StyleVisibility()->mWritingMode;
+ result.GetCSSValueValue()->SetIntValue(value, eCSSUnit_Enumerated);
+ } else if (aProperty == eCSSProperty_text_orientation) {
+ uint8_t value =
+ aCachedBaseStyleContext->StyleVisibility()->mTextOrientation;
+ result.GetCSSValueValue()->SetIntValue(value, eCSSUnit_Enumerated);
+ } else if (aProperty == eCSSProperty_direction) {
+ uint8_t value = aCachedBaseStyleContext->StyleVisibility()->mDirection;
+ result.GetCSSValueValue()->SetIntValue(value, eCSSUnit_Enumerated);
+ }
+
mBaseStyleValues.Put(aProperty, result);
}
void
KeyframeEffectReadOnly::EnsureBaseStyles(
const ServoComputedValuesWithParent& aServoValues,
const nsTArray<AnimationProperty>& aProperties)
{
@@ -595,96 +832,53 @@ KeyframeEffectReadOnly::EnsureBaseStyle(
}
void
KeyframeEffectReadOnly::WillComposeStyle()
{
ComputedTiming computedTiming = GetComputedTiming();
mProgressOnLastCompose = computedTiming.mProgress;
mCurrentIterationOnLastCompose = computedTiming.mCurrentIteration;
+
+ if (mLogicalProperties.IsEmpty()) {
+ return;
+ }
+
+ uint8_t currentWritingMode, currentTextOrientation, currentDirection;
+ WritingModeStylesAt(computedTiming, currentWritingMode,
+ currentTextOrientation, currentDirection);
+ if (mCurrentWritingMode == currentWritingMode &&
+ mCurrentTextOrientation == currentTextOrientation &&
+ mCurrentDirection == currentDirection) {
+ return;
+ }
+
+ UpdateLogicalProperties(mProperties);
}
void
KeyframeEffectReadOnly::ComposeStyleRule(
RefPtr<AnimValuesStyleRule>& aStyleRule,
const AnimationProperty& aProperty,
const AnimationPropertySegment& aSegment,
const ComputedTiming& aComputedTiming)
{
- StyleAnimationValue fromValue =
- CompositeValue(aProperty.mProperty, aStyleRule,
- aSegment.mFromValue.mGecko,
- aSegment.mFromComposite);
- StyleAnimationValue toValue =
- CompositeValue(aProperty.mProperty, aStyleRule,
- aSegment.mToValue.mGecko,
- aSegment.mToComposite);
- if (fromValue.IsNull() || toValue.IsNull()) {
+ StyleAnimationValue animationValue;
+ CalculateAnimationValue(aStyleRule, aProperty, aSegment,
+ aComputedTiming, animationValue);
+
+ if (animationValue.IsNull()) {
return;
}
if (!aStyleRule) {
// Allocate the style rule now that we know we have animation data.
aStyleRule = new AnimValuesStyleRule();
}
-
- // Iteration composition for accumulate
- if (mEffectOptions.mIterationComposite ==
- IterationCompositeOperation::Accumulate &&
- aComputedTiming.mCurrentIteration > 0) {
- const AnimationPropertySegment& lastSegment =
- aProperty.mSegments.LastElement();
- // FIXME: Bug 1293492: Add a utility function to calculate both of
- // below StyleAnimationValues.
- StyleAnimationValue lastValue = lastSegment.mToValue.mGecko.IsNull()
- ? GetUnderlyingStyle(aProperty.mProperty, aStyleRule)
- : lastSegment.mToValue.mGecko;
- fromValue =
- StyleAnimationValue::Accumulate(aProperty.mProperty,
- lastValue,
- Move(fromValue),
- aComputedTiming.mCurrentIteration);
- toValue =
- StyleAnimationValue::Accumulate(aProperty.mProperty,
- lastValue,
- Move(toValue),
- aComputedTiming.mCurrentIteration);
- }
-
- // Special handling for zero-length segments
- if (aSegment.mToKey == aSegment.mFromKey) {
- if (aComputedTiming.mProgress.Value() < 0) {
- aStyleRule->AddValue(aProperty.mProperty, Move(fromValue));
- } else {
- aStyleRule->AddValue(aProperty.mProperty, Move(toValue));
- }
- return;
- }
-
- double positionInSegment =
- (aComputedTiming.mProgress.Value() - aSegment.mFromKey) /
- (aSegment.mToKey - aSegment.mFromKey);
- double valuePosition =
- ComputedTimingFunction::GetPortion(aSegment.mTimingFunction,
- positionInSegment,
- aComputedTiming.mBeforeFlag);
-
- MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
-
- StyleAnimationValue val;
- if (StyleAnimationValue::Interpolate(aProperty.mProperty,
- fromValue,
- toValue,
- valuePosition, val)) {
- aStyleRule->AddValue(aProperty.mProperty, Move(val));
- } else if (valuePosition < 0.5) {
- aStyleRule->AddValue(aProperty.mProperty, Move(fromValue));
- } else {
- aStyleRule->AddValue(aProperty.mProperty, Move(toValue));
- }
+ aStyleRule->AddValue(aProperty.mProperty, Move(animationValue));
}
// Bug 1333311 - We use two branches for Gecko and Stylo. However, it's
// better to remove the duplicated code.
void
KeyframeEffectReadOnly::ComposeStyleRule(
const RawServoAnimationValueMap& aAnimationValues,
const AnimationProperty& aProperty,