ScaledFont.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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. #include <LibGfx/TextLayout.h>
  10. namespace Gfx {
  11. ScaledFont::ScaledFont(NonnullRefPtr<Typeface> typeface, float point_width, float point_height, unsigned dpi_x, unsigned dpi_y)
  12. : m_typeface(move(typeface))
  13. , m_point_width(point_width)
  14. , m_point_height(point_height)
  15. {
  16. float units_per_em = m_typeface->units_per_em();
  17. m_x_scale = (point_width * dpi_x) / (POINTS_PER_INCH * units_per_em);
  18. m_y_scale = (point_height * dpi_y) / (POINTS_PER_INCH * units_per_em);
  19. auto metrics = m_typeface->metrics(m_x_scale, m_y_scale);
  20. m_pixel_size = m_point_height * (DEFAULT_DPI / POINTS_PER_INCH);
  21. m_pixel_size_rounded_up = static_cast<int>(ceilf(m_pixel_size));
  22. m_pixel_metrics = Gfx::FontPixelMetrics {
  23. .size = (float)pixel_size(),
  24. .x_height = metrics.x_height,
  25. .advance_of_ascii_zero = (float)glyph_width('0'),
  26. .ascent = metrics.ascender,
  27. .descent = metrics.descender,
  28. .line_gap = metrics.line_gap,
  29. };
  30. }
  31. float ScaledFont::width(StringView view) const { return measure_text_width(Utf8View(view), *this); }
  32. float ScaledFont::width(Utf8View const& view) const { return measure_text_width(view, *this); }
  33. float ScaledFont::glyph_width(u32 code_point) const
  34. {
  35. auto id = glyph_id_for_code_point(code_point);
  36. return m_typeface->glyph_advance(id, m_x_scale, m_y_scale, m_point_width, m_point_height);
  37. }
  38. template<typename CodePointIterator>
  39. static float glyph_or_emoji_width_impl(ScaledFont const& font, CodePointIterator& it)
  40. {
  41. if (auto const* emoji = Emoji::emoji_for_code_point_iterator(it))
  42. return font.pixel_size() * emoji->width() / emoji->height();
  43. return font.glyph_width(*it);
  44. }
  45. float ScaledFont::glyph_or_emoji_width(Utf8CodePointIterator& it) const
  46. {
  47. return glyph_or_emoji_width_impl(*this, it);
  48. }
  49. float ScaledFont::glyphs_horizontal_kerning(u32 left_code_point, u32 right_code_point) const
  50. {
  51. if (left_code_point == 0 || right_code_point == 0)
  52. return 0.f;
  53. auto left_glyph_id = glyph_id_for_code_point(left_code_point);
  54. auto right_glyph_id = glyph_id_for_code_point(right_code_point);
  55. if (left_glyph_id == 0 || right_glyph_id == 0)
  56. return 0.f;
  57. return m_typeface->glyphs_horizontal_kerning(left_glyph_id, right_glyph_id, m_x_scale);
  58. }
  59. NonnullRefPtr<ScaledFont> ScaledFont::scaled_with_size(float point_size) const
  60. {
  61. if (point_size == m_point_height && point_size == m_point_width)
  62. return *const_cast<ScaledFont*>(this);
  63. return m_typeface->scaled_font(point_size);
  64. }
  65. NonnullRefPtr<Font> ScaledFont::with_size(float point_size) const
  66. {
  67. return scaled_with_size(point_size);
  68. }
  69. Gfx::FontPixelMetrics ScaledFont::pixel_metrics() const
  70. {
  71. return m_pixel_metrics;
  72. }
  73. float ScaledFont::pixel_size() const
  74. {
  75. return m_pixel_size;
  76. }
  77. int ScaledFont::pixel_size_rounded_up() const
  78. {
  79. return m_pixel_size_rounded_up;
  80. }
  81. float ScaledFont::point_size() const
  82. {
  83. return m_point_height;
  84. }
  85. }