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