ScaledFont.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright (c) 2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Utf8View.h>
  7. #include <LibGfx/Font/Emoji.h>
  8. #include <LibGfx/Font/ScaledFont.h>
  9. namespace Gfx {
  10. ScaledFont::ScaledFont(NonnullRefPtr<Typeface> typeface, float point_width, float point_height, unsigned dpi_x, unsigned dpi_y)
  11. : m_typeface(move(typeface))
  12. , m_point_width(point_width)
  13. , m_point_height(point_height)
  14. {
  15. float units_per_em = m_typeface->units_per_em();
  16. m_x_scale = (point_width * dpi_x) / (POINTS_PER_INCH * units_per_em);
  17. m_y_scale = (point_height * dpi_y) / (POINTS_PER_INCH * units_per_em);
  18. auto metrics = m_typeface->metrics(m_x_scale, m_y_scale);
  19. m_pixel_size = m_point_height * (DEFAULT_DPI / POINTS_PER_INCH);
  20. m_pixel_size_rounded_up = static_cast<int>(ceilf(m_pixel_size));
  21. m_pixel_metrics = Gfx::FontPixelMetrics {
  22. .size = (float)pixel_size(),
  23. .x_height = metrics.x_height,
  24. .advance_of_ascii_zero = (float)glyph_width('0'),
  25. .ascent = metrics.ascender,
  26. .descent = metrics.descender,
  27. .line_gap = metrics.line_gap,
  28. };
  29. }
  30. float ScaledFont::width(StringView view) const { return unicode_view_width(Utf8View(view)); }
  31. float ScaledFont::width(Utf8View const& view) const { return unicode_view_width(view); }
  32. template<typename T>
  33. ALWAYS_INLINE float ScaledFont::unicode_view_width(T const& view) const
  34. {
  35. if (view.is_empty())
  36. return 0;
  37. float width = 0;
  38. float longest_width = 0;
  39. u32 last_code_point = 0;
  40. for (auto it = view.begin(); it != view.end(); last_code_point = *it, ++it) {
  41. auto code_point = *it;
  42. if (code_point == '\n' || code_point == '\r') {
  43. longest_width = max(width, longest_width);
  44. width = 0;
  45. continue;
  46. }
  47. auto kerning = glyphs_horizontal_kerning(last_code_point, code_point);
  48. width += kerning + glyph_or_emoji_width(it);
  49. }
  50. longest_width = max(width, longest_width);
  51. return longest_width;
  52. }
  53. bool ScaledFont::append_glyph_path_to(Gfx::DeprecatedPath& path, u32 glyph_id) const
  54. {
  55. return m_typeface->append_glyph_path_to(path, glyph_id, m_x_scale, m_y_scale);
  56. }
  57. float ScaledFont::glyph_left_bearing(u32 code_point) const
  58. {
  59. auto id = glyph_id_for_code_point(code_point);
  60. return glyph_metrics(id).left_side_bearing;
  61. }
  62. float ScaledFont::glyph_width(u32 code_point) const
  63. {
  64. auto id = glyph_id_for_code_point(code_point);
  65. return m_typeface->glyph_advance(id, m_x_scale, m_y_scale, m_point_width, m_point_height);
  66. }
  67. template<typename CodePointIterator>
  68. static float glyph_or_emoji_width_impl(ScaledFont const& font, CodePointIterator& it)
  69. {
  70. if (!font.has_color_bitmaps()) {
  71. if (auto const* emoji = Emoji::emoji_for_code_point_iterator(it))
  72. return font.pixel_size() * emoji->width() / emoji->height();
  73. }
  74. return font.glyph_width(*it);
  75. }
  76. float ScaledFont::glyph_or_emoji_width(Utf8CodePointIterator& it) const
  77. {
  78. return glyph_or_emoji_width_impl(*this, it);
  79. }
  80. float ScaledFont::glyphs_horizontal_kerning(u32 left_code_point, u32 right_code_point) const
  81. {
  82. if (left_code_point == 0 || right_code_point == 0)
  83. return 0.f;
  84. auto left_glyph_id = glyph_id_for_code_point(left_code_point);
  85. auto right_glyph_id = glyph_id_for_code_point(right_code_point);
  86. if (left_glyph_id == 0 || right_glyph_id == 0)
  87. return 0.f;
  88. return m_typeface->glyphs_horizontal_kerning(left_glyph_id, right_glyph_id, m_x_scale);
  89. }
  90. NonnullRefPtr<ScaledFont> ScaledFont::scaled_with_size(float point_size) const
  91. {
  92. if (point_size == m_point_height && point_size == m_point_width)
  93. return *const_cast<ScaledFont*>(this);
  94. return m_typeface->scaled_font(point_size);
  95. }
  96. NonnullRefPtr<Font> ScaledFont::with_size(float point_size) const
  97. {
  98. return scaled_with_size(point_size);
  99. }
  100. Gfx::FontPixelMetrics ScaledFont::pixel_metrics() const
  101. {
  102. return m_pixel_metrics;
  103. }
  104. float ScaledFont::pixel_size() const
  105. {
  106. return m_pixel_size;
  107. }
  108. int ScaledFont::pixel_size_rounded_up() const
  109. {
  110. return m_pixel_size_rounded_up;
  111. }
  112. float ScaledFont::point_size() const
  113. {
  114. return m_point_height;
  115. }
  116. }