diff --git a/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp b/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp index 999d9d48da..5a9711f132 100644 --- a/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp +++ b/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp @@ -12,6 +12,61 @@ namespace PDF { +static bool is_standard_latin_font(FlyString const& font) +{ + return font.is_one_of( + "Times-Roman", + "Helvetica", + "Courier", + "Times-Bold", + "Helvetica-Bold", + "Courier-Bold", + "Times-Italic", + "Helvetica-Oblique", + "Courier-Oblique", + "Times-BoldItalic", + "Helvetica-BoldOblique", + "Courier-BoldOblique"); +} + +PDFErrorOr PDFFont::CommonData::load_from_dict(Document* document, NonnullRefPtr dict) +{ + auto base_font = TRY(dict->get_name(document, CommonNames::BaseFont))->name(); + is_standard_font = is_standard_latin_font(base_font); + + if (dict->contains(CommonNames::Encoding)) { + auto encoding_object = MUST(dict->get_object(document, CommonNames::Encoding)); + encoding = TRY(Encoding::from_object(document, encoding_object)); + } else { + // FIXME: The spec doesn't specify what the encoding should be in this case + if (is_standard_font) + encoding = Encoding::standard_encoding(); + // Otherwise, use the built-in encoding of the font. + } + + if (dict->contains(CommonNames::ToUnicode)) + to_unicode = TRY(dict->get_stream(document, CommonNames::ToUnicode)); + + if (dict->contains(CommonNames::FirstChar) && dict->contains(CommonNames::LastChar) && dict->contains(CommonNames::Widths)) { + auto first_char = dict->get_value(CommonNames::FirstChar).get(); + auto last_char = dict->get_value(CommonNames::LastChar).get(); + auto widths_array = TRY(dict->get_array(document, CommonNames::Widths)); + + VERIFY(widths_array->size() == static_cast(last_char - first_char + 1)); + + for (size_t i = 0; i < widths_array->size(); i++) + widths.set(first_char + i, widths_array->at(i).to_int()); + } + + if (dict->contains(CommonNames::FontDescriptor)) { + auto descriptor = TRY(dict->get_dict(document, CommonNames::FontDescriptor)); + if (descriptor->contains(CommonNames::MissingWidth)) + missing_width = descriptor->get_value(CommonNames::MissingWidth).to_int(); + } + + return {}; +} + PDFErrorOr> PDFFont::create(Document* document, NonnullRefPtr dict) { auto subtype = TRY(dict->get_name(document, CommonNames::Subtype))->name(); diff --git a/Userland/Libraries/LibPDF/Fonts/PDFFont.h b/Userland/Libraries/LibPDF/Fonts/PDFFont.h index 22ba6595b9..48823b918c 100644 --- a/Userland/Libraries/LibPDF/Fonts/PDFFont.h +++ b/Userland/Libraries/LibPDF/Fonts/PDFFont.h @@ -6,8 +6,10 @@ #pragma once +#include #include #include +#include namespace PDF { @@ -19,6 +21,17 @@ public: TrueType }; + // This is used both by Type 1 and TrueType fonts. + struct CommonData { + RefPtr to_unicode; + RefPtr encoding; + HashMap widths; + u16 missing_width; + bool is_standard_font; + + PDFErrorOr load_from_dict(Document*, NonnullRefPtr); + }; + static PDFErrorOr> create(Document*, NonnullRefPtr); virtual ~PDFFont() = default;