diff --git a/Userland/Libraries/LibPDF/CMakeLists.txt b/Userland/Libraries/LibPDF/CMakeLists.txt index 955d3b7c37..2862b23cf8 100644 --- a/Userland/Libraries/LibPDF/CMakeLists.txt +++ b/Userland/Libraries/LibPDF/CMakeLists.txt @@ -9,6 +9,7 @@ set(SOURCES Fonts/CFF.cpp Fonts/PDFFont.cpp Fonts/PS1FontProgram.cpp + Fonts/SimpleFont.cpp Fonts/TrueTypeFont.cpp Fonts/Type0Font.cpp Fonts/Type1Font.cpp diff --git a/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp b/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp index ed38f7d650..30eccd2f81 100644 --- a/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp +++ b/Userland/Libraries/LibPDF/Fonts/PDFFont.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -14,7 +15,7 @@ namespace PDF { -static bool is_standard_latin_font(DeprecatedFlyString const& font) +[[maybe_unused]] static bool is_standard_latin_font(DeprecatedFlyString const& font) { return font.is_one_of( "Times-Roman", "TimesNewRoman", @@ -31,65 +32,31 @@ static bool is_standard_latin_font(DeprecatedFlyString const& font) "Courier-BoldOblique", "CourierNew,BoldItalic"); } -PDFErrorOr PDFFont::CommonData::load_from_dict(Document* document, NonnullRefPtr dict, float font_size) -{ - auto base_font = TRY(dict->get_name(document, CommonNames::BaseFont))->name(); - if ((is_standard_font = is_standard_latin_font(base_font))) { - auto replacement = replacement_for_standard_latin_font(base_font); - float point_size = (font_size * POINTS_PER_INCH) / DEFAULT_DPI; - font = Gfx::FontDatabase::the().get(replacement.get<0>(), replacement.get<1>(), point_size); - if (!font) - return Error(Error::Type::Internal, DeprecatedString::formatted("Failed to load {} {} at {}pt", replacement.get<0>(), replacement.get<1>(), point_size)); - } - - 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, float font_size) +PDFErrorOr> PDFFont::create(Document* document, NonnullRefPtr const& dict, float font_size) { auto subtype = TRY(dict->get_name(document, CommonNames::Subtype))->name(); - if (subtype == "Type0") - return TRY(Type0Font::create(document, dict)); + RefPtr font; if (subtype == "Type1") - return TRY(Type1Font::create(document, dict, font_size)); - if (subtype == "TrueType") - return TRY(TrueTypeFont::create(document, dict, font_size)); + font = adopt_ref(*new Type1Font()); + else if (subtype == "TrueType") + font = adopt_ref(*new TrueTypeFont()); + else if (subtype == "Type0") + font = adopt_ref(*new Type0Font()); + else + return Error::internal_error("Unhandled font subtype: {}", subtype); - return Error(Error::Type::Internal, TRY(String::formatted("Unhandled font subtype: {}", subtype)).to_deprecated_string()); + TRY(font->initialize(document, dict, font_size)); + return font.release_nonnull(); } -Tuple PDFFont::replacement_for_standard_latin_font(StringView name) +PDFErrorOr PDFFont::initialize(Document* document, NonnullRefPtr const& dict, float) +{ + m_base_font_name = TRY(dict->get_name(document, CommonNames::BaseFont))->name(); + return {}; +} + +PDFErrorOr> PDFFont::replacement_for(StringView name, float font_size) { bool is_bold = name.contains("bold"sv, CaseSensitivity::CaseInsensitive); bool is_italic = name.contains("italic"sv, CaseSensitivity::CaseInsensitive); @@ -115,7 +82,11 @@ Tuple PDFFont::replacement_for_standard_lati font_variant = "Regular"; } - return { font_family, font_variant }; + float point_size = (font_size * POINTS_PER_INCH) / DEFAULT_DPI; + auto font = Gfx::FontDatabase::the().get(font_family, font_variant, point_size); + if (!font) + Error::internal_error("Failed to load {} {} at {}pt", font_family, font_variant, point_size); + return font.release_nonnull(); } } diff --git a/Userland/Libraries/LibPDF/Fonts/PDFFont.h b/Userland/Libraries/LibPDF/Fonts/PDFFont.h index 57d1df9a40..8bd9d62737 100644 --- a/Userland/Libraries/LibPDF/Fonts/PDFFont.h +++ b/Userland/Libraries/LibPDF/Fonts/PDFFont.h @@ -22,35 +22,21 @@ public: TrueType }; - // This is used both by Type 1 and TrueType fonts. - struct CommonData { - DeprecatedFlyString base_font_name; - RefPtr font; - RefPtr to_unicode; - RefPtr encoding; - HashMap widths; - u16 missing_width; - bool is_standard_font; - - PDFErrorOr load_from_dict(Document*, NonnullRefPtr, float font_size); - }; - - static PDFErrorOr> create(Document*, NonnullRefPtr, float font_size); + static PDFErrorOr> create(Document*, NonnullRefPtr const&, float font_size); virtual ~PDFFont() = default; - virtual float get_char_width(u16 char_code) const = 0; + virtual PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float font_size, float character_spacing, float horizontal_scaling) = 0; - virtual void draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u32 char_code, Color color) = 0; - - virtual bool is_standard_font() const { return m_is_standard_font; } virtual Type type() const = 0; - virtual DeprecatedFlyString base_font_name() const = 0; + DeprecatedFlyString base_font_name() const { return m_base_font_name; }; protected: - static Tuple replacement_for_standard_latin_font(StringView); + virtual PDFErrorOr initialize(Document* document, NonnullRefPtr const& dict, float font_size); + static PDFErrorOr> replacement_for(StringView name, float font_size); - bool m_is_standard_font { false }; +private: + DeprecatedFlyString m_base_font_name; }; } diff --git a/Userland/Libraries/LibPDF/Fonts/SimpleFont.cpp b/Userland/Libraries/LibPDF/Fonts/SimpleFont.cpp new file mode 100644 index 0000000000..358e22024a --- /dev/null +++ b/Userland/Libraries/LibPDF/Fonts/SimpleFont.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023, Rodrigo Tobar . + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace PDF { + +PDFErrorOr SimpleFont::initialize(Document* document, NonnullRefPtr const& dict, float font_size) +{ + TRY(PDFFont::initialize(document, dict, font_size)); + if (dict->contains(CommonNames::Encoding)) { + auto encoding_object = MUST(dict->get_object(document, CommonNames::Encoding)); + m_encoding = TRY(Encoding::from_object(document, encoding_object)); + } + + if (dict->contains(CommonNames::ToUnicode)) + m_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++) + m_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)) + m_missing_width = descriptor->get_value(CommonNames::MissingWidth).to_int(); + } + + return {}; +} + +float SimpleFont::get_char_width(u8 char_code) const +{ + return static_cast(m_widths.get(char_code).value_or(m_missing_width)) / 1000.0f; +} + +PDFErrorOr SimpleFont::draw_string(Gfx::Painter& painter, Gfx::FloatPoint glyph_position, DeprecatedString const& string, Color const& paint_color, float font_size, float character_spacing, float horizontal_scaling) +{ + auto so = make_object(string, true); + for (auto char_code : string.bytes()) { + auto char_width = get_char_width(char_code); + auto glyph_width = char_width * font_size; + draw_glyph(painter, glyph_position, glyph_width, char_code, paint_color); + auto tx = glyph_width; + tx += character_spacing; + tx *= horizontal_scaling; + glyph_position += { tx, 0.0f }; + } + return glyph_position; +} + +} diff --git a/Userland/Libraries/LibPDF/Fonts/SimpleFont.h b/Userland/Libraries/LibPDF/Fonts/SimpleFont.h new file mode 100644 index 0000000000..61bc7b2eed --- /dev/null +++ b/Userland/Libraries/LibPDF/Fonts/SimpleFont.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, Rodrigo Tobar . + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace PDF { + +class SimpleFont : public PDFFont { +public: + PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float font_size, float character_spacing, float horizontal_scaling) override; + +protected: + PDFErrorOr initialize(Document* document, NonnullRefPtr const& dict, float font_size) override; + virtual void draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Color color) = 0; + RefPtr& encoding() { return m_encoding; } + RefPtr const& encoding() const { return m_encoding; } + +private: + float get_char_width(u8 char_code) const; + + RefPtr m_encoding; + RefPtr m_to_unicode; + HashMap m_widths; + u16 m_missing_width; +}; + +} diff --git a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp index 5cd2bc7bee..369830b1ed 100644 --- a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp +++ b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.cpp @@ -13,57 +13,31 @@ namespace PDF { -PDFErrorOr TrueTypeFont::parse_data(Document* document, NonnullRefPtr dict, float font_size) +PDFErrorOr TrueTypeFont::initialize(Document* document, NonnullRefPtr const& dict, float font_size) { - PDFFont::CommonData data; - TRY(data.load_from_dict(document, dict, font_size)); + TRY(SimpleFont::initialize(document, dict, font_size)); - if (!data.is_standard_font) { - auto descriptor = TRY(dict->get_dict(document, CommonNames::FontDescriptor)); + if (dict->contains(CommonNames::FontDescriptor)) { + auto descriptor = MUST(dict->get_dict(document, CommonNames::FontDescriptor)); if (descriptor->contains(CommonNames::FontFile2)) { auto font_file_stream = TRY(descriptor->get_stream(document, CommonNames::FontFile2)); auto ttf_font = TRY(OpenType::Font::try_load_from_externally_owned_memory(font_file_stream->bytes())); float point_size = (font_size * POINTS_PER_INCH) / DEFAULT_DPI; - data.font = adopt_ref(*new Gfx::ScaledFont(*ttf_font, point_size, point_size)); + m_font = adopt_ref(*new Gfx::ScaledFont(*ttf_font, font_size, point_size)); } } - return data; + return {}; } -PDFErrorOr> TrueTypeFont::create(Document* document, NonnullRefPtr dict, float font_size) +void TrueTypeFont::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float, u8 char_code, Color color) { - auto data = TRY(parse_data(document, dict, font_size)); - return adopt_ref(*new TrueTypeFont(move(data))); -} - -TrueTypeFont::TrueTypeFont(PDFFont::CommonData data) - : m_data(data) -{ - m_is_standard_font = m_data.is_standard_font; -} - -float TrueTypeFont::get_char_width(u16 char_code) const -{ - u16 width; - if (auto char_code_width = m_data.widths.get(char_code); char_code_width.has_value()) { - width = char_code_width.value(); - } else { - // FIXME: Should we do something with m_data.missing_width here? - width = m_data.font->glyph_width(char_code); - } - - return static_cast(width) / 1000.0f; -} - -void TrueTypeFont::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float, u32 char_code, Color color) -{ - if (!m_data.font) + if (!m_font) return; // Account for the reversed font baseline - auto position = point.translated(0, -m_data.font->baseline()); - painter.draw_glyph(position, char_code, *m_data.font, color); + auto position = point.translated(0, -m_font->baseline()); + painter.draw_glyph(position, char_code, *m_font, color); } } diff --git a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h index bdfeac2545..02fba97f5b 100644 --- a/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h +++ b/Userland/Libraries/LibPDF/Fonts/TrueTypeFont.h @@ -8,28 +8,20 @@ #include #include -#include +#include namespace PDF { -class TrueTypeFont : public PDFFont { +class TrueTypeFont : public SimpleFont { public: - static PDFErrorOr parse_data(Document* document, NonnullRefPtr dict, float font_size); - - static PDFErrorOr> create(Document*, NonnullRefPtr, float font_size); - - TrueTypeFont(PDFFont::CommonData); - ~TrueTypeFont() override = default; - - float get_char_width(u16 char_code) const override; - - void draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float, u32, Color) override; - + void draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float, u8, Color) override; Type type() const override { return PDFFont::Type::TrueType; } - DeprecatedFlyString base_font_name() const override { return m_data.base_font_name; } + +protected: + PDFErrorOr initialize(Document*, NonnullRefPtr const&, float font_size) override; private: - PDFFont::CommonData m_data; + RefPtr m_font; }; } diff --git a/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp b/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp index 0febd0934e..e88ee96937 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type0Font.cpp @@ -9,8 +9,10 @@ namespace PDF { -PDFErrorOr> Type0Font::create(Document* document, NonnullRefPtr dict) +PDFErrorOr Type0Font::initialize(Document* document, NonnullRefPtr const& dict, float font_size) { + TRY(PDFFont::initialize(document, dict, font_size)); + // FIXME: Support arbitrary CMaps auto cmap_value = TRY(dict->get_object(document, CommonNames::Encoding)); if (!cmap_value->is() || cmap_value->cast()->name() != CommonNames::IdentityH) @@ -67,14 +69,10 @@ PDFErrorOr> Type0Font::create(Document* document, Nonnu } } - return adopt_ref(*new Type0Font(system_info, widths, default_width)); -} - -Type0Font::Type0Font(CIDSystemInfo const& system_info, HashMap const& widths, u16 missing_width) - : m_system_info(system_info) - , m_widths(widths) - , m_missing_width(missing_width) -{ + m_system_info = move(system_info); + m_widths = move(widths); + m_missing_width = default_width; + return {}; } float Type0Font::get_char_width(u16 char_code) const @@ -89,4 +87,9 @@ float Type0Font::get_char_width(u16 char_code) const return static_cast(width) / 1000.0f; } +PDFErrorOr Type0Font::draw_string(Gfx::Painter&, Gfx::FloatPoint, DeprecatedString const&, Color const&, float, float, float) +{ + return Error::rendering_unsupported_error("Type0 font not implemented yet"); +}; + } diff --git a/Userland/Libraries/LibPDF/Fonts/Type0Font.h b/Userland/Libraries/LibPDF/Fonts/Type0Font.h index d5745e899e..83bc785f78 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type0Font.h +++ b/Userland/Libraries/LibPDF/Fonts/Type0Font.h @@ -19,19 +19,15 @@ struct CIDSystemInfo { class Type0Font : public PDFFont { public: - static PDFErrorOr> create(Document*, NonnullRefPtr); - - Type0Font(CIDSystemInfo const&, HashMap const& widths, u16 missing_width); - ~Type0Font() override = default; - - float get_char_width(u16 char_code) const override; - - void draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float, u32, Color) override {}; - + PDFErrorOr draw_string(Gfx::Painter&, Gfx::FloatPoint pos, DeprecatedString const&, Color const&, float, float, float) override; Type type() const override { return PDFFont::Type::Type0; } - DeprecatedFlyString base_font_name() const override { return ""; } + +protected: + PDFErrorOr initialize(Document*, NonnullRefPtr const&, float) override; private: + float get_char_width(u16 char_code) const; + CIDSystemInfo m_system_info; HashMap m_widths; u16 m_missing_width; diff --git a/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp b/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp index 4c97c98701..49a828e3d8 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type1Font.cpp @@ -13,81 +13,58 @@ namespace PDF { -PDFErrorOr Type1Font::parse_data(Document* document, NonnullRefPtr dict, float font_size) +PDFErrorOr Type1Font::initialize(Document* document, NonnullRefPtr const& dict, float font_size) { - Type1Font::Data data; - TRY(data.load_from_dict(document, dict, font_size)); + TRY(SimpleFont::initialize(document, dict, font_size)); - if (!data.is_standard_font) { + // auto is_standard_font = is_standard_latin_font(font->base_font_name()); + + // If there's an embedded font program we use that; otherwise we try to find a replacement font + if (dict->contains(CommonNames::FontDescriptor)) { auto descriptor = TRY(dict->get_dict(document, CommonNames::FontDescriptor)); if (descriptor->contains(CommonNames::FontFile3)) { auto font_file_stream = TRY(descriptor->get_stream(document, CommonNames::FontFile3)); auto font_file_dict = font_file_stream->dict(); if (font_file_dict->contains(CommonNames::Subtype) && font_file_dict->get_name(CommonNames::Subtype)->name() == CommonNames::Type1C) { - data.font_program = TRY(CFF::create(font_file_stream->bytes(), data.encoding)); - if (!data.encoding) - data.encoding = data.font_program->encoding(); - return data; + m_font_program = TRY(CFF::create(font_file_stream->bytes(), encoding())); } + } else if (descriptor->contains(CommonNames::FontFile)) { + auto font_file_stream = TRY(descriptor->get_stream(document, CommonNames::FontFile)); + auto font_file_dict = font_file_stream->dict(); + + if (!font_file_dict->contains(CommonNames::Length1, CommonNames::Length2)) + return Error::parse_error("Embedded type 1 font is incomplete"sv); + + auto length1 = TRY(document->resolve(font_file_dict->get_value(CommonNames::Length1))).get(); + auto length2 = TRY(document->resolve(font_file_dict->get_value(CommonNames::Length2))).get(); + + m_font_program = TRY(PS1FontProgram::create(font_file_stream->bytes(), encoding(), length1, length2)); } - if (!descriptor->contains(CommonNames::FontFile)) - return data; - - auto font_file_stream = TRY(descriptor->get_stream(document, CommonNames::FontFile)); - auto font_file_dict = font_file_stream->dict(); - - if (!font_file_dict->contains(CommonNames::Length1, CommonNames::Length2)) - return Error { Error::Type::Parse, "Embedded type 1 font is incomplete" }; - - auto length1 = TRY(document->resolve(font_file_dict->get_value(CommonNames::Length1))).get(); - auto length2 = TRY(document->resolve(font_file_dict->get_value(CommonNames::Length2))).get(); - - data.font_program = TRY(PS1FontProgram::create(font_file_stream->bytes(), data.encoding, length1, length2)); - - if (!data.encoding) - data.encoding = data.font_program->encoding(); + } + if (!m_font_program) { + m_font = TRY(replacement_for(base_font_name().to_lowercase(), font_size)); } - return data; + VERIFY(m_font_program || m_font); + return {}; } -PDFErrorOr> Type1Font::create(Document* document, NonnullRefPtr dict, float font_size) +void Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Color color) { - auto data = TRY(Type1Font::parse_data(document, dict, font_size)); - return adopt_ref(*new Type1Font(data)); -} - -Type1Font::Type1Font(Data data) - : m_data(move(data)) -{ - m_is_standard_font = m_data.is_standard_font; -} - -float Type1Font::get_char_width(u16 char_code) const -{ - u16 width; - if (auto char_code_width = m_data.widths.get(char_code); char_code_width.has_value()) { - width = char_code_width.value(); - } else { - width = m_data.missing_width; - } - - return static_cast(width) / 1000.0f; -} - -void Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u32 char_code, Color color) -{ - if (!m_data.font_program) { - if (m_data.font) { - // Account for the reversed font baseline - auto position = point.translated(0, -m_data.font->baseline()); - painter.draw_glyph(position, char_code, *m_data.font, color); - } + if (!m_font_program) { + // Account for the reversed font baseline + auto position = point.translated(0, -m_font->baseline()); + painter.draw_glyph(position, char_code, *m_font, color); return; } - auto char_name = m_data.encoding->get_name(char_code); - auto translation = m_data.font_program->glyph_translation(char_name, width); + auto effective_encoding = encoding(); + if (!effective_encoding) + effective_encoding = m_font_program->encoding(); + if (!effective_encoding) + effective_encoding = Encoding::standard_encoding(); + auto char_name = effective_encoding->get_name(char_code); + auto translation = m_font_program->glyph_translation(char_name, width); point = point.translated(translation); auto glyph_position = Gfx::GlyphRasterPosition::get_nearest_fit_for(point); @@ -98,7 +75,7 @@ void Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float w if (maybe_bitmap.has_value()) { bitmap = maybe_bitmap.value(); } else { - bitmap = m_data.font_program->rasterize_glyph(char_name, width, glyph_position.subpixel_offset); + bitmap = m_font_program->rasterize_glyph(char_name, width, glyph_position.subpixel_offset); m_glyph_cache.set(index, bitmap); } diff --git a/Userland/Libraries/LibPDF/Fonts/Type1Font.h b/Userland/Libraries/LibPDF/Fonts/Type1Font.h index 04d7c36ca6..c85df6d7b0 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1Font.h +++ b/Userland/Libraries/LibPDF/Fonts/Type1Font.h @@ -7,33 +7,22 @@ #pragma once #include -#include +#include #include namespace PDF { -class Type1Font : public PDFFont { +class Type1Font : public SimpleFont { public: - struct Data : PDFFont::CommonData { - RefPtr font_program; - }; - - static PDFErrorOr parse_data(Document*, NonnullRefPtr font_dict, float font_size); - - static PDFErrorOr> create(Document*, NonnullRefPtr, float font_size); - - Type1Font(Data); - ~Type1Font() override = default; - - float get_char_width(u16 char_code) const override; - - void draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u32 char_code, Color color) override; - + void draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Color color) override; Type type() const override { return PDFFont::Type::Type1; } - DeprecatedFlyString base_font_name() const override { return m_data.base_font_name; }; + +protected: + PDFErrorOr initialize(Document*, NonnullRefPtr const&, float font_size) override; private: - Data m_data; + RefPtr m_font_program; + RefPtr m_font; HashMap> m_glyph_cache; }; diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index 91b93ed0de..98f2d2a206 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -730,22 +730,11 @@ PDFErrorOr Renderer::show_text(DeprecatedString const& string) auto font_size = text_rendering_matrix.x_scale() * text_state().font_size; - auto glyph_position = text_rendering_matrix.map(Gfx::FloatPoint { 0.0f, 0.0f }); - - auto original_position = glyph_position; - - for (auto char_code : string.bytes()) { - auto char_width = text_state().font->get_char_width(char_code); - auto glyph_width = char_width * font_size; - text_state().font->draw_glyph(m_painter, glyph_position, glyph_width, char_code, state().paint_color); - auto tx = glyph_width; - tx += text_state().character_spacing; - tx *= text_state().horizontal_scaling; - glyph_position += { tx, 0.0f }; - } + auto start_position = text_rendering_matrix.map(Gfx::FloatPoint { 0.0f, 0.0f }); + auto end_position = TRY(text_state().font->draw_string(m_painter, start_position, string, state().paint_color, font_size, text_state().character_spacing, text_state().horizontal_scaling)); // Update text matrix - auto delta_x = glyph_position.x() - original_position.x(); + auto delta_x = end_position.x() - start_position.x(); m_text_rendering_matrix_is_dirty = true; m_text_matrix.translate(delta_x / text_rendering_matrix.x_scale(), 0.0f); return {};