/* * Copyright (c) 2023, Rodrigo Tobar . * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include namespace PDF { class Reader; // CFF spec: https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf class CFF : public Type1FontProgram { private: // CFF spec, "Table 9 Top DICT Operator Entries" enum class TopDictOperator { Version = 0, Notice, FullName, FamilyName, Weight, FontBBox, UniqueID = 13, XUID, Charset = 15, Encoding, CharStrings, Private, Copyright = (12 << 8), IsFixedPitch, ItalicAngle, UnderlinePosition, UnderlineThickness, PaintType, CharstringType, FontMatrix, StrokeWidth, SyntheticBase = (12 << 8 | 20), PostScript, BaseFontName, BaseFontBlend, // CFF spec, "Table 10 CIDFont Operator Extensions" RegistryOrderingSupplement = (12 << 8 | 30), CIDFontVersion, CIDFontRevision, CIDFontType, CIDCount, UIDBase, FDArray, FDSelect, FontName, }; // CFF spec, "Table 23 Private DICT Operators" enum class PrivDictOperator { BlueValues = 6, OtherBlues, FamilyBlues, FamilyOtherBlues, BlueScale = (12 << 8 | 9), BlueShift, BlueFuzz, StdHW = 10, StdVW, StemSnapH = (12 << 8 | 12), StemSnapV, ForceBold, LanguageGroup = (12 << 8 | 17), ExpansionFactor, InitialRandomSeed, Subrs = 19, DefaultWidthX, NominalWidthX, }; public: static PDFErrorOr> create(ReadonlyBytes const&, RefPtr encoding); // to private using Card8 = u8; using Card16 = u16; using Offset = i32; using OffSize = u8; using SID = u16; using DictOperand = Variant; static float to_number(DictOperand operand) { if (operand.has()) return operand.get(); return operand.get(); } static int load_int_dict_operand(u8 b0, Reader&); static float load_float_dict_operand(Reader&); static PDFErrorOr load_dict_operand(u8, Reader&); using IndexDataHandler = Function(ReadonlyBytes const&)>; static PDFErrorOr parse_index(Reader& reader, IndexDataHandler&&); static PDFErrorOr parse_index_data(OffSize offset_size, Card16 count, Reader& reader, IndexDataHandler&); template using DictEntryHandler = Function(OperatorT, Vector const&)>; template static PDFErrorOr parse_dict(Reader& reader, DictEntryHandler&& handler); template static PDFErrorOr parse_dict_operator(u8, Reader&); // CFF spec, "8 Top DICT INDEX" struct TopDict { int charset_offset = 0; int encoding_offset = 0; int charstrings_offset = 0; Vector local_subroutines; Optional defaultWidthX; Optional nominalWidthX; bool is_cid_keyed = false; int fdselect_offset = 0; int fdarray_offset = 0; }; static PDFErrorOr> parse_top_dicts(Reader&, ReadonlyBytes const& cff_bytes); static PDFErrorOr> parse_strings(Reader&); static PDFErrorOr> parse_charstrings(Reader&&, Vector const& local_subroutines, Vector const& global_subroutines); static DeprecatedFlyString resolve_sid(SID, Vector const&); static PDFErrorOr> parse_charset(Reader&&, size_t); static PDFErrorOr> parse_fdselect(Reader&&, size_t); static PDFErrorOr> parse_encoding(Reader&&, HashMap& supplemental); }; }