diff --git a/Userland/Libraries/LibPDF/CommonNames.h b/Userland/Libraries/LibPDF/CommonNames.h index 537ec02298..f3cc473735 100644 --- a/Userland/Libraries/LibPDF/CommonNames.h +++ b/Userland/Libraries/LibPDF/CommonNames.h @@ -81,6 +81,7 @@ A(ML) \ A(Matrix) \ A(MediaBox) \ + A(MissingWidth) \ A(N) \ A(Next) \ A(O) \ diff --git a/Userland/Libraries/LibPDF/Fonts.cpp b/Userland/Libraries/LibPDF/Fonts.cpp index aa9b20cdf6..b43678db4b 100644 --- a/Userland/Libraries/LibPDF/Fonts.cpp +++ b/Userland/Libraries/LibPDF/Fonts.cpp @@ -63,12 +63,29 @@ PDFErrorOr> Type1Font::create(Document* document, Nonnu if (dict->contains(CommonNames::ToUnicode)) to_unicode = MUST(dict->get_stream(document, CommonNames::ToUnicode)); - return adopt_ref(*new Type1Font(to_unicode, encoding.release_nonnull())); + auto first_char = dict->get_value(CommonNames::FirstChar).get(); + auto last_char = dict->get_value(CommonNames::LastChar).get(); + auto widths_array = MUST(dict->get_array(document, CommonNames::Widths)); + + VERIFY(widths_array->size() == static_cast(last_char - first_char + 1)); + + HashMap widths; + for (size_t i = 0; i < widths_array->size(); i++) + widths.set(first_char + i, widths_array->at(i).get()); + + u16 missing_width = 0; + auto descriptor = MUST(dict->get_dict(document, CommonNames::FontDescriptor)); + if (descriptor->contains(CommonNames::MissingWidth)) + missing_width = descriptor->get_value(CommonNames::MissingWidth).get(); + + return adopt_ref(*new Type1Font(to_unicode, encoding.release_nonnull(), widths, missing_width)); } -Type1Font::Type1Font(RefPtr to_unicode, NonnullRefPtr encoding) +Type1Font::Type1Font(RefPtr to_unicode, NonnullRefPtr encoding, HashMap const& widths, u16 missing_width) : m_to_unicode(to_unicode) , m_encoding(encoding) + , m_widths(widths) + , m_missing_width(missing_width) { } @@ -81,4 +98,16 @@ u32 Type1Font::char_code_to_code_point(u16 char_code) const return descriptor.code_point; } +float Type1Font::get_char_width(u16 char_code) const +{ + u16 width; + if (auto char_code_width = m_widths.get(char_code); char_code_width.has_value()) { + width = char_code_width.value(); + } else { + width = m_missing_width; + } + + return static_cast(width) / 1000.0f; +} + } diff --git a/Userland/Libraries/LibPDF/Fonts.h b/Userland/Libraries/LibPDF/Fonts.h index 51a45e19b2..3d98305e61 100644 --- a/Userland/Libraries/LibPDF/Fonts.h +++ b/Userland/Libraries/LibPDF/Fonts.h @@ -18,20 +18,24 @@ public: virtual ~PDFFont() = default; virtual u32 char_code_to_code_point(u16 char_code) const = 0; + virtual float get_char_width(u16 char_code) const = 0; }; class Type1Font : public PDFFont { public: static PDFErrorOr> create(Document*, NonnullRefPtr); - Type1Font(RefPtr to_unicode, NonnullRefPtr); + Type1Font(RefPtr to_unicode, NonnullRefPtr, HashMap const& m_widths, u16 missing_width); ~Type1Font() override = default; u32 char_code_to_code_point(u16 char_code) const override; + float get_char_width(u16 char_code) const override; private: RefPtr m_to_unicode; NonnullRefPtr m_encoding; + HashMap m_widths; + u16 m_missing_width; }; } diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index bb180f26e9..fd7985e132 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -641,8 +641,9 @@ void Renderer::show_text(String const& string, float shift) { auto& text_rendering_matrix = calculate_text_rendering_matrix(); - auto font_size = static_cast(text_rendering_matrix.x_scale() * text_state().font_size); - auto font = Gfx::FontDatabase::the().get(text_state().font_family, text_state().font_variant, font_size); + auto font_size = text_rendering_matrix.x_scale() * text_state().font_size; + auto font_size_int = static_cast(text_rendering_matrix.x_scale() * text_state().font_size); + auto font = Gfx::FontDatabase::the().get(text_state().font_family, text_state().font_variant, font_size_int); VERIFY(font); auto glyph_position = text_rendering_matrix.map(Gfx::FloatPoint { 0.0f, 0.0f }); @@ -653,11 +654,12 @@ void Renderer::show_text(String const& string, float shift) for (auto char_code : string.bytes()) { auto code_point = text_state().font->char_code_to_code_point(char_code); + auto char_width = text_state().font->get_char_width(char_code); if (code_point != 0x20) m_painter.draw_glyph(glyph_position.to_type(), code_point, *font, state().paint_color); - auto glyph_width = static_cast(font->glyph_width(code_point)); + auto glyph_width = char_width * font_size; auto tx = (glyph_width - shift / 1000.0f); tx += text_state().character_spacing;