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
40class SkFont;
41class 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 */
49class SKSHAPER_API SkShaper {
50public:
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
101private:
102 template <typename RunIteratorSubclass>
103 class TrivialRunIterator : public RunIteratorSubclass {
104 public:
105 static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, "");
106 TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {}
107 void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; }
108 size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; }
109 bool atEnd() const override { return fAtEnd; }
110 private:
111 size_t fEnd;
112 bool fAtEnd;
113 };
114
115public:
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:
126 TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes)
127 : TrivialRunIterator(utf8Bytes), fFont(font) {}
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:
141 TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes)
142 : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {}
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:
156 TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes)
157 : TrivialRunIterator(utf8Bytes), fScript(script) {}
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:
167 TrivialLanguageRunIterator(const char* language, size_t utf8Bytes)
168 : TrivialRunIterator(utf8Bytes), fLanguage(language) {}
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 {
179 constexpr Range() : fBegin(0), fSize(0) {}
180 constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {}
181 size_t fBegin;
182 size_t fSize;
183 constexpr size_t begin() const { return fBegin; }
184 constexpr size_t end() const { return begin() + size(); }
185 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
247private:
248 SkShaper(const SkShaper&) = delete;
249 SkShaper& operator=(const SkShaper&) = delete;
250};
251
252/**
253 * Helper for shaping text directly into a SkTextBlob.
254 */
255class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler {
256public:
257 SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset)
258 : fUtf8Text(utf8Text)
259 , fOffset(offset) {}
260 sk_sp<SkTextBlob> makeBlob();
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
270private:
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