mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:58:11 +00:00
LibGfx+LibWeb: Use ref-counted object to store glyph run
...to avoid allocating a copy of glyph run for painting commands. We can't simply save pointers to a glyph run in layout/paintable tree because it should be safe to deallocate layout and paintable trees after painting commands are recorded, if in the future we decide to move command execution to a separate thread.
This commit is contained in:
parent
cf6999f5f3
commit
06c176bbfb
9 changed files with 32 additions and 15 deletions
|
@ -100,6 +100,23 @@ struct DrawEmoji {
|
||||||
|
|
||||||
using DrawGlyphOrEmoji = Variant<DrawGlyph, DrawEmoji>;
|
using DrawGlyphOrEmoji = Variant<DrawGlyph, DrawEmoji>;
|
||||||
|
|
||||||
|
class GlyphRun : public RefCounted<GlyphRun> {
|
||||||
|
public:
|
||||||
|
GlyphRun() = default;
|
||||||
|
GlyphRun(Vector<Gfx::DrawGlyphOrEmoji>&& glyphs)
|
||||||
|
: m_glyphs(move(glyphs))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Vector<Gfx::DrawGlyphOrEmoji> const& glyphs() const { return m_glyphs; }
|
||||||
|
[[nodiscard]] bool is_empty() const { return m_glyphs.is_empty(); }
|
||||||
|
|
||||||
|
void append(Gfx::DrawGlyphOrEmoji glyph) { m_glyphs.append(glyph); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<Gfx::DrawGlyphOrEmoji> m_glyphs;
|
||||||
|
};
|
||||||
|
|
||||||
Variant<DrawGlyph, DrawEmoji> prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font);
|
Variant<DrawGlyph, DrawEmoji> prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font);
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
|
|
|
@ -26,7 +26,7 @@ void LineBox::add_fragment(Node const& layout_node, int start, int length, CSSPi
|
||||||
m_fragments.last().set_width(m_fragments.last().width() + content_width);
|
m_fragments.last().set_width(m_fragments.last().width() + content_width);
|
||||||
for (auto glyph : glyph_run) {
|
for (auto glyph : glyph_run) {
|
||||||
glyph.visit([&](auto& glyph) { glyph.position.translate_by(fragment_width.to_float(), 0); });
|
glyph.visit([&](auto& glyph) { glyph.position.translate_by(fragment_width.to_float(), 0); });
|
||||||
m_fragments.last().m_glyph_run.append(glyph);
|
m_fragments.last().m_glyph_run->append(glyph);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Vector<Gfx::DrawGlyphOrEmoji> glyph_run_copy { glyph_run };
|
Vector<Gfx::DrawGlyphOrEmoji> glyph_run_copy { glyph_run };
|
||||||
|
|
|
@ -19,7 +19,7 @@ class LineBoxFragment {
|
||||||
friend class LineBox;
|
friend class LineBox;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LineBoxFragment(Node const& layout_node, int start, int length, CSSPixelPoint offset, CSSPixelSize size, CSSPixels border_box_top, CSSPixels border_box_bottom, Vector<Gfx::DrawGlyphOrEmoji> glyph_run = {})
|
LineBoxFragment(Node const& layout_node, int start, int length, CSSPixelPoint offset, CSSPixelSize size, CSSPixels border_box_top, CSSPixels border_box_bottom, Vector<Gfx::DrawGlyphOrEmoji> glyphs)
|
||||||
: m_layout_node(layout_node)
|
: m_layout_node(layout_node)
|
||||||
, m_start(start)
|
, m_start(start)
|
||||||
, m_length(length)
|
, m_length(length)
|
||||||
|
@ -27,7 +27,7 @@ public:
|
||||||
, m_size(size)
|
, m_size(size)
|
||||||
, m_border_box_top(border_box_top)
|
, m_border_box_top(border_box_top)
|
||||||
, m_border_box_bottom(border_box_bottom)
|
, m_border_box_bottom(border_box_bottom)
|
||||||
, m_glyph_run(move(glyph_run))
|
, m_glyph_run(adopt_ref(*new Gfx::GlyphRun(move(glyphs))))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public:
|
||||||
|
|
||||||
bool is_atomic_inline() const;
|
bool is_atomic_inline() const;
|
||||||
|
|
||||||
Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run() const { return m_glyph_run; }
|
Gfx::GlyphRun const& glyph_run() const { return *m_glyph_run; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JS::NonnullGCPtr<Node const> m_layout_node;
|
JS::NonnullGCPtr<Node const> m_layout_node;
|
||||||
|
@ -71,7 +71,7 @@ private:
|
||||||
CSSPixels m_border_box_top { 0 };
|
CSSPixels m_border_box_top { 0 };
|
||||||
CSSPixels m_border_box_bottom { 0 };
|
CSSPixels m_border_box_bottom { 0 };
|
||||||
CSSPixels m_baseline { 0 };
|
CSSPixels m_baseline { 0 };
|
||||||
Vector<Gfx::DrawGlyphOrEmoji> m_glyph_run;
|
NonnullRefPtr<Gfx::GlyphRun> m_glyph_run;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
namespace Web::Painting {
|
namespace Web::Painting {
|
||||||
|
|
||||||
struct DrawGlyphRun {
|
struct DrawGlyphRun {
|
||||||
Vector<Gfx::DrawGlyphOrEmoji> glyph_run;
|
NonnullRefPtr<Gfx::GlyphRun> glyph_run;
|
||||||
Color color;
|
Color color;
|
||||||
Gfx::IntRect rect;
|
Gfx::IntRect rect;
|
||||||
Gfx::FloatPoint translation;
|
Gfx::FloatPoint translation;
|
||||||
|
|
|
@ -49,7 +49,7 @@ void CommandList::execute(CommandExecutor& executor)
|
||||||
auto& command = command_with_scroll_id.command;
|
auto& command = command_with_scroll_id.command;
|
||||||
if (command.has<DrawGlyphRun>()) {
|
if (command.has<DrawGlyphRun>()) {
|
||||||
auto scale = command.get<DrawGlyphRun>().scale;
|
auto scale = command.get<DrawGlyphRun>().scale;
|
||||||
for (auto const& glyph_or_emoji : command.get<DrawGlyphRun>().glyph_run) {
|
for (auto const& glyph_or_emoji : command.get<DrawGlyphRun>().glyph_run->glyphs()) {
|
||||||
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
|
||||||
auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
|
auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
|
||||||
auto const& font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
|
auto const& font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
|
||||||
|
@ -89,7 +89,7 @@ void CommandList::execute(CommandExecutor& executor)
|
||||||
|
|
||||||
auto result = command.visit(
|
auto result = command.visit(
|
||||||
[&](DrawGlyphRun const& command) {
|
[&](DrawGlyphRun const& command) {
|
||||||
return executor.draw_glyph_run(command.glyph_run, command.color, command.translation, command.scale);
|
return executor.draw_glyph_run(command.glyph_run->glyphs(), command.color, command.translation, command.scale);
|
||||||
},
|
},
|
||||||
[&](DrawText const& command) {
|
[&](DrawText const& command) {
|
||||||
return executor.draw_text(command.rect, command.raw_text, command.alignment, command.color,
|
return executor.draw_text(command.rect, command.raw_text, command.alignment, command.color,
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
|
|
||||||
CSSPixelRect const absolute_rect() const;
|
CSSPixelRect const absolute_rect() const;
|
||||||
|
|
||||||
Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run() const { return m_glyph_run; }
|
Gfx::GlyphRun const& glyph_run() const { return *m_glyph_run; }
|
||||||
|
|
||||||
CSSPixelRect selection_rect(Gfx::Font const&) const;
|
CSSPixelRect selection_rect(Gfx::Font const&) const;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ private:
|
||||||
int m_start;
|
int m_start;
|
||||||
int m_length;
|
int m_length;
|
||||||
Painting::BorderRadiiData m_border_radii_data;
|
Painting::BorderRadiiData m_border_radii_data;
|
||||||
Vector<Gfx::DrawGlyphOrEmoji> m_glyph_run;
|
NonnullRefPtr<Gfx::GlyphRun> m_glyph_run;
|
||||||
Vector<ShadowData> m_shadows;
|
Vector<ShadowData> m_shadows;
|
||||||
bool m_contained_by_inline_node { false };
|
bool m_contained_by_inline_node { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -206,11 +206,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, double scale)
|
void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale)
|
||||||
{
|
{
|
||||||
auto transformed_baseline_start = state().translation.map(baseline_start).to_type<float>();
|
auto transformed_baseline_start = state().translation.map(baseline_start).to_type<float>();
|
||||||
append(DrawGlyphRun {
|
append(DrawGlyphRun {
|
||||||
.glyph_run = Vector<Gfx::DrawGlyphOrEmoji> { glyph_run },
|
.glyph_run = glyph_run,
|
||||||
.color = color,
|
.color = color,
|
||||||
.rect = state().translation.map(rect),
|
.rect = state().translation.map(rect),
|
||||||
.translation = transformed_baseline_start,
|
.translation = transformed_baseline_start,
|
||||||
|
|
|
@ -100,7 +100,7 @@ public:
|
||||||
void draw_signed_distance_field(Gfx::IntRect const& dst_rect, Color color, Gfx::GrayscaleBitmap const& sdf, float smoothing);
|
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.
|
// 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, double scale);
|
void draw_text_run(Gfx::IntPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale);
|
||||||
|
|
||||||
void add_clip_rect(Gfx::IntRect const& rect);
|
void add_clip_rect(Gfx::IntRect const& rect);
|
||||||
|
|
||||||
|
|
|
@ -590,8 +590,8 @@ void paint_text_shadow(PaintContext& context, PaintableFragment const& fragment,
|
||||||
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;
|
Vector<Gfx::DrawGlyphOrEmoji> scaled_glyph_run;
|
||||||
scaled_glyph_run.ensure_capacity(fragment.glyph_run().size());
|
scaled_glyph_run.ensure_capacity(fragment.glyph_run().glyphs().size());
|
||||||
for (auto glyph : fragment.glyph_run()) {
|
for (auto glyph : fragment.glyph_run().glyphs()) {
|
||||||
glyph.visit([&](auto& glyph) {
|
glyph.visit([&](auto& glyph) {
|
||||||
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
|
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());
|
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue