SimpleFont.cpp 4.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright (c) 2023, Rodrigo Tobar <rtobarc@gmail.com>.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGfx/Forward.h>
  7. #include <LibPDF/CommonNames.h>
  8. #include <LibPDF/Error.h>
  9. #include <LibPDF/Fonts/PDFFont.h>
  10. #include <LibPDF/Fonts/SimpleFont.h>
  11. #include <LibPDF/Fonts/TrueTypeFont.h>
  12. #include <LibPDF/Fonts/Type1Font.h>
  13. #include <LibPDF/Renderer.h>
  14. namespace PDF {
  15. PDFErrorOr<void> SimpleFont::initialize(Document* document, NonnullRefPtr<DictObject> const& dict, float font_size)
  16. {
  17. TRY(PDFFont::initialize(document, dict, font_size));
  18. if (dict->contains(CommonNames::Encoding)) {
  19. auto encoding_object = MUST(dict->get_object(document, CommonNames::Encoding));
  20. m_encoding = TRY(Encoding::from_object(document, encoding_object));
  21. }
  22. if (dict->contains(CommonNames::ToUnicode))
  23. m_to_unicode = TRY(dict->get_stream(document, CommonNames::ToUnicode));
  24. if (dict->contains(CommonNames::FirstChar) && dict->contains(CommonNames::LastChar) && dict->contains(CommonNames::Widths)) {
  25. auto first_char = dict->get_value(CommonNames::FirstChar).get<int>();
  26. auto last_char = dict->get_value(CommonNames::LastChar).get<int>();
  27. auto widths_array = TRY(dict->get_array(document, CommonNames::Widths));
  28. VERIFY(widths_array->size() == static_cast<size_t>(last_char - first_char + 1));
  29. for (size_t i = 0; i < widths_array->size(); i++)
  30. m_widths.set(first_char + i, widths_array->at(i).to_int());
  31. }
  32. if (dict->contains(CommonNames::FontDescriptor)) {
  33. auto descriptor = TRY(dict->get_dict(document, CommonNames::FontDescriptor));
  34. if (descriptor->contains(CommonNames::MissingWidth))
  35. m_missing_width = descriptor->get_value(CommonNames::MissingWidth).to_int();
  36. }
  37. return {};
  38. }
  39. PDFErrorOr<Gfx::FloatPoint> SimpleFont::draw_string(Gfx::Painter& painter, Gfx::FloatPoint glyph_position, ByteString const& string, Renderer const& renderer)
  40. {
  41. auto horizontal_scaling = renderer.text_state().horizontal_scaling;
  42. auto const& text_rendering_matrix = renderer.calculate_text_rendering_matrix();
  43. // TrueType fonts are prescaled to text_rendering_matrix.x_scale() * text_state().font_size / horizontal_scaling,
  44. // cf `Renderer::text_set_font()`. That's the width we get back from `get_glyph_width()` if we use a fallback
  45. // (or built-in) font. Scale the width size too, so the m_width.get() codepath is consistent.
  46. auto const font_size = text_rendering_matrix.x_scale() * renderer.text_state().font_size / horizontal_scaling;
  47. auto character_spacing = renderer.text_state().character_spacing;
  48. auto word_spacing = renderer.text_state().word_spacing;
  49. for (auto char_code : string.bytes()) {
  50. // Use the width specified in the font's dictionary if available,
  51. // and use the default width for the given font otherwise.
  52. float glyph_width;
  53. if (auto width = m_widths.get(char_code); width.has_value())
  54. glyph_width = font_size * width.value() * m_font_matrix.x_scale();
  55. else if (auto width = get_glyph_width(char_code); width.has_value())
  56. glyph_width = width.value();
  57. else
  58. glyph_width = font_size * m_missing_width * m_font_matrix.x_scale();
  59. Gfx::FloatPoint glyph_render_position = text_rendering_matrix.map(glyph_position);
  60. TRY(draw_glyph(painter, glyph_render_position, glyph_width, char_code, renderer));
  61. // glyph_width is scaled by `text_rendering_matrix.x_scale() * renderer.text_state().font_size / horizontal_scaling`,
  62. // but it should only be scaled by `renderer.text_state().font_size`.
  63. // FIXME: Having to divide here isn't pretty. Refactor things so that this isn't needed.
  64. auto tx = glyph_width / text_rendering_matrix.x_scale() * horizontal_scaling;
  65. tx += character_spacing;
  66. // ISO 32000 (PDF 2.0), 9.3.3 Wordspacing
  67. // "Word spacing shall be applied to every occurrence of the single-byte character code 32
  68. // in a string when using a simple font (including Type 3) or a composite font that defines
  69. // code 32 as a single-byte code."
  70. if (char_code == ' ')
  71. tx += word_spacing;
  72. glyph_position += { tx, 0.0f };
  73. }
  74. return glyph_position;
  75. }
  76. }