summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Olsson <matthewcolsson@gmail.com>2022-03-24 21:56:14 -0700
committerAndreas Kling <kling@serenityos.org>2022-03-31 18:10:45 +0200
commitd2771eafc54c56bdc900e839e772d5cc5b44fa93 (patch)
treed8420cfa3ba3f0352d8f4c588d255ae24b8071bd
parent130846f337e6da970209a5dc97a43027564c7547 (diff)
downloadserenity-d2771eafc54c56bdc900e839e772d5cc5b44fa93.zip
LibPDF: Use Font /Widths array to derive character widths
This makes the spacing between chars _much_ better!
-rw-r--r--Userland/Libraries/LibPDF/CommonNames.h1
-rw-r--r--Userland/Libraries/LibPDF/Fonts.cpp33
-rw-r--r--Userland/Libraries/LibPDF/Fonts.h6
-rw-r--r--Userland/Libraries/LibPDF/Renderer.cpp8
4 files changed, 42 insertions, 6 deletions
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<NonnullRefPtr<Type1Font>> 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<int>();
+ auto last_char = dict->get_value(CommonNames::LastChar).get<int>();
+ auto widths_array = MUST(dict->get_array(document, CommonNames::Widths));
+
+ VERIFY(widths_array->size() == static_cast<size_t>(last_char - first_char + 1));
+
+ HashMap<u16, u16> widths;
+ for (size_t i = 0; i < widths_array->size(); i++)
+ widths.set(first_char + i, widths_array->at(i).get<int>());
+
+ 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<int>();
+
+ return adopt_ref(*new Type1Font(to_unicode, encoding.release_nonnull(), widths, missing_width));
}
-Type1Font::Type1Font(RefPtr<StreamObject> to_unicode, NonnullRefPtr<Encoding> encoding)
+Type1Font::Type1Font(RefPtr<StreamObject> to_unicode, NonnullRefPtr<Encoding> encoding, HashMap<u16, u16> 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<float>(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<NonnullRefPtr<Type1Font>> create(Document*, NonnullRefPtr<DictObject>);
- Type1Font(RefPtr<StreamObject> to_unicode, NonnullRefPtr<Encoding>);
+ Type1Font(RefPtr<StreamObject> to_unicode, NonnullRefPtr<Encoding>, HashMap<u16, u16> 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<StreamObject> m_to_unicode;
NonnullRefPtr<Encoding> m_encoding;
+ HashMap<u16, u16> 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<int>(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<int>(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<int>(), code_point, *font, state().paint_color);
- auto glyph_width = static_cast<float>(font->glyph_width(code_point));
+ auto glyph_width = char_width * font_size;
auto tx = (glyph_width - shift / 1000.0f);
tx += text_state().character_spacing;