TextDirection.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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/Array.h>
  8. #include <AK/Utf32View.h>
  9. #include <AK/Vector.h>
  10. namespace Gfx {
  11. enum class BidirectionalClass {
  12. STRONG_LTR,
  13. STRONG_RTL,
  14. WEAK_NUMBERS,
  15. WEAK_SEPARATORS,
  16. NEUTRAL,
  17. };
  18. extern Array<BidirectionalClass, 0x1F000> const char_bidi_class_lookup_table;
  19. constexpr BidirectionalClass get_char_bidi_class(u32 ch)
  20. {
  21. if (ch >= char_bidi_class_lookup_table.size())
  22. return BidirectionalClass::STRONG_LTR;
  23. return char_bidi_class_lookup_table[ch];
  24. }
  25. // 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)
  26. constexpr u32 get_mirror_char(u32 ch)
  27. {
  28. if (ch == 0x28)
  29. return 0x29;
  30. if (ch == 0x29)
  31. return 0x28;
  32. if (ch == 0x3C)
  33. return 0x3E;
  34. if (ch == 0x3E)
  35. return 0x3C;
  36. if (ch == 0x5B)
  37. return 0x5D;
  38. if (ch == 0x7B)
  39. return 0x7D;
  40. if (ch == 0x7D)
  41. return 0x7B;
  42. if (ch == 0xAB)
  43. return 0xBB;
  44. if (ch == 0xBB)
  45. return 0xAB;
  46. if (ch == 0x2039)
  47. return 0x203A;
  48. if (ch == 0x203A)
  49. return 0x2039;
  50. return ch;
  51. }
  52. enum class TextDirection {
  53. LTR,
  54. RTL,
  55. };
  56. constexpr TextDirection bidi_class_to_direction(BidirectionalClass class_)
  57. {
  58. VERIFY(class_ != BidirectionalClass::NEUTRAL);
  59. if (class_ == BidirectionalClass::STRONG_LTR || class_ == BidirectionalClass::WEAK_NUMBERS || class_ == BidirectionalClass::WEAK_SEPARATORS)
  60. return TextDirection::LTR;
  61. return TextDirection::RTL;
  62. }
  63. // Assumes the text has a homogeneous direction
  64. template<typename TextType>
  65. constexpr TextDirection get_text_direction(TextType text)
  66. {
  67. for (u32 code_point : text) {
  68. auto char_direction = get_char_bidi_class(code_point);
  69. if (char_direction != BidirectionalClass::NEUTRAL)
  70. return bidi_class_to_direction(char_direction);
  71. }
  72. return TextDirection::LTR;
  73. }
  74. class DirectionalRun {
  75. public:
  76. DirectionalRun(Vector<u32> code_points, u8 embedding_level)
  77. : m_code_points(move(code_points))
  78. , m_embedding_level(embedding_level)
  79. {
  80. }
  81. [[nodiscard]] Utf32View text() const { return { m_code_points.data(), m_code_points.size() }; }
  82. [[nodiscard]] u8 embedding_level() const { return m_embedding_level; }
  83. [[nodiscard]] TextDirection direction() const { return (m_embedding_level % 2) == 0 ? TextDirection::LTR : TextDirection::RTL; }
  84. Vector<u32>& code_points() { return m_code_points; }
  85. private:
  86. Vector<u32> m_code_points;
  87. u8 m_embedding_level;
  88. };
  89. }