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