mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:07:47 +00:00
LibWeb: Use glyph run to represent text in PaintTextShadow command
Given that we have a glyph run where the position of each glyph is calculated for text fragments during layout, we can reuse it to avoid this work during painting.
This commit is contained in:
parent
9f01e0f826
commit
b5f9c1d003
8 changed files with 33 additions and 17 deletions
Binary file not shown.
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
@ -225,7 +225,7 @@ CommandResult PaintingCommandExecutorCPU::paint_inner_box_shadow(PaintOuterBoxSh
|
||||||
return CommandResult::Continue;
|
return CommandResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult PaintingCommandExecutorCPU::paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, String const& text, Gfx::Font const& font, Color const& color, int fragment_baseline, Gfx::IntPoint const& draw_location)
|
CommandResult PaintingCommandExecutorCPU::paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color const& color, int fragment_baseline, Gfx::IntPoint const& draw_location)
|
||||||
{
|
{
|
||||||
// FIXME: Figure out the maximum bitmap size for all shadows and then allocate it once and reuse it?
|
// FIXME: Figure out the maximum bitmap size for all shadows and then allocate it once and reuse it?
|
||||||
auto maybe_shadow_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, shadow_bounding_rect.size());
|
auto maybe_shadow_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, shadow_bounding_rect.size());
|
||||||
|
@ -237,8 +237,17 @@ CommandResult PaintingCommandExecutorCPU::paint_text_shadow(int blur_radius, Gfx
|
||||||
|
|
||||||
Gfx::Painter shadow_painter { *shadow_bitmap };
|
Gfx::Painter shadow_painter { *shadow_bitmap };
|
||||||
// FIXME: "Spread" the shadow somehow.
|
// FIXME: "Spread" the shadow somehow.
|
||||||
Gfx::IntPoint baseline_start(text_rect.x(), text_rect.y() + fragment_baseline);
|
Gfx::IntPoint const baseline_start(text_rect.x(), text_rect.y() + fragment_baseline);
|
||||||
shadow_painter.draw_text_run(baseline_start, Utf8View(text), font, color);
|
shadow_painter.translate(baseline_start);
|
||||||
|
for (auto const& glyph_or_emoji : glyph_run) {
|
||||||
|
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
||||||
|
auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
|
||||||
|
shadow_painter.draw_glyph(glyph.position, glyph.code_point, *glyph.font, color);
|
||||||
|
} else {
|
||||||
|
auto const& emoji = glyph_or_emoji.get<Gfx::DrawEmoji>();
|
||||||
|
shadow_painter.draw_emoji(emoji.position.to_type<int>(), *emoji.emoji, *emoji.font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Blur
|
// Blur
|
||||||
Gfx::StackBlurFilter filter(*shadow_bitmap);
|
Gfx::StackBlurFilter filter(*shadow_bitmap);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&) override;
|
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&) override;
|
||||||
CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) override;
|
CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||||
CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) override;
|
CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||||
CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, String const& text, Gfx::Font const&, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) override;
|
CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) override;
|
||||||
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
||||||
CommandResult fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule winding_rule, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
CommandResult fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule winding_rule, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
||||||
CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
||||||
|
|
|
@ -165,7 +165,7 @@ CommandResult PaintingCommandExecutorGPU::paint_inner_box_shadow(PaintOuterBoxSh
|
||||||
return CommandResult::Continue;
|
return CommandResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult PaintingCommandExecutorGPU::paint_text_shadow(int, Gfx::IntRect const&, Gfx::IntRect const&, String const&, Gfx::Font const&, Color const&, int, Gfx::IntPoint const&)
|
CommandResult PaintingCommandExecutorGPU::paint_text_shadow(int, Gfx::IntRect const&, Gfx::IntRect const&, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int, Gfx::IntPoint const&)
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME
|
||||||
return CommandResult::Continue;
|
return CommandResult::Continue;
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&) override;
|
CommandResult paint_linear_gradient(Gfx::IntRect const&, Web::Painting::LinearGradientData const&) override;
|
||||||
CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) override;
|
CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||||
CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) override;
|
CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) override;
|
||||||
CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, String const& text, Gfx::Font const&, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) override;
|
CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) override;
|
||||||
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
||||||
CommandResult fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule winding_rule, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
CommandResult fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule winding_rule, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
||||||
CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Optional<Gfx::FloatPoint> const& aa_translation) override;
|
||||||
|
|
|
@ -344,14 +344,13 @@ void RecordingPainter::paint_inner_box_shadow_params(PaintOuterBoxShadowParams p
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingPainter::paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Utf8View text, Gfx::Font const& font, Color color, int fragment_baseline, Gfx::IntPoint draw_location)
|
void RecordingPainter::paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, int fragment_baseline, Gfx::IntPoint draw_location)
|
||||||
{
|
{
|
||||||
push_command(PaintTextShadow {
|
push_command(PaintTextShadow {
|
||||||
.blur_radius = blur_radius,
|
.blur_radius = blur_radius,
|
||||||
.shadow_bounding_rect = bounding_rect,
|
.shadow_bounding_rect = bounding_rect,
|
||||||
.text_rect = text_rect,
|
.text_rect = text_rect,
|
||||||
.text = String::from_utf8(text.as_string()).release_value_but_fixme_should_propagate_errors(),
|
.glyph_run = Vector<Gfx::DrawGlyphOrEmoji> { glyph_run },
|
||||||
.font = font,
|
|
||||||
.color = color,
|
.color = color,
|
||||||
.fragment_baseline = fragment_baseline,
|
.fragment_baseline = fragment_baseline,
|
||||||
.draw_location = state().translation.map(draw_location) });
|
.draw_location = state().translation.map(draw_location) });
|
||||||
|
@ -497,7 +496,7 @@ void RecordingPainter::execute(PaintingCommandExecutor& executor)
|
||||||
return executor.paint_inner_box_shadow(command.outer_box_shadow_params);
|
return executor.paint_inner_box_shadow(command.outer_box_shadow_params);
|
||||||
},
|
},
|
||||||
[&](PaintTextShadow const& command) {
|
[&](PaintTextShadow const& command) {
|
||||||
return executor.paint_text_shadow(command.blur_radius, command.shadow_bounding_rect, command.text_rect, command.text, command.font, command.color, command.fragment_baseline, command.draw_location);
|
return executor.paint_text_shadow(command.blur_radius, command.shadow_bounding_rect, command.text_rect, command.glyph_run, command.color, command.fragment_baseline, command.draw_location);
|
||||||
},
|
},
|
||||||
[&](FillRectWithRoundedCorners const& command) {
|
[&](FillRectWithRoundedCorners const& command) {
|
||||||
return executor.fill_rect_with_rounded_corners(command.rect, command.color, command.top_left_radius, command.top_right_radius, command.bottom_left_radius, command.bottom_right_radius, command.aa_translation);
|
return executor.fill_rect_with_rounded_corners(command.rect, command.color, command.top_left_radius, command.top_right_radius, command.bottom_left_radius, command.bottom_right_radius, command.aa_translation);
|
||||||
|
|
|
@ -141,8 +141,7 @@ struct PaintTextShadow {
|
||||||
int blur_radius;
|
int blur_radius;
|
||||||
Gfx::IntRect shadow_bounding_rect;
|
Gfx::IntRect shadow_bounding_rect;
|
||||||
Gfx::IntRect text_rect;
|
Gfx::IntRect text_rect;
|
||||||
String text;
|
Vector<Gfx::DrawGlyphOrEmoji> glyph_run;
|
||||||
NonnullRefPtr<Gfx::Font> font;
|
|
||||||
Color color;
|
Color color;
|
||||||
int fragment_baseline;
|
int fragment_baseline;
|
||||||
Gfx::IntPoint draw_location;
|
Gfx::IntPoint draw_location;
|
||||||
|
@ -373,7 +372,7 @@ public:
|
||||||
virtual CommandResult paint_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const&, Gfx::IntPoint const& position) = 0;
|
virtual CommandResult paint_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const&, Gfx::IntPoint const& position) = 0;
|
||||||
virtual CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) = 0;
|
virtual CommandResult paint_outer_box_shadow(PaintOuterBoxShadowParams const&) = 0;
|
||||||
virtual CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) = 0;
|
virtual CommandResult paint_inner_box_shadow(PaintOuterBoxShadowParams const&) = 0;
|
||||||
virtual CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, String const&, Gfx::Font const&, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) = 0;
|
virtual CommandResult paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const>, Color const&, int fragment_baseline, Gfx::IntPoint const& draw_location) = 0;
|
||||||
virtual CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const& aa_translation) = 0;
|
virtual CommandResult fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const& aa_translation) = 0;
|
||||||
virtual CommandResult fill_path_using_color(Gfx::Path const&, Color const& color, Gfx::Painter::WindingRule, Optional<Gfx::FloatPoint> const& aa_translation) = 0;
|
virtual CommandResult fill_path_using_color(Gfx::Path const&, Color const& color, Gfx::Painter::WindingRule, Optional<Gfx::FloatPoint> const& aa_translation) = 0;
|
||||||
virtual CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Optional<Gfx::FloatPoint> const& aa_translation) = 0;
|
virtual CommandResult fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const& paint_style, Gfx::Painter::WindingRule winding_rule, float opacity, Optional<Gfx::FloatPoint> const& aa_translation) = 0;
|
||||||
|
@ -493,7 +492,7 @@ public:
|
||||||
|
|
||||||
void paint_outer_box_shadow_params(PaintOuterBoxShadowParams params);
|
void paint_outer_box_shadow_params(PaintOuterBoxShadowParams params);
|
||||||
void paint_inner_box_shadow_params(PaintOuterBoxShadowParams params);
|
void paint_inner_box_shadow_params(PaintOuterBoxShadowParams params);
|
||||||
void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Utf8View text, Gfx::Font const& font, Color color, int fragment_baseline, Gfx::IntPoint draw_location);
|
void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, int fragment_baseline, Gfx::IntPoint draw_location);
|
||||||
|
|
||||||
void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius);
|
void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius);
|
||||||
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius);
|
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius);
|
||||||
|
|
|
@ -586,10 +586,19 @@ void paint_text_shadow(PaintContext& context, Layout::LineBoxFragment const& fra
|
||||||
auto fragment_width = context.enclosing_device_pixels(fragment.width()).value();
|
auto fragment_width = context.enclosing_device_pixels(fragment.width()).value();
|
||||||
auto fragment_height = context.enclosing_device_pixels(fragment.height()).value();
|
auto fragment_height = context.enclosing_device_pixels(fragment.height()).value();
|
||||||
auto draw_rect = context.enclosing_device_rect(fragment.absolute_rect()).to_type<int>();
|
auto draw_rect = context.enclosing_device_rect(fragment.absolute_rect()).to_type<int>();
|
||||||
auto text = Utf8View(fragment.text());
|
auto const& scaled_font = fragment.layout_node().scaled_font(context);
|
||||||
auto& font = fragment.layout_node().scaled_font(context);
|
|
||||||
auto fragment_baseline = context.rounded_device_pixels(fragment.baseline()).value();
|
auto fragment_baseline = context.rounded_device_pixels(fragment.baseline()).value();
|
||||||
|
|
||||||
|
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 = &scaled_font;
|
||||||
|
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
|
||||||
|
});
|
||||||
|
scaled_glyph_run.append(move(glyph));
|
||||||
|
}
|
||||||
|
|
||||||
// Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse
|
// Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse
|
||||||
for (auto& layer : shadow_layers.in_reverse()) {
|
for (auto& layer : shadow_layers.in_reverse()) {
|
||||||
int offset_x = context.rounded_device_pixels(layer.offset_x).value();
|
int offset_x = context.rounded_device_pixels(layer.offset_x).value();
|
||||||
|
@ -613,7 +622,7 @@ void paint_text_shadow(PaintContext& context, Layout::LineBoxFragment const& fra
|
||||||
draw_rect.y() + offset_y - margin
|
draw_rect.y() + offset_y - margin
|
||||||
};
|
};
|
||||||
|
|
||||||
context.recording_painter().paint_text_shadow(blur_radius, bounding_rect, text_rect, text, font, layer.color, fragment_baseline, draw_location);
|
context.recording_painter().paint_text_shadow(blur_radius, bounding_rect, text_rect, scaled_glyph_run, layer.color, fragment_baseline, draw_location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue