From c0849434574d064f798342f1ee1f0eda53c3dbd4 Mon Sep 17 00:00:00 2001 From: Rodrigo Tobar Date: Sun, 5 Feb 2023 14:04:48 +0800 Subject: [PATCH] LibPDF: Index Type1 glyphs by name, not char code Storing glyphs indexed by char code in a Type1 Font Program binds a Font Program instance to the particular Encoding that was used at Font Program construction time. This makes it difficult to reuse Font Program instances against different Encodings, which would be otherwise possible. This commit changes how we store the glyphs on Type1 Font Programs. Instead of storing them on a map indexed by char code, the map is now indexed by glyph name. In turn, when rendering a glyph we use the Encoding object to turn the char code into a glyph name, which in turn is used to index into the map of glyphs. This is the first step towards reusability of Type1 Font Programs. It also unlocks the ability to render glyphs that are described via the "seac" command (standard encoding accented character), which requires accessing the base and accent glyphs by name. --- Userland/Libraries/LibPDF/Fonts/CFF.cpp | 20 +++++++++---------- .../Libraries/LibPDF/Fonts/PS1FontProgram.cpp | 3 +-- Userland/Libraries/LibPDF/Fonts/Type1Font.cpp | 5 +++-- .../LibPDF/Fonts/Type1FontProgram.cpp | 12 +++++------ .../Libraries/LibPDF/Fonts/Type1FontProgram.h | 12 +++++------ 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Userland/Libraries/LibPDF/Fonts/CFF.cpp b/Userland/Libraries/LibPDF/Fonts/CFF.cpp index 2aad6a1b07..63e856c13e 100644 --- a/Userland/Libraries/LibPDF/Fonts/CFF.cpp +++ b/Userland/Libraries/LibPDF/Fonts/CFF.cpp @@ -108,29 +108,27 @@ PDFErrorOr> CFF::create(ReadonlyBytes const& cff_bytes, RefPt glyph.width += float(nominalWidthX); } + for (size_t i = 0; i < glyphs.size(); i++) { + if (i == 0) { + TRY(cff->add_glyph(0, move(glyphs[0]))); + continue; + } + auto const& name = charset[i - 1]; + TRY(cff->add_glyph(name, move(glyphs[i]))); + } + // Encoding given or read if (encoding) { - for (size_t i = 0; i < glyphs.size(); i++) { - if (i == 0) { - TRY(cff->add_glyph(0, move(glyphs[0]))); - continue; - } - auto const& name = charset[i - 1]; - u16 code = encoding->get_char_code(name); - TRY(cff->add_glyph(code, move(glyphs[i]))); - } cff->set_encoding(move(encoding)); } else { auto encoding = Encoding::create(); for (size_t i = 0; i < glyphs.size(); i++) { if (i == 0) { - TRY(cff->add_glyph(0, move(glyphs[0]))); encoding->set(0, ".notdef"); continue; } auto code = encoding_codes[i - 1]; auto char_name = charset[i - 1]; - TRY(cff->add_glyph(code, move(glyphs[i]))); encoding->set(code, char_name); } cff->set_encoding(move(encoding)); diff --git a/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp b/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp index b7a813a8a3..38e87a5b55 100644 --- a/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp +++ b/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp @@ -92,9 +92,8 @@ PDFErrorOr PS1FontProgram::parse_encrypted_portion(ByteBuffer const& buffe auto line = TRY(decrypt(reader.bytes().slice(reader.offset(), encrypted_size), m_encryption_key, m_lenIV)); reader.move_by(encrypted_size); auto glyph_name = word.substring_view(1); - auto char_code = encoding()->get_char_code(glyph_name); GlyphParserState state; - TRY(add_glyph(char_code, TRY(parse_glyph(line, subroutines, state, false)))); + TRY(add_glyph(glyph_name, TRY(parse_glyph(line, subroutines, state, false)))); } } } diff --git a/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp b/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp index 334c5ce991..4c97c98701 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp @@ -86,7 +86,8 @@ void Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float w return; } - auto translation = m_data.font_program->glyph_translation(char_code, width); + auto char_name = m_data.encoding->get_name(char_code); + auto translation = m_data.font_program->glyph_translation(char_name, width); point = point.translated(translation); auto glyph_position = Gfx::GlyphRasterPosition::get_nearest_fit_for(point); @@ -97,7 +98,7 @@ void Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float w if (maybe_bitmap.has_value()) { bitmap = maybe_bitmap.value(); } else { - bitmap = m_data.font_program->rasterize_glyph(char_code, width, glyph_position.subpixel_offset); + bitmap = m_data.font_program->rasterize_glyph(char_name, width, glyph_position.subpixel_offset); m_glyph_cache.set(index, bitmap); } diff --git a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp index 920e344927..060fad86de 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp @@ -52,9 +52,9 @@ enum ExtendedCommand { Flex1, }; -RefPtr Type1FontProgram::rasterize_glyph(u32 char_code, float width, Gfx::GlyphSubpixelOffset subpixel_offset) +RefPtr Type1FontProgram::rasterize_glyph(DeprecatedFlyString const& char_name, float width, Gfx::GlyphSubpixelOffset subpixel_offset) { - auto path = build_char(char_code, width, subpixel_offset); + auto path = build_char(char_name, width, subpixel_offset); auto bounding_box = path.bounding_box().size(); u32 w = (u32)ceilf(bounding_box.width()) + 2; @@ -65,9 +65,9 @@ RefPtr Type1FontProgram::rasterize_glyph(u32 char_code, float width return rasterizer.accumulate(); } -Gfx::Path Type1FontProgram::build_char(u32 char_code, float width, Gfx::GlyphSubpixelOffset subpixel_offset) +Gfx::Path Type1FontProgram::build_char(DeprecatedFlyString const& char_name, float width, Gfx::GlyphSubpixelOffset subpixel_offset) { - auto maybe_glyph = m_glyph_map.get(char_code); + auto maybe_glyph = m_glyph_map.get(char_name); if (!maybe_glyph.has_value()) return {}; @@ -84,9 +84,9 @@ Gfx::Path Type1FontProgram::build_char(u32 char_code, float width, Gfx::GlyphSub return glyph.path.copy_transformed(transform); } -Gfx::FloatPoint Type1FontProgram::glyph_translation(u32 char_code, float width) const +Gfx::FloatPoint Type1FontProgram::glyph_translation(DeprecatedFlyString const& char_name, float width) const { - auto maybe_glyph = m_glyph_map.get(char_code); + auto maybe_glyph = m_glyph_map.get(char_name); if (!maybe_glyph.has_value()) return {}; diff --git a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h index c4240a7cf3..a6e2140f7e 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h +++ b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h @@ -20,8 +20,8 @@ class Encoding; class Type1FontProgram : public RefCounted { public: - RefPtr rasterize_glyph(u32 char_code, float width, Gfx::GlyphSubpixelOffset subpixel_offset); - Gfx::FloatPoint glyph_translation(u32 char_code, float width) const; + RefPtr rasterize_glyph(DeprecatedFlyString const& char_name, float width, Gfx::GlyphSubpixelOffset subpixel_offset); + Gfx::FloatPoint glyph_translation(DeprecatedFlyString const& char_name, float width) const; RefPtr encoding() const { return m_encoding; } protected: @@ -68,18 +68,18 @@ protected: m_font_matrix = move(font_matrix); } - PDFErrorOr add_glyph(u16 char_code, Glyph&& glyph) + PDFErrorOr add_glyph(DeprecatedFlyString name, Glyph&& glyph) { - TRY(m_glyph_map.try_set(char_code, glyph)); + TRY(m_glyph_map.try_set(move(name), move(glyph))); return {}; } private: - HashMap m_glyph_map; + HashMap m_glyph_map; Gfx::AffineTransform m_font_matrix; RefPtr m_encoding; - Gfx::Path build_char(u32 char_code, float width, Gfx::GlyphSubpixelOffset subpixel_offset); + Gfx::Path build_char(DeprecatedFlyString const& char_name, float width, Gfx::GlyphSubpixelOffset subpixel_offset); Gfx::AffineTransform glyph_transform_to_device_space(Glyph const& glyph, float width) const; };