LibWeb: Implement CSS progress() math function
`no-clamp` tests are added in-tree since there aren't any in WPT yet.
This commit is contained in:
parent
043adecb13
commit
fdca036ff3
13 changed files with 489 additions and 1 deletions
|
|
@ -443,6 +443,7 @@
|
|||
"new-base-60",
|
||||
"newa",
|
||||
"nko-cardinal",
|
||||
"no-clamp",
|
||||
"no-clip",
|
||||
"no-close-quote",
|
||||
"no-common-ligatures",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,27 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"progress": {
|
||||
"parameter-validation": "consistent",
|
||||
"__comment": "`no-clamp` is implemented ad-hoc in the parser since it's unusual in that it isn't comma separated",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "<number>|<dimension>|<percentage>",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "start-value",
|
||||
"type": "<number>|<dimension>|<percentage>",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "end-value",
|
||||
"type": "<number>|<dimension>|<percentage>",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"random": {
|
||||
"parameter-validation": "consistent",
|
||||
"parameters": [
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ static void serialize_a_math_function(StringBuilder& builder, CalculationNode co
|
|||
// Concatenate all of the results using ", " (comma followed by space), then append the result to s.
|
||||
|
||||
// Spec issue: https://github.com/w3c/csswg-drafts/issues/11783
|
||||
// The three AD-HOCs in this step are mentioned there.
|
||||
// The four AD-HOCs in this step are mentioned there.
|
||||
// AD-HOC: Numeric nodes have no children and should serialize directly.
|
||||
// AD-HOC: calc-operator nodes should also serialize directly, instead of separating their children by commas.#
|
||||
if (fn.type() == CalculationNode::Type::Numeric || fn.is_calc_operator_node()) {
|
||||
|
|
@ -334,6 +334,14 @@ static void serialize_a_math_function(StringBuilder& builder, CalculationNode co
|
|||
builder.append(CSS::to_string(rounding_strategy));
|
||||
first = false;
|
||||
}
|
||||
|
||||
// AD-HOC: For `progress()` we serialize 'no-clamp' separately since it's not a calculation node and shouldn't
|
||||
// be followed by a comma.
|
||||
if (fn.type() == CalculationNode::Type::Progress) {
|
||||
if (static_cast<ProgressCalculationNode const&>(fn).no_clamp())
|
||||
builder.append("no-clamp "sv);
|
||||
}
|
||||
|
||||
for (auto const& child : fn.children()) {
|
||||
if (!first)
|
||||
builder.append(", "sv);
|
||||
|
|
@ -612,6 +620,8 @@ StringView CalculationNode::name() const
|
|||
return "atan2"sv;
|
||||
case Type::Pow:
|
||||
return "pow"sv;
|
||||
case Type::Progress:
|
||||
return "progress"sv;
|
||||
case Type::Sqrt:
|
||||
return "sqrt"sv;
|
||||
case Type::Hypot:
|
||||
|
|
@ -1004,6 +1014,113 @@ GC::Ptr<CSSNumericValue> ProductCalculationNode::reify(JS::Realm& realm) const
|
|||
return CSSMathProduct::create(realm, numeric_type().value(), reified_children.as_nonnull());
|
||||
}
|
||||
|
||||
NonnullRefPtr<ProgressCalculationNode const> ProgressCalculationNode::create(bool no_clamp, NonnullRefPtr<CalculationNode const> value, NonnullRefPtr<CalculationNode const> start_value, NonnullRefPtr<CalculationNode const> end_value)
|
||||
{
|
||||
// https://drafts.csswg.org/css-values-5/#progress
|
||||
// The result of progress() is a <number> made consistent with the consistent type of its arguments
|
||||
auto numeric_type = NumericType {}.made_consistent_with(add_the_types({ value, start_value, end_value }).value()).value();
|
||||
|
||||
return adopt_ref(*new (nothrow) ProgressCalculationNode(no_clamp, move(value), move(start_value), move(end_value), numeric_type));
|
||||
}
|
||||
|
||||
ProgressCalculationNode::ProgressCalculationNode(bool no_clamp, NonnullRefPtr<CalculationNode const> value, NonnullRefPtr<CalculationNode const> start_value, NonnullRefPtr<CalculationNode const> end_value, Optional<NumericType> numeric_type)
|
||||
: CalculationNode(Type::Progress, numeric_type)
|
||||
, m_no_clamp(no_clamp)
|
||||
, m_value(move(value))
|
||||
, m_start_value(move(start_value))
|
||||
, m_end_value(move(end_value))
|
||||
{
|
||||
}
|
||||
|
||||
ProgressCalculationNode::~ProgressCalculationNode() = default;
|
||||
|
||||
bool ProgressCalculationNode::contains_percentage() const
|
||||
{
|
||||
return m_value->contains_percentage()
|
||||
|| m_start_value->contains_percentage()
|
||||
|| m_end_value->contains_percentage();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CalculationNode const> ProgressCalculationNode::with_simplified_children(CalculationContext const& calculation_context, CalculationResolutionContext const& calculation_resolution_context) const
|
||||
{
|
||||
auto simplified_value = simplify_a_calculation_tree(m_value, calculation_context, calculation_resolution_context);
|
||||
auto simplified_start_value = simplify_a_calculation_tree(m_start_value, calculation_context, calculation_resolution_context);
|
||||
auto simplified_end_value = simplify_a_calculation_tree(m_end_value, calculation_context, calculation_resolution_context);
|
||||
|
||||
if (simplified_value == m_value && simplified_start_value == m_start_value && simplified_end_value == m_end_value)
|
||||
return *this;
|
||||
|
||||
return create(m_no_clamp, move(simplified_value), move(simplified_start_value), move(simplified_end_value));
|
||||
}
|
||||
|
||||
Optional<CalculatedStyleValue::CalculationResult> ProgressCalculationNode::run_operation_if_possible(CalculationContext const& context, CalculationResolutionContext const& resolution_context) const
|
||||
{
|
||||
auto maybe_value = try_get_value_with_canonical_unit(*m_value, context, resolution_context);
|
||||
auto maybe_start_value = try_get_value_with_canonical_unit(*m_start_value, context, resolution_context);
|
||||
auto maybe_end_value = try_get_value_with_canonical_unit(*m_end_value, context, resolution_context);
|
||||
|
||||
if (!maybe_value.has_value() || !maybe_start_value.has_value() || !maybe_end_value.has_value())
|
||||
return {};
|
||||
|
||||
// https://drafts.csswg.org/css-values-5/#calculate-a-progress-function
|
||||
// If the progress start value and progress end value are different values
|
||||
if (maybe_start_value != maybe_end_value) {
|
||||
// (progress value - progress start value) / (progress end value - progress start value), clamped to the [0,1] range if no-clamp is not specified.
|
||||
auto progress = (maybe_value->value() - maybe_start_value->value()) / (maybe_end_value->value() - maybe_start_value->value());
|
||||
|
||||
if (!m_no_clamp)
|
||||
progress = clamp(progress, 0.0, 1.0);
|
||||
|
||||
return CalculatedStyleValue::CalculationResult { progress, numeric_type() };
|
||||
}
|
||||
|
||||
// If the progress start value and progress end value are the same value
|
||||
{
|
||||
// 0 if no-clamp is not specified.
|
||||
if (!m_no_clamp)
|
||||
return CalculatedStyleValue::CalculationResult { 0.0, numeric_type() };
|
||||
|
||||
// Otherwise, 0, -∞, or +∞, depending on whether progress value is equal to, less than, or greater than the shared value.
|
||||
if (maybe_value->value() == maybe_start_value->value())
|
||||
return CalculatedStyleValue::CalculationResult { 0.0, numeric_type() };
|
||||
if (maybe_value->value() < maybe_start_value->value())
|
||||
return CalculatedStyleValue::CalculationResult { -AK::Infinity<double>, numeric_type() };
|
||||
|
||||
return CalculatedStyleValue::CalculationResult { AK::Infinity<double>, numeric_type() };
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressCalculationNode::dump(StringBuilder& builder, int indent) const
|
||||
{
|
||||
builder.appendff("{: >{}}PROGRESS (no-clamp: {})\n", "", indent, m_no_clamp);
|
||||
m_value->dump(builder, indent + 2);
|
||||
m_start_value->dump(builder, indent + 2);
|
||||
m_end_value->dump(builder, indent + 2);
|
||||
}
|
||||
|
||||
bool ProgressCalculationNode::equals(CalculationNode const& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return true;
|
||||
|
||||
if (type() != other.type())
|
||||
return false;
|
||||
|
||||
auto const& other_progress = static_cast<ProgressCalculationNode const&>(other);
|
||||
|
||||
return m_no_clamp == other_progress.m_no_clamp
|
||||
&& m_value->equals(other_progress.m_value)
|
||||
&& m_start_value->equals(other_progress.m_start_value)
|
||||
&& m_end_value->equals(other_progress.m_end_value);
|
||||
}
|
||||
|
||||
bool ProgressCalculationNode::is_computationally_independent() const
|
||||
{
|
||||
return m_value->is_computationally_independent()
|
||||
&& m_start_value->is_computationally_independent()
|
||||
&& m_end_value->is_computationally_independent();
|
||||
}
|
||||
|
||||
NonnullRefPtr<NegateCalculationNode const> NegateCalculationNode::create(NonnullRefPtr<CalculationNode const> value)
|
||||
{
|
||||
return adopt_ref(*new (nothrow) NegateCalculationNode(move(value)));
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ private:
|
|||
X(Clamp) \
|
||||
X(Sum) \
|
||||
X(Product) \
|
||||
X(Progress) \
|
||||
X(Negate) \
|
||||
X(Invert) \
|
||||
X(Abs) \
|
||||
|
|
@ -217,6 +218,7 @@ public:
|
|||
case Type::Atan:
|
||||
case Type::Atan2:
|
||||
case Type::Pow:
|
||||
case Type::Progress:
|
||||
case Type::Sqrt:
|
||||
case Type::Hypot:
|
||||
case Type::Log:
|
||||
|
|
@ -335,6 +337,32 @@ private:
|
|||
Vector<NonnullRefPtr<CalculationNode const>> m_values;
|
||||
};
|
||||
|
||||
class ProgressCalculationNode final : public CalculationNode {
|
||||
public:
|
||||
static NonnullRefPtr<ProgressCalculationNode const> create(bool no_clamp, NonnullRefPtr<CalculationNode const> value, NonnullRefPtr<CalculationNode const> start_value, NonnullRefPtr<CalculationNode const> end_value);
|
||||
~ProgressCalculationNode();
|
||||
|
||||
virtual bool contains_percentage() const override;
|
||||
virtual NonnullRefPtr<CalculationNode const> with_simplified_children(CalculationContext const&, CalculationResolutionContext const&) const override;
|
||||
virtual Optional<CalculatedStyleValue::CalculationResult> run_operation_if_possible(CalculationContext const&, CalculationResolutionContext const&) const override;
|
||||
|
||||
virtual Vector<NonnullRefPtr<CalculationNode const>> children() const override { return { { m_value, m_start_value, m_end_value } }; }
|
||||
|
||||
virtual void dump(StringBuilder&, int indent) const override;
|
||||
virtual bool equals(CalculationNode const&) const override;
|
||||
virtual bool is_computationally_independent() const override;
|
||||
|
||||
bool no_clamp() const { return m_no_clamp; }
|
||||
|
||||
private:
|
||||
ProgressCalculationNode(bool no_clamp, NonnullRefPtr<CalculationNode const> value, NonnullRefPtr<CalculationNode const> start_value, NonnullRefPtr<CalculationNode const> end_value, Optional<NumericType> numeric_type);
|
||||
|
||||
bool m_no_clamp;
|
||||
NonnullRefPtr<CalculationNode const> m_value;
|
||||
NonnullRefPtr<CalculationNode const> m_start_value;
|
||||
NonnullRefPtr<CalculationNode const> m_end_value;
|
||||
};
|
||||
|
||||
class NegateCalculationNode final : public CalculationNode {
|
||||
public:
|
||||
static NonnullRefPtr<NegateCalculationNode const> create(NonnullRefPtr<CalculationNode const>);
|
||||
|
|
|
|||
|
|
@ -124,6 +124,15 @@ static Optional<RoundingStrategy> parse_rounding_strategy(TokenStream<ComponentV
|
|||
RefPtr<CalculationNode const> Parser::parse_math_function(Function const& function, CalculationContext const& context)
|
||||
{
|
||||
TokenStream stream { function.value };
|
||||
|
||||
// AD-HOC: `progress()`'s `no-clamp` argument that isn't comma separated like the other arguments, so we need to
|
||||
// parse it first.
|
||||
bool progress_function_no_clamp = false;
|
||||
if (function.name.equals_ignoring_ascii_case("progress"sv)) {
|
||||
if (auto keyword = parse_specific_keyword_value(stream, { { Keyword::NoClamp } }))
|
||||
progress_function_no_clamp = true;
|
||||
}
|
||||
|
||||
auto arguments = parse_a_comma_separated_list_of_component_values(stream);
|
||||
auto const& percentages_resolve_as = context.percentages_resolve_as;
|
||||
""")
|
||||
|
|
@ -393,6 +402,11 @@ RefPtr<CalculationNode const> Parser::parse_math_function(Function const& functi
|
|||
""")
|
||||
# Generate the call to the constructor
|
||||
out.write(f" return {name_titlecase}CalculationNode::create(")
|
||||
if name == "progress":
|
||||
out.write("progress_function_no_clamp")
|
||||
if parameters:
|
||||
out.write(", ")
|
||||
|
||||
for parameter_index, parameter in enumerate(parameters):
|
||||
parameter_type_string = parameter["type"]
|
||||
if parameter_type_string == "<rounding-strategy>":
|
||||
|
|
|
|||
12
Tests/LibWeb/Text/expected/css/progress-no-clamp.txt
Normal file
12
Tests/LibWeb/Text/expected/css/progress-no-clamp.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
specified: calc(-1)
|
||||
computed: -1
|
||||
specified: calc(2)
|
||||
computed: 2
|
||||
specified: progress(no-clamp 1em, 0px, 100px)
|
||||
computed: 0
|
||||
specified: calc(-infinity)
|
||||
computed: -2147483648
|
||||
specified: calc(0)
|
||||
computed: 0
|
||||
specified: calc(infinity)
|
||||
computed: 2147483647
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 23 tests
|
||||
|
||||
23 Pass
|
||||
Pass progress(1, 0, 1) should be used-value-equivalent to 1
|
||||
Pass progress(progress(1, 0, 1), progress(0px, 0px, 1px), progress(1deg, 0deg, 1deg)) should be used-value-equivalent to 1
|
||||
Pass progress(sign(-10px) * 10px, (10px - 10px), 10px * progress(1deg, 0deg, 1deg)) should be used-value-equivalent to 0
|
||||
Pass calc(progress(100px, 0px, 50px) * 10px + 100px) should be used-value-equivalent to 110px
|
||||
Pass calc(progress(100, 0, sign(50px))) should be used-value-equivalent to 1
|
||||
Pass calc(progress(abs(5%), hypot(3%, 4%), 10%)) should be used-value-equivalent to 0
|
||||
Pass progress(50em, 10em, 110em) should be used-value-equivalent to 0.4
|
||||
Pass progress(1000em, 10em, 110em) should be used-value-equivalent to 1
|
||||
Pass scale(progress(50em, 10rem, 110em)) should be used-value-equivalent to scale(1)
|
||||
Pass scale(progress(1000em, 10rem, 110em)) should be used-value-equivalent to scale(1)
|
||||
Pass scale(progress(0em, 0rem, 0em)) should be used-value-equivalent to scale(0)
|
||||
Pass scale(progress(sign(1em - 1rem) * 1ex, 0rem, 0em)) should be used-value-equivalent to scale(0)
|
||||
Pass calc(progress(1, 0, 1) * 10px) should be used-value-equivalent to 10px
|
||||
Pass calc(progress(1, 0, 1) * 1s) should be used-value-equivalent to 1s
|
||||
Pass calc(progress(1, 0, 1) * 1deg) should be used-value-equivalent to 1deg
|
||||
Pass calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 10em, 2rem, 12em) / 2) should be used-value-equivalent to 0.4
|
||||
Pass calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 10) should be used-value-equivalent to 10
|
||||
Pass calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 30) should be used-value-equivalent to 30
|
||||
Pass calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) / 4) should be used-value-equivalent to 0.25
|
||||
Pass calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 4) should be used-value-equivalent to 4
|
||||
Pass calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 2) should be used-value-equivalent to 2
|
||||
Pass rotate3d(progress(21em, 1rem, 11em), progress(21em, 1rem, 11em), progress(21em, 1rem, 11em), calc(progress(11em, 1rem, 11em) * 2deg)) should be used-value-equivalent to rotate3d(2, 2, 2, 2deg)
|
||||
Pass calc(50% - 0px * clamp(0, progress(0cqw, 0px, 0px), 1)) should be used-value-equivalent to 50px
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 27 tests
|
||||
|
||||
27 Pass
|
||||
Pass e.style['opacity'] = "progress()" should not set the property value
|
||||
Pass e.style['opacity'] = "progress( )" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(,)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(1, )" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(1)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(50%, 0)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(0, 1,)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(from,)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(from 1, 0)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(from 1, 0 1)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(from 1 0)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(0,, 0)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(to,,,,)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(0,,, 10,, 200)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(0,,, 10,,, 200)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(0,, 10,, 200)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(0 from 10 to 200)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(5%, 0, 8" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(5%, 0deg, 8deg" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(5, 0deg, 8deg" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(5, 0%, 8deg" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(5, 0%, sign(10px)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(5%, 0px, 10px" should not set the property value
|
||||
Pass e.style['letter-spacing'] = "calc(1px * progress(10deg, 0, 10))" should not set the property value
|
||||
Pass e.style['letter-spacing'] = "calc(1px * progress(10, 0px, 10))" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(10px * 10px, 10px * 10px, 10px * 10px)" should not set the property value
|
||||
Pass e.style['opacity'] = "progress(10px, 10px * 10px, 10px * 10px)" should not set the property value
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 34 tests
|
||||
|
||||
34 Pass
|
||||
Pass 'progress(100px, 0px, 100px)' as a specified value should serialize as 'calc(1)'.
|
||||
Pass 'scale(progress(100px, 0px, 100px))' as a specified value should serialize as 'scale(calc(1))'.
|
||||
Pass 'progress(100px, 0px, 100px)' as a computed value should serialize as '1'.
|
||||
Pass 'scale(progress(100px, 0px, 100px))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
|
||||
Pass 'progress(10em, 0px, 10em)' as a specified value should serialize as 'progress(10em, 0px, 10em)'.
|
||||
Pass 'scale(progress(10em, 0px, 10em))' as a specified value should serialize as 'scale(progress(10em, 0px, 10em))'.
|
||||
Pass 'progress(10em, 0px, 10em)' as a computed value should serialize as '1'.
|
||||
Pass 'scale(progress(10em, 0px, 10em))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
|
||||
Pass 'progress(10em, 0px, 10rem)' as a specified value should serialize as 'progress(10em, 0px, 10rem)'.
|
||||
Pass 'scale(progress(10em, 0px, 10rem))' as a specified value should serialize as 'scale(progress(10em, 0px, 10rem))'.
|
||||
Pass 'progress(10em, 0px, 10rem)' as a computed value should serialize as '1'.
|
||||
Pass 'scale(progress(10em, 0px, 10rem))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
|
||||
Pass 'progress(100px, (10px - 10px), 100px)' as a specified value should serialize as 'calc(1)'.
|
||||
Pass 'scale(progress(100px, (10px - 10px), 100px))' as a specified value should serialize as 'scale(calc(1))'.
|
||||
Pass 'progress(100px, (10px - 10px), 100px)' as a computed value should serialize as '1'.
|
||||
Pass 'scale(progress(100px, (10px - 10px), 100px))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'.
|
||||
Pass 'progress(1%, (10% - 10%), 100%)' as a specified value should serialize as 'calc(0.01)'.
|
||||
Pass 'scale(progress(1%, (10% - 10%), 100%))' as a specified value should serialize as 'scale(calc(0.01))'.
|
||||
Pass 'progress(1%, (10% - 10%), 100%)' as a computed value should serialize as '0.01'.
|
||||
Pass 'scale(progress(1%, (10% - 10%), 100%))' as a computed value should serialize as 'matrix(0.01, 0, 0, 0.01, 0, 0)'.
|
||||
Pass 'calc(0.5 * progress(100px, 0px, 100px))' as a specified value should serialize as 'calc(0.5)'.
|
||||
Pass 'scale(calc(0.5 * progress(100px, 0px, 100px)))' as a specified value should serialize as 'scale(calc(0.5))'.
|
||||
Pass 'calc(0.5 * progress(100px, 0px, 100px))' as a computed value should serialize as '0.5'.
|
||||
Pass 'scale(calc(0.5 * progress(100px, 0px, 100px)))' as a computed value should serialize as 'matrix(0.5, 0, 0, 0.5, 0, 0)'.
|
||||
Pass 'calc(0.5 * progress(200px, 0px, 100px))' as a specified value should serialize as 'calc(0.5)'.
|
||||
Pass 'scale(calc(0.5 * progress(200px, 0px, 100px)))' as a specified value should serialize as 'scale(calc(0.5))'.
|
||||
Pass 'calc(0.5 * progress(200px, 0px, 100px))' as a computed value should serialize as '0.5'.
|
||||
Pass 'scale(calc(0.5 * progress(200px, 0px, 100px)))' as a computed value should serialize as 'matrix(0.5, 0, 0, 0.5, 0, 0)'.
|
||||
Pass 'calc(0.5 * progress(-100px, 0px, 100px))' as a specified value should serialize as 'calc(0)'.
|
||||
Pass 'scale(calc(0.5 * progress(-100px, 0px, 100px)))' as a specified value should serialize as 'scale(calc(0))'.
|
||||
Pass 'calc(0.5 * progress(-100px, 0px, 100px))' as a computed value should serialize as '0'.
|
||||
Pass 'scale(calc(0.5 * progress(-100px, 0px, 100px)))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'.
|
||||
Pass 'calc(50px * progress(100px, 0px, 100px))' as a specified value should serialize as 'calc(50px)'.
|
||||
Pass 'calc(1px * progress(abs(10%), (10% - 10%), 100% / 10))' as a computed value should serialize as '1px'.
|
||||
28
Tests/LibWeb/Text/input/css/progress-no-clamp.html
Normal file
28
Tests/LibWeb/Text/input/css/progress-no-clamp.html
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<!doctype html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
function printProperty(property, value) {
|
||||
const element = document.createElement("div");
|
||||
document.body.append(element);
|
||||
element.style[property] = value;
|
||||
println(`specified: ${element.style[property]}`);
|
||||
println(`computed: ${getComputedStyle(element)[property]}`);
|
||||
element.remove();
|
||||
}
|
||||
|
||||
test(() => {
|
||||
// Should produce negative numbers
|
||||
printProperty("z-index", "progress(no-clamp -100px, 0px, 100px)");
|
||||
|
||||
// Should produce numbers greater than 1
|
||||
printProperty("z-index", "progress(no-clamp 200px, 0px, 100px)");
|
||||
|
||||
// Should serialize correctly when not resolvable at parse time
|
||||
printProperty("z-index", "progress(no-clamp 1em, 0px, 100px)");
|
||||
|
||||
// Should produce the expected values when the start and end values are the same
|
||||
printProperty("z-index", "progress(no-clamp 0px, 1px, 1px)"); // -infinity
|
||||
printProperty("z-index", "progress(no-clamp 1px, 1px, 1px)"); // 0
|
||||
printProperty("z-index", "progress(no-clamp 2px, 1px, 1px)"); // +infinity
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#progress">
|
||||
<link rel="author" title="sakhapov@chromuim.org">
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../support/numeric-testcommon.js"></script>
|
||||
<style>
|
||||
:root {
|
||||
font-size: 10px;
|
||||
}
|
||||
#wrapper {
|
||||
width: 100px;
|
||||
}
|
||||
#target {
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
<div id="wrapper">
|
||||
<div id="target"></div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
// Identity tests
|
||||
test_math_used('progress(1, 0, 1)', '1', {type:'number'});
|
||||
|
||||
// Nestings
|
||||
test_math_used('progress(progress(1, 0, 1), progress(0px, 0px, 1px), progress(1deg, 0deg, 1deg))', '1', {type:'number'});
|
||||
test_math_used('progress(sign(-10px) * 10px, (10px - 10px), 10px * progress(1deg, 0deg, 1deg))', '0', {type:'number'});
|
||||
|
||||
// General calculations
|
||||
test_math_used('calc(progress(100px, 0px, 50px) * 10px + 100px)', '110px');
|
||||
test_math_used('calc(progress(100, 0, sign(50px)))', '1', {type:'number'});
|
||||
test_math_used('calc(progress(abs(5%), hypot(3%, 4%), 10%))', '0', {type:'number', approx:0.001});
|
||||
test_math_used('progress(50em, 10em, 110em)', '0.4', {type:'number', approx:0.1});
|
||||
test_math_used('progress(1000em, 10em, 110em)', '1', {type:'number', approx:0.1});
|
||||
test_math_used('scale(progress(50em, 10rem, 110em))', 'scale(1)', {prop:'transform', type:'number', approx:0.1});
|
||||
test_math_used('scale(progress(1000em, 10rem, 110em))', 'scale(1)', {prop:'transform', type:'number', approx:0.1});
|
||||
test_math_used('scale(progress(0em, 0rem, 0em))', 'scale(0)', {prop:'transform', type:'number'});
|
||||
test_math_used('scale(progress(sign(1em - 1rem) * 1ex, 0rem, 0em))', 'scale(0)', {prop:'transform', type:'number'});
|
||||
|
||||
// Type checking
|
||||
test_math_used('calc(progress(1, 0, 1) * 10px)', '10px');
|
||||
test_math_used('calc(progress(1, 0, 1) * 1s)', '1s', {type:'time'});
|
||||
test_math_used('calc(progress(1, 0, 1) * 1deg)', '1deg', {type:'angle', approx:0.001});
|
||||
|
||||
// Test different number accepting properties
|
||||
test_math_used('calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 10em, 2rem, 12em) / 2)', '0.4', {prop:'opacity', type:'number'});
|
||||
test_math_used('calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 10)', '10', {prop:'order', type:'number'});
|
||||
test_math_used('calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 30)', '30', {prop:'flex-grow', type:'number'});
|
||||
test_math_used('calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) / 4)', '0.25', {prop:'flex-grow', type:'number'});
|
||||
test_math_used('calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 4)', '4', {prop:'column-count', type:'number'});
|
||||
test_math_used('calc(progress(sign(1001em - 10lh * progress(100px, 2rex, 10ex)) * 20em, 2rem, 12em) * 2)', '2', {prop:'scale'});
|
||||
test_math_used('rotate3d(progress(21em, 1rem, 11em), progress(21em, 1rem, 11em), progress(21em, 1rem, 11em), calc(progress(11em, 1rem, 11em) * 2deg))', 'rotate3d(2, 2, 2, 2deg)', {prop:'transform'});
|
||||
|
||||
test_math_used('calc(50% - 0px * clamp(0, progress(0cqw, 0px, 0px), 1))', '50px', {type:'length', prop:'width'});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#progress">
|
||||
<link rel="author" title="sakhapov@chromuim.org">
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../support/parsing-testcommon.js"></script>
|
||||
<script>
|
||||
function test_invalid_number(value) {
|
||||
test_invalid_value('opacity', value);
|
||||
}
|
||||
function test_invalid_length(value) {
|
||||
// 'letter-spacing' accepts <length> only, not <percentage> or any mixes.
|
||||
test_invalid_value('letter-spacing', value);
|
||||
}
|
||||
|
||||
// Syntax checking
|
||||
test_invalid_number('progress()');
|
||||
test_invalid_number('progress( )');
|
||||
test_invalid_number('progress(,)');
|
||||
test_invalid_number('progress(1, )');
|
||||
test_invalid_number('progress(1)');
|
||||
test_invalid_number('progress(50%, 0)');
|
||||
test_invalid_number('progress(0, 1,)');
|
||||
test_invalid_number('progress(from,)');
|
||||
test_invalid_number('progress(from 1, 0)');
|
||||
test_invalid_number('progress(from 1, 0 1)');
|
||||
test_invalid_number('progress(from 1 0)');
|
||||
test_invalid_number('progress(0,, 0)');
|
||||
test_invalid_number('progress(to,,,,)');
|
||||
test_invalid_number('progress(0,,, 10,, 200)');
|
||||
test_invalid_number('progress(0,,, 10,,, 200)');
|
||||
test_invalid_number('progress(0,, 10,, 200)');
|
||||
test_invalid_number('progress(0 from 10 to 200)');
|
||||
|
||||
// General tests
|
||||
test_invalid_number('progress(5%, 0, 8');
|
||||
test_invalid_number('progress(5%, 0deg, 8deg');
|
||||
test_invalid_number('progress(5, 0deg, 8deg');
|
||||
test_invalid_number('progress(5, 0%, 8deg');
|
||||
test_invalid_number('progress(5, 0%, sign(10px)');
|
||||
test_invalid_number('progress(5%, 0px, 10px');
|
||||
test_invalid_length('calc(1px * progress(10deg, 0, 10))');
|
||||
test_invalid_length('calc(1px * progress(10, 0px, 10))');
|
||||
test_invalid_number('progress(10px * 10px, 10px * 10px, 10px * 10px)');
|
||||
test_invalid_number('progress(10px, 10px * 10px, 10px * 10px)');
|
||||
</script>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-values-5/#progress">
|
||||
<link rel="author" title="sakhapov@chromuim.org">
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../support/serialize-testcommon.js"></script>
|
||||
<div id=target></div>
|
||||
<script>
|
||||
function test_serialization(t,s,c) {
|
||||
test_specified_serialization('opacity', t, s);
|
||||
test_specified_serialization('transform', `scale(${t})`, `scale(${s})`);
|
||||
test_computed_serialization('opacity', t, c);
|
||||
test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`);
|
||||
}
|
||||
|
||||
test_serialization(
|
||||
'progress(100px, 0px, 100px)',
|
||||
'calc(1)',
|
||||
'1',
|
||||
);
|
||||
test_serialization(
|
||||
'progress(10em, 0px, 10em)',
|
||||
'progress(10em, 0px, 10em)',
|
||||
'1',
|
||||
);
|
||||
test_serialization(
|
||||
'progress(10em, 0px, 10rem)',
|
||||
'progress(10em, 0px, 10rem)',
|
||||
'1',
|
||||
);
|
||||
test_serialization(
|
||||
'progress(100px, (10px - 10px), 100px)',
|
||||
'calc(1)',
|
||||
'1',
|
||||
);
|
||||
test_serialization(
|
||||
'progress(1%, (10% - 10%), 100%)',
|
||||
'calc(0.01)',
|
||||
'0.01',
|
||||
);
|
||||
test_serialization(
|
||||
'calc(0.5 * progress(100px, 0px, 100px))',
|
||||
'calc(0.5)',
|
||||
'0.5'
|
||||
);
|
||||
test_serialization(
|
||||
'calc(0.5 * progress(200px, 0px, 100px))',
|
||||
'calc(0.5)',
|
||||
'0.5'
|
||||
);
|
||||
test_serialization(
|
||||
'calc(0.5 * progress(-100px, 0px, 100px))',
|
||||
'calc(0)',
|
||||
'0'
|
||||
);
|
||||
test_specified_serialization(
|
||||
'width',
|
||||
'calc(50px * progress(100px, 0px, 100px))',
|
||||
'calc(50px)'
|
||||
);
|
||||
test_computed_serialization(
|
||||
'width',
|
||||
'calc(1px * progress(abs(10%), (10% - 10%), 100% / 10))',
|
||||
'1px',
|
||||
);
|
||||
</script>
|
||||
Loading…
Reference in a new issue