Skip to content

Commit

Permalink
Add support for the animation-composition property.
Browse files Browse the repository at this point in the history
Implement animation-composition property, previously exclusively
accessed via Web Animations API.

Fixed: 1342699
Change-Id: I3457bdd1a6dac9d9a3783cd8f462e2782d1acd30
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4181161
Reviewed-by: Kevin Ellis <kevers@chromium.org>
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Daniil Sakhapov <sakhapov@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1095559}
  • Loading branch information
danielsakhapov authored and Chromium LUCI CQ committed Jan 23, 2023
1 parent 6e4bb3f commit 28bd6a1
Show file tree
Hide file tree
Showing 28 changed files with 256 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,7 @@ enum CSSSampleId {
kAnimationRange = 740,
kAnimationRangeStart = 741,
kAnimationRangeEnd = 742,
kAnimationComposition = 743,
// 1. Add new features above this line (don't change the assigned numbers of
// the existing items).
// 2. Run the src/tools/metrics/histograms/update_use_counter_css.py script
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CSSAnimationData::CSSAnimationData() {
direction_list_.push_back(InitialDirection());
fill_mode_list_.push_back(InitialFillMode());
play_state_list_.push_back(InitialPlayState());
composition_list_.push_back(InitialComposition());
}

CSSAnimationData::CSSAnimationData(const CSSAnimationData& other) = default;
Expand Down
19 changes: 19 additions & 0 deletions third_party/blink/renderer/core/animation/css/css_animation_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/animation/css/css_timing_data.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/style/style_name_or_keyword.h"
Expand Down Expand Up @@ -48,13 +49,27 @@ class CORE_EXPORT CSSAnimationData final : public CSSTimingData {
const Vector<EAnimPlayState>& PlayStateList() const {
return play_state_list_;
}
const Vector<EffectModel::CompositeOperation>& CompositionList() const {
return composition_list_;
}

EffectModel::CompositeOperation GetComposition(size_t animation_index) const {
if (!composition_list_.size()) {
return EffectModel::kCompositeReplace;
}
wtf_size_t index = animation_index % composition_list_.size();
return composition_list_[index];
}

Vector<AtomicString>& NameList() { return name_list_; }
Vector<StyleTimeline>& TimelineList() { return timeline_list_; }
Vector<double>& IterationCountList() { return iteration_count_list_; }
Vector<Timing::PlaybackDirection>& DirectionList() { return direction_list_; }
Vector<Timing::FillMode>& FillModeList() { return fill_mode_list_; }
Vector<EAnimPlayState>& PlayStateList() { return play_state_list_; }
Vector<EffectModel::CompositeOperation>& CompositionList() {
return composition_list_;
}

static const AtomicString& InitialName();
static const StyleTimeline& InitialTimeline();
Expand All @@ -64,6 +79,9 @@ class CORE_EXPORT CSSAnimationData final : public CSSTimingData {
static Timing::FillMode InitialFillMode() { return Timing::FillMode::NONE; }
static double InitialIterationCount() { return 1.0; }
static EAnimPlayState InitialPlayState() { return EAnimPlayState::kPlaying; }
static EffectModel::CompositeOperation InitialComposition() {
return EffectModel::CompositeOperation::kCompositeReplace;
}

private:
Vector<AtomicString> name_list_;
Expand All @@ -72,6 +90,7 @@ class CORE_EXPORT CSSAnimationData final : public CSSTimingData {
Vector<Timing::PlaybackDirection> direction_list_;
Vector<Timing::FillMode> fill_mode_list_;
Vector<EAnimPlayState> play_state_list_;
Vector<EffectModel::CompositeOperation> composition_list_;
};

} // namespace blink
Expand Down
117 changes: 85 additions & 32 deletions third_party/blink/renderer/core/animation/css/css_animations.cc

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions third_party/blink/renderer/core/animation/keyframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,8 @@ class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
void SetComposite(EffectModel::CompositeOperation composite) {
composite_ = composite;
}
bool HasComposite() const { return composite_.has_value(); }
EffectModel::CompositeOperation Composite() const {
return composite_.value();
absl::optional<EffectModel::CompositeOperation> Composite() const {
return composite_;
}

void SetEasing(scoped_refptr<TimingFunction> easing) {
Expand Down
16 changes: 16 additions & 0 deletions third_party/blink/renderer/core/css/css_properties.json5
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,22 @@
// Properties with StyleBuilder handling

// Animation Priority properties
{
name: "animation-composition",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "InitialValue"],
keywords: ["replace", "add", "accumulate"],
style_builder_template: "animation",
style_builder_template_args: {
attribute: "Composition",
},
typedom_types: ["Keyword"],
separator: ",",
include_paths: ["third_party/blink/renderer/core/animation/effect_model.h"],
default_value: "EffectModel::kCompositeReplace",
type_name: "EffectModel::CompositeOperation",
valid_for_marker: true,
runtime_flag: "CSSAnimationComposition"
},
{
name: "animation-delay",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "InitialValue"],
Expand Down
30 changes: 30 additions & 0 deletions third_party/blink/renderer/core/css/css_value_id_mappings.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_VALUE_ID_MAPPINGS_H_

#include "base/notreached.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/css/css_value_id_mappings_generated.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"

Expand Down Expand Up @@ -70,6 +71,35 @@ inline ETextAlign CssValueIDToPlatformEnum(CSSValueID v) {
return detail::cssValueIDToPlatformEnumGenerated<ETextAlign>(v);
}

template <>
inline CSSValueID PlatformEnumToCSSValueID(EffectModel::CompositeOperation v) {
switch (v) {
case EffectModel::kCompositeReplace:
return CSSValueID::kReplace;
case EffectModel::kCompositeAdd:
return CSSValueID::kAdd;
case EffectModel::kCompositeAccumulate:
return CSSValueID::kAccumulate;
}
NOTREACHED();
return CSSValueID::kReplace;
}

template <>
inline EffectModel::CompositeOperation CssValueIDToPlatformEnum(CSSValueID v) {
switch (v) {
case CSSValueID::kReplace:
return EffectModel::kCompositeReplace;
case CSSValueID::kAdd:
return EffectModel::kCompositeAdd;
case CSSValueID::kAccumulate:
return EffectModel::kCompositeAccumulate;
default:
NOTREACHED();
return EffectModel::kCompositeReplace;
}
}

template <>
inline ETextOrientation CssValueIDToPlatformEnum(CSSValueID v) {
if (v == CSSValueID::kSidewaysRight) { // Legacy -webkit-auto. Eqiuvalent to
Expand Down
6 changes: 6 additions & 0 deletions third_party/blink/renderer/core/css/css_value_keywords.json5
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,12 @@
"logical",
"visual",

//
// animation-composition
//
"replace",
"accumulate",

//
// animation-direction
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,39 @@ const CSSValue* AnchorScroll::CSSValueFromComputedStyleInternal(
style.AnchorScroll()->GetName().GetName());
}

const CSSValue* AnimationComposition::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext&) const {
DCHECK(RuntimeEnabledFeatures::CSSAnimationCompositionEnabled());
return css_parsing_utils::ConsumeCommaSeparatedList(
css_parsing_utils::ConsumeIdent<CSSValueID::kReplace, CSSValueID::kAdd,
CSSValueID::kAccumulate>,
range);
}

const CSSValue* AnimationComposition::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const LayoutObject*,
bool allow_visited_style) const {
DCHECK(RuntimeEnabledFeatures::CSSAnimationCompositionEnabled());
if (!style.Animations()) {
return InitialValue();
}
CSSValueList* list = CSSValueList::CreateCommaSeparated();
const auto& composition_list = style.Animations()->CompositionList();
for (const auto& composition : composition_list) {
list->Append(*CSSIdentifierValue::Create(composition));
}
return list;
}

const CSSValue* AnimationComposition::InitialValue() const {
CSSValueList* list = CSSValueList::CreateCommaSeparated();
list->Append(*CSSIdentifierValue::Create(CSSValueID::kReplace));
return list;
}

const CSSValue* AnimationDelay::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
Expand Down
15 changes: 15 additions & 0 deletions third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/css/resolver/css_to_style_map.h"

#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/css/css_border_image_slice_value.h"
#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
Expand Down Expand Up @@ -508,6 +509,20 @@ absl::optional<Timing::TimelineOffset> CSSToStyleMap::MapAnimationRangeEnd(
return MapAnimationRange(value);
}

EffectModel::CompositeOperation CSSToStyleMap::MapAnimationComposition(
StyleResolverState& state,
const CSSValue& value) {
switch (To<CSSIdentifierValue>(value).GetValueID()) {
case CSSValueID::kAdd:
return EffectModel::kCompositeAdd;
case CSSValueID::kAccumulate:
return EffectModel::kCompositeAccumulate;
case CSSValueID::kReplace:
default:
return EffectModel::kCompositeReplace;
}
}

CSSTransitionData::TransitionProperty CSSToStyleMap::MapAnimationProperty(
StyleResolverState& state,
const CSSValue& value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ class CSSToStyleMap {
static absl::optional<Timing::TimelineOffset> MapAnimationRangeEnd(
StyleResolverState&,
const CSSValue&);
static EffectModel::CompositeOperation MapAnimationComposition(
StyleResolverState&,
const CSSValue&);
static CSSTransitionData::TransitionProperty MapAnimationProperty(
StyleResolverState&,
const CSSValue&);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,10 @@
implied_by: ["HTMLSelectMenuElement"],
status: "experimental",
},
{
name: "CSSAnimationComposition",
status: "experimental"
},
{
// Whether <image> values are allowed as counter style <symbol>
name: "CSSAtRuleCounterStyleImageSymbols",
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ PASS KeyframeEffect.getKeyframes() returns frames with expected easing values, w
PASS KeyframeEffect.getKeyframes() returns frames with expected easing values, when the easing is specified on each keyframe
PASS KeyframeEffect.getKeyframes() returns frames with expected easing values, when the easing is specified on some keyframes
PASS KeyframeEffect.getKeyframes() returns frames with expected composite values, when the composite is set on the effect using animation-composition on the element
FAIL KeyframeEffect.getKeyframes() returns frames with expected composite values, when the composite is specified on each keyframe assert_equals: value of 'composite' on ComputedKeyframe #0 expected "replace" but got "auto"
FAIL KeyframeEffect.getKeyframes() returns frames with expected composite values, when the composite is specified on some keyframes assert_equals: value of 'composite' on ComputedKeyframe #0 expected "add" but got "auto"
PASS KeyframeEffect.getKeyframes() returns frames with expected composite values, when the composite is specified on each keyframe
PASS KeyframeEffect.getKeyframes() returns frames with expected composite values, when the composite is specified on some keyframes
PASS KeyframeEffect.getKeyframes() returns expected frames for a simple animation that specifies a single shorthand property
PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with a 0% keyframe and no 100% keyframe
PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with a 100% keyframe and no 0% keyframe
Expand All @@ -17,8 +17,8 @@ PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with
PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time, and all with the same easing function
PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different easing functions
PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different but equivalent easing functions
FAIL KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different composite operations assert_equals: Number of keyframes should match expected 3 but got 2
FAIL KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different easing functions and composite operations assert_equals: Number of keyframes should match expected 4 but got 3
PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different composite operations
FAIL KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different easing functions and composite operations assert_array_equals: properties on Keyframe #1 should match lengths differ, expected array ["composite", "computedOffset", "easing", "marginTop", "offset", "paddingLeft"] length 6, got ["composite", "computedOffset", "easing", "fontSize", "offset"] length 5
PASS KeyframeEffect.getKeyframes() returns expected frames for overlapping keyframes
FAIL KeyframeEffect.getKeyframes() returns expected values for animations with filter properties and missing keyframes assert_equals: value for 'filter' on Keyframe #1 should match expected "blur(5px) sepia(60%) saturate(30%)" but got "blur(5px) sepia(0.6) saturate(0.3)"
PASS KeyframeEffect.getKeyframes() returns expected values for animation with drop-shadow of filter property
Expand Down

0 comments on commit 28bd6a1

Please sign in to comment.