• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
153 class SkConvertToUTF32 {
154 public:
SkConvertToUTF32()155     SkConvertToUTF32() {}
156 
convert(const void * text,size_t byteLength,SkTextEncoding encoding)157     const SkUnichar* convert(const void* text, size_t byteLength, SkTextEncoding encoding) {
158         const SkUnichar* uni;
159         switch (encoding) {
160             case SkTextEncoding::kUTF8: {
161                 uni = fStorage.reset(byteLength);
162                 const char* ptr = (const char*)text;
163                 const char* end = ptr + byteLength;
164                 for (int i = 0; ptr < end; ++i) {
165                     fStorage[i] = SkUTF::NextUTF8(&ptr, end);
166                 }
167             } break;
168             case SkTextEncoding::kUTF16: {
169                 uni = fStorage.reset(byteLength);
170                 const uint16_t* ptr = (const uint16_t*)text;
171                 const uint16_t* end = ptr + (byteLength >> 1);
172                 for (int i = 0; ptr < end; ++i) {
173                     fStorage[i] = SkUTF::NextUTF16(&ptr, end);
174                 }
175             } break;
176             case SkTextEncoding::kUTF32:
177                 uni = (const SkUnichar*)text;
178                 break;
179             default:
180                 SK_ABORT("unexpected enum");
181         }
182         return uni;
183     }
184 
185 private:
186     SkAutoSTMalloc<256, SkUnichar> fStorage;
187 };
188 
textToGlyphs(const void * text,size_t byteLength,SkTextEncoding encoding,SkGlyphID glyphs[],int maxGlyphCount) const189 int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
190                          SkGlyphID glyphs[], int maxGlyphCount) const {
191     if (0 == byteLength) {
192         return 0;
193     }
194 
195     SkASSERT(text);
196 
197     int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
198     if (!glyphs || count > maxGlyphCount) {
199         return count;
200     }
201 
202     if (encoding == SkTextEncoding::kGlyphID) {
203         memcpy(glyphs, text, count << 1);
204         return count;
205     }
206 
207     SkConvertToUTF32 storage;
208     const SkUnichar* uni = storage.convert(text, byteLength, encoding);
209 
210     this->getTypefaceOrDefault()->unicharsToGlyphs(uni, count, glyphs);
211     return count;
212 }
213 
measureText(const void * text,size_t length,SkTextEncoding encoding,SkRect * bounds,const SkPaint * paint) const214 SkScalar SkFont::measureText(const void* text, size_t length, SkTextEncoding encoding,
215                              SkRect* bounds, const SkPaint* paint) const {
216 
217     SkAutoToGlyphs atg(*this, text, length, encoding);
218     const int glyphCount = atg.count();
219     if (glyphCount == 0) {
220         if (bounds) {
221             bounds->setEmpty();
222         }
223         return 0;
224     }
225     const SkGlyphID* glyphIDs = atg.glyphs();
226 
227     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this, paint);
228     SkBulkGlyphMetrics metrics{strikeSpec};
229     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, glyphCount));
230 
231     SkScalar width = 0;
232     if (bounds) {
233         *bounds = glyphs[0]->rect();
234         width = glyphs[0]->advanceX();
235         for (int i = 1; i < glyphCount; ++i) {
236             SkRect r = glyphs[i]->rect();
237             r.offset(width, 0);
238             bounds->join(r);
239             width += glyphs[i]->advanceX();
240         }
241     } else {
242         for (auto glyph : glyphs) {
243             width += glyph->advanceX();
244         }
245     }
246 
247     const SkScalar scale = strikeSpec.strikeToSourceRatio();
248     if (scale != 1) {
249         width *= scale;
250         if (bounds) {
251             bounds->fLeft *= scale;
252             bounds->fTop *= scale;
253             bounds->fRight *= scale;
254             bounds->fBottom *= scale;
255         }
256     }
257 
258     return width;
259 }
260 
getWidthsBounds(const SkGlyphID glyphIDs[],int count,SkScalar widths[],SkRect bounds[],const SkPaint * paint) const261 void SkFont::getWidthsBounds(const SkGlyphID glyphIDs[],
262                              int count,
263                              SkScalar widths[],
264                              SkRect bounds[],
265                              const SkPaint* paint) const {
266     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this, paint);
267     SkBulkGlyphMetrics metrics{strikeSpec};
268     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
269 
270     SkScalar scale = strikeSpec.strikeToSourceRatio();
271 
272     if (bounds) {
273         SkMatrix scaleMat = SkMatrix::MakeScale(scale);
274         SkRect* cursor = bounds;
275         for (auto glyph : glyphs) {
276             scaleMat.mapRectScaleTranslate(cursor++, glyph->rect());
277         }
278     }
279 
280     if (widths) {
281         SkScalar* cursor = widths;
282         for (auto glyph : glyphs) {
283             *cursor++ = glyph->advanceX() * scale;
284         }
285     }
286 }
287 
getPos(const SkGlyphID glyphIDs[],int count,SkPoint pos[],SkPoint origin) const288 void SkFont::getPos(const SkGlyphID glyphIDs[], int count, SkPoint pos[], SkPoint origin) const {
289     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this);
290     SkBulkGlyphMetrics metrics{strikeSpec};
291     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
292 
293     SkPoint sum = origin;
294     for (auto glyph : glyphs) {
295         *pos++ = sum;
296         sum += glyph->advanceVector() * strikeSpec.strikeToSourceRatio();
297     }
298 }
299 
getXPos(const SkGlyphID glyphIDs[],int count,SkScalar xpos[],SkScalar origin) const300 void SkFont::getXPos(
301         const SkGlyphID glyphIDs[], int count, SkScalar xpos[], SkScalar origin) const {
302 
303     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this);
304     SkBulkGlyphMetrics metrics{strikeSpec};
305     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
306 
307     SkScalar loc = origin;
308     SkScalar* cursor = xpos;
309     for (auto glyph : glyphs) {
310         *cursor++ = loc;
311         loc += glyph->advanceX() * strikeSpec.strikeToSourceRatio();
312     }
313 }
314 
getPaths(const SkGlyphID glyphIDs[],int count,void (* proc)(const SkPath *,const SkMatrix &,void *),void * ctx) const315 void SkFont::getPaths(const SkGlyphID glyphIDs[], int count,
316                       void (*proc)(const SkPath*, const SkMatrix&, void*), void* ctx) const {
317     SkFont font(*this);
318     SkScalar scale = font.setupForAsPaths(nullptr);
319     const SkMatrix mx = SkMatrix::MakeScale(scale);
320 
321     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(font);
322     SkBulkGlyphMetricsAndPaths paths{strikeSpec};
323     SkSpan<const SkGlyph*> glyphs = paths.glyphs(SkMakeSpan(glyphIDs, count));
324 
325     for (auto glyph : glyphs) {
326         proc(glyph->path(), mx, ctx);
327     }
328 }
329 
getPath(SkGlyphID glyphID,SkPath * path) const330 bool SkFont::getPath(SkGlyphID glyphID, SkPath* path) const {
331     struct Pair {
332         SkPath* fPath;
333         bool    fWasSet;
334     } pair = { path, false };
335 
336     this->getPaths(&glyphID, 1, [](const SkPath* orig, const SkMatrix& mx, void* ctx) {
337         Pair* pair = static_cast<Pair*>(ctx);
338         if (orig) {
339             orig->transform(mx, pair->fPath);
340             pair->fWasSet = true;
341         }
342     }, &pair);
343     return pair.fWasSet;
344 }
345 
getMetrics(SkFontMetrics * metrics) const346 SkScalar SkFont::getMetrics(SkFontMetrics* metrics) const {
347 
348     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this, nullptr);
349 
350     SkFontMetrics storage;
351     if (nullptr == metrics) {
352         metrics = &storage;
353     }
354 
355     auto cache = strikeSpec.findOrCreateExclusiveStrike();
356     *metrics = cache->getFontMetrics();
357 
358     if (strikeSpec.strikeToSourceRatio() != 1) {
359         SkFontPriv::ScaleFontMetrics(metrics, strikeSpec.strikeToSourceRatio());
360     }
361     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
362 }
363 
getTypefaceOrDefault() const364 SkTypeface* SkFont::getTypefaceOrDefault() const {
365     return fTypeface ? fTypeface.get() : SkTypeface::GetDefaultTypeface();
366 }
367 
refTypefaceOrDefault() const368 sk_sp<SkTypeface> SkFont::refTypefaceOrDefault() const {
369     return fTypeface ? fTypeface : SkTypeface::MakeDefault();
370 }
371 
372 //////////////////////////////////////////////////////////////////////////////////////////////////
373 
ScaleFontMetrics(SkFontMetrics * metrics,SkScalar scale)374 void SkFontPriv::ScaleFontMetrics(SkFontMetrics* metrics, SkScalar scale) {
375     metrics->fTop *= scale;
376     metrics->fAscent *= scale;
377     metrics->fDescent *= scale;
378     metrics->fBottom *= scale;
379     metrics->fLeading *= scale;
380     metrics->fAvgCharWidth *= scale;
381     metrics->fMaxCharWidth *= scale;
382     metrics->fXMin *= scale;
383     metrics->fXMax *= scale;
384     metrics->fXHeight *= scale;
385     metrics->fCapHeight *= scale;
386     metrics->fUnderlineThickness *= scale;
387     metrics->fUnderlinePosition *= scale;
388     metrics->fStrikeoutThickness *= scale;
389     metrics->fStrikeoutPosition *= scale;
390 }
391 
GetFontBounds(const SkFont & font)392 SkRect SkFontPriv::GetFontBounds(const SkFont& font) {
393     SkMatrix m;
394     m.setScale(font.getSize() * font.getScaleX(), font.getSize());
395     m.postSkew(font.getSkewX(), 0);
396 
397     SkTypeface* typeface = font.getTypefaceOrDefault();
398 
399     SkRect bounds;
400     m.mapRect(&bounds, typeface->getBounds());
401     return bounds;
402 }
403 
CountTextElements(const void * text,size_t byteLength,SkTextEncoding encoding)404 int SkFontPriv::CountTextElements(const void* text, size_t byteLength, SkTextEncoding encoding) {
405     switch (encoding) {
406         case SkTextEncoding::kUTF8:
407             return SkUTF::CountUTF8(reinterpret_cast<const char*>(text), byteLength);
408         case SkTextEncoding::kUTF16:
409             return SkUTF::CountUTF16(reinterpret_cast<const uint16_t*>(text), byteLength);
410         case SkTextEncoding::kUTF32:
411             return byteLength >> 2;
412         case SkTextEncoding::kGlyphID:
413             return byteLength >> 1;
414     }
415     SkASSERT(false);
416     return 0;
417 }
418 
GlyphsToUnichars(const SkFont & font,const SkGlyphID glyphs[],int count,SkUnichar text[])419 void SkFontPriv::GlyphsToUnichars(const SkFont& font, const SkGlyphID glyphs[], int count,
420                                   SkUnichar text[]) {
421     if (count <= 0) {
422         return;
423     }
424 
425     auto typeface = font.getTypefaceOrDefault();
426     const unsigned numGlyphsInTypeface = typeface->countGlyphs();
427     SkAutoTArray<SkUnichar> unichars(numGlyphsInTypeface);
428     typeface->getGlyphToUnicodeMap(unichars.get());
429 
430     for (int i = 0; i < count; ++i) {
431         unsigned id = glyphs[i];
432         text[i] = (id < numGlyphsInTypeface) ? unichars[id] : 0xFFFD;
433     }
434 }
435