mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-23 09:48:56 +00:00
LibWeb/CSS: Parse the paint-order
property
This commit is contained in:
parent
1052ee20b0
commit
a87a9156d5
Notes:
github-actions[bot]
2025-08-28 09:32:32 +00:00
Author: https://github.com/tcl3
Commit: a87a9156d5
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5977
Reviewed-by: https://github.com/AtkinsSJ ✅
25 changed files with 376 additions and 17 deletions
|
@ -1951,6 +1951,47 @@ ShapeRendering ComputedProperties::shape_rendering() const
|
||||||
return keyword_to_shape_rendering(value.to_keyword()).release_value();
|
return keyword_to_shape_rendering(value.to_keyword()).release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PaintOrderList ComputedProperties::paint_order() const
|
||||||
|
{
|
||||||
|
auto const& value = property(PropertyID::PaintOrder);
|
||||||
|
if (value.is_keyword()) {
|
||||||
|
auto keyword = value.as_keyword().keyword();
|
||||||
|
if (keyword == Keyword::Normal)
|
||||||
|
return InitialValues::paint_order();
|
||||||
|
auto paint_order_keyword = keyword_to_paint_order(keyword);
|
||||||
|
VERIFY(paint_order_keyword.has_value());
|
||||||
|
switch (*paint_order_keyword) {
|
||||||
|
case PaintOrder::Fill:
|
||||||
|
return InitialValues::paint_order();
|
||||||
|
case PaintOrder::Stroke:
|
||||||
|
return PaintOrderList { PaintOrder::Stroke, PaintOrder::Fill, PaintOrder::Markers };
|
||||||
|
case PaintOrder::Markers:
|
||||||
|
return PaintOrderList { PaintOrder::Markers, PaintOrder::Fill, PaintOrder::Stroke };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VERIFY(value.is_value_list());
|
||||||
|
auto const& value_list = value.as_value_list();
|
||||||
|
// The list must contain 2 values at this point, since the third value is omitted during parsing due to the
|
||||||
|
// shortest-serialization principle.
|
||||||
|
VERIFY(value_list.size() == 2);
|
||||||
|
PaintOrderList paint_order_list {};
|
||||||
|
|
||||||
|
// We use the sum of the keyword values to infer what the missing keyword is. Since each keyword can only appear in
|
||||||
|
// the list once, the sum of their values will always be 3.
|
||||||
|
auto sum = 0;
|
||||||
|
for (auto i = 0; i < 2; i++) {
|
||||||
|
auto keyword = value_list.value_at(i, false)->as_keyword().keyword();
|
||||||
|
auto paint_order_keyword = keyword_to_paint_order(keyword);
|
||||||
|
VERIFY(paint_order_keyword.has_value());
|
||||||
|
sum += to_underlying(*paint_order_keyword);
|
||||||
|
paint_order_list[i] = *paint_order_keyword;
|
||||||
|
}
|
||||||
|
VERIFY(sum <= 3);
|
||||||
|
paint_order_list[2] = static_cast<PaintOrder>(3 - sum);
|
||||||
|
return paint_order_list;
|
||||||
|
}
|
||||||
|
|
||||||
WillChange ComputedProperties::will_change() const
|
WillChange ComputedProperties::will_change() const
|
||||||
{
|
{
|
||||||
auto const& value = property(PropertyID::WillChange);
|
auto const& value = property(PropertyID::WillChange);
|
||||||
|
|
|
@ -199,6 +199,7 @@ public:
|
||||||
ClipRule clip_rule() const;
|
ClipRule clip_rule() const;
|
||||||
float flood_opacity() const;
|
float flood_opacity() const;
|
||||||
CSS::ShapeRendering shape_rendering() const;
|
CSS::ShapeRendering shape_rendering() const;
|
||||||
|
PaintOrderList paint_order() const;
|
||||||
|
|
||||||
WillChange will_change() const;
|
WillChange will_change() const;
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,8 @@ using CursorData = Variant<NonnullRefPtr<CursorStyleValue const>, CursorPredefin
|
||||||
|
|
||||||
using ListStyleType = Variant<CounterStyleNameKeyword, String>;
|
using ListStyleType = Variant<CounterStyleNameKeyword, String>;
|
||||||
|
|
||||||
|
using PaintOrderList = Array<PaintOrder, 3>;
|
||||||
|
|
||||||
class InitialValues {
|
class InitialValues {
|
||||||
public:
|
public:
|
||||||
static AspectRatio aspect_ratio() { return AspectRatio { true, {} }; }
|
static AspectRatio aspect_ratio() { return AspectRatio { true, {} }; }
|
||||||
|
@ -259,6 +261,7 @@ public:
|
||||||
}
|
}
|
||||||
static CSS::ScrollbarWidth scrollbar_width() { return CSS::ScrollbarWidth::Auto; }
|
static CSS::ScrollbarWidth scrollbar_width() { return CSS::ScrollbarWidth::Auto; }
|
||||||
static CSS::ShapeRendering shape_rendering() { return CSS::ShapeRendering::Auto; }
|
static CSS::ShapeRendering shape_rendering() { return CSS::ShapeRendering::Auto; }
|
||||||
|
static PaintOrderList paint_order() { return { PaintOrder::Fill, PaintOrder::Stroke, PaintOrder::Markers }; }
|
||||||
static WillChange will_change() { return WillChange::make_auto(); }
|
static WillChange will_change() { return WillChange::make_auto(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -590,6 +593,7 @@ public:
|
||||||
CSS::ClipRule clip_rule() const { return m_inherited.clip_rule; }
|
CSS::ClipRule clip_rule() const { return m_inherited.clip_rule; }
|
||||||
Color flood_color() const { return m_noninherited.flood_color; }
|
Color flood_color() const { return m_noninherited.flood_color; }
|
||||||
float flood_opacity() const { return m_noninherited.flood_opacity; }
|
float flood_opacity() const { return m_noninherited.flood_opacity; }
|
||||||
|
PaintOrderList paint_order() const { return m_inherited.paint_order; }
|
||||||
|
|
||||||
LengthPercentage const& cx() const { return m_noninherited.cx; }
|
LengthPercentage const& cx() const { return m_noninherited.cx; }
|
||||||
LengthPercentage const& cy() const { return m_noninherited.cy; }
|
LengthPercentage const& cy() const { return m_noninherited.cy; }
|
||||||
|
@ -702,6 +706,7 @@ protected:
|
||||||
CSS::FillRule fill_rule { InitialValues::fill_rule() };
|
CSS::FillRule fill_rule { InitialValues::fill_rule() };
|
||||||
Optional<SVGPaint> stroke;
|
Optional<SVGPaint> stroke;
|
||||||
float fill_opacity { InitialValues::fill_opacity() };
|
float fill_opacity { InitialValues::fill_opacity() };
|
||||||
|
PaintOrderList paint_order { InitialValues::paint_order() };
|
||||||
Vector<Variant<LengthPercentage, NumberOrCalculated>> stroke_dasharray;
|
Vector<Variant<LengthPercentage, NumberOrCalculated>> stroke_dasharray;
|
||||||
LengthPercentage stroke_dashoffset { InitialValues::stroke_dashoffset() };
|
LengthPercentage stroke_dashoffset { InitialValues::stroke_dashoffset() };
|
||||||
CSS::StrokeLinecap stroke_linecap { InitialValues::stroke_linecap() };
|
CSS::StrokeLinecap stroke_linecap { InitialValues::stroke_linecap() };
|
||||||
|
@ -1032,6 +1037,7 @@ public:
|
||||||
void set_flood_color(Color value) { m_noninherited.flood_color = value; }
|
void set_flood_color(Color value) { m_noninherited.flood_color = value; }
|
||||||
void set_flood_opacity(float value) { m_noninherited.flood_opacity = value; }
|
void set_flood_opacity(float value) { m_noninherited.flood_opacity = value; }
|
||||||
void set_shape_rendering(CSS::ShapeRendering value) { m_noninherited.shape_rendering = value; }
|
void set_shape_rendering(CSS::ShapeRendering value) { m_noninherited.shape_rendering = value; }
|
||||||
|
void set_paint_order(PaintOrderList value) { m_inherited.paint_order = value; }
|
||||||
|
|
||||||
void set_cx(LengthPercentage cx) { m_noninherited.cx = move(cx); }
|
void set_cx(LengthPercentage cx) { m_noninherited.cx = move(cx); }
|
||||||
void set_cy(LengthPercentage cy) { m_noninherited.cy = move(cy); }
|
void set_cy(LengthPercentage cy) { m_noninherited.cy = move(cy); }
|
||||||
|
|
|
@ -575,6 +575,11 @@
|
||||||
"legal",
|
"legal",
|
||||||
"ledger"
|
"ledger"
|
||||||
],
|
],
|
||||||
|
"paint-order": [
|
||||||
|
"fill",
|
||||||
|
"stroke",
|
||||||
|
"markers"
|
||||||
|
],
|
||||||
"pointer-events": [
|
"pointer-events": [
|
||||||
"auto",
|
"auto",
|
||||||
"all",
|
"all",
|
||||||
|
|
|
@ -319,6 +319,7 @@
|
||||||
"luminosity",
|
"luminosity",
|
||||||
"manipulation",
|
"manipulation",
|
||||||
"mark",
|
"mark",
|
||||||
|
"markers",
|
||||||
"marktext",
|
"marktext",
|
||||||
"match-parent",
|
"match-parent",
|
||||||
"match-source",
|
"match-source",
|
||||||
|
@ -498,6 +499,7 @@
|
||||||
"strict",
|
"strict",
|
||||||
"strict-origin",
|
"strict-origin",
|
||||||
"strict-origin-when-cross-origin",
|
"strict-origin-when-cross-origin",
|
||||||
|
"stroke",
|
||||||
"stroke-box",
|
"stroke-box",
|
||||||
"style",
|
"style",
|
||||||
"sub",
|
"sub",
|
||||||
|
|
|
@ -454,6 +454,7 @@ private:
|
||||||
RefPtr<StyleValue const> parse_math_depth_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_math_depth_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_opacity_value(PropertyID property_id, TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_opacity_value(PropertyID property_id, TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_overflow_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_overflow_value(TokenStream<ComponentValue>&);
|
||||||
|
RefPtr<StyleValue const> parse_paint_order_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_place_content_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_place_content_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_place_items_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_place_items_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<StyleValue const> parse_place_self_value(TokenStream<ComponentValue>&);
|
RefPtr<StyleValue const> parse_place_self_value(TokenStream<ComponentValue>&);
|
||||||
|
|
|
@ -701,6 +701,10 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
||||||
if (auto parsed_value = parse_overflow_value(tokens); parsed_value && !tokens.has_next_token())
|
if (auto parsed_value = parse_overflow_value(tokens); parsed_value && !tokens.has_next_token())
|
||||||
return parsed_value.release_nonnull();
|
return parsed_value.release_nonnull();
|
||||||
return ParseError::SyntaxError;
|
return ParseError::SyntaxError;
|
||||||
|
case PropertyID::PaintOrder:
|
||||||
|
if (auto parsed_value = parse_paint_order_value(tokens); parsed_value && !tokens.has_next_token())
|
||||||
|
return parsed_value.release_nonnull();
|
||||||
|
return ParseError::SyntaxError;
|
||||||
case PropertyID::PlaceContent:
|
case PropertyID::PlaceContent:
|
||||||
if (auto parsed_value = parse_place_content_value(tokens); parsed_value && !tokens.has_next_token())
|
if (auto parsed_value = parse_place_content_value(tokens); parsed_value && !tokens.has_next_token())
|
||||||
return parsed_value.release_nonnull();
|
return parsed_value.release_nonnull();
|
||||||
|
@ -3856,6 +3860,84 @@ RefPtr<StyleValue const> Parser::parse_overflow_value(TokenStream<ComponentValue
|
||||||
{ *maybe_x_value, *maybe_x_value });
|
{ *maybe_x_value, *maybe_x_value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<StyleValue const> Parser::parse_paint_order_value(TokenStream<ComponentValue>& tokens)
|
||||||
|
{
|
||||||
|
if (auto normal = parse_all_as_single_keyword_value(tokens, Keyword::Normal))
|
||||||
|
return normal;
|
||||||
|
|
||||||
|
bool has_fill = false;
|
||||||
|
bool has_stroke = false;
|
||||||
|
bool has_markers = false;
|
||||||
|
|
||||||
|
auto parse_paint_order_keyword = [&](auto& inner_tokens) -> RefPtr<StyleValue const> {
|
||||||
|
auto maybe_value = parse_keyword_value(inner_tokens);
|
||||||
|
if (!maybe_value)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
switch (maybe_value->to_keyword()) {
|
||||||
|
case Keyword::Fill:
|
||||||
|
if (has_fill)
|
||||||
|
return nullptr;
|
||||||
|
has_fill = true;
|
||||||
|
break;
|
||||||
|
case Keyword::Markers:
|
||||||
|
if (has_markers)
|
||||||
|
return nullptr;
|
||||||
|
has_markers = true;
|
||||||
|
break;
|
||||||
|
case Keyword::Stroke:
|
||||||
|
if (has_stroke)
|
||||||
|
return nullptr;
|
||||||
|
has_stroke = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maybe_value.release_nonnull();
|
||||||
|
};
|
||||||
|
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.is_empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto transaction = tokens.begin_transaction();
|
||||||
|
auto first_keyword_value = parse_paint_order_keyword(tokens);
|
||||||
|
if (!first_keyword_value)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (!tokens.has_next_token()) {
|
||||||
|
transaction.commit();
|
||||||
|
return first_keyword_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto second_keyword_value = parse_paint_order_keyword(tokens);
|
||||||
|
if (!second_keyword_value)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.has_next_token()) {
|
||||||
|
// The third keyword is parsed to ensure it is valid, but it doesn't get added to the list. This follows the
|
||||||
|
// shortest-serialization principle, as the value can always be inferred.
|
||||||
|
if (auto third_keyword_value = parse_paint_order_keyword(tokens); !third_keyword_value)
|
||||||
|
return nullptr;
|
||||||
|
tokens.discard_whitespace();
|
||||||
|
if (tokens.has_next_token())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
auto expected_second_keyword = Keyword::Fill;
|
||||||
|
if (first_keyword_value->to_keyword() == Keyword::Fill)
|
||||||
|
expected_second_keyword = Keyword::Stroke;
|
||||||
|
|
||||||
|
if (expected_second_keyword == second_keyword_value->to_keyword())
|
||||||
|
return first_keyword_value;
|
||||||
|
|
||||||
|
return StyleValueList::create({ first_keyword_value.release_nonnull(), second_keyword_value.release_nonnull() }, StyleValueList::Separator::Space);
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<StyleValue const> Parser::parse_place_content_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<StyleValue const> Parser::parse_place_content_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
|
|
|
@ -2889,6 +2889,17 @@
|
||||||
"unitless-length"
|
"unitless-length"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"paint-order": {
|
||||||
|
"animation-type": "discrete",
|
||||||
|
"inherited": true,
|
||||||
|
"initial": "normal",
|
||||||
|
"valid-identifiers": [
|
||||||
|
"normal"
|
||||||
|
],
|
||||||
|
"valid-types": [
|
||||||
|
"paint-order"
|
||||||
|
]
|
||||||
|
},
|
||||||
"place-content": {
|
"place-content": {
|
||||||
"inherited": false,
|
"inherited": false,
|
||||||
"initial": "normal",
|
"initial": "normal",
|
||||||
|
|
|
@ -854,6 +854,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
||||||
else if (stroke_width.is_percentage())
|
else if (stroke_width.is_percentage())
|
||||||
computed_values.set_stroke_width(CSS::LengthPercentage { stroke_width.as_percentage().percentage() });
|
computed_values.set_stroke_width(CSS::LengthPercentage { stroke_width.as_percentage().percentage() });
|
||||||
computed_values.set_shape_rendering(computed_style.shape_rendering());
|
computed_values.set_shape_rendering(computed_style.shape_rendering());
|
||||||
|
computed_values.set_paint_order(computed_style.paint_order());
|
||||||
|
|
||||||
auto const& mask_image = computed_style.property(CSS::PropertyID::MaskImage);
|
auto const& mask_image = computed_style.property(CSS::PropertyID::MaskImage);
|
||||||
if (mask_image.is_url()) {
|
if (mask_image.is_url()) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ static ReadonlySpan<NamedPropertyID> attribute_style_properties()
|
||||||
NamedPropertyID(CSS::PropertyID::MaskType),
|
NamedPropertyID(CSS::PropertyID::MaskType),
|
||||||
NamedPropertyID(CSS::PropertyID::Opacity),
|
NamedPropertyID(CSS::PropertyID::Opacity),
|
||||||
NamedPropertyID(CSS::PropertyID::Overflow),
|
NamedPropertyID(CSS::PropertyID::Overflow),
|
||||||
|
NamedPropertyID(CSS::PropertyID::PaintOrder),
|
||||||
NamedPropertyID(CSS::PropertyID::PointerEvents),
|
NamedPropertyID(CSS::PropertyID::PointerEvents),
|
||||||
NamedPropertyID(CSS::PropertyID::R, { SVG::TagNames::circle }),
|
NamedPropertyID(CSS::PropertyID::R, { SVG::TagNames::circle }),
|
||||||
NamedPropertyID(CSS::PropertyID::Rx, { SVG::TagNames::ellipse, SVG::TagNames::rect }),
|
NamedPropertyID(CSS::PropertyID::Rx, { SVG::TagNames::ellipse, SVG::TagNames::rect }),
|
||||||
|
|
|
@ -41,6 +41,7 @@ All properties associated with getComputedStyle(document.body):
|
||||||
"math-depth",
|
"math-depth",
|
||||||
"math-shift",
|
"math-shift",
|
||||||
"math-style",
|
"math-style",
|
||||||
|
"paint-order",
|
||||||
"pointer-events",
|
"pointer-events",
|
||||||
"quotes",
|
"quotes",
|
||||||
"shape-rendering",
|
"shape-rendering",
|
||||||
|
|
|
@ -610,6 +610,8 @@ All supported properties and their default values exposed from CSSStylePropertie
|
||||||
'padding-right': '0px'
|
'padding-right': '0px'
|
||||||
'paddingTop': '0px'
|
'paddingTop': '0px'
|
||||||
'padding-top': '0px'
|
'padding-top': '0px'
|
||||||
|
'paintOrder': 'normal'
|
||||||
|
'paint-order': 'normal'
|
||||||
'placeContent': 'normal'
|
'placeContent': 'normal'
|
||||||
'place-content': 'normal'
|
'place-content': 'normal'
|
||||||
'placeItems': 'normal legacy'
|
'placeItems': 'normal legacy'
|
||||||
|
|
|
@ -39,6 +39,7 @@ list-style-type: disc
|
||||||
math-depth: 0
|
math-depth: 0
|
||||||
math-shift: normal
|
math-shift: normal
|
||||||
math-style: normal
|
math-style: normal
|
||||||
|
paint-order: normal
|
||||||
pointer-events: auto
|
pointer-events: auto
|
||||||
quotes: auto
|
quotes: auto
|
||||||
shape-rendering: auto
|
shape-rendering: auto
|
||||||
|
@ -91,7 +92,7 @@ background-position-x: 0%
|
||||||
background-position-y: 0%
|
background-position-y: 0%
|
||||||
background-repeat: repeat
|
background-repeat: repeat
|
||||||
background-size: auto
|
background-size: auto
|
||||||
block-size: 1395px
|
block-size: 1410px
|
||||||
border-block-end-color: rgb(0, 0, 0)
|
border-block-end-color: rgb(0, 0, 0)
|
||||||
border-block-end-style: none
|
border-block-end-style: none
|
||||||
border-block-end-width: 0px
|
border-block-end-width: 0px
|
||||||
|
@ -167,7 +168,7 @@ grid-row-start: auto
|
||||||
grid-template-areas: none
|
grid-template-areas: none
|
||||||
grid-template-columns: none
|
grid-template-columns: none
|
||||||
grid-template-rows: none
|
grid-template-rows: none
|
||||||
height: 2535px
|
height: 2550px
|
||||||
inline-size: 784px
|
inline-size: 784px
|
||||||
inset-block-end: auto
|
inset-block-end: auto
|
||||||
inset-block-start: auto
|
inset-block-start: auto
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 257 tests
|
Found 258 tests
|
||||||
|
|
||||||
250 Pass
|
251 Pass
|
||||||
7 Fail
|
7 Fail
|
||||||
Pass accent-color
|
Pass accent-color
|
||||||
Pass border-collapse
|
Pass border-collapse
|
||||||
|
@ -43,6 +43,7 @@ Pass list-style-type
|
||||||
Pass math-depth
|
Pass math-depth
|
||||||
Pass math-shift
|
Pass math-shift
|
||||||
Pass math-style
|
Pass math-style
|
||||||
|
Pass paint-order
|
||||||
Pass pointer-events
|
Pass pointer-events
|
||||||
Pass quotes
|
Pass quotes
|
||||||
Pass shape-rendering
|
Pass shape-rendering
|
||||||
|
|
|
@ -2,15 +2,15 @@ Harness status: OK
|
||||||
|
|
||||||
Found 20 tests
|
Found 20 tests
|
||||||
|
|
||||||
15 Pass
|
14 Pass
|
||||||
5 Fail
|
6 Fail
|
||||||
Pass The serialization of border: 1px; border-top: 1px; should be canonical.
|
Pass The serialization of border: 1px; border-top: 1px; should be canonical.
|
||||||
Pass The serialization of border: 1px solid red; should be canonical.
|
Pass The serialization of border: 1px solid red; should be canonical.
|
||||||
Pass The serialization of border: 1px red; should be canonical.
|
Pass The serialization of border: 1px red; should be canonical.
|
||||||
Pass The serialization of border: red; should be canonical.
|
Pass The serialization of border: red; should be canonical.
|
||||||
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
|
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
|
||||||
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; should be canonical.
|
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; should be canonical.
|
||||||
Pass The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; should be canonical.
|
Fail The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; should be canonical.
|
||||||
Fail The serialization of border: 1px; border-top: 2px; should be canonical.
|
Fail The serialization of border: 1px; border-top: 2px; should be canonical.
|
||||||
Fail The serialization of border: 1px; border-top: 1px !important; should be canonical.
|
Fail The serialization of border: 1px; border-top: 1px !important; should be canonical.
|
||||||
Fail The serialization of border: 1px; border-top-color: red; should be canonical.
|
Fail The serialization of border: 1px; border-top-color: red; should be canonical.
|
||||||
|
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
||||||
|
|
||||||
Found 38 tests
|
Found 38 tests
|
||||||
|
|
||||||
30 Pass
|
32 Pass
|
||||||
8 Fail
|
6 Fail
|
||||||
Pass Property fill has initial value rgb(0, 0, 0)
|
Pass Property fill has initial value rgb(0, 0, 0)
|
||||||
Pass Property fill inherits
|
Pass Property fill inherits
|
||||||
Pass Property fill-rule has initial value nonzero
|
Pass Property fill-rule has initial value nonzero
|
||||||
|
@ -32,8 +32,8 @@ Fail Property marker-mid has initial value none
|
||||||
Fail Property marker-mid inherits
|
Fail Property marker-mid inherits
|
||||||
Fail Property marker-end has initial value none
|
Fail Property marker-end has initial value none
|
||||||
Fail Property marker-end inherits
|
Fail Property marker-end inherits
|
||||||
Fail Property paint-order has initial value normal
|
Pass Property paint-order has initial value normal
|
||||||
Fail Property paint-order inherits
|
Pass Property paint-order inherits
|
||||||
Pass Property color-interpolation has initial value srgb
|
Pass Property color-interpolation has initial value srgb
|
||||||
Pass Property color-interpolation inherits
|
Pass Property color-interpolation inherits
|
||||||
Pass Property shape-rendering has initial value auto
|
Pass Property shape-rendering has initial value auto
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 3 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
Pass e.style['paint-order'] = "normal stroke" should not set the property value
|
||||||
|
Pass e.style['paint-order'] = "fill fill" should not set the property value
|
||||||
|
Pass e.style['paint-order'] = "markers normal" should not set the property value
|
|
@ -0,0 +1,21 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 16 tests
|
||||||
|
|
||||||
|
16 Pass
|
||||||
|
Pass e.style['paint-order'] = "normal" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "fill" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "stroke" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "markers" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "fill stroke" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "fill markers" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "stroke fill" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "stroke markers" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "markers fill" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "markers stroke" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "fill stroke markers" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "fill markers stroke" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "stroke fill markers" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "stroke markers fill" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "markers fill stroke" should set the property value
|
||||||
|
Pass e.style['paint-order'] = "markers stroke fill" should set the property value
|
|
@ -0,0 +1,49 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 44 tests
|
||||||
|
|
||||||
|
44 Pass
|
||||||
|
Pass 'paint-order' computed style serialization, "normal" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill" => "fill" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke" => "stroke" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers" => "markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill stroke" => "fill" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill markers" => "fill markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke fill" => "stroke" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke markers" => "stroke markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers fill" => "markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers stroke" => "markers stroke" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill stroke markers" => "fill" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill markers stroke" => "fill markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke fill markers" => "stroke" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke markers fill" => "stroke markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers fill stroke" => "markers" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers stroke fill" => "markers stroke" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "foo" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill foo" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke foo" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers foo" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "normal foo" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill markers stroke foo" => "normal" (property)
|
||||||
|
Pass 'paint-order' computed style serialization, "normal" => "normal" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill" => "fill" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke" => "stroke" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers" => "markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill stroke" => "fill" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill markers" => "fill markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke fill" => "stroke" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke markers" => "stroke markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers fill" => "markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers stroke" => "markers stroke" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill stroke markers" => "fill" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill markers stroke" => "fill markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke fill markers" => "stroke" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke markers fill" => "stroke markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers fill stroke" => "markers" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers stroke fill" => "markers stroke" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "foo" => "normal" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill foo" => "normal" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "stroke foo" => "normal" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "markers foo" => "normal" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "normal foo" => "normal" (presentation attribute)
|
||||||
|
Pass 'paint-order' computed style serialization, "fill markers stroke foo" => "normal" (presentation attribute)
|
|
@ -1,8 +1,8 @@
|
||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 47 tests
|
Found 48 tests
|
||||||
|
|
||||||
44 Pass
|
45 Pass
|
||||||
3 Fail
|
3 Fail
|
||||||
Pass clip-path presentation attribute supported on an irrelevant element
|
Pass clip-path presentation attribute supported on an irrelevant element
|
||||||
Pass clip-rule presentation attribute supported on an irrelevant element
|
Pass clip-rule presentation attribute supported on an irrelevant element
|
||||||
|
@ -29,6 +29,7 @@ Pass mask-type presentation attribute supported on an irrelevant element
|
||||||
Pass mask presentation attribute supported on an irrelevant element
|
Pass mask presentation attribute supported on an irrelevant element
|
||||||
Pass opacity presentation attribute supported on an irrelevant element
|
Pass opacity presentation attribute supported on an irrelevant element
|
||||||
Pass overflow presentation attribute supported on an irrelevant element
|
Pass overflow presentation attribute supported on an irrelevant element
|
||||||
|
Pass paint-order presentation attribute supported on an irrelevant element
|
||||||
Pass pointer-events presentation attribute supported on an irrelevant element
|
Pass pointer-events presentation attribute supported on an irrelevant element
|
||||||
Pass shape-rendering presentation attribute supported on an irrelevant element
|
Pass shape-rendering presentation attribute supported on an irrelevant element
|
||||||
Pass stop-color presentation attribute supported on an irrelevant element
|
Pass stop-color presentation attribute supported on an irrelevant element
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 57 tests
|
Found 58 tests
|
||||||
|
|
||||||
53 Pass
|
54 Pass
|
||||||
4 Fail
|
4 Fail
|
||||||
Pass clip-path presentation attribute supported on a relevant element
|
Pass clip-path presentation attribute supported on a relevant element
|
||||||
Pass clip-rule presentation attribute supported on a relevant element
|
Pass clip-rule presentation attribute supported on a relevant element
|
||||||
|
@ -32,6 +32,7 @@ Pass mask-type presentation attribute supported on a relevant element
|
||||||
Pass mask presentation attribute supported on a relevant element
|
Pass mask presentation attribute supported on a relevant element
|
||||||
Pass opacity presentation attribute supported on a relevant element
|
Pass opacity presentation attribute supported on a relevant element
|
||||||
Pass overflow presentation attribute supported on a relevant element
|
Pass overflow presentation attribute supported on a relevant element
|
||||||
|
Pass paint-order presentation attribute supported on a relevant element
|
||||||
Pass pointer-events presentation attribute supported on a relevant element
|
Pass pointer-events presentation attribute supported on a relevant element
|
||||||
Pass r presentation attribute supported on a relevant element
|
Pass r presentation attribute supported on a relevant element
|
||||||
Pass rx presentation attribute supported on a relevant element
|
Pass rx presentation attribute supported on a relevant element
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Harness status: OK
|
Harness status: OK
|
||||||
|
|
||||||
Found 47 tests
|
Found 48 tests
|
||||||
|
|
||||||
44 Pass
|
45 Pass
|
||||||
3 Fail
|
3 Fail
|
||||||
Pass clip-path presentation attribute supported on an unknown SVG element
|
Pass clip-path presentation attribute supported on an unknown SVG element
|
||||||
Pass clip-rule presentation attribute supported on an unknown SVG element
|
Pass clip-rule presentation attribute supported on an unknown SVG element
|
||||||
|
@ -29,6 +29,7 @@ Pass mask-type presentation attribute supported on an unknown SVG element
|
||||||
Pass mask presentation attribute supported on an unknown SVG element
|
Pass mask presentation attribute supported on an unknown SVG element
|
||||||
Pass opacity presentation attribute supported on an unknown SVG element
|
Pass opacity presentation attribute supported on an unknown SVG element
|
||||||
Pass overflow presentation attribute supported on an unknown SVG element
|
Pass overflow presentation attribute supported on an unknown SVG element
|
||||||
|
Pass paint-order presentation attribute supported on an unknown SVG element
|
||||||
Pass pointer-events presentation attribute supported on an unknown SVG element
|
Pass pointer-events presentation attribute supported on an unknown SVG element
|
||||||
Pass shape-rendering presentation attribute supported on an unknown SVG element
|
Pass shape-rendering presentation attribute supported on an unknown SVG element
|
||||||
Pass stop-color presentation attribute supported on an unknown SVG element
|
Pass stop-color presentation attribute supported on an unknown SVG element
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:h="http://www.w3.org/1999/xhtml"
|
||||||
|
width="800px" height="800px">
|
||||||
|
<title>SVG Painting: parsing paint-order with invalid values</title>
|
||||||
|
<metadata>
|
||||||
|
<h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html#PaintOrderProperty"/>
|
||||||
|
<h:meta name="assert" content="paint-order supports only the grammar 'normal | [ fill || stroke || markers ]'."/>
|
||||||
|
<h:meta name="assert" content="paint-order uses the shortest serialization."/>
|
||||||
|
</metadata>
|
||||||
|
<g id="target"></g>
|
||||||
|
<h:script src="../../../resources/testharness.js"/>
|
||||||
|
<h:script src="../../../resources/testharnessreport.js"/>
|
||||||
|
<h:script src="../../../css/support/parsing-testcommon.js"/>
|
||||||
|
<script><![CDATA[
|
||||||
|
|
||||||
|
test_invalid_value("paint-order", "normal stroke");
|
||||||
|
test_invalid_value("paint-order", "fill fill");
|
||||||
|
test_invalid_value("paint-order", "markers normal");
|
||||||
|
|
||||||
|
]]></script>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 947 B |
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:h="http://www.w3.org/1999/xhtml"
|
||||||
|
width="800px" height="800px">
|
||||||
|
<title>SVG Painting: parsing paint-order with valid values</title>
|
||||||
|
<metadata>
|
||||||
|
<h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html#PaintOrderProperty"/>
|
||||||
|
<h:meta name="assert" content="paint-order supports the full grammar 'normal | [ fill || stroke || markers ]'."/>
|
||||||
|
<h:meta name="assert" content="paint-order uses the shortest serialization."/>
|
||||||
|
</metadata>
|
||||||
|
<g id="target"></g>
|
||||||
|
<h:script src="../../../resources/testharness.js"/>
|
||||||
|
<h:script src="../../../resources/testharnessreport.js"/>
|
||||||
|
<h:script src="../../../css/support/parsing-testcommon.js"/>
|
||||||
|
<script><![CDATA[
|
||||||
|
|
||||||
|
test_valid_value("paint-order", "normal");
|
||||||
|
|
||||||
|
test_valid_value("paint-order", "fill");
|
||||||
|
test_valid_value("paint-order", "stroke");
|
||||||
|
test_valid_value("paint-order", "markers");
|
||||||
|
|
||||||
|
test_valid_value("paint-order", "fill stroke", "fill");
|
||||||
|
test_valid_value("paint-order", "fill markers");
|
||||||
|
test_valid_value("paint-order", "stroke fill", "stroke");
|
||||||
|
test_valid_value("paint-order", "stroke markers");
|
||||||
|
test_valid_value("paint-order", "markers fill", "markers");
|
||||||
|
test_valid_value("paint-order", "markers stroke");
|
||||||
|
|
||||||
|
test_valid_value("paint-order", "fill stroke markers", "fill");
|
||||||
|
test_valid_value("paint-order", "fill markers stroke", "fill markers");
|
||||||
|
test_valid_value("paint-order", "stroke fill markers", "stroke");
|
||||||
|
test_valid_value("paint-order", "stroke markers fill", "stroke markers");
|
||||||
|
test_valid_value("paint-order", "markers fill stroke", "markers");
|
||||||
|
test_valid_value("paint-order", "markers stroke fill", "markers stroke");
|
||||||
|
|
||||||
|
]]></script>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,62 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml">
|
||||||
|
<title>'paint-order' computed style serialization</title>
|
||||||
|
<h:script src="../../../resources/testharness.js"/>
|
||||||
|
<h:script src="../../../resources/testharnessreport.js"/>
|
||||||
|
<text id="text" x="100" y="100"/>
|
||||||
|
<script><![CDATA[
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function make_tests(check, type) {
|
||||||
|
let tests = [
|
||||||
|
// Single keyword
|
||||||
|
["normal", "normal"],
|
||||||
|
["fill", "fill"],
|
||||||
|
["stroke", "stroke"],
|
||||||
|
["markers", "markers"],
|
||||||
|
// Two keywords
|
||||||
|
["fill stroke", "fill"],
|
||||||
|
["fill markers", "fill markers"],
|
||||||
|
["stroke fill", "stroke"],
|
||||||
|
["stroke markers", "stroke markers"],
|
||||||
|
["markers fill", "markers"],
|
||||||
|
["markers stroke", "markers stroke"],
|
||||||
|
// Three keywords
|
||||||
|
["fill stroke markers", "fill"],
|
||||||
|
["fill markers stroke", "fill markers"],
|
||||||
|
["stroke fill markers", "stroke"],
|
||||||
|
["stroke markers fill", "stroke markers"],
|
||||||
|
["markers fill stroke", "markers"],
|
||||||
|
["markers stroke fill", "markers stroke"],
|
||||||
|
// Invalid
|
||||||
|
["foo", "normal"],
|
||||||
|
["fill foo", "normal"],
|
||||||
|
["stroke foo", "normal"],
|
||||||
|
["markers foo", "normal"],
|
||||||
|
["normal foo", "normal"],
|
||||||
|
["fill markers stroke foo", "normal"],
|
||||||
|
];
|
||||||
|
for (let [value, expected] of tests) {
|
||||||
|
test(() => {
|
||||||
|
check(value, expected);
|
||||||
|
}, `${document.title}, "${value}" => "${expected}" (${type})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = document.getElementById("text");
|
||||||
|
|
||||||
|
make_tests((value, expected) => {
|
||||||
|
text.setAttribute("style", "paint-order: " + value);
|
||||||
|
let actual = getComputedStyle(text).paintOrder;
|
||||||
|
text.removeAttribute("style");
|
||||||
|
assert_equals(actual, expected, value);
|
||||||
|
}, "property");
|
||||||
|
|
||||||
|
make_tests((value, expected) => {
|
||||||
|
text.setAttribute("paint-order", value);
|
||||||
|
let actual = getComputedStyle(text).paintOrder;
|
||||||
|
text.removeAttribute("paint-order");
|
||||||
|
assert_equals(actual, expected, value);
|
||||||
|
}, "presentation attribute");
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
Loading…
Add table
Add a link
Reference in a new issue