LibWeb: Improve list item marker positioning and alpha/roman text

This commit is a three-parter that is hard to separate without breaking
marker rendering:

  1. Any marker style that results in a string, except for a literal
     string (e.g. `list-style-type: "@"`), should get the string ". "
     appended. We forgot to do this for the alpha and roman types.

  2. Instead of using the "pixel size rounded up" from a font and adding
     an arbitrary 1 to that, we now use the exact pixel size for as long
     as possible to improve our vertical positioning of markers.

  3. Instead of always adding a "default marker width" to the marker
     content width, we now only do this if we did not have text metrics
     available (i.e. the marker style is not a text type). This greatly
     improves horizontal positioning of text markers.
This commit is contained in:
Jelle Raaijmakers 2025-07-15 13:37:13 +02:00 committed by Sam Atkins
commit 788d5368a7
Notes: github-actions[bot] 2025-07-15 18:06:51 +00:00
26 changed files with 152 additions and 129 deletions

View file

@ -28,33 +28,40 @@ Optional<String> ListItemMarkerBox::text() const
return m_list_style_type.visit(
[index](CSS::CounterStyleNameKeyword keyword) -> Optional<String> {
String text;
switch (keyword) {
case CSS::CounterStyleNameKeyword::Square:
case CSS::CounterStyleNameKeyword::Circle:
case CSS::CounterStyleNameKeyword::Disc:
case CSS::CounterStyleNameKeyword::DisclosureClosed:
case CSS::CounterStyleNameKeyword::DisclosureOpen:
return {};
case CSS::CounterStyleNameKeyword::Decimal:
return MUST(String::formatted("{}.", index));
case CSS::CounterStyleNameKeyword::DecimalLeadingZero:
// This is weird, but in accordance to spec.
return MUST(index < 10 ? String::formatted("0{}.", index) : String::formatted("{}.", index));
case CSS::CounterStyleNameKeyword::LowerAlpha:
case CSS::CounterStyleNameKeyword::LowerLatin:
return String::bijective_base_from(index - 1, String::Case::Lower);
case CSS::CounterStyleNameKeyword::UpperAlpha:
case CSS::CounterStyleNameKeyword::UpperLatin:
return String::bijective_base_from(index - 1, String::Case::Upper);
case CSS::CounterStyleNameKeyword::LowerRoman:
return String::roman_number_from(index, String::Case::Lower);
case CSS::CounterStyleNameKeyword::UpperRoman:
return String::roman_number_from(index, String::Case::Upper);
case CSS::CounterStyleNameKeyword::None:
return {};
case CSS::CounterStyleNameKeyword::Decimal:
text = String::number(index);
break;
case CSS::CounterStyleNameKeyword::DecimalLeadingZero:
// This is weird, but in accordance to spec.
text = index < 10 ? MUST(String::formatted("0{}", index)) : String::number(index);
break;
case CSS::CounterStyleNameKeyword::LowerAlpha:
case CSS::CounterStyleNameKeyword::LowerLatin:
text = String::bijective_base_from(index - 1, String::Case::Lower);
break;
case CSS::CounterStyleNameKeyword::UpperAlpha:
case CSS::CounterStyleNameKeyword::UpperLatin:
text = String::bijective_base_from(index - 1, String::Case::Upper);
break;
case CSS::CounterStyleNameKeyword::LowerRoman:
text = String::roman_number_from(index, String::Case::Lower);
break;
case CSS::CounterStyleNameKeyword::UpperRoman:
text = String::roman_number_from(index, String::Case::Upper);
break;
default:
VERIFY_NOT_REACHED();
}
return MUST(String::formatted("{}. ", text));
},
[](String const& string) -> Optional<String> {
return string;