diff --git a/Userland/Libraries/LibPDF/Fonts/CFF.cpp b/Userland/Libraries/LibPDF/Fonts/CFF.cpp index 58fa24b097..a6851a17f9 100644 --- a/Userland/Libraries/LibPDF/Fonts/CFF.cpp +++ b/Userland/Libraries/LibPDF/Fonts/CFF.cpp @@ -72,7 +72,8 @@ PDFErrorOr> CFF::create(ReadonlyBytes const& cff_bytes, RefPt // CFF spec, "8 Top DICT INDEX" int charset_offset = 0; - Vector encoding_codes; + Vector encoding_codes; // Maps GID to its codepoint. + HashMap encoding_supplemental; // Maps codepoint to SID. auto charstrings_offset = 0; Vector subroutines; float defaultWidthX = 0; @@ -125,7 +126,7 @@ PDFErrorOr> CFF::create(ReadonlyBytes const& cff_bytes, RefPt dbgln("CFF: Built-in Expert Encoding not yet implemented"); break; default: - encoding_codes = TRY(parse_encoding(Reader(cff_bytes.slice(encoding_offset)))); + encoding_codes = TRY(parse_encoding(Reader(cff_bytes.slice(encoding_offset)), encoding_supplemental)); break; } break; @@ -236,10 +237,14 @@ PDFErrorOr> CFF::create(ReadonlyBytes const& cff_bytes, RefPt encoding->set(0, ".notdef"); continue; } + if (i >= encoding_codes.size() || i >= charset.size()) + break; auto code = encoding_codes[i - 1]; auto char_name = charset[i - 1]; encoding->set(code, char_name); } + for (auto const& entry : encoding_supplemental) + encoding->set(entry.key, resolve_sid(entry.value, strings)); cff->set_encoding(move(encoding)); } @@ -711,7 +716,7 @@ PDFErrorOr> CFF::parse_charstrings(Reader&& reader, Vector> CFF::parse_encoding(Reader&& reader) +PDFErrorOr> CFF::parse_encoding(Reader&& reader, HashMap& supplemental) { // CFF spec, "12 Encodings" Vector encoding_codes; @@ -739,9 +744,17 @@ PDFErrorOr> CFF::parse_encoding(Reader&& reader) } else return error(DeprecatedString::formatted("Invalid encoding format: {}", format)); - // TODO: support encoding supplements when highest bit is set (tables 14 and 15). - if (format_raw & 0x80) - dbgln("CFF: Support for multiply-encoded glyphs not yet implemented"); + if (format_raw & 0x80) { + // CFF spec, "Table 14 Supplemental Encoding Data" + auto n_sups = TRY(reader.try_read()); + dbgln_if(CFF_DEBUG, "CFF encoding, {} supplemental entries", n_sups); + for (u8 i = 0; i < n_sups; i++) { + // CFF spec, "Table 15 Supplement Format" + auto code = TRY(reader.try_read()); + SID name = TRY(reader.try_read()); + TRY(supplemental.try_set(code, name)); + } + } return encoding_codes; } diff --git a/Userland/Libraries/LibPDF/Fonts/CFF.h b/Userland/Libraries/LibPDF/Fonts/CFF.h index 89cdc1de73..11d0fb305a 100644 --- a/Userland/Libraries/LibPDF/Fonts/CFF.h +++ b/Userland/Libraries/LibPDF/Fonts/CFF.h @@ -98,7 +98,7 @@ public: static DeprecatedFlyString resolve_sid(SID, Vector const&); static PDFErrorOr> parse_charset(Reader&&, size_t, Vector const&); - static PDFErrorOr> parse_encoding(Reader&&); + static PDFErrorOr> parse_encoding(Reader&&, HashMap& supplemental); }; }