Skip to content

Commit

Permalink
Add view-timeline-inset to view-timeline shorthand
Browse files Browse the repository at this point in the history
Per recent spec update [1].

[1] w3c/csswg-drafts#9189

Fixed: 1469850
I2S: https://groups.google.com/a/chromium.org/g/blink-dev/c/yjfaImiMaXE/m/4LKuoM4SAQAJ
Change-Id: If4011ef0b3dd0bee8737626e41a6c2c5342cb025
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4798148
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1188194}
  • Loading branch information
andruud authored and Chromium LUCI CQ committed Aug 25, 2023
1 parent 3d665ed commit 4245aa6
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 25 deletions.
7 changes: 7 additions & 0 deletions third_party/blink/renderer/core/css/css_properties.json5
Original file line number Diff line number Diff line change
Expand Up @@ -7397,6 +7397,13 @@
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
runtime_flag: "ScrollTimeline",
},
{
name: "-alternative-view-timeline-with-inset",
alternative_of: "view-timeline",
longhands: ["view-timeline-name", "view-timeline-axis", "view-timeline-inset"],
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
runtime_flag: "CSSViewTimelineInsetShorthand",
},
{
name: "-webkit-border-after",
alias_for: "border-block-end",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,7 @@ bool CSSPropertyEquality::PropertiesEqual(const PropertyHandle& property,
case CSSPropertyID::kToggle:
case CSSPropertyID::kTransition:
case CSSPropertyID::kViewTimeline:
case CSSPropertyID::kAlternativeViewTimelineWithInset:
case CSSPropertyID::kWebkitColumnBreakAfter:
case CSSPropertyID::kWebkitColumnBreakBefore:
case CSSPropertyID::kWebkitColumnBreakInside:
Expand Down
16 changes: 16 additions & 0 deletions third_party/blink/renderer/core/css/css_property_names_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,20 @@ TEST(CSSPropertyNamesTest, AlternativeAnimationDelay) {
}
}

TEST(CSSPropertyNamesTest, AlternativeViewTimelineWithInset) {
{
ScopedCSSViewTimelineInsetShorthandForTest feature(false);
EXPECT_EQ(CSSPropertyID::kViewTimeline,
UnresolvedCSSPropertyID(/* execution_context */ nullptr,
"view-timeline"));
}

{
ScopedCSSViewTimelineInsetShorthandForTest feature(true);
EXPECT_EQ(CSSPropertyID::kAlternativeViewTimelineWithInset,
UnresolvedCSSPropertyID(/* execution_context */ nullptr,
"view-timeline"));
}
}

} // namespace blink
Original file line number Diff line number Diff line change
Expand Up @@ -2631,14 +2631,30 @@ CSSValue* ComputedStyleUtils::ValueForAnimationTimelineList(
&ValueForAnimationTimeline);
}

CSSValue* ComputedStyleUtils::ValueForTimelineInset(
const TimelineInset& inset,
const ComputedStyle& style) {
return MakeGarbageCollected<CSSValuePair>(
ComputedStyleUtils::ZoomAdjustedPixelValueForLength(inset.GetStart(),
style),
ComputedStyleUtils::ZoomAdjustedPixelValueForLength(inset.GetEnd(),
style),
CSSValuePair::kDropIdenticalValues);
}

CSSValue* ComputedStyleUtils::SingleValueForTimelineShorthand(
const ScopedCSSName* name,
TimelineAxis axis) {
TimelineAxis axis,
absl::optional<TimelineInset> inset,
const ComputedStyle& style) {
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
list->Append(*ValueForCustomIdentOrNone(name));
if (axis != TimelineAxis::kBlock) {
list->Append(*CSSIdentifierValue::Create(axis));
}
if (inset.value_or(TimelineInset()) != TimelineInset()) {
list->Append(*ValueForTimelineInset(inset.value(), style));
}
return list;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,13 @@ class CORE_EXPORT ComputedStyleUtils {
static CSSValue* ValueForAnimationTimingFunctionList(const CSSTimingData*);
static CSSValue* ValueForAnimationTimelineList(const CSSAnimationData*);

static CSSValue* SingleValueForTimelineShorthand(const ScopedCSSName* name,
TimelineAxis);
static CSSValue* ValueForTimelineInset(const TimelineInset&,
const ComputedStyle&);
static CSSValue* SingleValueForTimelineShorthand(
const ScopedCSSName* name,
TimelineAxis,
absl::optional<TimelineInset>,
const ComputedStyle&);
static CSSValueList* ValuesForBorderRadiusCorner(const LengthSize&,
const ComputedStyle&);
static CSSValue* ValueForBorderRadiusCorner(const LengthSize&,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8806,12 +8806,7 @@ const CSSValue* ViewTimelineInset::CSSValueFromComputedStyleInternal(
}
CSSValueList* list = CSSValueList::CreateCommaSeparated();
for (const TimelineInset& inset : vector) {
list->Append(*MakeGarbageCollected<CSSValuePair>(
ComputedStyleUtils::ZoomAdjustedPixelValueForLength(inset.GetStart(),
style),
ComputedStyleUtils::ZoomAdjustedPixelValueForLength(inset.GetEnd(),
style),
CSSValuePair::kDropIdenticalValues));
list->Append(*ComputedStyleUtils::ValueForTimelineInset(inset, style));
}
return list;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3194,13 +3194,21 @@ const CSSValue* ScrollPaddingInline::CSSValueFromComputedStyleInternal(

namespace {

// Consume a single name, axis, and attachment, then append the result to
// `name_list` and `axis_list` respectively.
// Consume a single name, axis, and optionally inset, then append the result to
// `name_list`, `axis_list`, and `inset_list` respectively.
//
// Insets are only relevant for the view-timeline shorthand, and not for
// the scroll-timeline shorthand, hence `inset_list` may be nullptr.
//
// https://drafts.csswg.org/scroll-animations-1/#view-timeline-shorthand
// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand
bool ConsumeTimelineItemInto(CSSParserTokenRange& range,
const CSSParserContext& context,
CSSValueList* name_list,
CSSValueList* axis_list) {
CSSValueList* axis_list,
CSSValueList* inset_list) {
using css_parsing_utils::ConsumeSingleTimelineAxis;
using css_parsing_utils::ConsumeSingleTimelineInset;
using css_parsing_utils::ConsumeSingleTimelineName;

CSSValue* name = ConsumeSingleTimelineName(range, context);
Expand All @@ -3209,13 +3217,39 @@ bool ConsumeTimelineItemInto(CSSParserTokenRange& range,
return false;
}

CSSValue* axis = ConsumeSingleTimelineAxis(range);
CSSValue* axis = nullptr;
CSSValue* inset = nullptr;

// [ <'view-timeline-axis'> || <'view-timeline-inset'> ]
while (true) {
if (!axis && (axis = ConsumeSingleTimelineAxis(range))) {
continue;
}
if (inset_list && !inset &&
(inset = ConsumeSingleTimelineInset(range, context))) {
continue;
}
break;
}

if (!axis) {
axis = CSSIdentifierValue::Create(CSSValueID::kBlock);
}
if (inset_list && !inset) {
inset = MakeGarbageCollected<CSSValuePair>(
CSSIdentifierValue::Create(CSSValueID::kAuto),
CSSIdentifierValue::Create(CSSValueID::kAuto),
CSSValuePair::kDropIdenticalValues);
}

DCHECK(name_list);
DCHECK(axis_list);
name_list->Append(*name);
axis_list->Append(*axis);
if (inset) {
DCHECK(inset_list);
inset_list->Append(*inset);
}

return true;
}
Expand All @@ -3233,42 +3267,64 @@ bool ParseTimelineShorthand(CSSPropertyID shorthand_id,

CSSValueList* name_list = CSSValueList::CreateCommaSeparated();
CSSValueList* axis_list = CSSValueList::CreateCommaSeparated();
CSSValueList* inset_list =
shorthand.length() == 3u ? CSSValueList::CreateCommaSeparated() : nullptr;

do {
if (!ConsumeTimelineItemInto(range, context, name_list, axis_list)) {
if (!ConsumeTimelineItemInto(range, context, name_list, axis_list,
inset_list)) {
return false;
}
} while (ConsumeCommaIncludingWhitespace(range));

DCHECK(name_list->length());
DCHECK(axis_list->length());
DCHECK(!inset_list || inset_list->length());
DCHECK_EQ(name_list->length(), axis_list->length());
DCHECK_EQ(inset_list ? name_list->length() : 0,
inset_list ? inset_list->length() : 0);

DCHECK_EQ(shorthand.length(), 2u);
DCHECK_GE(shorthand.length(), 2u);
DCHECK_LE(shorthand.length(), 3u);
AddProperty(shorthand.properties()[0]->PropertyID(), shorthand_id, *name_list,
important, IsImplicitProperty::kNotImplicit, properties);
AddProperty(shorthand.properties()[1]->PropertyID(), shorthand_id, *axis_list,
important, IsImplicitProperty::kNotImplicit, properties);
if (inset_list) {
DCHECK_EQ(shorthand.length(), 3u);
AddProperty(shorthand.properties()[2]->PropertyID(), shorthand_id,
*inset_list, important, IsImplicitProperty::kNotImplicit,
properties);
}

return range.AtEnd();
}

static CSSValue* CSSValueForTimelineShorthand(
const HeapVector<Member<const ScopedCSSName>>& name_vector,
const Vector<TimelineAxis>& axis_vector) {
const Vector<TimelineAxis>& axis_vector,
const Vector<TimelineInset>* inset_vector,
const ComputedStyle& style) {
CSSValueList* list = CSSValueList::CreateCommaSeparated();

if (name_vector.size() != axis_vector.size()) {
return list;
}
if (inset_vector && name_vector.size() != inset_vector->size()) {
return list;
}
if (name_vector.empty()) {
list->Append(*ComputedStyleUtils::SingleValueForTimelineShorthand(
/* name */ nullptr, TimelineAxis::kBlock));
/* name */ nullptr, TimelineAxis::kBlock, /* inset */ absl::nullopt,
style));
return list;
}
for (wtf_size_t i = 0; i < name_vector.size(); ++i) {
list->Append(*ComputedStyleUtils::SingleValueForTimelineShorthand(
name_vector[i].Get(), axis_vector[i]));
name_vector[i].Get(), axis_vector[i],
inset_vector ? absl::optional<TimelineInset>((*inset_vector)[i])
: absl::optional<TimelineInset>(),
style));
}

return list;
Expand Down Expand Up @@ -3377,7 +3433,8 @@ const CSSValue* ScrollTimeline::CSSValueFromComputedStyleInternal(
style.ScrollTimelineName() ? style.ScrollTimelineName()->GetNames()
: HeapVector<Member<const ScopedCSSName>>{};
const Vector<TimelineAxis>& axis_vector = style.ScrollTimelineAxis();
return CSSValueForTimelineShorthand(name_vector, axis_vector);
return CSSValueForTimelineShorthand(name_vector, axis_vector,
/* inset_vector */ nullptr, style);
}

bool TextDecoration::ParseShorthand(
Expand Down Expand Up @@ -3556,7 +3613,34 @@ const CSSValue* ViewTimeline::CSSValueFromComputedStyleInternal(
style.ViewTimelineName() ? style.ViewTimelineName()->GetNames()
: HeapVector<Member<const ScopedCSSName>>{};
const Vector<TimelineAxis>& axis_vector = style.ViewTimelineAxis();
return CSSValueForTimelineShorthand(name_vector, axis_vector);
return CSSValueForTimelineShorthand(name_vector, axis_vector,
/* inset_vector */ nullptr, style);
}

bool AlternativeViewTimelineWithInset::ParseShorthand(
bool important,
CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext& local_context,
HeapVector<CSSPropertyValue, 64>& properties) const {
return ParseTimelineShorthand(
CSSPropertyID::kAlternativeViewTimelineWithInset,
alternativeViewTimelineWithInsetShorthand(), important, range, context,
local_context, properties);
}

const CSSValue*
AlternativeViewTimelineWithInset::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const LayoutObject*,
bool allow_visited_style) const {
const HeapVector<Member<const ScopedCSSName>>& name_vector =
style.ViewTimelineName() ? style.ViewTimelineName()->GetNames()
: HeapVector<Member<const ScopedCSSName>>{};
const Vector<TimelineAxis>& axis_vector = style.ViewTimelineAxis();
const Vector<TimelineInset>& inset_vector = style.ViewTimelineInset();
return CSSValueForTimelineShorthand(name_vector, axis_vector, &inset_vector,
style);
}

bool WebkitColumnBreakAfter::ParseShorthand(
Expand Down
48 changes: 43 additions & 5 deletions third_party/blink/renderer/core/css/style_property_serializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,8 @@ String StylePropertySerializer::SerializeShorthand(
}
case CSSPropertyID::kViewTimeline:
return ViewTimelineValue();
case CSSPropertyID::kAlternativeViewTimelineWithInset:
return AlternativeViewTimelineWithInsetValue();
case CSSPropertyID::kWhiteSpace:
return WhiteSpaceValue();
case CSSPropertyID::kGridColumnGap:
Expand Down Expand Up @@ -837,14 +839,28 @@ String StylePropertySerializer::ContainerValue() const {

namespace {

bool IsIdentifier(const CSSValue& value, CSSValueID ident) {
const auto* ident_value = DynamicTo<CSSIdentifierValue>(value);
return ident_value && ident_value->GetValueID() == ident;
}

bool IsIdentifierPair(const CSSValue& value, CSSValueID ident) {
const auto* pair_value = DynamicTo<CSSValuePair>(value);
return pair_value && IsIdentifier(pair_value->First(), ident) &&
IsIdentifier(pair_value->Second(), ident);
}

CSSValue* TimelineValueItem(wtf_size_t index,
const CSSValueList& name_list,
const CSSValueList& axis_list) {
const CSSValueList& axis_list,
const CSSValueList* inset_list) {
DCHECK_LT(index, name_list.length());
DCHECK_LT(index, axis_list.length());
DCHECK(!inset_list || index < inset_list->length());

const CSSValue& name = name_list.Item(index);
const CSSValue& axis = axis_list.Item(index);
const CSSValue* inset = inset_list ? &inset_list->Item(index) : nullptr;

CSSValueList* list = CSSValueList::CreateSpaceSeparated();

Expand All @@ -853,10 +869,12 @@ CSSValue* TimelineValueItem(wtf_size_t index,
// (It would set view-timeline-name to inline).
list->Append(name);

if (const auto* ident_value = DynamicTo<CSSIdentifierValue>(axis);
!ident_value || ident_value->GetValueID() != CSSValueID::kBlock) {
if (!IsIdentifier(axis, CSSValueID::kBlock)) {
list->Append(axis);
}
if (inset && !IsIdentifierPair(*inset, CSSValueID::kAuto)) {
list->Append(*inset);
}

return list;
}
Expand All @@ -865,24 +883,33 @@ CSSValue* TimelineValueItem(wtf_size_t index,

String StylePropertySerializer::TimelineValue(
const StylePropertyShorthand& shorthand) const {
CHECK_EQ(shorthand.length(), 2u);
CHECK_GE(shorthand.length(), 2u);
CHECK_LE(shorthand.length(), 3u);

const CSSValueList& name_list = To<CSSValueList>(
*property_set_.GetPropertyCSSValue(*shorthand.properties()[0]));
const CSSValueList& axis_list = To<CSSValueList>(
*property_set_.GetPropertyCSSValue(*shorthand.properties()[1]));
const CSSValueList* inset_list =
shorthand.length() == 3u
? To<CSSValueList>(
property_set_.GetPropertyCSSValue(*shorthand.properties()[2]))
: nullptr;

// The scroll/view-timeline shorthand can not expand to longhands of two
// different lengths, so we can also not contract two different-longhands
// into a single shorthand.
if (name_list.length() != axis_list.length()) {
return "";
}
if (inset_list && name_list.length() != inset_list->length()) {
return "";
}

CSSValueList* list = CSSValueList::CreateCommaSeparated();

for (wtf_size_t i = 0; i < name_list.length(); ++i) {
list->Append(*TimelineValueItem(i, name_list, axis_list));
list->Append(*TimelineValueItem(i, name_list, axis_list, inset_list));
}

return list->CssText();
Expand All @@ -906,6 +933,17 @@ String StylePropertySerializer::ViewTimelineValue() const {
return TimelineValue(viewTimelineShorthand());
}

String StylePropertySerializer::AlternativeViewTimelineWithInsetValue() const {
CHECK_EQ(alternativeViewTimelineWithInsetShorthand().length(), 3u);
CHECK_EQ(alternativeViewTimelineWithInsetShorthand().properties()[0],
&GetCSSPropertyViewTimelineName());
CHECK_EQ(alternativeViewTimelineWithInsetShorthand().properties()[1],
&GetCSSPropertyViewTimelineAxis());
CHECK_EQ(alternativeViewTimelineWithInsetShorthand().properties()[2],
&GetCSSPropertyViewTimelineInset());
return TimelineValue(alternativeViewTimelineWithInsetShorthand());
}

namespace {

CSSValue* AnimationDelayShorthandValueItem(wtf_size_t index,
Expand Down

0 comments on commit 4245aa6

Please sign in to comment.