diff --git a/Userland/Libraries/LibPDF/CommonNames.h b/Userland/Libraries/LibPDF/CommonNames.h index 12530c549e..ee8c1a7ad4 100644 --- a/Userland/Libraries/LibPDF/CommonNames.h +++ b/Userland/Libraries/LibPDF/CommonNames.h @@ -27,6 +27,8 @@ A(CF) \ A(CFM) \ A(CalRGB) \ + A(CIDFontType0) \ + A(CIDFontType2) \ A(CIDSystemInfo) \ A(CIDToGIDMap) \ A(Colors) \ diff --git a/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp b/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp index 0e31fdb377..bf469c704a 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp @@ -9,6 +9,57 @@ namespace PDF { +class CIDFontType { +public: + virtual ~CIDFontType() = default; + virtual PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float, float) = 0; +}; + +class CIDFontType0 : public CIDFontType { +public: + PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float, float) override; +}; + +PDFErrorOr CIDFontType0::draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float, float) +{ + // ISO 32000 (PDF 2.0) 9.7.4.2 Glyph selection in CIDFonts + // "When the CIDFont contains an embedded font program that is represented in the Compact Font Format (CFF), + // the FontFile3 entry in the font descriptor (...) shall be either CIDFontType0C or OpenType. + // There are two cases, depending on the contents of the font program: + // * The "CFF" font program has a Top DICT that uses CIDFont operators: The CIDs shall be used to determine + // the GID value for the glyph procedure using the charset table in the CFF program. + // The GID value shall then be used to look up the glyph procedure using the CharStrings INDEX table [...] + // * The "CFF" font program has a Top DICT that does not use CIDFont operators: The CIDs shall be used + // directly as GID values, and the glyph procedure shall be retrieved using the CharStrings INDEX" + return Error::rendering_unsupported_error("Type0 font CIDFontType0 not implemented yet"); +} + +class CIDFontType2 : public CIDFontType { +public: + PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float, float) override; +}; + +PDFErrorOr CIDFontType2::draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float, float) +{ + // ISO 32000 (PDF 2.0) 9.7.4.2 Glyph selection in CIDFonts + // "For Type 2, the CIDFont program is actually a TrueType font program, which has no native notion of CIDs. + // In a TrueType font program, glyph descriptions are identified by glyph index values. + // Glyph indices are internal to the font and are not defined consistently from one font to another. + // Instead, a TrueType font program contains a "cmap" table that provides mappings directly from + // character codes to glyph indices for one or more predefined encodings. + // TrueType font programs are integrated with the CID-keyed font architecture in one of two ways, + // depending on whether the font program is embedded in the PDF file: + // * If the TrueType font program is embedded, the Type 2 CIDFont dictionary shall contain a CIDToGIDMap entry + // that maps CIDs to the glyph indices for the appropriate glyph descriptions in that font program. + // * If the TrueType font program is not embedded but is referenced by name, and the Type 2 CIDFont dictionary + // contains a CIDToGIDMap entry, the CIDToGIDMap entry shall be ignored, since it is not meaningful + /// to refer to glyph indices in an external font program." + return Error::rendering_unsupported_error("Type0 font CIDFontType2 not implemented yet"); +} + +Type0Font::Type0Font() = default; +Type0Font::~Type0Font() = default; + PDFErrorOr Type0Font::initialize(Document* document, NonnullRefPtr const& dict, float font_size) { TRY(PDFFont::initialize(document, dict, font_size)); @@ -27,6 +78,17 @@ PDFErrorOr Type0Font::initialize(Document* document, NonnullRefPtrget_value(CommonNames::Supplement).get(); CIDSystemInfo system_info { registry, ordering, supplement }; + auto subtype = TRY(descendant_font->get_name(document, CommonNames::Subtype))->name(); + if (subtype == CommonNames::CIDFontType0) { + // CFF-based + m_cid_font_type = TRY(try_make()); + } else if (subtype == CommonNames::CIDFontType2) { + // TrueType-based + m_cid_font_type = TRY(try_make()); + } else { + return Error { Error::Type::MalformedPDF, "invalid /Subtype for Type 0 font" }; + } + auto font_descriptor = TRY(descendant_font->get_dict(document, CommonNames::FontDescriptor)); u16 default_width = 1000; @@ -91,9 +153,9 @@ void Type0Font::set_font_size(float) { } -PDFErrorOr Type0Font::draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float, float) +PDFErrorOr Type0Font::draw_string(Gfx::Painter& painter, Gfx::FloatPoint glyph_position, DeprecatedString const& string, Color const& paint_color, float font_size, float character_spacing, float word_spacing, float horizontal_scaling) { - return Error::rendering_unsupported_error("Type0 font not implemented yet"); + return m_cid_font_type->draw_string(painter, glyph_position, string, paint_color, font_size, character_spacing, word_spacing, horizontal_scaling); } } diff --git a/Userland/Libraries/LibPDF/Fonts/Type0Font.h b/Userland/Libraries/LibPDF/Fonts/Type0Font.h index 50e25c8282..26158a95d0 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type0Font.h +++ b/Userland/Libraries/LibPDF/Fonts/Type0Font.h @@ -6,11 +6,14 @@ #pragma once +#include #include #include namespace PDF { +class CIDFontType; + struct CIDSystemInfo { DeprecatedString registry; DeprecatedString ordering; @@ -19,6 +22,9 @@ struct CIDSystemInfo { class Type0Font : public PDFFont { public: + Type0Font(); + ~Type0Font(); + void set_font_size(float font_size) override; PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint pos, DeprecatedString const&, Color const&, float, float, float, float) override; Type type() const override { return PDFFont::Type::Type0; } @@ -32,6 +38,7 @@ private: CIDSystemInfo m_system_info; HashMap m_widths; u16 m_missing_width; + OwnPtr m_cid_font_type; }; }