1 // Copyright 2021 Google LLC. 2 #ifndef Types_DEFINED 3 #define Types_DEFINED 4 5 #include <algorithm> 6 #include <cstddef> 7 #include "include/private/SkBitmaskEnum.h" 8 #include "include/private/SkTo.h" 9 10 namespace skia { 11 namespace text { 12 enum class TextAlign { 13 kLeft, 14 kRight, 15 kCenter, 16 kJustify, 17 kStart, 18 kEnd, 19 }; 20 21 enum class TextDirection { 22 kRtl, 23 kLtr, 24 }; 25 26 enum class LineBreakType { 27 kSortLineBreakBefore, 28 kHardLineBreakBefore, 29 }; 30 31 enum CodeUnitFlags : uint32_t { 32 kNoCodeUnitFlag = 0x000, 33 kPartOfWhiteSpace = 0x001, 34 kGraphemeStart = 0x002, 35 kSoftLineBreakBefore = 0x004, 36 kHardLineBreakBefore = 0x008, 37 // This information we get from SkShaper 38 kGlyphStart = 0x010, 39 kGlyphClusterStart = 0x020, 40 kNonExistingFlag = 0x040, 41 }; 42 43 typedef size_t TextIndex; 44 typedef size_t GlyphIndex; 45 const size_t EMPTY_INDEX = std::numeric_limits<size_t>::max(); 46 47 template <typename T> 48 class Range { 49 public: Range()50 Range() : fStart(0), fEnd(0) { } Range(T start,T end)51 Range(T start, T end) : fStart(start) , fEnd(end) { } 52 leftToRight()53 bool leftToRight() const { 54 return fEnd >= fStart; 55 } 56 normalize()57 void normalize() { 58 if (!this->leftToRight()) { 59 std::swap(this->fStart, this->fEnd); 60 } 61 } 62 63 // For RTL ranges start >= end width()64 int width() const { 65 return leftToRight() ? SkToInt(fEnd - fStart) : SkToInt(fStart - fEnd); 66 } 67 clean()68 void clean() { 69 fStart = 0; 70 fEnd = 0; 71 } 72 isEmpty()73 bool isEmpty() const { 74 return fEnd == fStart; 75 } 76 merge(Range tail)77 void merge(Range tail) { 78 auto ltr1 = this->leftToRight(); 79 auto ltr2 = tail.leftToRight(); 80 this->normalize(); 81 tail.normalize(); 82 SkASSERT(this->fEnd == tail.fStart || this->fStart == tail.fEnd); 83 this->fStart = std::min(this->fStart, tail.fStart); 84 this->fEnd = std::max(this->fEnd, tail.fEnd); 85 // TODO: Merging 2 different directions 86 if (!ltr1 || !ltr2) { 87 std::swap(this->fStart, this->fEnd); 88 std::swap(tail.fStart, tail.fEnd); 89 } 90 } 91 intersect(Range other)92 void intersect(Range other) { 93 auto ltr = this->leftToRight(); 94 95 this->normalize(); 96 other.normalize(); 97 this->fStart = std::max(this->fStart, other.fStart); 98 this->fEnd = std::min(this->fEnd, other.fEnd); 99 if (this->fStart > this->fEnd) { 100 // There is nothing in the intersection; make it empty 101 this->fEnd = this->fStart; 102 } else if (!ltr) { 103 std::swap(this->fStart, this->fEnd); 104 } 105 } 106 107 template<typename Visitor> iterate(Visitor visitor)108 void iterate(Visitor visitor) { 109 if (this->leftToRight()) { 110 for (auto index = this->fStart; index < this->fEnd; ++index) { 111 visitor(index); 112 } 113 } else { 114 for (auto index = this->fStart; index < this->fEnd; --index) { 115 visitor(index); 116 } 117 } 118 } 119 120 T fStart; 121 T fEnd; 122 }; 123 124 typedef Range<TextIndex> TextRange; 125 typedef Range<GlyphIndex> GlyphRange; 126 const Range EMPTY_RANGE = Range(EMPTY_INDEX, EMPTY_INDEX); 127 128 } // namespace text 129 } // namespace skia 130 131 namespace sknonstd { 132 template <> struct is_bitmask_enum<skia::text::CodeUnitFlags> : std::true_type {}; 133 } 134 135 #endif 136