From e103b1ec36f8d649a46dbfcd616aff8fa90c5889 Mon Sep 17 00:00:00 2001 From: MacDue Date: Sat, 18 Oct 2025 18:21:45 +0100 Subject: [PATCH] LibPDF: Separate resolving glyph IDs from drawing glyphs This will make reusing the logic to determine glyph IDs easier. No behaviour change intended. --- Userland/Libraries/LibGfx/Font/ScaledFont.h | 3 +- Userland/Libraries/LibGfx/Painter.cpp | 13 +++--- Userland/Libraries/LibGfx/Painter.h | 2 +- .../Libraries/LibPDF/Fonts/TrueTypeFont.cpp | 46 +++++++------------ .../Libraries/LibPDF/Fonts/TrueTypeFont.h | 3 ++ 5 files changed, 28 insertions(+), 39 deletions(-) diff --git a/Userland/Libraries/LibGfx/Font/ScaledFont.h b/Userland/Libraries/LibGfx/Font/ScaledFont.h index 738352f9dee..97cf58f34c7 100644 --- a/Userland/Libraries/LibGfx/Font/ScaledFont.h +++ b/Userland/Libraries/LibGfx/Font/ScaledFont.h @@ -30,6 +30,7 @@ public: ScaledGlyphMetrics glyph_metrics(u32 glyph_id) const { return m_font->glyph_metrics(glyph_id, m_x_scale, m_y_scale, m_point_width, m_point_height); } RefPtr rasterize_glyph(u32 glyph_id, GlyphSubpixelOffset) const; bool append_glyph_path_to(Gfx::Path&, u32 glyph_id) const; + Optional glyph_for_id(u32 id, GlyphSubpixelOffset) const; // ^Gfx::Font virtual NonnullRefPtr clone() const override { return MUST(try_clone()); } // FIXME: clone() should not need to be implemented @@ -80,8 +81,6 @@ public: virtual bool has_color_bitmaps() const override { return m_font->has_color_bitmaps(); } private: - Optional glyph_for_id(u32 id, GlyphSubpixelOffset) const; - NonnullRefPtr m_font; float m_x_scale { 0.0f }; float m_y_scale { 0.0f }; diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index c0a8beb0347..3ac47e8884b 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1371,14 +1372,14 @@ FLATTEN void Painter::draw_glyph(FloatPoint point, u32 code_point, Font const& f draw_glyph_internal(point, glyph_position, top_left, glyph, color); } -FLATTEN void Painter::draw_glyph_with_postscript_name(FloatPoint point, StringView name, Font const& font, Color color) +FLATTEN void Painter::draw_glyph_via_glyph_id(FloatPoint point, Gfx::ScaledFont const& font, u32 glyph_id, Color color) { - auto left_bearing = font.glyph_left_bearing_for_postscript_name(name); - if (!left_bearing.has_value()) - return; - auto top_left = point + FloatPoint(left_bearing.value(), 0); + auto top_left = point + Gfx::FloatPoint(font.glyph_metrics(glyph_id).left_side_bearing, 0); auto glyph_position = Gfx::GlyphRasterPosition::get_nearest_fit_for(top_left); - auto glyph = font.glyph_for_postscript_name(name, glyph_position.subpixel_offset).value(); + auto maybe_glyph = font.glyph_for_id(glyph_id, glyph_position.subpixel_offset); + if (!maybe_glyph.has_value()) + return; + auto glyph = maybe_glyph.release_value(); draw_glyph_internal(point, glyph_position, top_left, glyph, color); } diff --git a/Userland/Libraries/LibGfx/Painter.h b/Userland/Libraries/LibGfx/Painter.h index a691e1fccd1..1966d823f3d 100644 --- a/Userland/Libraries/LibGfx/Painter.h +++ b/Userland/Libraries/LibGfx/Painter.h @@ -114,9 +114,9 @@ public: void draw_glyph_or_emoji(IntPoint, Utf8CodePointIterator&, Font const&, Color); void draw_glyph(FloatPoint, u32, Color); void draw_glyph(FloatPoint, u32, Font const&, Color); - void draw_glyph_with_postscript_name(FloatPoint point, StringView name, Font const& font, Color color); void draw_glyph_or_emoji(FloatPoint, u32, Font const&, Color); void draw_glyph_or_emoji(FloatPoint, Utf8CodePointIterator&, Font const&, Color); + void draw_glyph_via_glyph_id(FloatPoint, Gfx::ScaledFont const&, u32, Color); void draw_circle_arc_intersecting(IntRect const&, IntPoint, int radius, Color, int thickness); // Streamlined text drawing routine that does no wrapping/elision/alignment. diff --git a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp index 7287eeadab8..edd38b0ab6b 100644 --- a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp +++ b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp @@ -62,40 +62,23 @@ NonnullOwnPtr TrueTypePainter::create(Document* document, Nonnu return adopt_own(*new TrueTypePainter { move(font), move(encoding), encoding_is_mac_roman_or_win_ansi, containing_pdf_font.is_nonsymbolic(), high_byte, is_zapf_dingbats }); } -static void do_draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u32 unicode, Gfx::ScaledFont const& font, ColorOrStyle const& style) +static void do_draw_glyph(Gfx::Painter& painter, u32 glyph_id, Gfx::FloatPoint point, float width, Gfx::ScaledFont const& font, ColorOrStyle const& style) { // Undo shift in Glyf::Glyph::append_simple_path() via OpenType::Font::rasterize_glyph(). auto position = point.translated(0, -font.pixel_metrics().ascent); if (style.has()) { - painter.draw_glyph(position, unicode, font, style.get()); + painter.draw_glyph_via_glyph_id(position, font, glyph_id, style.get()); } else { // FIXME: Bounding box and sample point look to be pretty wrong style.get>()->paint(Gfx::IntRect(position.x(), position.y(), width, 0), [&](auto sample) { - painter.draw_glyph(position, unicode, font, sample(Gfx::IntPoint(position.x(), position.y()))); + painter.draw_glyph_via_glyph_id(position, font, glyph_id, sample(Gfx::IntPoint(position.x(), position.y()))); }); } } -static void do_draw_glyph_with_postscript_name(Gfx::Painter& painter, Gfx::FloatPoint point, float width, StringView postscript_name, Gfx::ScaledFont const& font, ColorOrStyle const& style) +PDFErrorOr TrueTypePainter::resolve_glyph_id_for_char_code(u8 char_code) { - // Undo shift in Glyf::Glyph::append_simple_path() via OpenType::Font::rasterize_glyph(). - auto position = point.translated(0, -font.pixel_metrics().ascent); - - if (style.has()) { - painter.draw_glyph_with_postscript_name(position, postscript_name, font, style.get()); - } else { - // FIXME: Bounding box and sample point look to be pretty wrong - style.get>()->paint(Gfx::IntRect(position.x(), position.y(), width, 0), [&](auto sample) { - painter.draw_glyph_with_postscript_name(position, postscript_name, font, sample(Gfx::IntPoint(position.x(), position.y()))); - }); - } -} - -PDFErrorOr TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const& renderer) -{ - auto style = renderer.state().paint_style; - // 5.5.5 Character Encoding, Encodings for TrueType Fonts u32 unicode; @@ -126,17 +109,13 @@ PDFErrorOr TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPo // FIXME: Implement (1, 0) subtable support. auto char_name = m_encoding->get_name(char_code); u32 unicode = glyph_name_to_unicode(char_name, m_is_zapf_dingbats).value_or(char_code); - if (m_font->contains_glyph(unicode)) { - do_draw_glyph(painter, point, width, unicode, *m_font, style); - return {}; - } + if (m_font->contains_glyph(unicode)) + return m_font->glyph_id_for_code_point(unicode); // "In either of the cases above, if the glyph name cannot be mapped as specified, the glyph name is looked up // in the font program’s “post” table (if one is present) and the associated glyph description is used." - if (m_font->contains_glyph_for_postscript_name(char_name)) { - do_draw_glyph_with_postscript_name(painter, point, width, char_name, *m_font, style); - return {}; - } + if (m_font->contains_glyph_for_postscript_name(char_name)) + return m_font->glyph_id_for_postscript_name(char_name); return Error::malformed_error("Failed to draw glyph with postscript name"); } else if (m_high_byte.has_value()) { @@ -158,7 +137,14 @@ PDFErrorOr TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPo unicode = glyph_name_to_unicode(char_name, m_is_zapf_dingbats).value_or(char_code); } - do_draw_glyph(painter, point, width, unicode, *m_font, style); + return m_font->glyph_id_for_code_point(unicode); +} + +PDFErrorOr TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const& renderer) +{ + auto glyph_id = TRY(resolve_glyph_id_for_char_code(char_code)); + if (glyph_id.has_value()) + do_draw_glyph(painter, *glyph_id, point, width, m_font, renderer.state().paint_style); return {}; } diff --git a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h index ecd94a2d29a..aa9af3e0d1d 100644 --- a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h +++ b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h @@ -23,6 +23,9 @@ public: private: TrueTypePainter(AK::NonnullRefPtr, NonnullRefPtr, bool encoding_is_mac_roman_or_win_ansi, bool is_nonsymbolic, Optional high_byte, bool is_zapf_dingbats); + using GlyphID = Optional; + PDFErrorOr resolve_glyph_id_for_char_code(u8 char_code); + NonnullRefPtr m_font; NonnullRefPtr m_encoding; bool m_encoding_is_mac_roman_or_win_ansi { false };