LibWeb: Implement "text-overflow" property

The "text-overflow" property affects text that may get clipped if it is
larger than its container and does not do any line breaks.
The ellipsis character gets added to the end and the rest of the text
gets trunctated if the property is set to "ellipsis".
This patch implements this behavior in the InlineFormattingContext. :^)

The "text-overflow" property is also added  to the
getComputedStyle-print-all test.
This commit is contained in:
Tobias Christiansen 2024-07-29 18:14:33 +02:00 committed by Sam Atkins
parent 794069b3cf
commit da7f0897d1
Notes: github-actions[bot] 2024-08-03 09:05:37 +00:00
2 changed files with 39 additions and 1 deletions

View File

@ -200,6 +200,7 @@ text-decoration-style: solid
text-decoration-thickness: auto
text-indent: 0px
text-justify: auto
text-overflow: clip
text-shadow: none
text-transform: none
top: auto

View File

@ -337,6 +337,44 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode)
// putting it on the next line.
if (is_whitespace && next_width > 0 && line_builder.break_if_needed(item.border_box_width() + next_width))
break;
} else if (text_node.computed_values().text_overflow() == CSS::TextOverflow::Ellipsis
&& text_node.computed_values().overflow_x() != CSS::Overflow::Visible) {
// We may need to do an ellipsis if the text is too long for the container
constexpr u32 ellipsis_codepoint = 0x2026;
if (m_available_space.has_value()
&& item.width.to_double() > m_available_space.value().width.to_px_or_zero().to_double()) {
// Do the ellipsis
auto& glyph_run = item.glyph_run;
auto available_width = m_available_space.value().width.to_px_or_zero().to_double();
auto ellipsis_width = glyph_run->font().glyph_width(ellipsis_codepoint);
auto max_text_width = available_width - ellipsis_width;
auto& glyphs = glyph_run->glyphs();
auto last_glyph_index = 0;
auto last_glyph_position = Gfx::FloatPoint();
for (auto const& glyph_or_emoji : glyphs) {
auto this_position = Gfx::FloatPoint();
glyph_or_emoji.visit(
[&](Gfx::DrawGlyph glyph) {
this_position = glyph.position;
},
[&](Gfx::DrawEmoji emoji) {
this_position = emoji.position;
});
if (this_position.x() > max_text_width)
break;
last_glyph_index++;
last_glyph_position = this_position;
}
auto remove_item_count = glyphs.size() - last_glyph_index;
glyphs.remove(last_glyph_index - 1, remove_item_count);
glyphs.append(Gfx::DrawGlyph(last_glyph_position, ellipsis_codepoint));
}
}
line_builder.append_text_chunk(
text_node,
@ -414,5 +452,4 @@ void InlineFormattingContext::set_vertical_float_clearance(CSSPixels vertical_fl
{
m_vertical_float_clearance = vertical_float_clearance;
}
}