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 #ifdef SK_SHAPER_CORETEXT_AVAILABLE
58 static std::unique_ptr<SkShaper> MakeCoreText();
59 #endif
60
61 static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr);
62
63 SkShaper();
64 virtual ~SkShaper();
65
66 class RunIterator {
67 public:
68 virtual ~RunIterator() = default;
69 /** Set state to that of current run and move iterator to end of that run. */
70 virtual void consume() = 0;
71 /** Offset to one past the last (utf8) element in the current run. */
72 virtual size_t endOfCurrentRun() const = 0;
73 /** Return true if consume should no longer be called. */
74 virtual bool atEnd() const = 0;
75 };
76 class FontRunIterator : public RunIterator {
77 public:
78 virtual const SkFont& currentFont() const = 0;
79 };
80 class BiDiRunIterator : public RunIterator {
81 public:
82 /** The unicode bidi embedding level (even ltr, odd rtl) */
83 virtual uint8_t currentLevel() const = 0;
84 };
85 class ScriptRunIterator : public RunIterator {
86 public:
87 /** Should be iso15924 codes. */
88 virtual SkFourByteTag currentScript() const = 0;
89 };
90 class LanguageRunIterator : public RunIterator {
91 public:
92 /** Should be BCP-47, c locale names may also work. */
93 virtual const char* currentLanguage() const = 0;
94 };
95 struct Feature {
96 SkFourByteTag tag;
97 uint32_t value;
98 size_t start; // Offset to the start (utf8) element of the run.
99 size_t end; // Offset to one past the last (utf8) element of the run.
100 };
101
102private:
103 template <typename RunIteratorSubclass>
104 class TrivialRunIterator : public RunIteratorSubclass {
105 public:
106 static_assert(std::is_base_of<RunIterator, RunIteratorSubclass>::value, "");
107 TrivialRunIterator(size_t utf8Bytes) : fEnd(utf8Bytes), fAtEnd(fEnd == 0) {}
108 void consume() override { SkASSERT(!fAtEnd); fAtEnd = true; }
109 size_t endOfCurrentRun() const override { return fAtEnd ? fEnd : 0; }
110 bool atEnd() const override { return fAtEnd; }
111 private:
112 size_t fEnd;
113 bool fAtEnd;
114 };
115
116public:
117 static std::unique_ptr<FontRunIterator>
118 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes,
119 const SkFont& font, sk_sp<SkFontMgr> fallback);
120 static std::unique_ptr<SkShaper::FontRunIterator>
121 MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes,
122 const SkFont& font, sk_sp<SkFontMgr> fallback,
123 const char* requestName, SkFontStyle requestStyle,
124 const SkShaper::LanguageRunIterator*);
125 class TrivialFontRunIterator : public TrivialRunIterator<FontRunIterator> {
126 public:
127 TrivialFontRunIterator(const SkFont& font, size_t utf8Bytes)
128 : TrivialRunIterator(utf8Bytes), fFont(font) {}
129 const SkFont& currentFont() const override { return fFont; }
130 private:
131 SkFont fFont;
132 };
133
134 static std::unique_ptr<BiDiRunIterator>
135 MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
136 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
137 static std::unique_ptr<BiDiRunIterator>
138 MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
139 #endif
140 class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> {
141 public:
142 TrivialBiDiRunIterator(uint8_t bidiLevel, size_t utf8Bytes)
143 : TrivialRunIterator(utf8Bytes), fBidiLevel(bidiLevel) {}
144 uint8_t currentLevel() const override { return fBidiLevel; }
145 private:
146 uint8_t fBidiLevel;
147 };
148
149 static std::unique_ptr<ScriptRunIterator>
150 MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag script);
151 #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
152 static std::unique_ptr<ScriptRunIterator>
153 MakeHbIcuScriptRunIterator(const char* utf8, size_t utf8Bytes);
154 #endif
155 class TrivialScriptRunIterator : public TrivialRunIterator<ScriptRunIterator> {
156 public:
157 TrivialScriptRunIterator(SkFourByteTag script, size_t utf8Bytes)
158 : TrivialRunIterator(utf8Bytes), fScript(script) {}
159 SkFourByteTag currentScript() const override { return fScript; }
160 private:
161 SkFourByteTag fScript;
162 };
163
164 static std::unique_ptr<LanguageRunIterator>
165 MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes);
166 class TrivialLanguageRunIterator : public TrivialRunIterator<LanguageRunIterator> {
167 public:
168 TrivialLanguageRunIterator(const char* language, size_t utf8Bytes)
169 : TrivialRunIterator(utf8Bytes), fLanguage(language) {}
170 const char* currentLanguage() const override { return fLanguage.c_str(); }
171 private:
172 SkString fLanguage;
173 };
174
175 class RunHandler {
176 public:
177 virtual ~RunHandler() = default;
178
179 struct Range {
180 constexpr Range() : fBegin(0), fSize(0) {}
181 constexpr Range(size_t begin, size_t size) : fBegin(begin), fSize(size) {}
182 size_t fBegin;
183 size_t fSize;
184 constexpr size_t begin() const { return fBegin; }
185 constexpr size_t end() const { return begin() + size(); }
186 constexpr size_t size() const { return fSize; }
187 };
188
189 struct RunInfo {
190 const SkFont& fFont;
191 uint8_t fBidiLevel;
192 SkVector fAdvance;
193 size_t glyphCount;
194 Range utf8Range;
195 };
196
197 struct Buffer {
198 SkGlyphID* glyphs; // required
199 SkPoint* positions; // required, if (!offsets) put glyphs[i] at positions[i]
200 // if ( offsets) positions[i+1]-positions[i] are advances
201 SkPoint* offsets; // optional, if ( offsets) put glyphs[i] at positions[i]+offsets[i]
202 uint32_t* clusters; // optional, utf8+clusters[i] starts run which produced glyphs[i]
203 SkPoint point; // offset to add to all positions
204 };
205
206 /** Called when beginning a line. */
207 virtual void beginLine() = 0;
208
209 /** Called once for each run in a line. Can compute baselines and offsets. */
210 virtual void runInfo(const RunInfo&) = 0;
211
212 /** Called after all runInfo calls for a line. */
213 virtual void commitRunInfo() = 0;
214
215 /** Called for each run in a line after commitRunInfo. The buffer will be filled out. */
216 virtual Buffer runBuffer(const RunInfo&) = 0;
217
218 /** Called after each runBuffer is filled out. */
219 virtual void commitRunBuffer(const RunInfo&) = 0;
220
221 /** Called when ending a line. */
222 virtual void commitLine() = 0;
223 };
224
225 virtual void shape(const char* utf8, size_t utf8Bytes,
226 const SkFont& srcFont,
227 bool leftToRight,
228 SkScalar width,
229 RunHandler*) const = 0;
230
231 virtual void shape(const char* utf8, size_t utf8Bytes,
232 FontRunIterator&,
233 BiDiRunIterator&,
234 ScriptRunIterator&,
235 LanguageRunIterator&,
236 SkScalar width,
237 RunHandler*) const = 0;
238
239 virtual void shape(const char* utf8, size_t utf8Bytes,
240 FontRunIterator&,
241 BiDiRunIterator&,
242 ScriptRunIterator&,
243 LanguageRunIterator&,
244 const Feature* features, size_t featuresSize,
245 SkScalar width,
246 RunHandler*) const = 0;
247
248private:
249 SkShaper(const SkShaper&) = delete;
250 SkShaper& operator=(const SkShaper&) = delete;
251};
252
253/**
254 * Helper for shaping text directly into a SkTextBlob.
255 */
256class SKSHAPER_API SkTextBlobBuilderRunHandler final : public SkShaper::RunHandler {
257public:
258 SkTextBlobBuilderRunHandler(const char* utf8Text, SkPoint offset)
259 : fUtf8Text(utf8Text)
260 , fOffset(offset) {}
261 sk_sp<SkTextBlob> makeBlob();
262 SkPoint endPoint() { return fOffset; }
263
264 void beginLine() override;
265 void runInfo(const RunInfo&) override;
266 void commitRunInfo() override;
267 Buffer runBuffer(const RunInfo&) override;
268 void commitRunBuffer(const RunInfo&) override;
269 void commitLine() override;
270
271private:
272 SkTextBlobBuilder fBuilder;
273 char const * const fUtf8Text;
274 uint32_t* fClusters;
275 int fClusterOffset;
276 int fGlyphCount;
277 SkScalar fMaxRunAscent;
278 SkScalar fMaxRunDescent;
279 SkScalar fMaxRunLeading;
280 SkPoint fCurrentPosition;
281 SkPoint fOffset;
282};
283
284#endif // SkShaper_DEFINED
285