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 #ifdef USE_SKIA_TXT 19 #include "modules/skparagraph/include/drawing.h" 20 #endif 21 22 #include <memory> 23 24 #if !defined(SKSHAPER_IMPLEMENTATION) 25 #define SKSHAPER_IMPLEMENTATION 0 26 #endif 27 28 #if !defined(SKSHAPER_API) 29 #if defined(SKSHAPER_DLL) 30 #if defined(_MSC_VER) 31 #if SKSHAPER_IMPLEMENTATION 32 #define SKSHAPER_API __declspec(dllexport) 33 #else 34 #define SKSHAPER_API __declspec(dllimport) 35 #endif 36 #else 37 #define SKSHAPER_API __attribute__((visibility("default"))) 38 #endif 39 #else 40 #define SKSHAPER_API 41 #endif 42 #endif 43 44 class SkFont; 45 class SkFontMgr; 46 class SkUnicode; 47 48 #ifdef USE_SKIA_TXT 49 namespace SkiaRsText { 50 #endif 51 52 class SKSHAPER_API SkShaper { 53 public: 54 static std::unique_ptr<SkShaper> MakePrimitive(); 55 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE 56 #ifndef USE_SKIA_TXT 57 static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr); 58 static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr); 59 static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(std::unique_ptr<SkUnicode> unicode, 60 sk_sp<SkFontMgr> = nullptr); 61 #else 62 static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(std::shared_ptr<RSFontMgr> = nullptr); 63 static std::unique_ptr<SkShaper> MakeShapeThenWrap(std::shared_ptr<RSFontMgr> = nullptr); 64 static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(std::unique_ptr<SkUnicode> unicode, 65 std::shared_ptr<RSFontMgr> = nullptr); 66 #endif 67 static void PurgeHarfBuzzCache(); 68 #endif 69 #ifdef SK_SHAPER_CORETEXT_AVAILABLE 70 static std::unique_ptr<SkShaper> MakeCoreText(); 71 #endif 72 73 #ifndef USE_SKIA_TXT 74 static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr); 75 #else 76 static std::unique_ptr<SkShaper> Make(std::shared_ptr<RSFontMgr> = nullptr); 77 #endif 78 static void PurgeCaches(); 79 80 SkShaper(); 81 virtual ~SkShaper(); 82 83 class RunIterator { 84 public: 85 virtual ~RunIterator() = default; 86 /** Set state to that of current run and move iterator to end of that run. */ 87 virtual void consume() = 0; 88 /** Offset to one past the last (utf8) element in the current run. */ 89 virtual size_t endOfCurrentRun() const = 0; 90 /** Return true if consume should no longer be called. */ 91 virtual bool atEnd() const = 0; 92 }; 93 class FontRunIterator : public RunIterator { 94 public: 95 #ifndef USE_SKIA_TXT 96 virtual const SkFont& currentFont() const = 0; 97 #else 98 virtual const RSFont& currentFont() const = 0; 99 #endif 100 }; 101 class BiDiRunIterator : public RunIterator { 102 public: 103 /** The unicode bidi embedding level (even ltr, odd rtl) */ 104 virtual uint8_t currentLevel() const = 0; 105 }; 106 class ScriptRunIterator : public RunIterator { 107 public: 108 /** Should be iso15924 codes. */ 109 virtual SkFourByteTag currentScript() const = 0; 110 }; 111 class LanguageRunIterator : public RunIterator { 112 public: 113 /** Should be BCP-47, c locale names may also work. */ 114 virtual const char* currentLanguage() const = 0; 115 }; 116 struct Feature { 117 SkFourByteTag tag; 118 uint32_t value; 119 size_t start; // Offset to the start (utf8) element of the run. 120 size_t end; // Offset to one past the last (utf8) element of the run. 121 }; 122 123 private: 124 template <typename RunIteratorSubclass> 125 class TrivialRunIterator : public RunIteratorSubclass { 126 public: 127 static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, ""); TrivialRunIterator(size_t utf8Bytes)128 TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {} consume()129 void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; } endOfCurrentRun()130 size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; } atEnd()131 bool atEnd() const override { return fAtEnd; } 132 private: 133 size_t fEnd; 134 bool fAtEnd; 135 }; 136 137 public: 138 #ifndef USE_SKIA_TXT 139 static std::unique_ptr<FontRunIterator> 140 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 141 const SkFont& font, sk_sp<SkFontMgr> fallback); 142 static std::unique_ptr<SkShaper::FontRunIterator> 143 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 144 const SkFont& font, sk_sp<SkFontMgr> fallback, 145 const char* requestName, SkFontStyle requestStyle, 146 const SkShaper::LanguageRunIterator*); 147 class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { 148 public: TrivialFontRunIterator(const SkFont & font,size_t utf8Bytes)149 TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes) 150 : TrivialRunIterator(utf8Bytes), fFont(font) {} currentFont()151 const SkFont& currentFont() const override { return fFont; } 152 private: 153 SkFont fFont; 154 }; 155 #else 156 static std::unique_ptr<FontRunIterator> 157 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 158 const RSFont& font, std::shared_ptr<RSFontMgr> fallback); 159 static std::unique_ptr<SkShaper::FontRunIterator> 160 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 161 const RSFont& font, std::shared_ptr<RSFontMgr> fallback, 162 const char* requestName, RSFontStyle requestStyle, 163 const SkShaper::LanguageRunIterator*); 164 class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { 165 public: 166 TrivialFontRunIterator(const RSFont& font, size_t utf8Bytes) 167 : TrivialRunIterator(utf8Bytes), fFont(font) {} 168 const RSFont& currentFont() const override { return fFont; } 169 private: 170 RSFont fFont; 171 }; 172 #endif 173 174 static std::unique_ptr<BiDiRunIterator> 175 MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 176 #ifdef SK_UNICODE_AVAILABLE 177 static std::unique_ptr<BiDiRunIterator> 178 MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 179 static std::unique_ptr<BiDiRunIterator> 180 MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 181 #endif 182 class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> { 183 public: TrivialBiDiRunIterator(uint8_t bidiLevel,size_t utf8Bytes)184 TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes) 185 : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {} currentLevel()186 uint8_t currentLevel() const override { return fBidiLevel; } 187 private: 188 uint8_t fBidiLevel; 189 }; 190 191 static std::unique_ptr<ScriptRunIterator> 192 MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); 193 #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_UNICODE_AVAILABLE) 194 static std::unique_ptr<ScriptRunIterator> 195 MakeSkUnicodeHbScriptRunIterator(const char* utf8, size_t utf8Bytes); 196 static std::unique_ptr<ScriptRunIterator> 197 MakeSkUnicodeHbScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); 198 // Still used in some cases 199 static std::unique_ptr<ScriptRunIterator> 200 MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes); 201 #endif 202 class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> { 203 public: TrivialScriptRunIterator(SkFourByteTag script,size_t utf8Bytes)204 TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes) 205 : TrivialRunIterator(utf8Bytes), fScript(script) {} currentScript()206 SkFourByteTag currentScript() const override { return fScript; } 207 private: 208 SkFourByteTag fScript; 209 }; 210 211 static std::unique_ptr<LanguageRunIterator> 212 MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes); 213 class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> { 214 public: TrivialLanguageRunIterator(const char * language,size_t utf8Bytes)215 TrivialLanguageRunIterator(const char* language, size_t utf8Bytes) 216 : TrivialRunIterator(utf8Bytes), fLanguage(language) {} currentLanguage()217 const char* currentLanguage() const override { return fLanguage.c_str(); } 218 private: 219 SkString fLanguage; 220 }; 221 222 class RunHandler { 223 public: 224 virtual ~RunHandler() = default; 225 226 struct Range { RangeRange227 constexpr Range() : fBegin(0), fSize(0) {} RangeRange228 constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {} 229 size_t fBegin; 230 size_t fSize; beginRange231 constexpr size_t begin() const { return fBegin; } endRange232 constexpr size_t end() const { return begin() + size(); } sizeRange233 constexpr size_t size() const { return fSize; } 234 }; 235 236 struct RunInfo { 237 #ifndef USE_SKIA_TXT 238 const SkFont& fFont; 239 #else 240 const RSFont& fFont; 241 #endif 242 uint8_t fBidiLevel; 243 SkVector fAdvance; 244 size_t glyphCount; 245 Range utf8Range; 246 }; 247 248 struct Buffer { 249 SkGlyphID* glyphs; // required 250 SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i] 251 // if ( offsets) positions[i+1]-positions[i] are advances 252 SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i] 253 uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i] 254 SkPoint point; // offset to add to all positions 255 }; 256 257 /** Called when beginning a line. */ 258 virtual void beginLine() = 0; 259 260 /** Called once for each run in a line. Can compute baselines and offsets. */ 261 virtual void runInfo(const RunInfo&) = 0; 262 263 /** Called after all runInfo calls for a line. */ 264 virtual void commitRunInfo() = 0; 265 266 /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */ 267 virtual Buffer runBuffer(const RunInfo&) = 0; 268 269 /** Called after each runBuffer is filled out. */ 270 virtual void commitRunBuffer(const RunInfo&) = 0; 271 272 /** Called when ending a line. */ 273 virtual void commitLine() = 0; 274 }; 275 276 virtual void shape(const char* utf8, size_t utf8Bytes, 277 #ifndef USE_SKIA_TXT 278 const SkFont& srcFont, 279 #else 280 const RSFont& srcFont, 281 #endif 282 bool leftToRight, 283 SkScalar width, 284 RunHandler*) const = 0; 285 286 virtual void shape(const char* utf8, size_t utf8Bytes, 287 FontRunIterator&, 288 BiDiRunIterator&, 289 ScriptRunIterator&, 290 LanguageRunIterator&, 291 SkScalar width, 292 RunHandler*) const = 0; 293 294 virtual void shape(const char* utf8, size_t utf8Bytes, 295 FontRunIterator&, 296 BiDiRunIterator&, 297 ScriptRunIterator&, 298 LanguageRunIterator&, 299 const Feature* features, size_t featuresSize, 300 SkScalar width, 301 RunHandler*) const = 0; 302 303 private: 304 SkShaper(const SkShaper&) = delete; 305 SkShaper& operator=(const SkShaper&) = delete; 306 }; 307 308 #ifndef USE_SKIA_TXT 309 /** 310 * Helper for shaping text directly into a SkTextBlob. 311 */ 312 class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler { 313 public: SkTextBlobBuilderRunHandler(const char * utf8Text,SkPoint offset)314 SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset) 315 : fUtf8Text(utf8Text) 316 , fOffset(offset) {} 317 sk_sp<SkTextBlob> makeBlob(); endPoint()318 SkPoint endPoint() { return fOffset; } 319 320 void beginLine() override; 321 void runInfo(const RunInfo&) override; 322 void commitRunInfo() override; 323 Buffer runBuffer(const RunInfo&) override; 324 void commitRunBuffer(const RunInfo&) override; 325 void commitLine() override; 326 327 private: 328 SkTextBlobBuilder fBuilder; 329 char const * const fUtf8Text; 330 uint32_t* fClusters; 331 int fClusterOffset; 332 int fGlyphCount; 333 SkScalar fMaxRunAscent; 334 SkScalar fMaxRunDescent; 335 SkScalar fMaxRunLeading; 336 SkPoint fCurrentPosition; 337 SkPoint fOffset; 338 }; 339 #endif 340 341 #ifdef USE_SKIA_TXT 342 } 343 using SkShaper = SkiaRsText::SkShaper; 344 #endif 345 #endif // SkShaper_DEFINED 346