• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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