LibGfx+LibWeb: Implement GlyphRun::bounding_rect()

Allows us to skip painting of glyph runs lying outside of viewport.
This commit is contained in:
Aliaksandr Kalenik 2025-09-23 04:56:53 +02:00 committed by Alexander Kalenik
parent 9c204f36ec
commit 2cf10981af
6 changed files with 27 additions and 6 deletions

View File

@ -15,6 +15,19 @@
namespace Gfx {
FloatRect GlyphRun::bounding_rect() const
{
if (glyphs().is_empty())
return {};
auto const& first = glyphs().first();
FloatRect result { first.position, { first.glyph_width, m_line_height } };
for (auto const& glyph : glyphs()) {
FloatRect glyph_rect { glyph.position, { glyph.glyph_width, m_line_height } };
result.unite(glyph_rect);
}
return result;
}
Vector<NonnullRefPtr<GlyphRun>> shape_text(FloatPoint baseline_start, Utf16View const& string, FontCascadeList const& font_cascade_list)
{
if (string.is_empty())
@ -88,6 +101,7 @@ static hb_buffer_t* setup_text_shaping(Utf16View const& string, Font const& font
NonnullRefPtr<GlyphRun> shape_text(FloatPoint baseline_start, float letter_spacing, Utf16View const& string, Font const& font, GlyphRun::TextType text_type, ShapeFeatures const& features)
{
auto const& metrics = font.pixel_metrics();
auto& shaping_cache = font.shaping_cache();
// NOTE: We only cache shaping results for a specific set of features. If the features change, we clear the cache.
@ -146,7 +160,7 @@ NonnullRefPtr<GlyphRun> shape_text(FloatPoint baseline_start, float letter_spaci
for (size_t i = 0; i < glyph_count; ++i) {
auto position = point
- FloatPoint { 0, font.pixel_metrics().ascent }
- FloatPoint { 0, metrics.ascent }
+ FloatPoint { positions[i].x_offset, positions[i].y_offset } / text_shaping_resolution;
glyph_run.unchecked_append({
@ -163,7 +177,7 @@ NonnullRefPtr<GlyphRun> shape_text(FloatPoint baseline_start, float letter_spaci
point.translate_by(letter_spacing, 0);
}
return adopt_ref(*new GlyphRun(move(glyph_run), font, text_type, point.x() - baseline_start.x()));
return adopt_ref(*new GlyphRun(move(glyph_run), font, text_type, point.x() - baseline_start.x(), metrics.ascent + metrics.descent));
}
float measure_text_width(Utf16View const& string, Font const& font, ShapeFeatures const& features)

View File

@ -15,6 +15,7 @@
#include <LibGfx/FontCascadeList.h>
#include <LibGfx/Forward.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/ShapeFeature.h>
namespace Gfx {
@ -36,11 +37,12 @@ public:
Rtl,
};
GlyphRun(Vector<DrawGlyph>&& glyphs, NonnullRefPtr<Font const> font, TextType text_type, float width)
GlyphRun(Vector<DrawGlyph>&& glyphs, NonnullRefPtr<Font const> font, TextType text_type, float width, float line_height)
: m_glyphs(move(glyphs))
, m_font(move(font))
, m_text_type(text_type)
, m_width(width)
, m_line_height(line_height)
{
}
@ -50,12 +52,14 @@ public:
[[nodiscard]] Vector<DrawGlyph>& glyphs() { return m_glyphs; }
[[nodiscard]] bool is_empty() const { return m_glyphs.is_empty(); }
[[nodiscard]] float width() const { return m_width; }
[[nodiscard]] FloatRect bounding_rect() const;
private:
Vector<DrawGlyph> m_glyphs;
NonnullRefPtr<Font const> m_font;
TextType m_text_type;
float m_width { 0 };
float m_line_height { 0 };
};
NonnullRefPtr<GlyphRun> shape_text(FloatPoint baseline_start, float letter_spacing, Utf16View const&, Gfx::Font const& font, GlyphRun::TextType, ShapeFeatures const& features);

View File

@ -13,6 +13,7 @@ void DrawGlyphRun::translate_by(Gfx::IntPoint const& offset)
{
rect.translate_by(offset);
translation.translate_by(offset.to_type<float>());
bounding_rectangle.translate_by(offset);
}
Gfx::IntRect PaintOuterBoxShadow::bounding_rect() const

View File

@ -43,7 +43,9 @@ struct DrawGlyphRun {
Gfx::FloatPoint translation;
Color color;
Gfx::Orientation orientation { Gfx::Orientation::Horizontal };
Gfx::IntRect bounding_rectangle;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return bounding_rectangle; }
void translate_by(Gfx::IntPoint const& offset);
void dump(StringBuilder&) const;
};

View File

@ -553,13 +553,12 @@ void DisplayListPlayerSkia::paint_text_shadow(PaintTextShadow const& command)
SkPaint blur_paint;
blur_paint.setImageFilter(blur_image_filter);
canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, &blur_paint, nullptr, 0));
draw_glyph_run({
.glyph_run = command.glyph_run,
draw_glyph_run({ .glyph_run = command.glyph_run,
.scale = command.glyph_run_scale,
.rect = command.text_rect,
.translation = command.draw_location + command.text_rect.location().to_type<float>(),
.color = command.color,
});
.bounding_rectangle = command.bounding_rect() });
canvas.restore();
}

View File

@ -255,6 +255,7 @@ void DisplayListRecorder::draw_glyph_run(Gfx::FloatPoint baseline_start, Gfx::Gl
.translation = baseline_start,
.color = color,
.orientation = orientation,
.bounding_rectangle = glyph_run.bounding_rect().scaled(scale).translated(baseline_start).to_type<int>(),
});
}