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