TextDirection.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Utf32View.h>
  8. #include <AK/Vector.h>
  9. namespace Gfx {
  10. enum class BidirectionalClass {
  11. STRONG_LTR,
  12. STRONG_RTL,
  13. WEAK_NUMBERS,
  14. WEAK_SEPARATORS,
  15. NEUTRAL,
  16. };
  17. extern const Array<BidirectionalClass, 0x1F000> char_bidi_class_lookup_table;
  18. constexpr BidirectionalClass get_char_bidi_class(u32 ch)
  19. {
  20. if (ch >= char_bidi_class_lookup_table.size())
  21. return BidirectionalClass::STRONG_LTR;
  22. return char_bidi_class_lookup_table[ch];
  23. }
  24. // FIXME: These should be parsed from the official BidiMirroring.txt that specifies the mirroring character for each character (this function doesn't take into account a large amount of characters)
  25. constexpr u32 get_mirror_char(u32 ch)
  26. {
  27. if (ch == 0x28)
  28. return 0x29;
  29. if (ch == 0x29)
  30. return 0x28;
  31. if (ch == 0x3C)
  32. return 0x3E;
  33. if (ch == 0x3E)
  34. return 0x3C;
  35. if (ch == 0x5B)
  36. return 0x5D;
  37. if (ch == 0x7B)
  38. return 0x7D;
  39. if (ch == 0x7D)
  40. return 0x7B;
  41. if (ch == 0xAB)
  42. return 0xBB;
  43. if (ch == 0xBB)
  44. return 0xAB;
  45. if (ch == 0x2039)
  46. return 0x203A;
  47. if (ch == 0x203A)
  48. return 0x2039;
  49. return ch;
  50. }
  51. enum class TextDirection {
  52. LTR,
  53. RTL,
  54. };
  55. constexpr TextDirection bidi_class_to_direction(BidirectionalClass class_)
  56. {
  57. VERIFY(class_ != BidirectionalClass::NEUTRAL);
  58. if (class_ == BidirectionalClass::STRONG_LTR || class_ == BidirectionalClass::WEAK_NUMBERS || class_ == BidirectionalClass::WEAK_SEPARATORS)
  59. return TextDirection::LTR;
  60. return TextDirection::RTL;
  61. }
  62. // Assumes the text has a homogeneous direction
  63. template<typename TextType>
  64. constexpr TextDirection get_text_direction(TextType text)
  65. {
  66. for (u32 code_point : text) {
  67. auto char_direction = get_char_bidi_class(code_point);
  68. if (char_direction != BidirectionalClass::NEUTRAL)
  69. return bidi_class_to_direction(char_direction);
  70. }
  71. return TextDirection::LTR;
  72. }
  73. class DirectionalRun {
  74. public:
  75. DirectionalRun(Vector<u32> code_points, u8 embedding_level)
  76. : m_code_points(move(code_points))
  77. , m_embedding_level(embedding_level)
  78. {
  79. }
  80. [[nodiscard]] Utf32View text() const { return { m_code_points.data(), m_code_points.size() }; }
  81. [[nodiscard]] u8 embedding_level() const { return m_embedding_level; }
  82. [[nodiscard]] TextDirection direction() const { return (m_embedding_level % 2) == 0 ? TextDirection::LTR : TextDirection::RTL; }
  83. Vector<u32>& code_points() { return m_code_points; }
  84. private:
  85. Vector<u32> m_code_points;
  86. u8 m_embedding_level;
  87. };
  88. }