1 // Copyright 2021 Google LLC. 2 #ifndef Types_DEFINED 3 #define Types_DEFINED 4 5 #include <algorithm> 6 #include <cstddef> 7 #include "include/core/SkFont.h" 8 #include "include/core/SkSize.h" 9 #include "include/core/SkSpan.h" 10 #include "include/private/SkBitmaskEnum.h" 11 #include "include/private/SkTo.h" 12 13 namespace skia { 14 namespace text { 15 enum class TextAlign { 16 kLeft, 17 kRight, 18 kCenter, 19 kJustify, 20 kStart, 21 kEnd, 22 kNothing, 23 }; 24 25 enum class TextDirection { 26 kRtl, 27 kLtr, 28 }; 29 30 // This enum lists all possible ways to query output positioning 31 enum class PositionType { 32 kRandomText, 33 kGraphemeCluster, // Both the edge of the glyph cluster and the text grapheme 34 kGlyphCluster, 35 kGlyph, 36 kGlyphPart 37 }; 38 39 enum class LineBreakType { 40 kSortLineBreakBefore, 41 kHardLineBreakBefore, 42 }; 43 44 enum class LogicalRunType { 45 kText, 46 kLineBreak 47 }; 48 49 enum class CodeUnitFlags : uint8_t { 50 kNoCodeUnitFlag = (1 << 0), 51 kPartOfWhiteSpace = (1 << 1), 52 kGraphemeStart = (1 << 2), 53 kSoftLineBreakBefore = (1 << 3), 54 kHardLineBreakBefore = (1 << 4), 55 kAllCodeUnitFlags = ((1 << 5) - 1), 56 }; 57 58 enum class GlyphUnitFlags : uint8_t { 59 kNoGlyphUnitFlag = (1 << 0), 60 //kPartOfWhiteSpace = (1 << 1), 61 //kGraphemeStart = (1 << 2), 62 //kSoftLineBreakBefore = (1 << 3), 63 //kHardLineBreakBefore = (1 << 4), 64 kGlyphClusterStart = (1 << 5), 65 kGraphemeClusterStart = (1 << 6), 66 }; 67 68 typedef size_t TextIndex; 69 typedef size_t GlyphIndex; 70 typedef size_t RunIndex; 71 typedef size_t LineIndex; 72 const size_t EMPTY_INDEX = std::numeric_limits<size_t>::max(); 73 74 template <typename T> 75 class Range { 76 public: Range()77 Range() : fStart(0), fEnd(0) { } Range(T start,T end)78 Range(T start, T end) : fStart(start) , fEnd(end) { } 79 80 bool operator==(Range<T> other) { 81 return fStart == other.fStart && fEnd == other.fEnd; 82 } 83 clean()84 void clean() { 85 fStart = 0; 86 fEnd = 0; 87 } 88 isEmpty()89 bool isEmpty() const { 90 return fEnd == fStart; 91 } 92 contains(T index)93 bool contains(T index) const { 94 return index >= fStart && index < fEnd; 95 } 96 contains(Range<T> range)97 bool contains(Range<T> range) const { 98 return range.fStart >= fStart && range.fEnd < fEnd; 99 } 100 101 // For RTL ranges start >= end width()102 int width() const { 103 return SkToInt(fEnd - fStart); 104 } 105 merge(Range tail)106 void merge(Range tail) { 107 SkASSERT(this->fEnd == tail.fStart || this->fStart == tail.fEnd); 108 this->fStart = std::min(this->fStart, tail.fStart); 109 this->fEnd = std::max(this->fEnd, tail.fEnd); 110 } 111 intersect(Range other)112 void intersect(Range other) { 113 this->fStart = std::max(this->fStart, other.fStart); 114 this->fEnd = std::min(this->fEnd, other.fEnd); 115 if (this->fStart > this->fEnd) { 116 // There is nothing in the intersection; make it empty 117 this->fEnd = this->fStart; 118 } 119 } 120 121 template<typename Visitor> iterate(Visitor visitor)122 void iterate(Visitor visitor) { 123 if (this->leftToRight()) { 124 for (auto index = this->fStart; index < this->fEnd; ++index) { 125 visitor(index); 126 } 127 } else { 128 for (auto index = this->fStart; index < this->fEnd; --index) { 129 visitor(index); 130 } 131 } 132 } 133 134 T fStart; 135 T fEnd; 136 }; 137 138 typedef Range<TextIndex> TextRange; 139 typedef Range<GlyphIndex> GlyphRange; 140 struct DirTextRange : public TextRange { DirTextRangeDirTextRange141 DirTextRange(TextRange textRange, bool leftToRight) 142 : TextRange(textRange) 143 , fLeftToRight(leftToRight) { } DirTextRangeDirTextRange144 DirTextRange(TextIndex start, TextIndex end, bool leftToRight) 145 : TextRange(start, end) 146 , fLeftToRight(leftToRight) { } 147 beforeDirTextRange148 bool before(TextIndex index) const { 149 return fLeftToRight ? index >= fEnd : index < fStart; 150 } afterDirTextRange151 bool after(TextIndex index) const { 152 return fLeftToRight ? index < fEnd : index >= fStart; 153 } leftDirTextRange154 bool left() const { 155 return fLeftToRight ? fStart : fEnd; 156 } rightDirTextRange157 bool right() const { 158 return fLeftToRight ? fEnd : fStart; 159 } normalizedDirTextRange160 TextRange normalized() const { 161 return fLeftToRight ? TextRange(fStart, fEnd) : TextRange(fEnd, fStart); 162 } 163 bool fLeftToRight; 164 }; 165 166 const Range<size_t> EMPTY_RANGE = Range<size_t>(EMPTY_INDEX, EMPTY_INDEX); 167 168 // Blocks 169 enum BlockType { 170 kFontChain, 171 kPlaceholder, 172 }; 173 174 struct Placeholder { 175 SkSize dimensions; 176 float yOffsetFromBaseline; 177 }; 178 179 class FontChain : public SkRefCnt { 180 public: 181 // Returns the number of faces in the chain. Always >= 1 182 virtual size_t count() const = 0; 183 virtual sk_sp<SkTypeface> operator[](size_t index) const = 0; 184 virtual float fontSize() const = 0; 185 virtual SkString locale() const = 0; 186 }; 187 188 struct FontBlock { FontBlockFontBlock189 FontBlock(uint32_t count, sk_sp<FontChain> fontChain) 190 : type(BlockType::kFontChain) 191 , charCount(count) 192 , chain(fontChain) { } FontBlockFontBlock193 FontBlock() : FontBlock(0, nullptr) { } FontBlockFontBlock194 FontBlock(FontBlock& block) { 195 this->type = block.type; 196 this->charCount = block.charCount; 197 this->chain = block.chain; 198 } ~FontBlockFontBlock199 ~FontBlock() { } 200 201 BlockType type; 202 uint32_t charCount; 203 union { 204 sk_sp<FontChain> chain; 205 Placeholder placeholder; 206 }; 207 }; 208 209 struct ResolvedFontBlock { ResolvedFontBlockResolvedFontBlock210 ResolvedFontBlock(TextRange textRange, sk_sp<SkTypeface> typeface, SkScalar size, SkFontStyle fontStyle) 211 : textRange(textRange) 212 , typeface(typeface) 213 , size(size) 214 , style(fontStyle) { } 215 216 TextRange textRange; 217 sk_sp<SkTypeface> typeface; 218 float size; 219 SkFontStyle style; 220 }; 221 222 } // namespace text 223 } // namespace skia 224 225 namespace sknonstd { 226 template <> struct is_bitmask_enum<skia::text::CodeUnitFlags> : std::true_type {}; 227 template <> struct is_bitmask_enum<skia::text::GlyphUnitFlags> : std::true_type {}; 228 } 229 230 #endif 231