1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-08 05:27:14 +09:00

LibGfx+LibWeb: Add Path::glyph_run() and use in canvas

Canvas text painting needs to support per-glyph font fallbacks, which
means we can't hand over responsibility for text shaping to Skia and
instead need to extract glyph paths from our own shaped GlyphRun.
This commit is contained in:
Aliaksandr Kalenik 2025-04-19 18:40:17 +02:00 committed by Andreas Kling
parent 2c64c6d773
commit 1e7922fac8
Notes: github-actions[bot] 2025-04-21 07:52:25 +00:00
6 changed files with 22 additions and 2 deletions

View file

@ -15,6 +15,7 @@ class Color;
class Emoji;
class Font;
class GlyphRun;
class ImageDecoder;
struct FontPixelMetrics;

View file

@ -33,6 +33,7 @@ public:
virtual void quadratic_bezier_curve_to(FloatPoint through, FloatPoint point) = 0;
virtual void cubic_bezier_curve_to(FloatPoint c1, FloatPoint c2, FloatPoint p2) = 0;
virtual void text(Utf8View, Font const&) = 0;
virtual void glyph_run(GlyphRun const&) = 0;
virtual void append_path(Gfx::Path const&) = 0;
virtual void intersect(Gfx::Path const&) = 0;
@ -90,6 +91,7 @@ public:
void quadratic_bezier_curve_to(FloatPoint through, FloatPoint point) { impl().quadratic_bezier_curve_to(through, point); }
void cubic_bezier_curve_to(FloatPoint c1, FloatPoint c2, FloatPoint p2) { impl().cubic_bezier_curve_to(c1, c2, p2); }
void text(Utf8View text, Font const& font) { impl().text(text, font); }
void glyph_run(GlyphRun const& glyph_run) { impl().glyph_run(glyph_run); }
void horizontal_line_to(float x) { line_to({ x, last_point().y() }); }
void vertical_line_to(float y) { line_to({ last_point().x(), y }); }

View file

@ -11,6 +11,7 @@
#include <LibGfx/PathSkia.h>
#include <LibGfx/Rect.h>
#include <LibGfx/SkiaUtils.h>
#include <LibGfx/TextLayout.h>
#include <core/SkFont.h>
#include <core/SkPath.h>
#include <core/SkPathMeasure.h>
@ -139,6 +140,21 @@ void PathImplSkia::text(Utf8View string, Font const& font)
{
SkTextUtils::GetPath(string.as_string().characters_without_null_termination(), string.as_string().length(), SkTextEncoding::kUTF8, last_point().x(), last_point().y(), font.skia_font(1), m_path.ptr());
}
void PathImplSkia::glyph_run(GlyphRun const& glyph_run)
{
auto sk_font = glyph_run.font().skia_font(1);
m_path->setFillType(SkPathFillType::kWinding);
auto font_ascent = glyph_run.font().pixel_metrics().ascent;
for (auto const& glyph : glyph_run.glyphs()) {
SkPath glyph_path;
if (!sk_font.getPath(static_cast<SkGlyphID>(glyph.glyph_id), &glyph_path))
continue;
glyph_path.offset(glyph.position.x(), glyph.position.y() + font_ascent);
m_path->addPath(glyph_path);
}
}
NonnullOwnPtr<PathImpl> PathImplSkia::place_text_along(Utf8View text, Font const& font) const
{
auto sk_font = font.skia_font(1);

View file

@ -28,6 +28,7 @@ public:
virtual void quadratic_bezier_curve_to(FloatPoint through, FloatPoint point) override;
virtual void cubic_bezier_curve_to(FloatPoint c1, FloatPoint c2, FloatPoint p2) override;
virtual void text(Utf8View, Font const&) override;
virtual void glyph_run(GlyphRun const&) override;
virtual void append_path(Gfx::Path const&) override;
virtual void intersect(Gfx::Path const&) override;

View file

@ -235,8 +235,8 @@ Gfx::Path CanvasRenderingContext2D::text_path(StringView text, float x, float y,
auto const& font = font_cascade_list()->first();
Gfx::Path path;
path.move_to({ x, y });
path.text(Utf8View { text }, font);
auto glyph_run = Gfx::shape_text({ x, y }, 0, Utf8View(text), font, Gfx::GlyphRun::TextType::Ltr, {});
path.glyph_run(*glyph_run);
auto text_width = path.bounding_box().width();
Gfx::AffineTransform transform = {};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Before After
Before After