From 7494f2443019edaed27694513e3b2507efdff3a3 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 14 Feb 2024 09:06:52 -0500 Subject: [PATCH] LibPDF/CFF: Store if a font program is CID-keyed ...and reject CID-keyed font programs for Type1 fonts. --- Userland/Libraries/LibPDF/Fonts/CFF.cpp | 11 +++++++++++ Userland/Libraries/LibPDF/Fonts/CFF.h | 1 + Userland/Libraries/LibPDF/Fonts/Type1Font.cpp | 4 ++++ Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h | 10 ++++++++++ 4 files changed, 26 insertions(+) diff --git a/Userland/Libraries/LibPDF/Fonts/CFF.cpp b/Userland/Libraries/LibPDF/Fonts/CFF.cpp index 54fd327638..76a30767e3 100644 --- a/Userland/Libraries/LibPDF/Fonts/CFF.cpp +++ b/Userland/Libraries/LibPDF/Fonts/CFF.cpp @@ -126,6 +126,11 @@ PDFErrorOr> CFF::create(ReadonlyBytes const& cff_bytes, RefPt return error("CFFs with more than one font not yet implemented"); auto const& top_dict = top_dicts[0]; + if (top_dict.is_cid_keyed) { + // CFF spec, "18 CID-keyed Fonts" + cff->set_kind(CFF::Kind::CIDKeyed); + } + auto strings = TRY(parse_strings(reader)); // CFF spec "16 Local/Global Subrs INDEXes" @@ -350,6 +355,12 @@ PDFErrorOr> CFF::parse_top_dicts(Reader& reader, ReadonlyBy })); break; } + case TopDictOperator::RegistryOrderingSupplement: + // CFF Spec, "18 CID-keyed Fonts" + // "The Top DICT begins with ROS operator which specifies the Registry-Ordering-Supplement for the font. + // This will indicate to a CFF parser that special CID processing should be applied to this font." + top_dict.is_cid_keyed = true; + break; case TopDictOperator::FDSelect: if (!operands.is_empty()) top_dict.fdselect_offset = operands[0].get(); diff --git a/Userland/Libraries/LibPDF/Fonts/CFF.h b/Userland/Libraries/LibPDF/Fonts/CFF.h index ee3735cffd..0228009b6a 100644 --- a/Userland/Libraries/LibPDF/Fonts/CFF.h +++ b/Userland/Libraries/LibPDF/Fonts/CFF.h @@ -126,6 +126,7 @@ public: Vector local_subroutines; float defaultWidthX = 0; float nominalWidthX = 0; + bool is_cid_keyed = false; int fdselect_offset = 0; int fdarray_offset = 0; }; diff --git a/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp b/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp index 9cb62b2357..5c1890ea22 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp @@ -44,6 +44,10 @@ PDFErrorOr Type1Font::initialize(Document* document, NonnullRefPtrbytes(), encoding(), length1, length2)); } } + + if (m_font_program && m_font_program->kind() == Type1FontProgram::Kind::CIDKeyed) + return Error::parse_error("Type1 fonts must not be CID-keyed"sv); + if (!m_font_program) { m_font = TRY(replacement_for(base_font_name().to_lowercase(), font_size)); } diff --git a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h index 0f7be52214..76f5104250 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h +++ b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.h @@ -20,10 +20,17 @@ class Encoding; class Type1FontProgram : public RefCounted { public: + enum Kind { + NameKeyed, + CIDKeyed, + }; + 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; } + Kind kind() const { return m_kind; } + protected: struct AccentedCharacter { AccentedCharacter(u8 base_char_code, u8 accent_char_code, float adx, float ady) @@ -111,10 +118,13 @@ protected: void consolidate_glyphs(); + void set_kind(Kind kind) { m_kind = kind; } + private: HashMap m_glyph_map; Gfx::AffineTransform m_font_matrix; RefPtr m_encoding; + Kind m_kind { NameKeyed }; 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;