Flutter Engine
The Flutter Engine
SkShaper.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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
15#include "src/base/SkUTF.h"
16#include <limits.h>
17#include <algorithm>
18#include <cstring>
19#include <locale>
20#include <string>
21#include <utility>
22
23#if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
24
25#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE)
27#endif
28
29#if defined(SK_SHAPER_CORETEXT_AVAILABLE)
31#endif
32
33#endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
34
35#if !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
36std::unique_ptr<SkShaper> SkShaper::Make(sk_sp<SkFontMgr> fallback) {
37#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
38 std::unique_ptr<SkShaper> shaper = MakeShapeThenWrap(std::move(fallback));
39 if (shaper) {
40 return shaper;
41 }
42#elif defined(SK_SHAPER_CORETEXT_AVAILABLE)
43 if (auto shaper = SkShapers::CT::CoreText()) {
44 return shaper;
45 }
46#endif
48}
49
51#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
53#endif
54}
55
56std::unique_ptr<SkShaper::BiDiRunIterator>
57SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
58#if defined(SK_SHAPER_UNICODE_AVAILABLE)
59 std::unique_ptr<SkShaper::BiDiRunIterator> bidi = MakeIcuBiDiRunIterator(utf8, utf8Bytes, bidiLevel);
60 if (bidi) {
61 return bidi;
62 }
63#endif
64 return std::make_unique<SkShaper::TrivialBiDiRunIterator>(bidiLevel, utf8Bytes);
65}
66
67std::unique_ptr<SkShaper::ScriptRunIterator>
68SkShaper::MakeScriptRunIterator(const char* utf8, size_t utf8Bytes, SkFourByteTag scriptTag) {
69#if defined(SK_SHAPER_HARFBUZZ_AVAILABLE) && defined(SK_SHAPER_UNICODE_AVAILABLE)
70 std::unique_ptr<SkShaper::ScriptRunIterator> script =
71 SkShapers::HB::ScriptRunIterator(utf8, utf8Bytes, scriptTag);
72 if (script) {
73 return script;
74 }
75#endif
76 return std::make_unique<SkShaper::TrivialScriptRunIterator>(scriptTag, utf8Bytes);
77}
78#endif // !defined(SK_DISABLE_LEGACY_SKSHAPER_FUNCTIONS)
79
82
83/** Replaces invalid utf-8 sequences with REPLACEMENT CHARACTER U+FFFD. */
84static inline SkUnichar utf8_next(const char** ptr, const char* end) {
85 SkUnichar val = SkUTF::NextUTF8(ptr, end);
86 return val < 0 ? 0xFFFD : val;
87}
88
90public:
91 FontMgrRunIterator(const char* utf8, size_t utf8Bytes,
92 const SkFont& font, sk_sp<SkFontMgr> fallbackMgr,
93 const char* requestName, SkFontStyle requestStyle,
95 : fCurrent(utf8), fBegin(utf8), fEnd(fCurrent + utf8Bytes)
96 , fFallbackMgr(std::move(fallbackMgr))
97 , fFont(font)
98 , fFallbackFont(fFont)
99 , fCurrentFont(nullptr)
100 , fRequestName(requestName)
101 , fRequestStyle(requestStyle)
102 , fLanguage(lang)
103 {
104 // If fallback is not wanted, clients should use TrivialFontRunIterator.
105 SkASSERT(fFallbackMgr);
106 fFont.setTypeface(font.refTypeface());
107 fFallbackFont.setTypeface(nullptr);
108 }
109 FontMgrRunIterator(const char* utf8, size_t utf8Bytes,
110 const SkFont& font, sk_sp<SkFontMgr> fallbackMgr)
111 : FontMgrRunIterator(utf8, utf8Bytes, font, std::move(fallbackMgr),
112 nullptr, font.getTypeface()->fontStyle(), nullptr)
113 {}
114
115 void consume() override {
116 SkASSERT(fCurrent < fEnd);
117 SkASSERT(!fLanguage || this->endOfCurrentRun() <= fLanguage->endOfCurrentRun());
118 SkUnichar u = utf8_next(&fCurrent, fEnd);
119 // If the starting typeface can handle this character, use it.
120 if (fFont.unicharToGlyph(u)) {
121 fCurrentFont = &fFont;
122 // If the current fallback can handle this character, use it.
123 } else if (fFallbackFont.getTypeface() && fFallbackFont.unicharToGlyph(u)) {
124 fCurrentFont = &fFallbackFont;
125 // If not, try to find a fallback typeface
126 } else {
127 const char* language = fLanguage ? fLanguage->currentLanguage() : nullptr;
128 int languageCount = fLanguage ? 1 : 0;
129 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
130 fRequestName, fRequestStyle, &language, languageCount, u));
131 if (candidate) {
132 fFallbackFont.setTypeface(std::move(candidate));
133 fCurrentFont = &fFallbackFont;
134 } else {
135 fCurrentFont = &fFont;
136 }
137 }
138
139 while (fCurrent < fEnd) {
140 const char* prev = fCurrent;
141 u = utf8_next(&fCurrent, fEnd);
142
143 // End run if not using initial typeface and initial typeface has this character.
144 if (fCurrentFont->getTypeface() != fFont.getTypeface() && fFont.unicharToGlyph(u)) {
145 fCurrent = prev;
146 return;
147 }
148
149 // End run if current typeface does not have this character and some other font does.
150 if (!fCurrentFont->unicharToGlyph(u)) {
151 const char* language = fLanguage ? fLanguage->currentLanguage() : nullptr;
152 int languageCount = fLanguage ? 1 : 0;
153 sk_sp<SkTypeface> candidate(fFallbackMgr->matchFamilyStyleCharacter(
154 fRequestName, fRequestStyle, &language, languageCount, u));
155 if (candidate) {
156 fCurrent = prev;
157 return;
158 }
159 }
160 }
161 }
162 size_t endOfCurrentRun() const override {
163 return fCurrent - fBegin;
164 }
165 bool atEnd() const override {
166 return fCurrent == fEnd;
167 }
168
169 const SkFont& currentFont() const override {
170 return *fCurrentFont;
171 }
172
173private:
174 char const * fCurrent;
175 char const * const fBegin;
176 char const * const fEnd;
177 sk_sp<SkFontMgr> const fFallbackMgr;
178 SkFont fFont;
179 SkFont fFallbackFont;
180 SkFont* fCurrentFont;
181 char const * const fRequestName;
182 SkFontStyle const fRequestStyle;
183 SkShaper::LanguageRunIterator const * const fLanguage;
184};
185
186std::unique_ptr<SkShaper::FontRunIterator>
187SkShaper::MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes,
189{
190 return std::make_unique<FontMgrRunIterator>(utf8, utf8Bytes, font, std::move(fallback));
191}
192
193std::unique_ptr<SkShaper::FontRunIterator>
194SkShaper::MakeFontMgrRunIterator(const char* utf8, size_t utf8Bytes, const SkFont& font,
196 const char* requestName, SkFontStyle requestStyle,
197 const SkShaper::LanguageRunIterator* language)
198{
199 return std::make_unique<FontMgrRunIterator>(utf8, utf8Bytes, font, std::move(fallback),
200 requestName, requestStyle, language);
201}
202
203std::unique_ptr<SkShaper::LanguageRunIterator>
204SkShaper::MakeStdLanguageRunIterator(const char* utf8, size_t utf8Bytes) {
205 return std::make_unique<TrivialLanguageRunIterator>(std::locale().name().c_str(), utf8Bytes);
206}
207
209 fCurrentPosition = fOffset;
210 fMaxRunAscent = 0;
211 fMaxRunDescent = 0;
212 fMaxRunLeading = 0;
213}
215 SkFontMetrics metrics;
216 info.fFont.getMetrics(&metrics);
217 fMaxRunAscent = std::min(fMaxRunAscent, metrics.fAscent);
218 fMaxRunDescent = std::max(fMaxRunDescent, metrics.fDescent);
219 fMaxRunLeading = std::max(fMaxRunLeading, metrics.fLeading);
220}
221
223 fCurrentPosition.fY -= fMaxRunAscent;
224}
225
227 int glyphCount = SkTFitsIn<int>(info.glyphCount) ? info.glyphCount : INT_MAX;
228 int utf8RangeSize = SkTFitsIn<int>(info.utf8Range.size()) ? info.utf8Range.size() : INT_MAX;
229
230 const auto& runBuffer = fBuilder.allocRunTextPos(info.fFont, glyphCount, utf8RangeSize);
231 if (runBuffer.utf8text && fUtf8Text) {
232 memcpy(runBuffer.utf8text, fUtf8Text + info.utf8Range.begin(), utf8RangeSize);
233 }
234 fClusters = runBuffer.clusters;
235 fGlyphCount = glyphCount;
236 fClusterOffset = info.utf8Range.begin();
237
238 return { runBuffer.glyphs,
239 runBuffer.points(),
240 nullptr,
242 fCurrentPosition };
243}
244
246 SkASSERT(0 <= fClusterOffset);
247 for (int i = 0; i < fGlyphCount; ++i) {
248 SkASSERT(fClusters[i] >= (unsigned)fClusterOffset);
249 fClusters[i] -= fClusterOffset;
250 }
251 fCurrentPosition += info.fAdvance;
252}
254 fOffset += { 0, fMaxRunDescent + fMaxRunLeading - fMaxRunAscent };
255}
256
258 return fBuilder.make();
259}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static float prev(float f)
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkUnichar utf8_next(const char **ptr, const char *end)
Definition: SkShaper.cpp:84
int32_t SkUnichar
Definition: SkTypes.h:175
uint32_t SkFourByteTag
Definition: SkTypes.h:166
size_t endOfCurrentRun() const override
Definition: SkShaper.cpp:162
FontMgrRunIterator(const char *utf8, size_t utf8Bytes, const SkFont &font, sk_sp< SkFontMgr > fallbackMgr)
Definition: SkShaper.cpp:109
void consume() override
Definition: SkShaper.cpp:115
const SkFont & currentFont() const override
Definition: SkShaper.cpp:169
FontMgrRunIterator(const char *utf8, size_t utf8Bytes, const SkFont &font, sk_sp< SkFontMgr > fallbackMgr, const char *requestName, SkFontStyle requestStyle, const SkShaper::LanguageRunIterator *lang)
Definition: SkShaper.cpp:91
bool atEnd() const override
Definition: SkShaper.cpp:165
sk_sp< SkTypeface > matchFamilyStyleCharacter(const char familyName[], const SkFontStyle &, const char *bcp47[], int bcp47Count, SkUnichar character) const
Definition: SkFontMgr.cpp:114
Definition: SkFont.h:35
SkTypeface * getTypeface() const
Definition: SkFont.h:208
void setTypeface(sk_sp< SkTypeface > tf)
Definition: SkFont.cpp:90
SkGlyphID unicharToGlyph(SkUnichar uni) const
Definition: SkFont.cpp:173
virtual const char * currentLanguage() const =0
virtual size_t endOfCurrentRun() const =0
static std::unique_ptr< SkShaper > Make(sk_sp< SkFontMgr > fallback=nullptr)
Definition: SkShaper.cpp:36
static std::unique_ptr< ScriptRunIterator > MakeScriptRunIterator(const char *utf8, size_t utf8Bytes, SkFourByteTag script)
Definition: SkShaper.cpp:68
static std::unique_ptr< FontRunIterator > MakeFontMgrRunIterator(const char *utf8, size_t utf8Bytes, const SkFont &font, sk_sp< SkFontMgr > fallback)
Definition: SkShaper.cpp:187
SkShaper()
Definition: SkShaper.cpp:80
static std::unique_ptr< LanguageRunIterator > MakeStdLanguageRunIterator(const char *utf8, size_t utf8Bytes)
Definition: SkShaper.cpp:204
static void PurgeCaches()
Definition: SkShaper.cpp:50
virtual ~SkShaper()
Definition: SkShaper.cpp:81
static std::unique_ptr< BiDiRunIterator > MakeBiDiRunIterator(const char *utf8, size_t utf8Bytes, uint8_t bidiLevel)
Definition: SkShaper.cpp:57
void commitLine() override
Definition: SkShaper.cpp:253
void beginLine() override
Definition: SkShaper.cpp:208
void commitRunInfo() override
Definition: SkShaper.cpp:222
void runInfo(const RunInfo &) override
Definition: SkShaper.cpp:214
Buffer runBuffer(const RunInfo &) override
Definition: SkShaper.cpp:226
void commitRunBuffer(const RunInfo &) override
Definition: SkShaper.cpp:245
sk_sp< SkTextBlob > makeBlob()
Definition: SkShaper.cpp:257
sk_sp< SkTextBlob > make()
Definition: SkTextBlob.cpp:617
const RunBuffer & allocRunTextPos(const SkFont &font, int count, int textByteCount, const SkRect *bounds=nullptr)
Definition: SkTextBlob.cpp:592
glong glong end
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SKSHAPER_API std::unique_ptr< SkShaper > CoreText()
SKSHAPER_API void PurgeCaches()
SKSHAPER_API std::unique_ptr< SkShaper::ScriptRunIterator > ScriptRunIterator(const char *utf8, size_t utf8Bytes)
SKSHAPER_API std::unique_ptr< SkShaper > PrimitiveText()
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
Definition: SkUTF.cpp:118
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port fallback
Definition: switches.h:154
font
Font Metadata and Metrics.
Definition: ref_ptr.h:256
SkScalar fLeading
distance to add between lines, typically positive or zero
Definition: SkFontMetrics.h:57
SkScalar fAscent
distance to reserve above baseline, typically negative
Definition: SkFontMetrics.h:54
SkScalar fDescent
distance to reserve below baseline, typically positive
Definition: SkFontMetrics.h:55
float fY
y-axis value
Definition: SkPoint_impl.h:165