LibWeb: Generate logical property mappings

To support this, how we declare logical property aliases has changed.
Instead of `logical-alias-for` being a list of properties, it's now an
object with a `group` and `mapping`. The group is the name of a logical
property group in LogicalPropertyGroups.json. The mapping is which
side/dimension/corner this property is. Hopefully it's self-explanatory
enough.

The generated code is very much a copy of what was previously in
`StyleComputer::map_logical_alias_to_physical_property_id()`, so there
should be no behaviour change.
This commit is contained in:
Sam Atkins 2025-07-03 14:31:26 +01:00 committed by Andrew Kaster
parent 4c48a51860
commit 69d4811ef7
Notes: github-actions[bot] 2025-07-08 17:46:32 +00:00
9 changed files with 561 additions and 646 deletions

View file

@ -888,395 +888,6 @@ void StyleComputer::for_each_property_expanding_shorthands(PropertyID property_i
set_longhand_property(property_id, value);
}
// https://drafts.csswg.org/css-writing-modes-4/#logical-to-physical
PropertyID StyleComputer::map_logical_alias_to_physical_property_id(PropertyID property_id, LogicalAliasMappingContext mapping_context)
{
// FIXME: Note: The used direction depends on the computed writing-mode and text-orientation: in vertical writing
// modes, a text-orientation value of upright forces the used direction to ltr.
auto used_direction = mapping_context.direction;
switch (property_id) {
case PropertyID::BlockSize:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::Height;
return PropertyID::Width;
case PropertyID::BorderBlockEndColor:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::BorderBottomColor;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::BorderLeftColor;
return PropertyID::BorderRightColor;
case PropertyID::BorderBlockEndStyle:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::BorderBottomStyle;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::BorderLeftStyle;
return PropertyID::BorderRightStyle;
case PropertyID::BorderBlockEndWidth:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::BorderBottomWidth;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::BorderLeftWidth;
return PropertyID::BorderRightWidth;
case PropertyID::BorderBlockStartColor:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::BorderTopColor;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::BorderRightColor;
return PropertyID::BorderLeftColor;
case PropertyID::BorderBlockStartStyle:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::BorderTopStyle;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::BorderRightStyle;
return PropertyID::BorderLeftStyle;
case PropertyID::BorderBlockStartWidth:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::BorderTopWidth;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::BorderRightWidth;
return PropertyID::BorderLeftWidth;
case PropertyID::BorderEndEndRadius:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomRightRadius;
return PropertyID::BorderBottomLeftRadius;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomLeftRadius;
return PropertyID::BorderTopLeftRadius;
}
if (mapping_context.writing_mode == WritingMode::VerticalLr) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomRightRadius;
return PropertyID::BorderTopRightRadius;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopRightRadius;
return PropertyID::BorderBottomRightRadius;
case PropertyID::BorderEndStartRadius:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomLeftRadius;
return PropertyID::BorderBottomRightRadius;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopLeftRadius;
return PropertyID::BorderBottomLeftRadius;
}
if (mapping_context.writing_mode == WritingMode::VerticalLr) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopRightRadius;
return PropertyID::BorderBottomRightRadius;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomRightRadius;
return PropertyID::BorderTopRightRadius;
case PropertyID::BorderInlineStartColor:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderLeftColor;
return PropertyID::BorderRightColor;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopColor;
return PropertyID::BorderBottomColor;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomColor;
return PropertyID::BorderTopColor;
case PropertyID::BorderInlineStartStyle:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderLeftStyle;
return PropertyID::BorderRightStyle;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopStyle;
return PropertyID::BorderBottomStyle;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomStyle;
return PropertyID::BorderTopStyle;
case PropertyID::BorderInlineStartWidth:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderLeftWidth;
return PropertyID::BorderRightWidth;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopWidth;
return PropertyID::BorderBottomWidth;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomWidth;
return PropertyID::BorderTopWidth;
case PropertyID::BorderInlineEndColor:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderRightColor;
return PropertyID::BorderLeftColor;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomColor;
return PropertyID::BorderTopColor;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopColor;
return PropertyID::BorderBottomColor;
case PropertyID::BorderInlineEndStyle:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderRightStyle;
return PropertyID::BorderLeftStyle;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomStyle;
return PropertyID::BorderTopStyle;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopStyle;
return PropertyID::BorderBottomStyle;
case PropertyID::BorderInlineEndWidth:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderRightWidth;
return PropertyID::BorderLeftWidth;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomWidth;
return PropertyID::BorderTopWidth;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopWidth;
return PropertyID::BorderBottomWidth;
case PropertyID::BorderStartEndRadius:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopRightRadius;
return PropertyID::BorderTopLeftRadius;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomRightRadius;
return PropertyID::BorderTopRightRadius;
}
if (mapping_context.writing_mode == WritingMode::VerticalLr) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomLeftRadius;
return PropertyID::BorderTopLeftRadius;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopLeftRadius;
return PropertyID::BorderBottomLeftRadius;
case PropertyID::BorderStartStartRadius:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopLeftRadius;
return PropertyID::BorderTopRightRadius;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl)) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopRightRadius;
return PropertyID::BorderBottomRightRadius;
}
if (mapping_context.writing_mode == WritingMode::VerticalLr) {
if (used_direction == Direction::Ltr)
return PropertyID::BorderTopLeftRadius;
return PropertyID::BorderBottomLeftRadius;
}
if (used_direction == Direction::Ltr)
return PropertyID::BorderBottomLeftRadius;
return PropertyID::BorderTopLeftRadius;
case PropertyID::MarginBlockStart:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::MarginTop;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::MarginRight;
return PropertyID::MarginLeft;
case PropertyID::MarginBlockEnd:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::MarginBottom;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::MarginLeft;
return PropertyID::MarginRight;
case PropertyID::MarginInlineStart:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::MarginLeft;
return PropertyID::MarginRight;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::MarginTop;
return PropertyID::MarginBottom;
}
if (used_direction == Direction::Ltr)
return PropertyID::MarginBottom;
return PropertyID::MarginTop;
case PropertyID::MarginInlineEnd:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::MarginRight;
return PropertyID::MarginLeft;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::MarginBottom;
return PropertyID::MarginTop;
}
if (used_direction == Direction::Ltr)
return PropertyID::MarginTop;
return PropertyID::MarginBottom;
case PropertyID::MaxBlockSize:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::MaxHeight;
return PropertyID::MaxWidth;
case PropertyID::MaxInlineSize:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::MaxWidth;
return PropertyID::MaxHeight;
case PropertyID::MinBlockSize:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::MinHeight;
return PropertyID::MinWidth;
case PropertyID::MinInlineSize:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::MinWidth;
return PropertyID::MinHeight;
case PropertyID::PaddingBlockStart:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::PaddingTop;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::PaddingRight;
return PropertyID::PaddingLeft;
case PropertyID::PaddingBlockEnd:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::PaddingBottom;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::PaddingLeft;
return PropertyID::PaddingRight;
case PropertyID::PaddingInlineStart:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::PaddingLeft;
return PropertyID::PaddingRight;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::PaddingTop;
return PropertyID::PaddingBottom;
}
if (used_direction == Direction::Ltr)
return PropertyID::PaddingBottom;
return PropertyID::PaddingTop;
case PropertyID::PaddingInlineEnd:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::PaddingRight;
return PropertyID::PaddingLeft;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::PaddingBottom;
return PropertyID::PaddingTop;
}
if (used_direction == Direction::Ltr)
return PropertyID::PaddingTop;
return PropertyID::PaddingBottom;
case PropertyID::InlineSize:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::Width;
return PropertyID::Height;
case PropertyID::InsetBlockStart:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::Top;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::Right;
return PropertyID::Left;
case PropertyID::InsetBlockEnd:
if (mapping_context.writing_mode == WritingMode::HorizontalTb)
return PropertyID::Bottom;
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl))
return PropertyID::Left;
return PropertyID::Right;
case PropertyID::InsetInlineStart:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::Left;
return PropertyID::Right;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::Top;
return PropertyID::Bottom;
}
if (used_direction == Direction::Ltr)
return PropertyID::Bottom;
return PropertyID::Top;
case PropertyID::InsetInlineEnd:
if (mapping_context.writing_mode == WritingMode::HorizontalTb) {
if (used_direction == Direction::Ltr)
return PropertyID::Right;
return PropertyID::Left;
}
if (first_is_one_of(mapping_context.writing_mode, WritingMode::VerticalRl, WritingMode::SidewaysRl, WritingMode::VerticalLr)) {
if (used_direction == Direction::Ltr)
return PropertyID::Bottom;
return PropertyID::Top;
}
if (used_direction == Direction::Ltr)
return PropertyID::Top;
return PropertyID::Bottom;
default:
VERIFY(!property_is_logical_alias(property_id));
return property_id;
}
}
void StyleComputer::cascade_declarations(
CascadedProperties& cascaded_properties,
DOM::Element& element,
@ -1334,7 +945,7 @@ void StyleComputer::cascade_declarations(
if (property_is_logical_alias(longhand_id)) {
if (!logical_alias_mapping_context.has_value())
return;
physical_property_id = map_logical_alias_to_physical_property_id(longhand_id, logical_alias_mapping_context.value());
physical_property_id = map_logical_alias_to_physical_property(longhand_id, logical_alias_mapping_context.value());
} else {
physical_property_id = longhand_id;
}
@ -1523,7 +1134,7 @@ void StyleComputer::collect_animation_into(DOM::Element& element, Optional<CSS::
style_value = Parser::Parser::resolve_unresolved_style_value(Parser::ParsingParams { element.document() }, element, pseudo_element, property_id, style_value->as_unresolved());
for_each_property_expanding_shorthands(property_id, *style_value, [&](PropertyID longhand_id, CSSStyleValue const& longhand_value) {
auto physical_longhand_id = map_logical_alias_to_physical_property_id(longhand_id, LogicalAliasMappingContext { computed_properties.writing_mode(), computed_properties.direction() });
auto physical_longhand_id = map_logical_alias_to_physical_property(longhand_id, LogicalAliasMappingContext { computed_properties.writing_mode(), computed_properties.direction() });
auto physical_longhand_id_bitmap_index = to_underlying(physical_longhand_id) - to_underlying(first_longhand_property_id);
// Don't overwrite values if this is the result of a UseInitial
@ -2532,7 +2143,7 @@ void StyleComputer::compute_font(ComputedProperties& style, DOM::Element const*
}
}
StyleComputer::LogicalAliasMappingContext StyleComputer::compute_logical_alias_mapping_context(DOM::Element& element, Optional<CSS::PseudoElement> pseudo_element, ComputeStyleMode mode) const
LogicalAliasMappingContext StyleComputer::compute_logical_alias_mapping_context(DOM::Element& element, Optional<PseudoElement> pseudo_element, ComputeStyleMode mode) const
{
auto normalize_value = [&](auto property_id, auto value) {
if (!value || value->is_inherit() || value->is_unset()) {