1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 04:27:44 +00:00

LibWeb: Remove glyph run allocation in RecordingPainter::draw_text_run

Instead of allocating a new glyph run solely to shift each glyph by the
painter's offset, this offset could be encoded in a paint command and
applied later during command execution.
This commit is contained in:
Aliaksandr Kalenik 2024-03-01 13:22:35 +01:00 committed by Andreas Kling
parent 79fd8eb28d
commit aeb5a0d9e8
8 changed files with 21 additions and 16 deletions

View file

@ -41,6 +41,7 @@ struct DrawGlyphRun {
Vector<Gfx::DrawGlyphOrEmoji> glyph_run;
Color color;
Gfx::IntRect rect;
Gfx::FloatPoint translation;
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }

View file

@ -24,15 +24,17 @@ CommandExecutorCPU::CommandExecutorCPU(Gfx::Bitmap& bitmap)
.scaling_mode = {} });
}
CommandResult CommandExecutorCPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color)
CommandResult CommandExecutorCPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation)
{
auto& painter = this->painter();
for (auto& glyph_or_emoji : glyph_run) {
auto transformed_glyph = glyph_or_emoji;
transformed_glyph.visit([&](auto& glyph) { glyph.position.translate_by(translation); });
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
auto& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
auto& glyph = transformed_glyph.get<Gfx::DrawGlyph>();
painter.draw_glyph(glyph.position, glyph.code_point, *glyph.font, color);
} else {
auto& emoji = glyph_or_emoji.get<Gfx::DrawEmoji>();
auto& emoji = transformed_glyph.get<Gfx::DrawEmoji>();
painter.draw_emoji(emoji.position.to_type<int>(), *emoji.emoji, *emoji.font);
}
}

View file

@ -13,7 +13,7 @@ namespace Web::Painting {
class CommandExecutorCPU : public CommandExecutor {
public:
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&) override;
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation) override;
CommandResult draw_text(Gfx::IntRect const& rect, String const& raw_text, Gfx::TextAlignment alignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&) override;
CommandResult fill_rect(Gfx::IntRect const& rect, Color const&) override;
CommandResult draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) override;

View file

@ -31,9 +31,16 @@ CommandExecutorGPU::~CommandExecutorGPU()
painter().flush(m_target_bitmap);
}
CommandResult CommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color)
CommandResult CommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation)
{
painter().draw_glyph_run(glyph_run, color);
Vector<Gfx::DrawGlyphOrEmoji> transformed_glyph_run;
transformed_glyph_run.ensure_capacity(glyph_run.size());
for (auto& glyph : glyph_run) {
auto transformed_glyph = glyph;
transformed_glyph.visit([&](auto& glyph) { glyph.position.translate_by(translation); });
transformed_glyph_run.append(transformed_glyph);
}
painter().draw_glyph_run(transformed_glyph_run, color);
return CommandResult::Continue;
}

View file

@ -14,7 +14,7 @@ namespace Web::Painting {
class CommandExecutorGPU : public CommandExecutor {
public:
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&) override;
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation) override;
CommandResult draw_text(Gfx::IntRect const& rect, String const& raw_text, Gfx::TextAlignment alignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&) override;
CommandResult fill_rect(Gfx::IntRect const& rect, Color const&) override;
CommandResult draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) override;

View file

@ -87,7 +87,7 @@ void CommandList::execute(CommandExecutor& executor)
auto result = command.visit(
[&](DrawGlyphRun const& command) {
return executor.draw_glyph_run(command.glyph_run, command.color);
return executor.draw_glyph_run(command.glyph_run, command.color, command.translation);
},
[&](DrawText const& command) {
return executor.draw_text(command.rect, command.raw_text, command.alignment, command.color,

View file

@ -47,7 +47,7 @@ class CommandExecutor {
public:
virtual ~CommandExecutor() = default;
virtual CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&) = 0;
virtual CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation) = 0;
virtual CommandResult draw_text(Gfx::IntRect const&, String const&, Gfx::TextAlignment alignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&) = 0;
virtual CommandResult fill_rect(Gfx::IntRect const&, Color const&) = 0;
virtual CommandResult draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) = 0;

View file

@ -209,16 +209,11 @@ void RecordingPainter::draw_signed_distance_field(Gfx::IntRect const& dst_rect,
void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, Gfx::IntRect const& rect)
{
auto transformed_baseline_start = state().translation.map(baseline_start).to_type<float>();
Vector<Gfx::DrawGlyphOrEmoji> translated_glyph_run;
translated_glyph_run.ensure_capacity(glyph_run.size());
for (auto glyph : glyph_run) {
glyph.visit([&](auto& glyph) { glyph.position.translate_by(transformed_baseline_start); });
translated_glyph_run.append(glyph);
}
append(DrawGlyphRun {
.glyph_run = move(translated_glyph_run),
.glyph_run = Vector<Gfx::DrawGlyphOrEmoji> { glyph_run },
.color = color,
.rect = state().translation.map(rect),
.translation = transformed_baseline_start,
});
}