mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:07:36 +00:00
LibWeb: Remove glyph run allocation in paint_text_fragment()
Instead of allocating a new glyph run to scale glyph positions and fonts, a scale factor could be encoded in a paint command and applied later during command execution.
This commit is contained in:
parent
aeb5a0d9e8
commit
cf6999f5f3
11 changed files with 25 additions and 27 deletions
|
@ -11,12 +11,8 @@ namespace Web::Painting {
|
|||
|
||||
void DrawGlyphRun::translate_by(Gfx::IntPoint const& offset)
|
||||
{
|
||||
for (auto& glyph : glyph_run) {
|
||||
glyph.visit([&](auto& glyph) {
|
||||
glyph.translate_by(offset.to_type<float>());
|
||||
});
|
||||
}
|
||||
rect.translate_by(offset);
|
||||
translation.translate_by(offset.to_type<float>());
|
||||
}
|
||||
|
||||
Gfx::IntRect PaintOuterBoxShadow::bounding_rect() const
|
||||
|
|
|
@ -42,6 +42,7 @@ struct DrawGlyphRun {
|
|||
Color color;
|
||||
Gfx::IntRect rect;
|
||||
Gfx::FloatPoint translation;
|
||||
double scale { 1 };
|
||||
|
||||
[[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; }
|
||||
|
||||
|
|
|
@ -24,12 +24,15 @@ CommandExecutorCPU::CommandExecutorCPU(Gfx::Bitmap& bitmap)
|
|||
.scaling_mode = {} });
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorCPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation)
|
||||
CommandResult CommandExecutorCPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation, double scale)
|
||||
{
|
||||
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); });
|
||||
transformed_glyph.visit([&](auto& glyph) {
|
||||
glyph.position = glyph.position.scaled(scale).translated(translation);
|
||||
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
|
||||
});
|
||||
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
||||
auto& glyph = transformed_glyph.get<Gfx::DrawGlyph>();
|
||||
painter.draw_glyph(glyph.position, glyph.code_point, *glyph.font, color);
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Web::Painting {
|
|||
|
||||
class CommandExecutorCPU : public CommandExecutor {
|
||||
public:
|
||||
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation) override;
|
||||
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation, double scale) 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;
|
||||
|
|
|
@ -31,13 +31,16 @@ CommandExecutorGPU::~CommandExecutorGPU()
|
|||
painter().flush(m_target_bitmap);
|
||||
}
|
||||
|
||||
CommandResult CommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation)
|
||||
CommandResult CommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation, double scale)
|
||||
{
|
||||
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.visit([&](auto& glyph) {
|
||||
glyph.position = glyph.position.scaled(scale).translated(translation);
|
||||
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
|
||||
});
|
||||
transformed_glyph_run.append(transformed_glyph);
|
||||
}
|
||||
painter().draw_glyph_run(transformed_glyph_run, color);
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Web::Painting {
|
|||
|
||||
class CommandExecutorGPU : public CommandExecutor {
|
||||
public:
|
||||
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation) override;
|
||||
CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation, double scale) 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;
|
||||
|
|
|
@ -48,10 +48,12 @@ void CommandList::execute(CommandExecutor& executor)
|
|||
for (auto& command_with_scroll_id : m_commands) {
|
||||
auto& command = command_with_scroll_id.command;
|
||||
if (command.has<DrawGlyphRun>()) {
|
||||
auto scale = command.get<DrawGlyphRun>().scale;
|
||||
for (auto const& glyph_or_emoji : command.get<DrawGlyphRun>().glyph_run) {
|
||||
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
||||
auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
|
||||
unique_glyphs.ensure(glyph.font, [] { return HashTable<u32> {}; }).set(glyph.code_point);
|
||||
auto const& font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
|
||||
unique_glyphs.ensure(&font, [] { return HashTable<u32> {}; }).set(glyph.code_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +89,7 @@ void CommandList::execute(CommandExecutor& executor)
|
|||
|
||||
auto result = command.visit(
|
||||
[&](DrawGlyphRun const& command) {
|
||||
return executor.draw_glyph_run(command.glyph_run, command.color, command.translation);
|
||||
return executor.draw_glyph_run(command.glyph_run, command.color, command.translation, command.scale);
|
||||
},
|
||||
[&](DrawText const& command) {
|
||||
return executor.draw_text(command.rect, command.raw_text, command.alignment, command.color,
|
||||
|
|
|
@ -47,7 +47,7 @@ class CommandExecutor {
|
|||
public:
|
||||
virtual ~CommandExecutor() = default;
|
||||
|
||||
virtual CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation) = 0;
|
||||
virtual CommandResult draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const&, Gfx::FloatPoint translation, double scale) = 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;
|
||||
|
|
|
@ -668,23 +668,15 @@ void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_nod
|
|||
auto text = text_node.text_for_rendering();
|
||||
|
||||
DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) };
|
||||
Vector<Gfx::DrawGlyphOrEmoji> scaled_glyph_run;
|
||||
scaled_glyph_run.ensure_capacity(fragment.glyph_run().size());
|
||||
for (auto glyph : fragment.glyph_run()) {
|
||||
glyph.visit([&](auto& glyph) {
|
||||
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
|
||||
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
|
||||
});
|
||||
scaled_glyph_run.append(move(glyph));
|
||||
}
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), scaled_glyph_run, text_node.computed_values().color(), fragment_absolute_device_rect.to_type<int>());
|
||||
auto scale = context.device_pixels_per_css_pixel();
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), fragment.glyph_run(), text_node.computed_values().color(), fragment_absolute_device_rect.to_type<int>(), scale);
|
||||
|
||||
auto selection_rect = context.enclosing_device_rect(fragment.selection_rect(text_node.first_available_font())).to_type<int>();
|
||||
if (!selection_rect.is_empty()) {
|
||||
painter.fill_rect(selection_rect, CSS::SystemColor::highlight());
|
||||
RecordingPainterStateSaver saver(painter);
|
||||
painter.add_clip_rect(selection_rect);
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), scaled_glyph_run, CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type<int>());
|
||||
painter.draw_text_run(baseline_start.to_type<int>(), fragment.glyph_run(), CSS::SystemColor::highlight_text(), fragment_absolute_device_rect.to_type<int>(), scale);
|
||||
}
|
||||
|
||||
paint_text_decoration(context, text_node, fragment);
|
||||
|
|
|
@ -206,7 +206,7 @@ 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)
|
||||
void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, Gfx::IntRect const& rect, double scale)
|
||||
{
|
||||
auto transformed_baseline_start = state().translation.map(baseline_start).to_type<float>();
|
||||
append(DrawGlyphRun {
|
||||
|
@ -214,6 +214,7 @@ void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Span<Gfx::Dra
|
|||
.color = color,
|
||||
.rect = state().translation.map(rect),
|
||||
.translation = transformed_baseline_start,
|
||||
.scale = scale,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
void draw_signed_distance_field(Gfx::IntRect const& dst_rect, Color color, Gfx::GrayscaleBitmap const& sdf, float smoothing);
|
||||
|
||||
// Streamlined text drawing routine that does no wrapping/elision/alignment.
|
||||
void draw_text_run(Gfx::IntPoint baseline_start, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, Gfx::IntRect const& rect);
|
||||
void draw_text_run(Gfx::IntPoint baseline_start, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, Gfx::IntRect const& rect, double scale);
|
||||
|
||||
void add_clip_rect(Gfx::IntRect const& rect);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue