浏览代码

LibPDF: Add infrastructure for accented character glyphs

Type1 accented character glyphs are composed of two other glyphs in the
same font: a base glyph and an accent glyph, given as char codes in the
standard encoding. These two glyphs are then composed together to form
the accented character.

This commit adds the data structures to hold the information for
accented characters, and also the routine that composes the final glyph
path out of the two individual components. All glyphs must have been
loaded by the time this composition takes place, and thus a new
protected consolidate_glyphs() routine has been added to perform this
calculation.
Rodrigo Tobar 2 年之前
父节点
当前提交
3eaa27f53a

+ 1 - 0
Userland/Libraries/LibPDF/Fonts/CFF.cpp

@@ -116,6 +116,7 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
         auto const& name = charset[i - 1];
         auto const& name = charset[i - 1];
         TRY(cff->add_glyph(name, move(glyphs[i])));
         TRY(cff->add_glyph(name, move(glyphs[i])));
     }
     }
+    cff->consolidate_glyphs();
 
 
     // Encoding given or read
     // Encoding given or read
     if (encoding) {
     if (encoding) {

+ 1 - 0
Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp

@@ -98,6 +98,7 @@ PDFErrorOr<void> PS1FontProgram::parse_encrypted_portion(ByteBuffer const& buffe
         }
         }
     }
     }
 
 
+    consolidate_glyphs();
     return {};
     return {};
 }
 }
 
 

+ 18 - 0
Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp

@@ -110,6 +110,24 @@ Gfx::AffineTransform Type1FontProgram::glyph_transform_to_device_space(Glyph con
     return transform;
     return transform;
 }
 }
 
 
+void Type1FontProgram::consolidate_glyphs()
+{
+    for (auto& [name, glyph] : m_glyph_map) {
+        if (!glyph.is_accented_character())
+            continue;
+        auto maybe_base_glyph = m_glyph_map.get(glyph.accented_character().base_character);
+        if (!maybe_base_glyph.has_value())
+            continue;
+        auto glyph_path = maybe_base_glyph.value().path();
+        auto maybe_accent_glyph = m_glyph_map.get(glyph.accented_character().accent_character);
+        if (maybe_accent_glyph.has_value()) {
+            auto path = maybe_accent_glyph.value().path();
+            glyph_path.append_path(move(path));
+        }
+        glyph.path() = glyph_path;
+    }
+}
+
 PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes const& data, Vector<ByteBuffer> const& subroutines, GlyphParserState& state, bool is_type2)
 PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes const& data, Vector<ByteBuffer> const& subroutines, GlyphParserState& state, bool is_type2)
 {
 {
     auto push = [&](float value) -> PDFErrorOr<void> {
     auto push = [&](float value) -> PDFErrorOr<void> {

+ 23 - 0
Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h

@@ -25,6 +25,19 @@ public:
     RefPtr<Encoding> encoding() const { return m_encoding; }
     RefPtr<Encoding> encoding() const { return m_encoding; }
 
 
 protected:
 protected:
+    struct AccentedCharacter {
+        AccentedCharacter(u8 base_char_code, u8 accent_char_code, float adx, float ady)
+            : base_character(Encoding::standard_encoding()->get_name(base_char_code))
+            , accent_character(Encoding::standard_encoding()->get_name(accent_char_code))
+            , accent_origin(adx, ady)
+        {
+        }
+
+        DeprecatedFlyString base_character;
+        DeprecatedFlyString accent_character;
+        Gfx::FloatPoint accent_origin;
+    };
+
     class Glyph {
     class Glyph {
 
 
     public:
     public:
@@ -38,9 +51,17 @@ protected:
         Gfx::Path& path() { return m_path; }
         Gfx::Path& path() { return m_path; }
         Gfx::Path const& path() const { return m_path; }
         Gfx::Path const& path() const { return m_path; }
 
 
+        bool is_accented_character() const { return m_accented_character.has_value(); }
+        AccentedCharacter const& accented_character() const { return m_accented_character.value(); }
+        void set_accented_character(AccentedCharacter&& accented_character)
+        {
+            m_accented_character = move(accented_character);
+        }
+
     private:
     private:
         Gfx::Path m_path;
         Gfx::Path m_path;
         Optional<float> m_width;
         Optional<float> m_width;
+        Optional<AccentedCharacter> m_accented_character;
     };
     };
 
 
     struct GlyphParserState {
     struct GlyphParserState {
@@ -86,6 +107,8 @@ protected:
         return {};
         return {};
     }
     }
 
 
+    void consolidate_glyphs();
+
 private:
 private:
     HashMap<DeprecatedFlyString, Glyph> m_glyph_map;
     HashMap<DeprecatedFlyString, Glyph> m_glyph_map;
     Gfx::AffineTransform m_font_matrix;
     Gfx::AffineTransform m_font_matrix;