Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
47 return SkShapers::Primitive::PrimitiveText();
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,
188 const SkFont& font, sk_sp<SkFontMgr> fallback)
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,
195 sk_sp<SkFontMgr> fallback,
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
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
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
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()
const RunBuffer & allocRunTextPos(const SkFont &font, int count, int textByteCount, const SkRect *bounds=nullptr)
glong glong end
const char * name
Definition fuchsia.cc:50
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)
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
Definition SkUTF.cpp:118
Definition ref_ptr.h:256
SkScalar fLeading
distance to add between lines, typically positive or zero
SkScalar fAscent
distance to reserve above baseline, typically negative
SkScalar fDescent
distance to reserve below baseline, typically positive
float fY
y-axis value