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/base/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 GlyphUnitFlags : uint8_t { 50 kNoGlyphUnitFlag = (1 << 0), 51 //kPartOfWhiteSpace = (1 << 1), 52 //kGraphemeStart = (1 << 2), 53 //kSoftLineBreakBefore = (1 << 3), 54 //kHardLineBreakBefore = (1 << 4), 55 kGlyphClusterStart = (1 << 5), 56 kGraphemeClusterStart = (1 << 6), 57 }; 58 59 typedef size_t TextIndex; 60 typedef size_t GlyphIndex; 61 typedef size_t RunIndex; 62 typedef size_t LineIndex; 63 const size_t EMPTY_INDEX = std::numeric_limits<size_t>::max(); 64 65 template <typename T> 66 class Range { 67 public: Range()68 Range() : fStart(0), fEnd(0) { } Range(T start,T end)69 Range(T start, T end) : fStart(start) , fEnd(end) { } 70 71 bool operator==(Range<T> other) { 72 return fStart == other.fStart && fEnd == other.fEnd; 73 } 74 clean()75 void clean() { 76 fStart = 0; 77 fEnd = 0; 78 } 79 isEmpty()80 bool isEmpty() const { 81 return fEnd == fStart; 82 } 83 contains(T index)84 bool contains(T index) const { 85 return index >= fStart && index < fEnd; 86 } 87 contains(Range<T> range)88 bool contains(Range<T> range) const { 89 return range.fStart >= fStart && range.fEnd < fEnd; 90 } 91 92 // For RTL ranges start >= end width()93 int width() const { 94 return SkToInt(fEnd - fStart); 95 } 96 merge(Range tail)97 void merge(Range tail) { 98 SkASSERT(this->fEnd == tail.fStart || this->fStart == tail.fEnd); 99 this->fStart = std::min(this->fStart, tail.fStart); 100 this->fEnd = std::max(this->fEnd, tail.fEnd); 101 } 102 intersect(Range other)103 void intersect(Range other) { 104 this->fStart = std::max(this->fStart, other.fStart); 105 this->fEnd = std::min(this->fEnd, other.fEnd); 106 if (this->fStart > this->fEnd) { 107 // There is nothing in the intersection; make it empty 108 this->fEnd = this->fStart; 109 } 110 } 111 112 template<typename Visitor> iterate(Visitor visitor)113 void iterate(Visitor visitor) { 114 if (this->leftToRight()) { 115 for (auto index = this->fStart; index < this->fEnd; ++index) { 116 visitor(index); 117 } 118 } else { 119 for (auto index = this->fStart; index < this->fEnd; --index) { 120 visitor(index); 121 } 122 } 123 } 124 125 T fStart; 126 T fEnd; 127 }; 128 129 typedef Range<TextIndex> TextRange; 130 typedef Range<GlyphIndex> GlyphRange; 131 struct DirTextRange : public TextRange { DirTextRangeDirTextRange132 DirTextRange(TextRange textRange, bool leftToRight) 133 : TextRange(textRange) 134 , fLeftToRight(leftToRight) { } DirTextRangeDirTextRange135 DirTextRange(TextIndex start, TextIndex end, bool leftToRight) 136 : TextRange(start, end) 137 , fLeftToRight(leftToRight) { } 138 beforeDirTextRange139 bool before(TextIndex index) const { 140 return fLeftToRight ? index >= fEnd : index < fStart; 141 } afterDirTextRange142 bool after(TextIndex index) const { 143 return fLeftToRight ? index < fEnd : index >= fStart; 144 } leftDirTextRange145 bool left() const { 146 return fLeftToRight ? fStart : fEnd; 147 } rightDirTextRange148 bool right() const { 149 return fLeftToRight ? fEnd : fStart; 150 } normalizedDirTextRange151 TextRange normalized() const { 152 return fLeftToRight ? TextRange(fStart, fEnd) : TextRange(fEnd, fStart); 153 } 154 bool fLeftToRight; 155 }; 156 157 const Range<size_t> EMPTY_RANGE = Range<size_t>(EMPTY_INDEX, EMPTY_INDEX); 158 159 // Blocks 160 enum BlockType { 161 kFontChain, 162 kPlaceholder, 163 }; 164 165 struct Placeholder { 166 SkSize dimensions; 167 float yOffsetFromBaseline; 168 }; 169 170 class FontChain : public SkRefCnt { 171 public: 172 // Returns the number of faces in the chain. Always >= 1 173 virtual size_t count() const = 0; 174 virtual sk_sp<SkTypeface> operator[](size_t index) const = 0; 175 virtual float fontSize() const = 0; 176 virtual SkString locale() const = 0; 177 }; 178 179 struct FontBlock { FontBlockFontBlock180 FontBlock(uint32_t count, sk_sp<FontChain> fontChain) 181 : type(BlockType::kFontChain) 182 , charCount(count) 183 , chain(fontChain) { } FontBlockFontBlock184 FontBlock() : FontBlock(0, nullptr) { } FontBlockFontBlock185 FontBlock(FontBlock& block) { 186 this->type = block.type; 187 this->charCount = block.charCount; 188 this->chain = block.chain; 189 } ~FontBlockFontBlock190 ~FontBlock() { } 191 192 BlockType type; 193 uint32_t charCount; 194 union { 195 sk_sp<FontChain> chain; 196 Placeholder placeholder; 197 }; 198 }; 199 200 struct ResolvedFontBlock { ResolvedFontBlockResolvedFontBlock201 ResolvedFontBlock(TextRange textRange, sk_sp<SkTypeface> typeface, SkScalar size, SkFontStyle fontStyle) 202 : textRange(textRange) 203 , typeface(typeface) 204 , size(size) 205 , style(fontStyle) { } 206 207 TextRange textRange; 208 sk_sp<SkTypeface> typeface; 209 float size; 210 SkFontStyle style; 211 }; 212 213 } // namespace text 214 } // namespace skia 215 216 namespace sknonstd { 217 template <> struct is_bitmask_enum<skia::text::GlyphUnitFlags> : std::true_type {}; 218 } 219 220 #endif 221