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 class SkFont; 21 class SkFontMgr; 22 23 /** 24 Shapes text using HarfBuzz and places the shaped text into a 25 client-managed buffer. 26 27 If compiled without HarfBuzz, fall back on SkPaint::textToGlyphs. 28 */ 29 class SkShaper { 30 public: 31 static std::unique_ptr<SkShaper> MakePrimitive(); 32 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE 33 static std::unique_ptr<SkShaper> MakeShaperDrivenWrapper(sk_sp<SkFontMgr> = nullptr); 34 static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr); 35 static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr); 36 #endif 37 38 static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr); 39 40 SkShaper(); 41 virtual ~SkShaper(); 42 43 class RunIterator { 44 public: 45 virtual ~RunIterator() = default; 46 /** Set state to that of current run and move iterator to end of that run. */ 47 virtual void consume() = 0; 48 /** Offset to one past the last (utf8) element in the current run. */ 49 virtual size_t endOfCurrentRun() const = 0; 50 /** Return true if consume should no longer be called. */ 51 virtual bool atEnd() const = 0; 52 }; 53 54 private: 55 template <typename RunIteratorSubclass> 56 class TrivialRunIterator : public RunIteratorSubclass { 57 public: 58 static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, ""); TrivialRunIterator(size_t utf8Bytes)59 TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(false) {} consume()60 void consume() override { fAtEnd = true; } endOfCurrentRun()61 size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; } atEnd()62 bool atEnd() const override { return fAtEnd; } 63 private: 64 size_t fEnd; 65 bool fAtEnd; 66 }; 67 68 public: 69 class FontRunIterator : public RunIterator { 70 public: 71 virtual const SkFont& currentFont() const = 0; 72 }; 73 static std::unique_ptr<FontRunIterator> 74 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, 75 const SkFont& font, sk_sp<SkFontMgr> fallback); 76 class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> { 77 public: TrivialFontRunIterator(const SkFont & font,size_t utf8Bytes)78 TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes) 79 : TrivialRunIterator(utf8Bytes), fFont(font) {} currentFont()80 const SkFont& currentFont() const override { return fFont; } 81 private: 82 SkFont fFont; 83 }; 84 85 class BiDiRunIterator : public RunIterator { 86 public: 87 /** The unicode bidi embedding level (even ltr, odd rtl) */ 88 virtual uint8_t currentLevel() const = 0; 89 }; 90 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE 91 static std::unique_ptr<BiDiRunIterator> 92 MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel); 93 #endif 94 class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> { 95 public: TrivialBiDiRunIterator(uint8_t bidiLevel,size_t utf8Bytes)96 TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes) 97 : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {} currentLevel()98 uint8_t currentLevel() const override { return fBidiLevel; } 99 private: 100 uint8_t fBidiLevel; 101 }; 102 103 class ScriptRunIterator : public RunIterator { 104 public: 105 /** Should be iso15924 codes. */ 106 virtual SkFourByteTag currentScript() const = 0; 107 }; 108 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE 109 static std::unique_ptr<ScriptRunIterator> 110 MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes); 111 #endif 112 class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> { 113 public: TrivialScriptRunIterator(SkFourByteTag script,size_t utf8Bytes)114 TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes) 115 : TrivialRunIterator(utf8Bytes), fScript(script) {} currentScript()116 SkFourByteTag currentScript() const override { return fScript; } 117 private: 118 SkFourByteTag fScript; 119 }; 120 121 class LanguageRunIterator : public RunIterator { 122 public: 123 /** Should be BCP-47, c locale names may also work. */ 124 virtual const char* currentLanguage() const = 0; 125 }; 126 static std::unique_ptr<LanguageRunIterator> 127 MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes); 128 class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> { 129 public: TrivialLanguageRunIterator(const char * language,size_t utf8Bytes)130 TrivialLanguageRunIterator(const char* language, size_t utf8Bytes) 131 : TrivialRunIterator(utf8Bytes), fLanguage(language) {} currentLanguage()132 const char* currentLanguage() const override { return fLanguage.c_str(); } 133 private: 134 SkString fLanguage; 135 }; 136 137 class RunHandler { 138 public: 139 virtual ~RunHandler() = default; 140 141 struct Range { RangeRange142 constexpr Range() : fBegin(0), fSize(0) {} RangeRange143 constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {} 144 size_t fBegin; 145 size_t fSize; beginRange146 constexpr size_t begin() const { return fBegin; } endRange147 constexpr size_t end() const { return begin() + size(); } sizeRange148 constexpr size_t size() const { return fSize; } 149 }; 150 151 struct RunInfo { 152 const SkFont& fFont; 153 uint8_t fBidiLevel; 154 SkVector fAdvance; 155 size_t glyphCount; 156 Range utf8Range; 157 }; 158 159 struct Buffer { 160 SkGlyphID* glyphs; // required 161 SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i] 162 // if ( offsets) positions[i+1]-positions[i] are advances 163 SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i] 164 uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i] 165 SkPoint point; // offset to add to all positions 166 }; 167 168 /** Called when beginning a line. */ 169 virtual void beginLine() = 0; 170 171 /** Called once for each run in a line. Can compute baselines and offsets. */ 172 virtual void runInfo(const RunInfo&) = 0; 173 174 /** Called after all runInfo calls for a line. */ 175 virtual void commitRunInfo() = 0; 176 177 /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */ 178 virtual Buffer runBuffer(const RunInfo&) = 0; 179 180 /** Called after each runBuffer is filled out. */ 181 virtual void commitRunBuffer(const RunInfo&) = 0; 182 183 /** Called when ending a line. */ 184 virtual void commitLine() = 0; 185 }; 186 187 virtual void shape(const char* utf8, size_t utf8Bytes, 188 const SkFont& srcFont, 189 bool leftToRight, 190 SkScalar width, 191 RunHandler*) const = 0; 192 193 virtual void shape(const char* utf8, size_t utf8Bytes, 194 FontRunIterator&, 195 BiDiRunIterator&, 196 ScriptRunIterator&, 197 LanguageRunIterator&, 198 SkScalar width, 199 RunHandler*) const = 0; 200 201 private: 202 SkShaper(const SkShaper&) = delete; 203 SkShaper& operator=(const SkShaper&) = delete; 204 }; 205 206 /** 207 * Helper for shaping text directly into a SkTextBlob. 208 */ 209 class SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler { 210 public: SkTextBlobBuilderRunHandler(const char * utf8Text,SkPoint offset)211 SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset) 212 : fUtf8Text(utf8Text) 213 , fOffset(offset) {} 214 sk_sp<SkTextBlob> makeBlob(); endPoint()215 SkPoint endPoint() { return fOffset; } 216 217 void beginLine() override; 218 void runInfo(const RunInfo&) override; 219 void commitRunInfo() override; 220 Buffer runBuffer(const RunInfo&) override; 221 void commitRunBuffer(const RunInfo&) override; 222 void commitLine() override; 223 224 private: 225 SkTextBlobBuilder fBuilder; 226 char const * const fUtf8Text; 227 uint32_t* fClusters; 228 int fClusterOffset; 229 int fGlyphCount; 230 SkScalar fMaxRunAscent; 231 SkScalar fMaxRunDescent; 232 SkScalar fMaxRunLeading; 233 SkPoint fCurrentPosition; 234 SkPoint fOffset; 235 }; 236 237 #endif // SkShaper_DEFINED 238