1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:27:45 +00:00

LibPDF: Override Type 1 character mappings by encoding in font dict

If the font dictionary includes an "Encoding" entry, it will be used
instead of the PS1FontProgram's built-in encoding.
This commit is contained in:
Julian Offenhäuser 2022-11-23 11:27:39 +01:00 committed by Andreas Kling
parent 65ff80e8a5
commit e06a065594
3 changed files with 24 additions and 16 deletions

View file

@ -44,7 +44,7 @@ enum ExtendedCommand {
SetCurrentPoint = 33, SetCurrentPoint = 33,
}; };
PDFErrorOr<void> PS1FontProgram::parse(ReadonlyBytes const& bytes, size_t cleartext_length, size_t encrypted_length) PDFErrorOr<void> PS1FontProgram::create(ReadonlyBytes const& bytes, RefPtr<Encoding> encoding, size_t cleartext_length, size_t encrypted_length)
{ {
Reader reader(bytes); Reader reader(bytes);
if (reader.remaining() == 0) if (reader.remaining() == 0)
@ -57,22 +57,28 @@ PDFErrorOr<void> PS1FontProgram::parse(ReadonlyBytes const& bytes, size_t cleart
if (!seek_name(reader, CommonNames::Encoding)) if (!seek_name(reader, CommonNames::Encoding))
return error("Missing encoding array"); return error("Missing encoding array");
if (TRY(parse_word(reader)) == "StandardEncoding") { if (encoding) {
m_encoding = Encoding::standard_encoding(); // 9.6.6.2 Encodings for Type 1 Fonts:
// An Encoding entry may override a Type 1 fonts mapping from character codes to character names.
m_encoding = encoding;
} else { } else {
HashMap<u16, CharDescriptor> descriptors; if (TRY(parse_word(reader)) == "StandardEncoding") {
m_encoding = Encoding::standard_encoding();
} else {
HashMap<u16, CharDescriptor> descriptors;
while (reader.remaining()) { while (reader.remaining()) {
auto word = TRY(parse_word(reader)); auto word = TRY(parse_word(reader));
if (word == "readonly") { if (word == "readonly") {
break; break;
} else if (word == "dup") { } else if (word == "dup") {
u32 char_code = TRY(parse_int(reader)); u32 char_code = TRY(parse_int(reader));
auto name = TRY(parse_word(reader)); auto name = TRY(parse_word(reader));
descriptors.set(char_code, { name.starts_with('/') ? name.substring_view(1) : name.view(), char_code }); descriptors.set(char_code, { name.starts_with('/') ? name.substring_view(1) : name.view(), char_code });
}
} }
m_encoding = TRY(Encoding::create(descriptors));
} }
m_encoding = TRY(Encoding::create(descriptors));
} }
bool found_font_matrix = seek_name(reader, "FontMatrix"); bool found_font_matrix = seek_name(reader, "FontMatrix");

View file

@ -18,7 +18,7 @@ class Encoding;
class PS1FontProgram : public RefCounted<PS1FontProgram> { class PS1FontProgram : public RefCounted<PS1FontProgram> {
public: public:
PDFErrorOr<void> parse(ReadonlyBytes const&, size_t cleartext_length, size_t encrypted_length); PDFErrorOr<void> create(ReadonlyBytes const&, RefPtr<Encoding>, size_t cleartext_length, size_t encrypted_length);
RefPtr<Gfx::Bitmap> rasterize_glyph(u32 char_code, float width); RefPtr<Gfx::Bitmap> rasterize_glyph(u32 char_code, float width);
Gfx::Path build_char(u32 char_code, float width); Gfx::Path build_char(u32 char_code, float width);

View file

@ -31,8 +31,10 @@ PDFErrorOr<Type1Font::Data> Type1Font::parse_data(Document* document, NonnullRef
auto length2 = font_file_dict->get_value(CommonNames::Length2).get<int>(); auto length2 = font_file_dict->get_value(CommonNames::Length2).get<int>();
data.font_program = adopt_ref(*new PS1FontProgram()); data.font_program = adopt_ref(*new PS1FontProgram());
TRY(data.font_program->parse(font_file_stream->bytes(), length1, length2)); TRY(data.font_program->create(font_file_stream->bytes(), data.encoding, length1, length2));
data.encoding = data.font_program->encoding();
if (!data.encoding)
data.encoding = data.font_program->encoding();
} }
return data; return data;