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 virtual ~RunIterator() = default; 66 /** Set state to that of current run and move iterator to end of that run. */ 67 virtual void consume() = 0; 68 /** Offset to one past the last (utf8) element in the current run. */ 69 virtual size_t endOfCurrentRun() const = 0; 70 /** Return true if consume should no longer be called. */ 71 virtual bool atEnd() const = 0; 72 }; 73 class FontRunIterator : public RunIterator { 74 public: 75 virtual const SkFont& currentFont() const = 0; 76 }; 77 class BiDiRunIterator : public RunIterator { 78 public: 79 /** The unicode bidi embedding level (even ltr, odd rtl) */ 80 virtual uint8_t currentLevel() const = 0; 81 }; 82 class ScriptRunIterator : public RunIterator { 83 public: 84 /** Should be iso15924 codes. */ 85 virtual SkFourByteTag currentScript() const = 0; 86 }; 87 class LanguageRunIterator : public RunIterator { 88 public: 89 /** Should be BCP-47, c locale names may also work. */ 90 virtual const char* currentLanguage() const = 0; 91 }; 92 struct Feature { 93 SkFourByteTag tag; 94 uint32_t value; 95 size_t start; // Offset to the start (utf8) element of the run. 96 size_t end; // Offset to one past the last (utf8) element of the run. 97 }; 98 99 private: 100 template <typename RunIteratorSubclass> 101 class TrivialRunIterator : public RunIteratorSubclass { 102 public: 103 static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, ""); TrivialRunIterator(size_t utf8Bytes)104 TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {} consume()105 void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; } endOfCurrentRun()106 size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; } atEnd()107 bool atEnd() const override { return fAtEnd; } 108 private: 109 size_t fEnd; 110 bool fAtEnd; 111 }; 112 113 public: 114 static std::unique_ptr<FontRunIterator> 115 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 116 const SkFont& font, sk_sp<SkFontMgr> fallback); 117 static std::unique_ptr<SkShaper::FontRunIterator> 118 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 119 const SkFont& font, sk_sp<SkFontMgr> fallback, 120 const char* requestName, SkFontStyle requestStyle, 121 const SkShaper::LanguageRunIterator*); 122 class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { 123 public: TrivialFontRunIterator(const SkFont & font,size_t utf8Bytes)124 TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes) 125 : TrivialRunIterator(utf8Bytes), fFont(font) {} currentFont()126 const SkFont& currentFont() const override { return fFont; } 127 private: 128 SkFont fFont; 129 }; 130 131 static std::unique_ptr<BiDiRunIterator> 132 MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 133 #ifdef SK_UNICODE_AVAILABLE 134 static std::unique_ptr<BiDiRunIterator> 135 MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 136 static std::unique_ptr<BiDiRunIterator> 137 MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 138 #endif 139 class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> { 140 public: TrivialBiDiRunIterator(uint8_t bidiLevel,size_t utf8Bytes)141 TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes) 142 : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {} currentLevel()143 uint8_t currentLevel() const override { return fBidiLevel; } 144 private: 145 uint8_t fBidiLevel; 146 }; 147 148 static std::unique_ptr<ScriptRunIterator> 149 MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script); 150 #if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_UNICODE_AVAILABLE) 151 static std::unique_ptr<ScriptRunIterator> 152 MakeSkUnicodeHbScriptRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes); 153 static std::unique_ptr<ScriptRunIterator> 154 MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes); 155 #endif 156 class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> { 157 public: TrivialScriptRunIterator(SkFourByteTag script,size_t utf8Bytes)158 TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes) 159 : TrivialRunIterator(utf8Bytes), fScript(script) {} currentScript()160 SkFourByteTag currentScript() const override { return fScript; } 161 private: 162 SkFourByteTag fScript; 163 }; 164 165 static std::unique_ptr<LanguageRunIterator> 166 MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes); 167 class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> { 168 public: TrivialLanguageRunIterator(const char * language,size_t utf8Bytes)169 TrivialLanguageRunIterator(const char* language, size_t utf8Bytes) 170 : TrivialRunIterator(utf8Bytes), fLanguage(language) {} currentLanguage()171 const char* currentLanguage() const override { return fLanguage.c_str(); } 172 private: 173 SkString fLanguage; 174 }; 175 176 class RunHandler { 177 public: 178 virtual ~RunHandler() = default; 179 180 struct Range { RangeRange181 constexpr Range() : fBegin(0), fSize(0) {} RangeRange182 constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {} 183 size_t fBegin; 184 size_t fSize; beginRange185 constexpr size_t begin() const { return fBegin; } endRange186 constexpr size_t end() const { return begin() + size(); } sizeRange187 constexpr size_t size() const { return fSize; } 188 }; 189 190 struct RunInfo { 191 const SkFont& fFont; 192 uint8_t fBidiLevel; 193 SkVector fAdvance; 194 size_t glyphCount; 195 Range utf8Range; 196 }; 197 198 struct Buffer { 199 SkGlyphID* glyphs; // required 200 SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i] 201 // if ( offsets) positions[i+1]-positions[i] are advances 202 SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i] 203 uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i] 204 SkPoint point; // offset to add to all positions 205 }; 206 207 /** Called when beginning a line. */ 208 virtual void beginLine() = 0; 209 210 /** Called once for each run in a line. Can compute baselines and offsets. */ 211 virtual void runInfo(const RunInfo&) = 0; 212 213 /** Called after all runInfo calls for a line. */ 214 virtual void commitRunInfo() = 0; 215 216 /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */ 217 virtual Buffer runBuffer(const RunInfo&) = 0; 218 219 /** Called after each runBuffer is filled out. */ 220 virtual void commitRunBuffer(const RunInfo&) = 0; 221 222 /** Called when ending a line. */ 223 virtual void commitLine() = 0; 224 }; 225 226 virtual void shape(const char* utf8, size_t utf8Bytes, 227 const SkFont& srcFont, 228 bool leftToRight, 229 SkScalar width, 230 RunHandler*) const = 0; 231 232 virtual void shape(const char* utf8, size_t utf8Bytes, 233 FontRunIterator&, 234 BiDiRunIterator&, 235 ScriptRunIterator&, 236 LanguageRunIterator&, 237 SkScalar width, 238 RunHandler*) const = 0; 239 240 virtual void shape(const char* utf8, size_t utf8Bytes, 241 FontRunIterator&, 242 BiDiRunIterator&, 243 ScriptRunIterator&, 244 LanguageRunIterator&, 245 const Feature* features, size_t featuresSize, 246 SkScalar width, 247 RunHandler*) const = 0; 248 249 private: 250 SkShaper(const SkShaper&) = delete; 251 SkShaper& operator=(const SkShaper&) = delete; 252 }; 253 254 /** 255 * Helper for shaping text directly into a SkTextBlob. 256 */ 257 class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler { 258 public: SkTextBlobBuilderRunHandler(const char * utf8Text,SkPoint offset)259 SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset) 260 : fUtf8Text(utf8Text) 261 , fOffset(offset) {} 262 sk_sp<SkTextBlob> makeBlob(); endPoint()263 SkPoint endPoint() { return fOffset; } 264 265 void beginLine() override; 266 void runInfo(const RunInfo&) override; 267 void commitRunInfo() override; 268 Buffer runBuffer(const RunInfo&) override; 269 void commitRunBuffer(const RunInfo&) override; 270 void commitLine() override; 271 272 private: 273 SkTextBlobBuilder fBuilder; 274 char const * const fUtf8Text; 275 uint32_t* fClusters; 276 int fClusterOffset; 277 int fGlyphCount; 278 SkScalar fMaxRunAscent; 279 SkScalar fMaxRunDescent; 280 SkScalar fMaxRunLeading; 281 SkPoint fCurrentPosition; 282 SkPoint fOffset; 283 }; 284 285 #endif // SkShaper_DEFINED 286