LibWeb: Implement RecordingPainter::draw_text() via draw_text_run()

To get away from the ancient (and buggy) text layout code in
Gfx::Painter, we want to remove all the uses of Painter::draw_text().

As a first step towards this, we implement the draw_text() display list
command in terms of the draw_text_run() command by performing the very
simple necessary layout in draw_text() beforehand.
This commit is contained in:
Andreas Kling 2024-06-21 07:50:48 +02:00 committed by Andreas Kling
parent efce3d9671
commit 63f8feb9a4
Notes: sideshowbarker 2024-07-17 04:57:23 +09:00
4 changed files with 29 additions and 12 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -66,7 +66,7 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const
if (m_renders_as_alt_text) {
auto enclosing_rect = context.enclosing_device_rect(absolute_rect()).to_type<int>();
context.recording_painter().draw_rect(enclosing_rect, Gfx::Color::Black);
context.recording_painter().draw_text(enclosing_rect, m_alt_text, Platform::FontPlugin::the().default_font(), Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right);
context.recording_painter().draw_text(enclosing_rect, m_alt_text, Platform::FontPlugin::the().default_font(), Gfx::TextAlignment::Center, computed_values().color());
} else if (auto bitmap = m_image_provider.current_image_bitmap(image_rect.size().to_type<int>())) {
ScopedCornerRadiusClip corner_clip { context, image_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) };
auto image_int_rect = image_rect.to_type<int>();

View File

@ -222,19 +222,36 @@ void RecordingPainter::draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color col
});
}
void RecordingPainter::draw_text(Gfx::IntRect const& rect, String raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Color color, Gfx::TextElision elision, Gfx::TextWrapping wrapping)
void RecordingPainter::draw_text(Gfx::IntRect const& rect, String raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Color color)
{
if (rect.is_empty())
return;
append(DrawText {
.rect = state().translation.map(rect),
.raw_text = move(raw_text),
.alignment = alignment,
.color = color,
.elision = elision,
.wrapping = wrapping,
.font = font,
});
auto glyph_run = adopt_ref(*new Gfx::GlyphRun);
auto font_cascade_list = Gfx::FontCascadeList::create();
font_cascade_list->add(font);
float glyph_run_width = 0;
Gfx::for_each_glyph_position(
{ 0, 0 }, raw_text.code_points(), font_cascade_list, [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) {
glyph_run->append(glyph_or_emoji);
return IterationDecision::Continue;
},
Gfx::IncludeLeftBearing::No, glyph_run_width);
float baseline_x = 0;
if (alignment == Gfx::TextAlignment::CenterLeft) {
baseline_x = rect.x();
} else if (alignment == Gfx::TextAlignment::Center) {
baseline_x = static_cast<float>(rect.x()) + (static_cast<float>(rect.width()) - glyph_run_width) / 2.0f;
} else if (alignment == Gfx::TextAlignment::CenterRight) {
baseline_x = static_cast<float>(rect.right()) - glyph_run_width;
} else {
// Unimplemented alignment.
TODO();
}
auto metrics = font.pixel_metrics();
float baseline_y = static_cast<float>(rect.y()) + metrics.ascent + (static_cast<float>(rect.height()) - (metrics.ascent + metrics.descent)) / 2.0f;
draw_text_run(Gfx::IntPoint(roundf(baseline_x), roundf(baseline_y)), *glyph_run, color, rect, 1.0);
}
void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale)

View File

@ -95,7 +95,7 @@ public:
void draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color color, int thickness = 1, Gfx::LineStyle style = Gfx::LineStyle::Solid, Color alternate_color = Color::Transparent);
void draw_text(Gfx::IntRect const&, String, Gfx::Font const&, Gfx::TextAlignment = Gfx::TextAlignment::TopLeft, Color = Color::Black, Gfx::TextElision = Gfx::TextElision::None, Gfx::TextWrapping = Gfx::TextWrapping::DontWrap);
void draw_text(Gfx::IntRect const&, String, Gfx::Font const&, Gfx::TextAlignment, Color);
// Streamlined text drawing routine that does no wrapping/elision/alignment.
void draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale);