• 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/SkScalerContext.h"
17 #include "src/core/SkStrike.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      0
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 SkTMax<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 }
90 
setEdging(Edging e)91 void SkFont::setEdging(Edging e) {
92     fEdging = SkToU8(e);
93 }
94 
setHinting(SkFontHinting h)95 void SkFont::setHinting(SkFontHinting h) {
96     fHinting = SkToU8(h);
97 }
98 
setSize(SkScalar size)99 void SkFont::setSize(SkScalar size) {
100     fSize = valid_size(size);
101 }
setScaleX(SkScalar scale)102 void SkFont::setScaleX(SkScalar scale) {
103     fScaleX = scale;
104 }
setSkewX(SkScalar skew)105 void SkFont::setSkewX(SkScalar skew) {
106     fSkewX = skew;
107 }
108 
makeWithSize(SkScalar newSize) const109 SkFont SkFont::makeWithSize(SkScalar newSize) const {
110     SkFont font = *this;
111     font.setSize(newSize);
112     return font;
113 }
114 
115 ///////////////////////////////////////////////////////////////////////////////////////////////////
116 
setupForAsPaths(SkPaint * paint)117 SkScalar SkFont::setupForAsPaths(SkPaint* paint) {
118     constexpr uint32_t flagsToIgnore = kEmbeddedBitmaps_PrivFlag |
119                                        kForceAutoHinting_PrivFlag;
120 
121     fFlags = (fFlags & ~flagsToIgnore) | kSubpixel_PrivFlag;
122     this->setHinting(SkFontHinting::kNone);
123 
124     if (this->getEdging() == Edging::kSubpixelAntiAlias) {
125         this->setEdging(Edging::kAntiAlias);
126     }
127 
128     if (paint) {
129         paint->setStyle(SkPaint::kFill_Style);
130         paint->setPathEffect(nullptr);
131     }
132     SkScalar textSize = fSize;
133     this->setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths));
134     return textSize / SkFontPriv::kCanonicalTextSizeForPaths;
135 }
136 
hasSomeAntiAliasing() const137 bool SkFont::hasSomeAntiAliasing() const {
138     Edging edging = this->getEdging();
139     return edging == SkFont::Edging::kAntiAlias
140         || edging == SkFont::Edging::kSubpixelAntiAlias;
141 }
142 
unicharToGlyph(SkUnichar uni) const143 SkGlyphID SkFont::unicharToGlyph(SkUnichar uni) const {
144     return this->getTypefaceOrDefault()->unicharToGlyph(uni);
145 }
146 
unicharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const147 void SkFont::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
148     this->getTypefaceOrDefault()->unicharsToGlyphs(uni, count, glyphs);
149 }
150 
151 class SkConvertToUTF32 {
152 public:
SkConvertToUTF32()153     SkConvertToUTF32() {}
154 
convert(const void * text,size_t byteLength,SkTextEncoding encoding)155     const SkUnichar* convert(const void* text, size_t byteLength, SkTextEncoding encoding) {
156         const SkUnichar* uni;
157         switch (encoding) {
158             case SkTextEncoding::kUTF8: {
159                 uni = fStorage.reset(byteLength);
160                 const char* ptr = (const char*)text;
161                 const char* end = ptr + byteLength;
162                 for (int i = 0; ptr < end; ++i) {
163                     fStorage[i] = SkUTF::NextUTF8(&ptr, end);
164                 }
165             } break;
166             case SkTextEncoding::kUTF16: {
167                 uni = fStorage.reset(byteLength);
168                 const uint16_t* ptr = (const uint16_t*)text;
169                 const uint16_t* end = ptr + (byteLength >> 1);
170                 for (int i = 0; ptr < end; ++i) {
171                     fStorage[i] = SkUTF::NextUTF16(&ptr, end);
172                 }
173             } break;
174             case SkTextEncoding::kUTF32:
175                 uni = (const SkUnichar*)text;
176                 break;
177             default:
178                 SK_ABORT("unexpected enum");
179         }
180         return uni;
181     }
182 
183 private:
184     SkAutoSTMalloc<256, SkUnichar> fStorage;
185 };
186 
textToGlyphs(const void * text,size_t byteLength,SkTextEncoding encoding,SkGlyphID glyphs[],int maxGlyphCount) const187 int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
188                          SkGlyphID glyphs[], int maxGlyphCount) const {
189     if (0 == byteLength) {
190         return 0;
191     }
192 
193     SkASSERT(text);
194 
195     int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
196     if (!glyphs || count > maxGlyphCount) {
197         return count;
198     }
199 
200     if (encoding == SkTextEncoding::kGlyphID) {
201         memcpy(glyphs, text, count << 1);
202         return count;
203     }
204 
205     SkConvertToUTF32 storage;
206     const SkUnichar* uni = storage.convert(text, byteLength, encoding);
207 
208     this->getTypefaceOrDefault()->unicharsToGlyphs(uni, count, glyphs);
209     return count;
210 }
211 
measureText(const void * text,size_t length,SkTextEncoding encoding,SkRect * bounds,const SkPaint * paint) const212 SkScalar SkFont::measureText(const void* text, size_t length, SkTextEncoding encoding,
213                              SkRect* bounds, const SkPaint* paint) const {
214 
215     SkAutoToGlyphs atg(*this, text, length, encoding);
216     const int glyphCount = atg.count();
217     if (glyphCount == 0) {
218         if (bounds) {
219             bounds->setEmpty();
220         }
221         return 0;
222     }
223     const SkGlyphID* glyphIDs = atg.glyphs();
224 
225     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this, paint);
226     SkBulkGlyphMetrics metrics{strikeSpec};
227     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, glyphCount));
228 
229     SkScalar width = 0;
230     if (bounds) {
231         *bounds = glyphs[0]->rect();
232         width = glyphs[0]->advanceX();
233         for (int i = 1; i < glyphCount; ++i) {
234             SkRect r = glyphs[i]->rect();
235             r.offset(width, 0);
236             bounds->join(r);
237             width += glyphs[i]->advanceX();
238         }
239     } else {
240         for (auto glyph : glyphs) {
241             width += glyph->advanceX();
242         }
243     }
244 
245     const SkScalar scale = strikeSpec.strikeToSourceRatio();
246     if (scale != 1) {
247         width *= scale;
248         if (bounds) {
249             bounds->fLeft *= scale;
250             bounds->fTop *= scale;
251             bounds->fRight *= scale;
252             bounds->fBottom *= scale;
253         }
254     }
255 
256     return width;
257 }
258 
getWidthsBounds(const SkGlyphID glyphIDs[],int count,SkScalar widths[],SkRect bounds[],const SkPaint * paint) const259 void SkFont::getWidthsBounds(const SkGlyphID glyphIDs[],
260                              int count,
261                              SkScalar widths[],
262                              SkRect bounds[],
263                              const SkPaint* paint) const {
264     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this, paint);
265     SkBulkGlyphMetrics metrics{strikeSpec};
266     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
267 
268     SkScalar scale = strikeSpec.strikeToSourceRatio();
269 
270     if (bounds) {
271         SkMatrix scaleMat = SkMatrix::MakeScale(scale);
272         SkRect* cursor = bounds;
273         for (auto glyph : glyphs) {
274             scaleMat.mapRectScaleTranslate(cursor++, glyph->rect());
275         }
276     }
277 
278     if (widths) {
279         SkScalar* cursor = widths;
280         for (auto glyph : glyphs) {
281             *cursor++ = glyph->advanceX() * scale;
282         }
283     }
284 }
285 
getPos(const SkGlyphID glyphIDs[],int count,SkPoint pos[],SkPoint origin) const286 void SkFont::getPos(const SkGlyphID glyphIDs[], int count, SkPoint pos[], SkPoint origin) const {
287     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this);
288     SkBulkGlyphMetrics metrics{strikeSpec};
289     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
290 
291     SkPoint sum = origin;
292     for (auto glyph : glyphs) {
293         *pos++ = sum;
294         sum += glyph->advanceVector() * strikeSpec.strikeToSourceRatio();
295     }
296 }
297 
getXPos(const SkGlyphID glyphIDs[],int count,SkScalar xpos[],SkScalar origin) const298 void SkFont::getXPos(
299         const SkGlyphID glyphIDs[], int count, SkScalar xpos[], SkScalar origin) const {
300 
301     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this);
302     SkBulkGlyphMetrics metrics{strikeSpec};
303     SkSpan<const SkGlyph*> glyphs = metrics.glyphs(SkMakeSpan(glyphIDs, count));
304 
305     SkScalar loc = origin;
306     SkScalar* cursor = xpos;
307     for (auto glyph : glyphs) {
308         *cursor++ = loc;
309         loc += glyph->advanceX() * strikeSpec.strikeToSourceRatio();
310     }
311 }
312 
getPaths(const SkGlyphID glyphIDs[],int count,void (* proc)(const SkPath *,const SkMatrix &,void *),void * ctx) const313 void SkFont::getPaths(const SkGlyphID glyphIDs[], int count,
314                       void (*proc)(const SkPath*, const SkMatrix&, void*), void* ctx) const {
315     SkFont font(*this);
316     SkScalar scale = font.setupForAsPaths(nullptr);
317     const SkMatrix mx = SkMatrix::MakeScale(scale);
318 
319     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(font);
320     SkBulkGlyphMetricsAndPaths paths{strikeSpec};
321     SkSpan<const SkGlyph*> glyphs = paths.glyphs(SkMakeSpan(glyphIDs, count));
322 
323     for (auto glyph : glyphs) {
324         proc(glyph->path(), mx, ctx);
325     }
326 }
327 
getPath(SkGlyphID glyphID,SkPath * path) const328 bool SkFont::getPath(SkGlyphID glyphID, SkPath* path) const {
329     struct Pair {
330         SkPath* fPath;
331         bool    fWasSet;
332     } pair = { path, false };
333 
334     this->getPaths(&glyphID, 1, [](const SkPath* orig, const SkMatrix& mx, void* ctx) {
335         Pair* pair = static_cast<Pair*>(ctx);
336         if (orig) {
337             orig->transform(mx, pair->fPath);
338             pair->fWasSet = true;
339         }
340     }, &pair);
341     return pair.fWasSet;
342 }
343 
getMetrics(SkFontMetrics * metrics) const344 SkScalar SkFont::getMetrics(SkFontMetrics* metrics) const {
345 
346     SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(*this, nullptr);
347 
348     SkFontMetrics storage;
349     if (nullptr == metrics) {
350         metrics = &storage;
351     }
352 
353     auto cache = strikeSpec.findOrCreateExclusiveStrike();
354     *metrics = cache->getFontMetrics();
355 
356     if (strikeSpec.strikeToSourceRatio() != 1) {
357         SkFontPriv::ScaleFontMetrics(metrics, strikeSpec.strikeToSourceRatio());
358     }
359     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
360 }
361 
getTypefaceOrDefault() const362 SkTypeface* SkFont::getTypefaceOrDefault() const {
363     return fTypeface ? fTypeface.get() : SkTypeface::GetDefaultTypeface();
364 }
365 
refTypefaceOrDefault() const366 sk_sp<SkTypeface> SkFont::refTypefaceOrDefault() const {
367     return fTypeface ? fTypeface : SkTypeface::MakeDefault();
368 }
369 
370 //////////////////////////////////////////////////////////////////////////////////////////////////
371 
ScaleFontMetrics(SkFontMetrics * metrics,SkScalar scale)372 void SkFontPriv::ScaleFontMetrics(SkFontMetrics* metrics, SkScalar scale) {
373     metrics->fTop *= scale;
374     metrics->fAscent *= scale;
375     metrics->fDescent *= scale;
376     metrics->fBottom *= scale;
377     metrics->fLeading *= scale;
378     metrics->fAvgCharWidth *= scale;
379     metrics->fMaxCharWidth *= scale;
380     metrics->fXMin *= scale;
381     metrics->fXMax *= scale;
382     metrics->fXHeight *= scale;
383     metrics->fCapHeight *= scale;
384     metrics->fUnderlineThickness *= scale;
385     metrics->fUnderlinePosition *= scale;
386     metrics->fStrikeoutThickness *= scale;
387     metrics->fStrikeoutPosition *= scale;
388 }
389 
GetFontBounds(const SkFont & font)390 SkRect SkFontPriv::GetFontBounds(const SkFont& font) {
391     SkMatrix m;
392     m.setScale(font.getSize() * font.getScaleX(), font.getSize());
393     m.postSkew(font.getSkewX(), 0);
394 
395     SkTypeface* typeface = font.getTypefaceOrDefault();
396 
397     SkRect bounds;
398     m.mapRect(&bounds, typeface->getBounds());
399     return bounds;
400 }
401 
CountTextElements(const void * text,size_t byteLength,SkTextEncoding encoding)402 int SkFontPriv::CountTextElements(const void* text, size_t byteLength, SkTextEncoding encoding) {
403     switch (encoding) {
404         case SkTextEncoding::kUTF8:
405             return SkUTF::CountUTF8(reinterpret_cast<const char*>(text), byteLength);
406         case SkTextEncoding::kUTF16:
407             return SkUTF::CountUTF16(reinterpret_cast<const uint16_t*>(text), byteLength);
408         case SkTextEncoding::kUTF32:
409             return byteLength >> 2;
410         case SkTextEncoding::kGlyphID:
411             return byteLength >> 1;
412     }
413     SkASSERT(false);
414     return 0;
415 }
416 
GlyphsToUnichars(const SkFont & font,const SkGlyphID glyphs[],int count,SkUnichar text[])417 void SkFontPriv::GlyphsToUnichars(const SkFont& font, const SkGlyphID glyphs[], int count,
418                                   SkUnichar text[]) {
419     if (count <= 0) {
420         return;
421     }
422 
423     auto typeface = font.getTypefaceOrDefault();
424     const unsigned numGlyphsInTypeface = typeface->countGlyphs();
425     SkAutoTArray<SkUnichar> unichars(numGlyphsInTypeface);
426     typeface->getGlyphToUnicodeMap(unichars.get());
427 
428     for (int i = 0; i < count; ++i) {
429         unsigned id = glyphs[i];
430         text[i] = (id < numGlyphsInTypeface) ? unichars[id] : 0xFFFD;
431     }
432 }
433 
434 ///////////////////////////////////////////////////////////////////////////////////////////////////
435 #include "src/core/SkReadBuffer.h"
436 #include "src/core/SkWriteBuffer.h"
437 
438 // packed int at the beginning of the serialized font:
439 //
440 //  control_bits:8 size_as_byte:8 flags:12 edging:2 hinting:2
441 
442 enum {
443     kSize_Is_Byte_Bit   = 1 << 31,
444     kHas_ScaleX_Bit     = 1 << 30,
445     kHas_SkewX_Bit      = 1 << 29,
446     kHas_Typeface_Bit   = 1 << 28,
447 
448     kShift_for_Size     = 16,
449     kMask_For_Size      = 0xFF,
450 
451     kShift_For_Flags    = 4,
452     kMask_For_Flags     = 0xFFF,
453 
454     kShift_For_Edging   = 2,
455     kMask_For_Edging    = 0x3,
456 
457     kShift_For_Hinting  = 0,
458     kMask_For_Hinting   = 0x3
459 };
460 
scalar_is_byte(SkScalar x)461 static bool scalar_is_byte(SkScalar x) {
462     int ix = (int)x;
463     return ix == x && ix >= 0 && ix <= kMask_For_Size;
464 }
465 
Flatten(const SkFont & font,SkWriteBuffer & buffer)466 void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) {
467     SkASSERT((font.fFlags & ~kMask_For_Flags) == 0);
468     SkASSERT((font.fEdging & ~kMask_For_Edging) == 0);
469     SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0);
470 
471     uint32_t packed = 0;
472     packed |= font.fFlags << kShift_For_Flags;
473     packed |= font.fEdging << kShift_For_Edging;
474     packed |= font.fHinting << kShift_For_Hinting;
475 
476     if (scalar_is_byte(font.fSize)) {
477         packed |= kSize_Is_Byte_Bit;
478         packed |= (int)font.fSize << kShift_for_Size;
479     }
480     if (font.fScaleX != 1) {
481         packed |= kHas_ScaleX_Bit;
482     }
483     if (font.fSkewX != 0) {
484         packed |= kHas_SkewX_Bit;
485     }
486     if (font.fTypeface) {
487         packed |= kHas_Typeface_Bit;
488     }
489 
490     buffer.write32(packed);
491     if (!(packed & kSize_Is_Byte_Bit)) {
492         buffer.writeScalar(font.fSize);
493     }
494     if (packed & kHas_ScaleX_Bit) {
495         buffer.writeScalar(font.fScaleX);
496     }
497     if (packed & kHas_SkewX_Bit) {
498         buffer.writeScalar(font.fSkewX);
499     }
500     if (packed & kHas_Typeface_Bit) {
501         buffer.writeTypeface(font.fTypeface.get());
502     }
503 }
504 
Unflatten(SkFont * font,SkReadBuffer & buffer)505 bool SkFontPriv::Unflatten(SkFont* font, SkReadBuffer& buffer) {
506     const uint32_t packed = buffer.read32();
507 
508     if (packed & kSize_Is_Byte_Bit) {
509         font->fSize = (packed >> kShift_for_Size) & kMask_For_Size;
510     } else {
511         font->fSize = buffer.readScalar();
512     }
513     if (packed & kHas_ScaleX_Bit) {
514         font->fScaleX = buffer.readScalar();
515     }
516     if (packed & kHas_SkewX_Bit) {
517         font->fSkewX = buffer.readScalar();
518     }
519     if (packed & kHas_Typeface_Bit) {
520         font->fTypeface = buffer.readTypeface();
521     }
522 
523     SkASSERT(SkFont::kAllFlags <= kMask_For_Flags);
524     // we & with kAllFlags, to clear out any unknown flag bits
525     font->fFlags = SkToU8((packed >> kShift_For_Flags) & SkFont::kAllFlags);
526 
527     unsigned edging = (packed >> kShift_For_Edging) & kMask_For_Edging;
528     if (edging > (unsigned)SkFont::Edging::kSubpixelAntiAlias) {
529         edging = 0;
530     }
531     font->fEdging = SkToU8(edging);
532 
533     unsigned hinting = (packed >> kShift_For_Hinting) & kMask_For_Hinting;
534     if (hinting > (unsigned)SkFontHinting::kFull) {
535         hinting = 0;
536     }
537     font->fHinting = SkToU8(hinting);
538 
539     return buffer.isValid();
540 }
541