1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkShaper_DEFINED 9 #define SkShaper_DEFINED 10 11 #include "include/core/SkFontMgr.h" 12 #include "include/core/SkPoint.h" 13 #include "include/core/SkRefCnt.h" 14 #include "include/core/SkScalar.h" 15 #include "include/core/SkTextBlob.h" 16 #include "include/core/SkTypes.h" 17 18 #include <memory> 19 20 #if !defined(SKSHAPER_IMPLEMENTATION) 21 #define SKSHAPER_IMPLEMENTATION 0 22 #endif 23 24 #if !defined(SKSHAPER_API) 25 #if defined(SKSHAPER_DLL) 26 #if defined(_MSC_VER) 27 #if SKSHAPER_IMPLEMENTATION 28 #define SKSHAPER_API __declspec(dllexport) 29 #else 30 #define SKSHAPER_API __declspec(dllimport) 31 #endif 32 #else 33 #define SKSHAPER_API __attribute__((visibility("default"))) 34 #endif 35 #else 36 #define SKSHAPER_API 37 #endif 38 #endif 39 40 class SkFont; 41 class SkFontMgr; 42 class SkUnicode; 43 44 class SKSHAPER_API SkShaper { 45 public: 46 static std::unique_ptr<SkShaper> MakePrimitive(); 47 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE 48 static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr); 49 static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr); 50 static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr); 51 static void PurgeHarfBuzzCache(); 52 #endif 53 #ifdef SK_SHAPER_CORETEXT_AVAILABLE 54 static std::unique_ptr<SkShaper> MakeCoreText(); 55 #endif 56 57 static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr); 58 static void PurgeCaches(); 59 60 SkShaper(); 61 virtual ~SkShaper(); 62 63 class RunIterator { 64 public: 65 // Required until C++17 copy elision 66 RunIterator(const RunIterator&) = default; 67 // Required because above is required 68 RunIterator() = default; 69 virtual ~RunIterator() = default; 70 /** Set state to that of current run and move iterator to end of that run. */ 71 virtual void consume() = 0; 72 /** Offset to one past the last (utf8) element in the current run. */ 73 virtual size_t endOfCurrentRun() const = 0; 74 /** Return true if consume should no longer be called. */ 75 virtual bool atEnd() const = 0; 76 }; 77 class FontRunIterator : public RunIterator { 78 public: 79 virtual const SkFont& currentFont() const = 0; 80 }; 81 class BiDiRunIterator : public RunIterator { 82 public: 83 /** The unicode bidi embedding level (even ltr, odd rtl) */ 84 virtual uint8_t currentLevel() const = 0; 85 }; 86 class ScriptRunIterator : public RunIterator { 87 public: 88 /** Should be iso15924 codes. */ 89 virtual SkFourByteTag currentScript() const = 0; 90 }; 91 class LanguageRunIterator : public RunIterator { 92 public: 93 /** Should be BCP-47, c locale names may also work. */ 94 virtual const char* currentLanguage() const = 0; 95 }; 96 struct Feature { 97 SkFourByteTag tag; 98 uint32_t value; 99 size_t start; // Offset to the start (utf8) element of the run. 100 size_t end; // Offset to one past the last (utf8) element of the run. 101 }; 102 103 private: 104 template <typename RunIteratorSubclass> 105 class TrivialRunIterator : public RunIteratorSubclass { 106 public: 107 static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, ""); TrivialRunIterator(size_t utf8Bytes)108 TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {} consume()109 void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; } endOfCurrentRun()110 size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; } atEnd()111 bool atEnd() const override { return fAtEnd; } 112 private: 113 size_t fEnd; 114 bool fAtEnd; 115 }; 116 117 public: 118 static std::unique_ptr<FontRunIterator> 119 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 120 const SkFont& font, sk_sp<SkFontMgr> fallback); 121 static std::unique_ptr<SkShaper::FontRunIterator> 122 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 123 const SkFont& font, sk_sp<SkFontMgr> fallback, 124 const char* requestName, SkFontStyle requestStyle, 125 const SkShaper::LanguageRunIterator*); 126 class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { 127 public: TrivialFontRunIterator(const SkFont & font,size_t utf8Bytes)128 TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes) 129 : TrivialRunIterator(utf8Bytes), fFont(font) {} currentFont()130 const SkFont& currentFont() const override { return fFont; } 131 private: 132 SkFont fFont; 133 }; 134 135 static std::unique_ptr<BiDiRunIterator> 136 MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 137 #ifdef SK_UNICODE_AVAILABLE 138 static std::unique_ptr<BiDiRunIterator> 139 MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 140 static std::unique_ptr<BiDiRunIterator> 141 MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 142 #endif 143 class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> { 144 public: TrivialBiDiRunIterator(uint8_t bidiLevel,size_t utf8Bytes)145 TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes) 146 : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {} currentLevel()147 uint8_t currentLevel() const override { return fBidiLevel; } 148 private: 149 uint8_t fBidiLevel; 150 }; 151 152 static std::unique_ptr<ScriptRunIterator> 153 MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); 154 #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_UNICODE_AVAILABLE) 155 static std::unique_ptr<ScriptRunIterator> 156 MakeSkUnicodeHbScriptRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes); 157 static std::unique_ptr<ScriptRunIterator> 158 MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes); 159 #endif 160 class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> { 161 public: TrivialScriptRunIterator(SkFourByteTag script,size_t utf8Bytes)162 TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes) 163 : TrivialRunIterator(utf8Bytes), fScript(script) {} currentScript()164 SkFourByteTag currentScript() const override { return fScript; } 165 private: 166 SkFourByteTag fScript; 167 }; 168 169 static std::unique_ptr<LanguageRunIterator> 170 MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes); 171 class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> { 172 public: TrivialLanguageRunIterator(const char * language,size_t utf8Bytes)173 TrivialLanguageRunIterator(const char* language, size_t utf8Bytes) 174 : TrivialRunIterator(utf8Bytes), fLanguage(language) {} currentLanguage()175 const char* currentLanguage() const override { return fLanguage.c_str(); } 176 private: 177 SkString fLanguage; 178 }; 179 180 class RunHandler { 181 public: 182 virtual ~RunHandler() = default; 183 184 struct Range { RangeRange185 constexpr Range() : fBegin(0), fSize(0) {} RangeRange186 constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {} 187 size_t fBegin; 188 size_t fSize; beginRange189 constexpr size_t begin() const { return fBegin; } endRange190 constexpr size_t end() const { return begin() + size(); } sizeRange191 constexpr size_t size() const { return fSize; } 192 }; 193 194 struct RunInfo { 195 const SkFont& fFont; 196 uint8_t fBidiLevel; 197 SkVector fAdvance; 198 size_t glyphCount; 199 Range utf8Range; 200 }; 201 202 struct Buffer { 203 SkGlyphID* glyphs; // required 204 SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i] 205 // if ( offsets) positions[i+1]-positions[i] are advances 206 SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i] 207 uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i] 208 SkPoint point; // offset to add to all positions 209 }; 210 211 /** Called when beginning a line. */ 212 virtual void beginLine() = 0; 213 214 /** Called once for each run in a line. Can compute baselines and offsets. */ 215 virtual void runInfo(const RunInfo&) = 0; 216 217 /** Called after all runInfo calls for a line. */ 218 virtual void commitRunInfo() = 0; 219 220 /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */ 221 virtual Buffer runBuffer(const RunInfo&) = 0; 222 223 /** Called after each runBuffer is filled out. */ 224 virtual void commitRunBuffer(const RunInfo&) = 0; 225 226 /** Called when ending a line. */ 227 virtual void commitLine() = 0; 228 }; 229 230 virtual void shape(const char* utf8, size_t utf8Bytes, 231 const SkFont& srcFont, 232 bool leftToRight, 233 SkScalar width, 234 RunHandler*) const = 0; 235 236 virtual void shape(const char* utf8, size_t utf8Bytes, 237 FontRunIterator&, 238 BiDiRunIterator&, 239 ScriptRunIterator&, 240 LanguageRunIterator&, 241 SkScalar width, 242 RunHandler*) const = 0; 243 244 virtual void shape(const char* utf8, size_t utf8Bytes, 245 FontRunIterator&, 246 BiDiRunIterator&, 247 ScriptRunIterator&, 248 LanguageRunIterator&, 249 const Feature* features, size_t featuresSize, 250 SkScalar width, 251 RunHandler*) const = 0; 252 253 private: 254 SkShaper(const SkShaper&) = delete; 255 SkShaper& operator=(const SkShaper&) = delete; 256 }; 257 258 /** 259 * Helper for shaping text directly into a SkTextBlob. 260 */ 261 class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler { 262 public: SkTextBlobBuilderRunHandler(const char * utf8Text,SkPoint offset)263 SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset) 264 : fUtf8Text(utf8Text) 265 , fOffset(offset) {} 266 sk_sp<SkTextBlob> makeBlob(); endPoint()267 SkPoint endPoint() { return fOffset; } 268 269 void beginLine() override; 270 void runInfo(const RunInfo&) override; 271 void commitRunInfo() override; 272 Buffer runBuffer(const RunInfo&) override; 273 void commitRunBuffer(const RunInfo&) override; 274 void commitLine() override; 275 276 private: 277 SkTextBlobBuilder fBuilder; 278 char const * const fUtf8Text; 279 uint32_t* fClusters; 280 int fClusterOffset; 281 int fGlyphCount; 282 SkScalar fMaxRunAscent; 283 SkScalar fMaxRunDescent; 284 SkScalar fMaxRunLeading; 285 SkPoint fCurrentPosition; 286 SkPoint fOffset; 287 }; 288 289 #endif // SkShaper_DEFINED 290