• 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 #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