1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:27:35 +00:00

LibGfx+LibWeb: Calculate and save glyph positions during layout

Previously, we determined the positions of glyphs for each text run at
the time of painting, which constituted a significant portion of the
painting process according to profiles. However, since we already go
through each glyph to figure out the width of each fragment during
layout, we can simultaneously gather data about the position of each
glyph in the layout phase and utilize this information in the painting
phase.

I had to update expectations for a couple of reference tests. These
updates are due to the fact that we now measure glyph positions during
layout using a 1x font, and then linearly scale each glyph's position
to device pixels during painting. This approach should be acceptable,
considering we measure a fragment's width and height with an unscaled
font during layout.
This commit is contained in:
Aliaksandr Kalenik 2023-12-02 18:38:05 +01:00 committed by Andreas Kling
parent 1a35621930
commit 681771d210
17 changed files with 65 additions and 42 deletions

View file

@ -15,18 +15,24 @@
namespace Web::Layout {
void LineBox::add_fragment(Node const& layout_node, int start, int length, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, CSSPixels content_height, CSSPixels border_box_top, CSSPixels border_box_bottom)
void LineBox::add_fragment(Node const& layout_node, int start, int length, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, CSSPixels content_height, CSSPixels border_box_top, CSSPixels border_box_bottom, Span<Gfx::DrawGlyphOrEmoji const> glyph_run)
{
bool text_align_is_justify = layout_node.computed_values().text_align() == CSS::TextAlign::Justify;
if (!text_align_is_justify && !m_fragments.is_empty() && &m_fragments.last().layout_node() == &layout_node) {
auto const fragment_width = m_fragments.last().width();
// The fragment we're adding is from the last Layout::Node on the line.
// Expand the last fragment instead of adding a new one with the same Layout::Node.
m_fragments.last().m_length = (start - m_fragments.last().m_start) + length;
m_fragments.last().set_width(m_fragments.last().width() + content_width);
for (auto glyph : glyph_run) {
glyph.visit([&](auto& glyph) { glyph.position.translate_by(fragment_width.to_float(), 0); });
m_fragments.last().m_glyph_run.append(glyph);
}
} else {
Vector<Gfx::DrawGlyphOrEmoji> glyph_run_copy { glyph_run };
CSSPixels x_offset = leading_margin + leading_size + m_width;
CSSPixels y_offset = 0;
m_fragments.append(LineBoxFragment { layout_node, start, length, CSSPixelPoint(x_offset, y_offset), CSSPixelSize(content_width, content_height), border_box_top, border_box_bottom });
m_fragments.append(LineBoxFragment { layout_node, start, length, CSSPixelPoint(x_offset, y_offset), CSSPixelSize(content_width, content_height), border_box_top, border_box_bottom, move(glyph_run_copy) });
}
m_width += leading_margin + leading_size + content_width + trailing_size + trailing_margin;
m_height = max(m_height, content_height + border_box_top + border_box_bottom);