• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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