1 /*
2 * Copyright 2014 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 #include "include/core/SkPaint.h"
9 #include "include/core/SkPath.h"
10 #include "include/core/SkTypeface.h"
11 #include "include/private/SkTemplates.h"
12 #include "include/private/SkTo.h"
13 #include "src/core/SkDraw.h"
14 #include "src/core/SkFontPriv.h"
15 #include "src/core/SkPaintDefaults.h"
16 #include "src/core/SkScalerCache.h"
17 #include "src/core/SkScalerContext.h"
18 #include "src/core/SkStrikeCache.h"
19 #include "src/core/SkStrikeSpec.h"
20 #include "src/core/SkTLazy.h"
21 #include "src/core/SkUtils.h"
22 #include "src/utils/SkUTF.h"
23
24 #define kDefault_Size SkPaintDefaults_TextSize
25 #define kDefault_Flags SkFont::kBaselineSnap_PrivFlag
26 #define kDefault_Edging SkFont::Edging::kAntiAlias
27 #define kDefault_Hinting SkPaintDefaults_Hinting
28
valid_size(SkScalar size)29 static inline SkScalar valid_size(SkScalar size) {
30 return std::max<SkScalar>(0, size);
31 }
32
SkFont(sk_sp<SkTypeface> face,SkScalar size,SkScalar scaleX,SkScalar skewX)33 SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX)
34 : fTypeface(std::move(face))
35 , fSize(valid_size(size))
36 , fScaleX(scaleX)
37 , fSkewX(skewX)
38 , fFlags(kDefault_Flags)
39 , fEdging(static_cast<unsigned>(kDefault_Edging))
40 , fHinting(static_cast<unsigned>(kDefault_Hinting))
41 {}
42
SkFont(sk_sp<SkTypeface> face,SkScalar size)43 SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size) : SkFont(std::move(face), size, 1, 0) {}
44
SkFont(sk_sp<SkTypeface> face)45 SkFont::SkFont(sk_sp<SkTypeface> face) : SkFont(std::move(face), kDefault_Size, 1, 0) {}
46
SkFont()47 SkFont::SkFont() : SkFont(nullptr, kDefault_Size) {}
48
operator ==(const SkFont & b) const49 bool SkFont::operator==(const SkFont& b) const {
50 return fTypeface.get() == b.fTypeface.get() &&
51 fSize == b.fSize &&
52 fScaleX == b.fScaleX &&
53 fSkewX == b.fSkewX &&
54 fFlags == b.fFlags &&
55 fEdging == b.fEdging &&
56 fHinting == b.fHinting;
57 }
58
dump() const59 void SkFont::dump() const {
60 SkDebugf("typeface %p\n", fTypeface.get());
61 SkDebugf("size %g\n", fSize);
62 SkDebugf("skewx %g\n", fSkewX);
63 SkDebugf("scalex %g\n", fScaleX);
64 SkDebugf("flags 0x%X\n", fFlags);
65 SkDebugf("edging %d\n", (unsigned)fEdging);
66 SkDebugf("hinting %d\n", (unsigned)fHinting);
67 }
68
69 ///////////////////////////////////////////////////////////////////////////////////////////////////
70
set_clear_mask(uint32_t bits,bool cond,uint32_t mask)71 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
72 return cond ? bits | mask : bits & ~mask;
73 }
74
setForceAutoHinting(bool predicate)75 void SkFont::setForceAutoHinting(bool predicate) {
76 fFlags = set_clear_mask(fFlags, predicate, kForceAutoHinting_PrivFlag);
77 }
setEmbeddedBitmaps(bool predicate)78 void SkFont::setEmbeddedBitmaps(bool predicate) {
79 fFlags = set_clear_mask(fFlags, predicate, kEmbeddedBitmaps_PrivFlag);
80 }
setSubpixel(bool predicate)81 void SkFont::setSubpixel(bool predicate) {
82 fFlags = set_clear_mask(fFlags, predicate, kSubpixel_PrivFlag);
83 }
setLinearMetrics(bool predicate)84 void SkFont::setLinearMetrics(bool predicate) {
85 fFlags = set_clear_mask(fFlags, predicate, kLinearMetrics_PrivFlag);
86 }
setEmbolden(bool predicate)87 void SkFont::setEmbolden(bool predicate) {
88 fFlags = set_clear_mask(fFlags, predicate, kEmbolden_PrivFlag);
89 }
setBaselineSnap(bool predicate)90 void SkFont::setBaselineSnap(bool predicate) {
91 fFlags = set_clear_mask(fFlags, predicate, kBaselineSnap_PrivFlag);
92 }
setEdging(Edging e)93 void SkFont::setEdging(Edging e) {
94 fEdging = SkToU8(e);
95 }
96
setHinting(SkFontHinting h)97 void SkFont::setHinting(SkFontHinting h) {
98 fHinting = SkToU8(h);
99 }
100
setSize(SkScalar size)101 void SkFont::setSize(SkScalar size) {
102 fSize = valid_size(size);
103 }
setScaleX(SkScalar scale)104 void SkFont::setScaleX(SkScalar scale) {
105 fScaleX = scale;
106 }
setSkewX(SkScalar skew)107 void SkFont::setSkewX(SkScalar skew) {
108 fSkewX = skew;
109 }
110
makeWithSize(SkScalar newSize) const111 SkFont SkFont::makeWithSize(SkScalar newSize) const {
112 SkFont font = *this;
113 font.setSize(newSize);
114 return font;
115 }
116
117 ///////////////////////////////////////////////////////////////////////////////////////////////////
118
setupForAsPaths(SkPaint * paint)119 SkScalar SkFont::setupForAsPaths(SkPaint* paint) {
120 constexpr uint32_t flagsToIgnore = kEmbeddedBitmaps_PrivFlag |
121 kForceAutoHinting_PrivFlag;
122
123 fFlags = (fFlags & ~flagsToIgnore) | kSubpixel_PrivFlag;
124 this->setHinting(SkFontHinting::kNone);
125
126 if (this->getEdging() == Edging::kSubpixelAntiAlias) {
127 this->setEdging(Edging::kAntiAlias);
128 }
129
130 if (paint) {
131 paint->setStyle(SkPaint::kFill_Style);
132 paint->setPathEffect(nullptr);
133 }
134 SkScalar textSize = fSize;
135 this->setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths));
136 return textSize / SkFontPriv::kCanonicalTextSizeForPaths;
137 }
138
hasSomeAntiAliasing() const139 bool SkFont::hasSomeAntiAliasing() const {
140 Edging edging = this->getEdging();
141 return edging == SkFont::Edging::kAntiAlias
142 || edging == SkFont::Edging::kSubpixelAntiAlias;
143 }
144
unicharToGlyph(SkUnichar uni) const145 SkGlyphID SkFont::unicharToGlyph(SkUnichar uni) const {
146 return this->getTypefaceOrDefault()->unicharToGlyph(uni);
147 }
148
unicharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const149 void SkFont::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
150 this->getTypefaceOrDefault()->unicharsToGlyphs(uni, count, glyphs);
151 }
152
textToGlyphs(const void * text,size_t byteLength,SkTextEncoding encoding,SkGlyphID glyphs[],int maxGlyphCount) const153 int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
154 SkGlyphID glyphs[], int maxGlyphCount) const {
155 return this->getTypefaceOrDefault()->textToGlyphs(text, byteLength, encoding,
156 glyphs, maxGlyphCount);
157 }
158
measureText(const void * text,size_t length,SkTextEncoding encoding,SkRect * bounds,const SkPaint * paint) const159 SkScalar SkFont::measureText(const void* text, size_t length, SkTextEncoding encoding,
160 SkRect* bounds, const SkPaint* paint) const {
161
162 SkAutoToGlyphs atg(*this, text, length, encoding);
163 const int glyphCount = atg.count();
164 if (glyphCount == 0) {
165 if (bounds) {
166 bounds->setEmpty();
167 }
168 return 0;
169 }
170 const SkGlyphID* glyphIDs = atg.glyphs();
171
172 auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeCanonicalized(*this, paint);
173 SkBulkGlyphMetrics metrics{strikeSpec};
174 SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, glyphCount));
175
176 SkScalar width = 0;
177 if (bounds) {
178 *bounds = glyphs[0]->rect();
179 width = glyphs[0]->advanceX();
180 for (int i = 1; i < glyphCount; ++i) {
181 SkRect r = glyphs[i]->rect();
182 r.offset(width, 0);
183 bounds->join(r);
184 width += glyphs[i]->advanceX();
185 }
186 } else {
187 for (auto glyph : glyphs) {
188 width += glyph->advanceX();
189 }
190 }
191
192 if (strikeToSourceScale != 1) {
193 width *= strikeToSourceScale;
194 if (bounds) {
195 bounds->fLeft *= strikeToSourceScale;
196 bounds->fTop *= strikeToSourceScale;
197 bounds->fRight *= strikeToSourceScale;
198 bounds->fBottom *= strikeToSourceScale;
199 }
200 }
201
202 return width;
203 }
204
getWidthsBounds(const SkGlyphID glyphIDs[],int count,SkScalar widths[],SkRect bounds[],const SkPaint * paint) const205 void SkFont::getWidthsBounds(const SkGlyphID glyphIDs[],
206 int count,
207 SkScalar widths[],
208 SkRect bounds[],
209 const SkPaint* paint) const {
210 auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeCanonicalized(*this, paint);
211 SkBulkGlyphMetrics metrics{strikeSpec};
212 SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
213
214 if (bounds) {
215 SkMatrix scaleMat = SkMatrix::Scale(strikeToSourceScale, strikeToSourceScale);
216 SkRect* cursor = bounds;
217 for (auto glyph : glyphs) {
218 scaleMat.mapRectScaleTranslate(cursor++, glyph->rect());
219 }
220 }
221
222 if (widths) {
223 SkScalar* cursor = widths;
224 for (auto glyph : glyphs) {
225 *cursor++ = glyph->advanceX() * strikeToSourceScale;
226 }
227 }
228 }
229
getPos(const SkGlyphID glyphIDs[],int count,SkPoint pos[],SkPoint origin) const230 void SkFont::getPos(const SkGlyphID glyphIDs[], int count, SkPoint pos[], SkPoint origin) const {
231 auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeCanonicalized(*this);
232 SkBulkGlyphMetrics metrics{strikeSpec};
233 SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
234
235 SkPoint sum = origin;
236 for (auto glyph : glyphs) {
237 *pos++ = sum;
238 sum += glyph->advanceVector() * strikeToSourceScale;
239 }
240 }
241
getXPos(const SkGlyphID glyphIDs[],int count,SkScalar xpos[],SkScalar origin) const242 void SkFont::getXPos(
243 const SkGlyphID glyphIDs[], int count, SkScalar xpos[], SkScalar origin) const {
244
245 auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeCanonicalized(*this);
246 SkBulkGlyphMetrics metrics{strikeSpec};
247 SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
248
249 SkScalar loc = origin;
250 SkScalar* cursor = xpos;
251 for (auto glyph : glyphs) {
252 *cursor++ = loc;
253 loc += glyph->advanceX() * strikeToSourceScale;
254 }
255 }
256
getPaths(const SkGlyphID glyphIDs[],int count,void (* proc)(const SkPath *,const SkMatrix &,void *),void * ctx) const257 void SkFont::getPaths(const SkGlyphID glyphIDs[], int count,
258 void (*proc)(const SkPath*, const SkMatrix&, void*), void* ctx) const {
259 SkFont font(*this);
260 SkScalar scale = font.setupForAsPaths(nullptr);
261 const SkMatrix mx = SkMatrix::Scale(scale, scale);
262
263 SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(font);
264 SkBulkGlyphMetricsAndPaths paths{strikeSpec};
265 SkSpan<const SkGlyph*> glyphs = paths.glyphs(SkMakeSpan(glyphIDs, count));
266
267 for (auto glyph : glyphs) {
268 proc(glyph->path(), mx, ctx);
269 }
270 }
271
getPath(SkGlyphID glyphID,SkPath * path) const272 bool SkFont::getPath(SkGlyphID glyphID, SkPath* path) const {
273 struct Pair {
274 SkPath* fPath;
275 bool fWasSet;
276 } pair = { path, false };
277
278 this->getPaths(&glyphID, 1, [](const SkPath* orig, const SkMatrix& mx, void* ctx) {
279 Pair* pair = static_cast<Pair*>(ctx);
280 if (orig) {
281 orig->transform(mx, pair->fPath);
282 pair->fWasSet = true;
283 }
284 }, &pair);
285 return pair.fWasSet;
286 }
287
getMetrics(SkFontMetrics * metrics) const288 SkScalar SkFont::getMetrics(SkFontMetrics* metrics) const {
289
290 auto [strikeSpec, strikeToSourceScale] = SkStrikeSpec::MakeCanonicalized(*this, nullptr);
291
292 SkFontMetrics storage;
293 if (nullptr == metrics) {
294 metrics = &storage;
295 }
296
297 auto cache = strikeSpec.findOrCreateStrike();
298 *metrics = cache->getFontMetrics();
299
300 if (strikeToSourceScale != 1) {
301 SkFontPriv::ScaleFontMetrics(metrics, strikeToSourceScale);
302 }
303 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
304 }
305
getTypefaceOrDefault() const306 SkTypeface* SkFont::getTypefaceOrDefault() const {
307 return fTypeface ? fTypeface.get() : SkTypeface::GetDefaultTypeface();
308 }
309
refTypefaceOrDefault() const310 sk_sp<SkTypeface> SkFont::refTypefaceOrDefault() const {
311 return fTypeface ? fTypeface : SkTypeface::MakeDefault();
312 }
313
314 //////////////////////////////////////////////////////////////////////////////////////////////////
315
ScaleFontMetrics(SkFontMetrics * metrics,SkScalar scale)316 void SkFontPriv::ScaleFontMetrics(SkFontMetrics* metrics, SkScalar scale) {
317 metrics->fTop *= scale;
318 metrics->fAscent *= scale;
319 metrics->fDescent *= scale;
320 metrics->fBottom *= scale;
321 metrics->fLeading *= scale;
322 metrics->fAvgCharWidth *= scale;
323 metrics->fMaxCharWidth *= scale;
324 metrics->fXMin *= scale;
325 metrics->fXMax *= scale;
326 metrics->fXHeight *= scale;
327 metrics->fCapHeight *= scale;
328 metrics->fUnderlineThickness *= scale;
329 metrics->fUnderlinePosition *= scale;
330 metrics->fStrikeoutThickness *= scale;
331 metrics->fStrikeoutPosition *= scale;
332 }
333
GetFontBounds(const SkFont & font)334 SkRect SkFontPriv::GetFontBounds(const SkFont& font) {
335 SkMatrix m;
336 m.setScale(font.getSize() * font.getScaleX(), font.getSize());
337 m.postSkew(font.getSkewX(), 0);
338
339 SkTypeface* typeface = font.getTypefaceOrDefault();
340
341 SkRect bounds;
342 m.mapRect(&bounds, typeface->getBounds());
343 return bounds;
344 }
345
CountTextElements(const void * text,size_t byteLength,SkTextEncoding encoding)346 int SkFontPriv::CountTextElements(const void* text, size_t byteLength, SkTextEncoding encoding) {
347 switch (encoding) {
348 case SkTextEncoding::kUTF8:
349 return SkUTF::CountUTF8(reinterpret_cast<const char*>(text), byteLength);
350 case SkTextEncoding::kUTF16:
351 return SkUTF::CountUTF16(reinterpret_cast<const uint16_t*>(text), byteLength);
352 case SkTextEncoding::kUTF32:
353 return byteLength >> 2;
354 case SkTextEncoding::kGlyphID:
355 return byteLength >> 1;
356 }
357 SkASSERT(false);
358 return 0;
359 }
360
GlyphsToUnichars(const SkFont & font,const SkGlyphID glyphs[],int count,SkUnichar text[])361 void SkFontPriv::GlyphsToUnichars(const SkFont& font, const SkGlyphID glyphs[], int count,
362 SkUnichar text[]) {
363 if (count <= 0) {
364 return;
365 }
366
367 auto typeface = font.getTypefaceOrDefault();
368 const unsigned numGlyphsInTypeface = typeface->countGlyphs();
369 SkAutoTArray<SkUnichar> unichars(numGlyphsInTypeface);
370 typeface->getGlyphToUnicodeMap(unichars.get());
371
372 for (int i = 0; i < count; ++i) {
373 unsigned id = glyphs[i];
374 text[i] = (id < numGlyphsInTypeface) ? unichars[id] : 0xFFFD;
375 }
376 }
377