mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 19:27:45 +00:00
LibPDF: Use Font /Widths array to derive character widths
This makes the spacing between chars _much_ better!
This commit is contained in:
parent
130846f337
commit
d2771eafc5
4 changed files with 42 additions and 6 deletions
|
@ -81,6 +81,7 @@
|
||||||
A(ML) \
|
A(ML) \
|
||||||
A(Matrix) \
|
A(Matrix) \
|
||||||
A(MediaBox) \
|
A(MediaBox) \
|
||||||
|
A(MissingWidth) \
|
||||||
A(N) \
|
A(N) \
|
||||||
A(Next) \
|
A(Next) \
|
||||||
A(O) \
|
A(O) \
|
||||||
|
|
|
@ -63,12 +63,29 @@ PDFErrorOr<NonnullRefPtr<Type1Font>> Type1Font::create(Document* document, Nonnu
|
||||||
if (dict->contains(CommonNames::ToUnicode))
|
if (dict->contains(CommonNames::ToUnicode))
|
||||||
to_unicode = MUST(dict->get_stream(document, 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_to_unicode(to_unicode)
|
||||||
, m_encoding(encoding)
|
, 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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,20 +18,24 @@ public:
|
||||||
virtual ~PDFFont() = default;
|
virtual ~PDFFont() = default;
|
||||||
|
|
||||||
virtual u32 char_code_to_code_point(u16 char_code) const = 0;
|
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 {
|
class Type1Font : public PDFFont {
|
||||||
public:
|
public:
|
||||||
static PDFErrorOr<NonnullRefPtr<Type1Font>> create(Document*, NonnullRefPtr<DictObject>);
|
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;
|
~Type1Font() override = default;
|
||||||
|
|
||||||
u32 char_code_to_code_point(u16 char_code) const override;
|
u32 char_code_to_code_point(u16 char_code) const override;
|
||||||
|
float get_char_width(u16 char_code) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<StreamObject> m_to_unicode;
|
RefPtr<StreamObject> m_to_unicode;
|
||||||
NonnullRefPtr<Encoding> m_encoding;
|
NonnullRefPtr<Encoding> m_encoding;
|
||||||
|
HashMap<u16, u16> m_widths;
|
||||||
|
u16 m_missing_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -641,8 +641,9 @@ void Renderer::show_text(String const& string, float shift)
|
||||||
{
|
{
|
||||||
auto& text_rendering_matrix = calculate_text_rendering_matrix();
|
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_size = 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_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);
|
VERIFY(font);
|
||||||
|
|
||||||
auto glyph_position = text_rendering_matrix.map(Gfx::FloatPoint { 0.0f, 0.0f });
|
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()) {
|
for (auto char_code : string.bytes()) {
|
||||||
auto code_point = text_state().font->char_code_to_code_point(char_code);
|
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)
|
if (code_point != 0x20)
|
||||||
m_painter.draw_glyph(glyph_position.to_type<int>(), code_point, *font, state().paint_color);
|
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);
|
auto tx = (glyph_width - shift / 1000.0f);
|
||||||
tx += text_state().character_spacing;
|
tx += text_state().character_spacing;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue