Commit 3871f586 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Chromium LUCI CQ

Implement custom 'range' values for @counter-style

Bug: 687225
Change-Id: I57449229bf443ce33613a41b21e47f3fe52ca4f0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2586096
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Reviewed-by: default avatarAnders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836883}
parent 067f7942
...@@ -87,6 +87,27 @@ String SymbolToString(const CSSValue& value) { ...@@ -87,6 +87,27 @@ String SymbolToString(const CSSValue& value) {
return To<CSSCustomIdentValue>(value).Value(); return To<CSSCustomIdentValue>(value).Value();
} }
std::pair<int, int> BoundsToIntegerPair(const CSSValuePair& bounds) {
int lower_bound, upper_bound;
if (bounds.First().IsIdentifierValue()) {
DCHECK_EQ(CSSValueID::kInfinite,
To<CSSIdentifierValue>(bounds.First()).GetValueID());
lower_bound = std::numeric_limits<int>::min();
} else {
DCHECK(bounds.First().IsPrimitiveValue());
lower_bound = To<CSSPrimitiveValue>(bounds.First()).GetIntValue();
}
if (bounds.Second().IsIdentifierValue()) {
DCHECK_EQ(CSSValueID::kInfinite,
To<CSSIdentifierValue>(bounds.Second()).GetValueID());
upper_bound = std::numeric_limits<int>::max();
} else {
DCHECK(bounds.Second().IsPrimitiveValue());
upper_bound = To<CSSPrimitiveValue>(bounds.Second()).GetIntValue();
}
return std::make_pair(lower_bound, upper_bound);
}
// https://drafts.csswg.org/css-counter-styles/#cyclic-system // https://drafts.csswg.org/css-counter-styles/#cyclic-system
Vector<wtf_size_t> CyclicAlgorithm(int value, wtf_size_t num_symbols) { Vector<wtf_size_t> CyclicAlgorithm(int value, wtf_size_t num_symbols) {
DCHECK(num_symbols); DCHECK(num_symbols);
...@@ -253,6 +274,16 @@ CounterStyle::CounterStyle(const StyleRuleCounterStyle& rule) ...@@ -253,6 +274,16 @@ CounterStyle::CounterStyle(const StyleRuleCounterStyle& rule)
pad_symbol_ = SymbolToString(pair.Second()); pad_symbol_ = SymbolToString(pair.Second());
} }
if (const CSSValue* range = rule.GetRange()) {
if (range->IsIdentifierValue()) {
DCHECK_EQ(CSSValueID::kAuto, To<CSSIdentifierValue>(range)->GetValueID());
// Empty |range_| already means 'auto'.
} else {
for (const CSSValue* bounds : To<CSSValueList>(*range))
range_.push_back(BoundsToIntegerPair(To<CSSValuePair>(*bounds)));
}
}
// TODO(crbug.com/687225): Implement and populate other fields. // TODO(crbug.com/687225): Implement and populate other fields.
} }
...@@ -281,6 +312,9 @@ void CounterStyle::ResolveExtends(const CounterStyle& extended) { ...@@ -281,6 +312,9 @@ void CounterStyle::ResolveExtends(const CounterStyle& extended) {
pad_symbol_ = extended.pad_symbol_; pad_symbol_ = extended.pad_symbol_;
} }
if (!style_rule_->GetRange())
range_ = extended.range_;
// TODO(crbug.com/687225): Implement and populate other fields. // TODO(crbug.com/687225): Implement and populate other fields.
} }
...@@ -299,7 +333,13 @@ void CounterStyle::ResetFallback() { ...@@ -299,7 +333,13 @@ void CounterStyle::ResetFallback() {
} }
bool CounterStyle::RangeContains(int value) const { bool CounterStyle::RangeContains(int value) const {
// TODO(crbug.com/687225): Implement non-auto values of 'range' if (range_.size()) {
for (const auto& bounds : range_) {
if (value >= bounds.first && value <= bounds.second)
return true;
}
return false;
}
// 'range' value is auto // 'range' value is auto
switch (system_) { switch (system_) {
......
...@@ -101,6 +101,9 @@ class CORE_EXPORT CounterStyle final : public GarbageCollected<CounterStyle> { ...@@ -101,6 +101,9 @@ class CORE_EXPORT CounterStyle final : public GarbageCollected<CounterStyle> {
// Additive weights, for the 'additive' system only. // Additive weights, for the 'additive' system only.
Vector<wtf_size_t> additive_weights_; Vector<wtf_size_t> additive_weights_;
// Value of 'range' descriptor. Empty vector means 'auto'.
Vector<std::pair<int, int>> range_;
String negative_prefix_ = "-"; String negative_prefix_ = "-";
String negative_suffix_; String negative_suffix_;
......
...@@ -252,4 +252,78 @@ TEST_F(CounterStyleTest, PadLengthLimit) { ...@@ -252,4 +252,78 @@ TEST_F(CounterStyleTest, PadLengthLimit) {
EXPECT_EQ("0", foo.GenerateRepresentation(0)); EXPECT_EQ("0", foo.GenerateRepresentation(0));
} }
TEST_F(CounterStyleTest, SymbolicWithExtendedRange) {
InsertStyleElement(R"CSS(
@counter-style base {
system: symbolic;
symbols: A B;
}
@counter-style custom {
system: extends base;
range: infinite -2, 0 infinite;
}
@counter-style extended {
system: extends custom;
}
)CSS");
UpdateAllLifecyclePhasesForTest();
// Getting custom 'range' directly from descriptor value.
const CounterStyle& custom = GetCounterStyle("custom");
EXPECT_EQ("-AA", custom.GenerateRepresentation(-3));
EXPECT_EQ("-B", custom.GenerateRepresentation(-2));
// -1 is out of 'range' value. Fallback to 'decimal'
EXPECT_EQ("-1", custom.GenerateRepresentation(-1));
// 0 is within 'range' but not representable. Fallback to 'decimal'.
EXPECT_EQ("0", custom.GenerateRepresentation(0));
EXPECT_EQ("A", custom.GenerateRepresentation(1));
// Getting custom 'range' indirectly by extending a counter style.
const CounterStyle& extended = GetCounterStyle("extended");
EXPECT_EQ("-AA", extended.GenerateRepresentation(-3));
EXPECT_EQ("-B", extended.GenerateRepresentation(-2));
EXPECT_EQ("-1", extended.GenerateRepresentation(-1));
EXPECT_EQ("0", extended.GenerateRepresentation(0));
EXPECT_EQ("A", extended.GenerateRepresentation(1));
}
TEST_F(CounterStyleTest, AdditiveWithExtendedRange) {
InsertStyleElement(R"CSS(
@counter-style base {
system: additive;
additive-symbols: 2 B, 1 A;
}
@counter-style custom {
system: extends base;
range: infinite -2, 0 infinite;
}
@counter-style extended {
system: extends custom;
}
)CSS");
UpdateAllLifecyclePhasesForTest();
// Getting custom 'range' directly from descriptor value.
const CounterStyle& custom = GetCounterStyle("custom");
EXPECT_EQ("-BA", custom.GenerateRepresentation(-3));
EXPECT_EQ("-B", custom.GenerateRepresentation(-2));
// -1 is out of 'range' value. Fallback to 'decimal'.
EXPECT_EQ("-1", custom.GenerateRepresentation(-1));
// 0 is within 'range' but not representable. Fallback to 'decimal'.
EXPECT_EQ("0", custom.GenerateRepresentation(0));
EXPECT_EQ("A", custom.GenerateRepresentation(1));
// Getting custom 'range' indirectly by extending a counter style.
const CounterStyle& extended = GetCounterStyle("extended");
EXPECT_EQ("-BA", extended.GenerateRepresentation(-3));
EXPECT_EQ("-B", extended.GenerateRepresentation(-2));
EXPECT_EQ("-1", extended.GenerateRepresentation(-1));
EXPECT_EQ("0", extended.GenerateRepresentation(0));
EXPECT_EQ("A", extended.GenerateRepresentation(1));
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment