Home | History | Annotate | Download | only in core
      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 "SkDraw.h"
      9 #include "SkFontPriv.h"
     10 #include "SkPaint.h"
     11 #include "SkPaintDefaults.h"
     12 #include "SkPath.h"
     13 #include "SkScalerContext.h"
     14 #include "SkStrike.h"
     15 #include "SkStrikeCache.h"
     16 #include "SkTo.h"
     17 #include "SkTLazy.h"
     18 #include "SkTypeface.h"
     19 #include "SkUTF.h"
     20 #include "SkUtils.h"
     21 
     22 #define kDefault_Size       SkPaintDefaults_TextSize
     23 #define kDefault_Flags      0
     24 #define kDefault_Edging     SkFont::Edging::kAntiAlias
     25 #define kDefault_Hinting    SkPaintDefaults_Hinting
     26 
     27 static inline SkScalar valid_size(SkScalar size) {
     28     return SkTMax<SkScalar>(0, size);
     29 }
     30 
     31 SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX)
     32     : fTypeface(std::move(face))
     33     , fSize(valid_size(size))
     34     , fScaleX(scaleX)
     35     , fSkewX(skewX)
     36     , fFlags(kDefault_Flags)
     37     , fEdging(static_cast<unsigned>(kDefault_Edging))
     38     , fHinting(static_cast<unsigned>(kDefault_Hinting))
     39 {}
     40 
     41 SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size) : SkFont(std::move(face), size, 1, 0) {}
     42 
     43 SkFont::SkFont(sk_sp<SkTypeface> face) : SkFont(std::move(face), kDefault_Size, 1, 0) {}
     44 
     45 SkFont::SkFont() : SkFont(nullptr, kDefault_Size) {}
     46 
     47 bool SkFont::operator==(const SkFont& b) const {
     48     return  fTypeface.get() == b.fTypeface.get() &&
     49             fSize           == b.fSize &&
     50             fScaleX         == b.fScaleX &&
     51             fSkewX          == b.fSkewX &&
     52             fFlags          == b.fFlags &&
     53             fEdging         == b.fEdging &&
     54             fHinting        == b.fHinting;
     55 }
     56 
     57 void SkFont::dump() const {
     58     SkDebugf("typeface %p\n", fTypeface.get());
     59     SkDebugf("size %g\n", fSize);
     60     SkDebugf("skewx %g\n", fSkewX);
     61     SkDebugf("scalex %g\n", fScaleX);
     62     SkDebugf("flags 0x%X\n", fFlags);
     63     SkDebugf("edging %d\n", (unsigned)fEdging);
     64     SkDebugf("hinting %d\n", (unsigned)fHinting);
     65 }
     66 
     67 ///////////////////////////////////////////////////////////////////////////////////////////////////
     68 
     69 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
     70     return cond ? bits | mask : bits & ~mask;
     71 }
     72 
     73 void SkFont::setForceAutoHinting(bool predicate) {
     74     fFlags = set_clear_mask(fFlags, predicate, kForceAutoHinting_PrivFlag);
     75 }
     76 void SkFont::setEmbeddedBitmaps(bool predicate) {
     77     fFlags = set_clear_mask(fFlags, predicate, kEmbeddedBitmaps_PrivFlag);
     78 }
     79 void SkFont::setSubpixel(bool predicate) {
     80     fFlags = set_clear_mask(fFlags, predicate, kSubpixel_PrivFlag);
     81 }
     82 void SkFont::setLinearMetrics(bool predicate) {
     83     fFlags = set_clear_mask(fFlags, predicate, kLinearMetrics_PrivFlag);
     84 }
     85 void SkFont::setEmbolden(bool predicate) {
     86     fFlags = set_clear_mask(fFlags, predicate, kEmbolden_PrivFlag);
     87 }
     88 
     89 void SkFont::setEdging(Edging e) {
     90     fEdging = SkToU8(e);
     91 }
     92 
     93 void SkFont::setHinting(SkFontHinting h) {
     94     fHinting = SkToU8(h);
     95 }
     96 
     97 void SkFont::setSize(SkScalar size) {
     98     fSize = valid_size(size);
     99 }
    100 void SkFont::setScaleX(SkScalar scale) {
    101     fScaleX = scale;
    102 }
    103 void SkFont::setSkewX(SkScalar skew) {
    104     fSkewX = skew;
    105 }
    106 
    107 SkFont SkFont::makeWithSize(SkScalar newSize) const {
    108     SkFont font = *this;
    109     font.setSize(newSize);
    110     return font;
    111 }
    112 
    113 ///////////////////////////////////////////////////////////////////////////////////////////////////
    114 
    115 SkScalar SkFont::setupForAsPaths(SkPaint* paint) {
    116     constexpr uint32_t flagsToIgnore = kLinearMetrics_PrivFlag        |
    117                                        kEmbeddedBitmaps_PrivFlag      |
    118                                        kForceAutoHinting_PrivFlag;
    119 
    120     fFlags = (fFlags & ~flagsToIgnore) | kSubpixel_PrivFlag;
    121     this->setHinting(kNo_SkFontHinting);
    122 
    123     if (this->getEdging() == Edging::kSubpixelAntiAlias) {
    124         this->setEdging(Edging::kAntiAlias);
    125     }
    126 
    127     if (paint) {
    128         paint->setStyle(SkPaint::kFill_Style);
    129         paint->setPathEffect(nullptr);
    130     }
    131     SkScalar textSize = fSize;
    132     this->setSize(SkIntToScalar(SkFontPriv::kCanonicalTextSizeForPaths));
    133     return textSize / SkFontPriv::kCanonicalTextSizeForPaths;
    134 }
    135 
    136 bool SkFont::hasSomeAntiAliasing() const {
    137     Edging edging = this->getEdging();
    138     return edging == SkFont::Edging::kAntiAlias
    139         || edging == SkFont::Edging::kSubpixelAntiAlias;
    140 }
    141 
    142 class SkCanonicalizeFont {
    143 public:
    144     SkCanonicalizeFont(const SkFont& font, const SkPaint* paint) : fFont(&font) {
    145         if (paint) {
    146             fPaint = *paint;
    147         }
    148         if (font.isLinearMetrics() ||
    149             SkDraw::ShouldDrawTextAsPaths(font, fPaint, SkMatrix::I()))
    150         {
    151             SkFont* f = fLazyFont.set(font);
    152             fScale = f->setupForAsPaths(nullptr);
    153             fFont = f;
    154             fPaint.reset();
    155         }
    156     }
    157 
    158     const SkFont& getFont() const { return *fFont; }
    159     const SkPaint& getPaint() const { return fPaint; }
    160     SkScalar getScale() const { return fScale; }
    161 
    162 private:
    163     const SkFont*    fFont;
    164     SkTLazy<SkFont>  fLazyFont;
    165     SkPaint          fPaint;
    166     SkScalar         fScale = 0;
    167 };
    168 
    169 SkGlyphID SkFont::unicharToGlyph(SkUnichar uni) const {
    170     return this->getTypefaceOrDefault()->unicharToGlyph(uni);
    171 }
    172 
    173 int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
    174                          uint16_t glyphs[], int maxGlyphCount) const {
    175     if (0 == byteLength) {
    176         return 0;
    177     }
    178 
    179     SkASSERT(text);
    180 
    181     int count = SkFontPriv::CountTextElements(text, byteLength, encoding);
    182     if (!glyphs || count > maxGlyphCount) {
    183         return count;
    184     }
    185 
    186     // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding
    187     SkTypeface::Encoding typefaceEncoding;
    188     switch (encoding) {
    189         case kUTF8_SkTextEncoding:
    190             typefaceEncoding = SkTypeface::kUTF8_Encoding;
    191             break;
    192         case kUTF16_SkTextEncoding:
    193             typefaceEncoding = SkTypeface::kUTF16_Encoding;
    194             break;
    195         case kUTF32_SkTextEncoding:
    196             typefaceEncoding = SkTypeface::kUTF32_Encoding;
    197             break;
    198         default:
    199             SkASSERT(kGlyphID_SkTextEncoding == encoding);
    200             // we can early exit, since we already have glyphIDs
    201             memcpy(glyphs, text, count << 1);
    202             return count;
    203     }
    204 
    205     (void) this->getTypefaceOrDefault()->charsToGlyphs(text, typefaceEncoding, glyphs,count);
    206     return count;
    207 }
    208 
    209 void SkFont::glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const {
    210     if (count <= 0) {
    211         return;
    212     }
    213 
    214     auto typeface = this->getTypefaceOrDefault();
    215     const unsigned numGlyphsInTypeface = typeface->countGlyphs();
    216     SkAutoTArray<SkUnichar> unichars(numGlyphsInTypeface);
    217     typeface->getGlyphToUnicodeMap(unichars.get());
    218 
    219     for (int i = 0; i < count; ++i) {
    220         unsigned id = glyphs[i];
    221         text[i] = (id < numGlyphsInTypeface) ? unichars[id] : 0xFFFD;
    222     }
    223 }
    224 
    225 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
    226     bounds->set(SkIntToScalar(g.fLeft),
    227                 SkIntToScalar(g.fTop),
    228                 SkIntToScalar(g.fLeft + g.fWidth),
    229                 SkIntToScalar(g.fTop + g.fHeight));
    230 }
    231 
    232 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, SkScalar dx) {
    233     bounds->join(SkIntToScalar(g.fLeft) + dx,
    234                  SkIntToScalar(g.fTop),
    235                  SkIntToScalar(g.fLeft + g.fWidth) + dx,
    236                  SkIntToScalar(g.fTop + g.fHeight));
    237 }
    238 
    239 SkScalar SkFont::measureText(const void* text, size_t length, SkTextEncoding encoding,
    240                              SkRect* bounds, const SkPaint* paint) const {
    241     SkCanonicalizeFont canon(*this, paint);
    242     const SkFont& font = canon.getFont();
    243     const SkScalar scale = canon.getScale();
    244 
    245     SkAutoToGlyphs atg(font, text, length, encoding);
    246     const int count = atg.count();
    247     if (count == 0) {
    248         if (bounds) {
    249             bounds->setEmpty();
    250         }
    251         return 0;
    252     }
    253     const uint16_t* glyphs = atg.glyphs();
    254 
    255     auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, canon.getPaint());
    256 
    257     SkScalar width = 0;
    258     if (bounds) {
    259         const SkGlyph* g = &cache->getGlyphIDMetrics(glyphs[0]);
    260         set_bounds(*g, bounds);
    261         width = g->fAdvanceX;
    262         for (int i = 1; i < count; ++i) {
    263             g = &cache->getGlyphIDMetrics(glyphs[i]);
    264             join_bounds_x(*g, bounds, width);
    265             width += g->fAdvanceX;
    266         }
    267     } else {
    268         for (int i = 0; i < count; ++i) {
    269             width += cache->getGlyphIDAdvance(glyphs[i]).fAdvanceX;
    270         }
    271     }
    272 
    273     if (scale) {
    274         width *= scale;
    275         if (bounds) {
    276             bounds->fLeft *= scale;
    277             bounds->fTop *= scale;
    278             bounds->fRight *= scale;
    279             bounds->fBottom *= scale;
    280         }
    281     }
    282 
    283     return width;
    284 }
    285 
    286 static SkRect make_bounds(const SkGlyph& g, SkScalar scale) {
    287     return {
    288         g.fLeft * scale,
    289         g.fTop * scale,
    290         (g.fLeft + g.fWidth) * scale,
    291         (g.fTop + g.fHeight) * scale
    292     };
    293 }
    294 
    295 template <typename HANDLER>
    296 void VisitGlyphs(const SkFont& origFont, const SkPaint* paint, const uint16_t glyphs[], int count,
    297                  HANDLER handler) {
    298     if (count <= 0) {
    299         return;
    300     }
    301 
    302     SkCanonicalizeFont canon(origFont, paint);
    303     const SkFont& font = canon.getFont();
    304     SkScalar scale = canon.getScale();
    305     if (!scale) {
    306         scale = 1;
    307     }
    308 
    309     auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, canon.getPaint());
    310     handler(cache.get(), glyphs, count, scale);
    311 }
    312 
    313 void SkFont::getWidthsBounds(const uint16_t glyphs[], int count, SkScalar widths[], SkRect bounds[],
    314                              const SkPaint* paint) const {
    315     VisitGlyphs(*this, paint, glyphs, count, [widths, bounds]
    316                 (SkStrike* cache, const uint16_t glyphs[], int count, SkScalar scale) {
    317         for (int i = 0; i < count; ++i) {
    318             const SkGlyph* g;
    319             if (bounds) {
    320                 g = &cache->getGlyphIDMetrics(glyphs[i]);
    321                 bounds[i] = make_bounds(*g, scale);
    322             } else {
    323                 g = &cache->getGlyphIDAdvance(glyphs[i]);
    324             }
    325             if (widths) {
    326                 widths[i] = g->fAdvanceX * scale;
    327             }
    328         }
    329     });
    330 }
    331 
    332 void SkFont::getPos(const uint16_t glyphs[], int count, SkPoint pos[], SkPoint origin) const {
    333     VisitGlyphs(*this, nullptr, glyphs, count, [pos, origin]
    334                       (SkStrike* cache, const uint16_t glyphs[], int count, SkScalar scale) {
    335         SkPoint loc = origin;
    336         for (int i = 0; i < count; ++i) {
    337             pos[i] = loc;
    338             loc.fX += cache->getGlyphIDAdvance(glyphs[i]).fAdvanceX * scale;
    339         }
    340     });
    341 }
    342 
    343 void SkFont::getXPos(const uint16_t glyphs[], int count, SkScalar xpos[], SkScalar origin) const {
    344     VisitGlyphs(*this, nullptr, glyphs, count, [xpos, origin]
    345                       (SkStrike* cache, const uint16_t glyphs[], int count, SkScalar scale) {
    346         SkScalar x = origin;
    347         for (int i = 0; i < count; ++i) {
    348             xpos[i] = x;
    349             x += cache->getGlyphIDAdvance(glyphs[i]).fAdvanceX * scale;
    350         }
    351     });
    352 }
    353 
    354 void SkFont::getPaths(const uint16_t glyphs[], int count,
    355                       void (*proc)(const SkPath*, const SkMatrix&, void*), void* ctx) const {
    356     SkFont font(*this);
    357     SkScalar scale = font.setupForAsPaths(nullptr);
    358     if (!scale) {
    359         scale = 1;
    360     }
    361     const SkMatrix mx = SkMatrix::MakeScale(scale, scale);
    362 
    363     auto exclusive = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font);
    364     auto cache = exclusive.get();
    365 
    366     for (int i = 0; i < count; ++i) {
    367         proc(cache->findPath(cache->getGlyphIDMetrics(glyphs[i])), mx, ctx);
    368     }
    369 }
    370 
    371 bool SkFont::getPath(uint16_t glyphID, SkPath* path) const {
    372     struct Pair {
    373         SkPath* fPath;
    374         bool    fWasSet;
    375     } pair = { path, false };
    376 
    377     this->getPaths(&glyphID, 1, [](const SkPath* orig, const SkMatrix& mx, void* ctx) {
    378         Pair* pair = static_cast<Pair*>(ctx);
    379         if (orig) {
    380             orig->transform(mx, pair->fPath);
    381             pair->fWasSet = true;
    382         }
    383     }, &pair);
    384     return pair.fWasSet;
    385 }
    386 
    387 SkScalar SkFont::getMetrics(SkFontMetrics* metrics) const {
    388     SkCanonicalizeFont canon(*this, nullptr);
    389     const SkFont& font = canon.getFont();
    390     SkScalar scale = canon.getScale();
    391 
    392     SkFontMetrics storage;
    393     if (nullptr == metrics) {
    394         metrics = &storage;
    395     }
    396 
    397     auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font);
    398     *metrics = cache->getFontMetrics();
    399 
    400     if (scale) {
    401         SkFontPriv::ScaleFontMetrics(metrics, scale);
    402     }
    403     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
    404 }
    405 
    406 SkTypeface* SkFont::getTypefaceOrDefault() const {
    407     return fTypeface ? fTypeface.get() : SkTypeface::GetDefaultTypeface();
    408 }
    409 
    410 sk_sp<SkTypeface> SkFont::refTypefaceOrDefault() const {
    411     return fTypeface ? fTypeface : SkTypeface::MakeDefault();
    412 }
    413 
    414 //////////////////////////////////////////////////////////////////////////////////////////////////
    415 
    416 void SkFontPriv::ScaleFontMetrics(SkFontMetrics* metrics, SkScalar scale) {
    417     metrics->fTop *= scale;
    418     metrics->fAscent *= scale;
    419     metrics->fDescent *= scale;
    420     metrics->fBottom *= scale;
    421     metrics->fLeading *= scale;
    422     metrics->fAvgCharWidth *= scale;
    423     metrics->fMaxCharWidth *= scale;
    424     metrics->fXMin *= scale;
    425     metrics->fXMax *= scale;
    426     metrics->fXHeight *= scale;
    427     metrics->fCapHeight *= scale;
    428     metrics->fUnderlineThickness *= scale;
    429     metrics->fUnderlinePosition *= scale;
    430     metrics->fStrikeoutThickness *= scale;
    431     metrics->fStrikeoutPosition *= scale;
    432 }
    433 
    434 SkRect SkFontPriv::GetFontBounds(const SkFont& font) {
    435     SkMatrix m;
    436     m.setScale(font.getSize() * font.getScaleX(), font.getSize());
    437     m.postSkew(font.getSkewX(), 0);
    438 
    439     SkTypeface* typeface = font.getTypefaceOrDefault();
    440 
    441     SkRect bounds;
    442     m.mapRect(&bounds, typeface->getBounds());
    443     return bounds;
    444 }
    445 
    446 int SkFontPriv::CountTextElements(const void* text, size_t byteLength, SkTextEncoding encoding) {
    447     switch (encoding) {
    448         case kUTF8_SkTextEncoding:
    449             return SkUTF::CountUTF8(reinterpret_cast<const char*>(text), byteLength);
    450         case kUTF16_SkTextEncoding:
    451             return SkUTF::CountUTF16(reinterpret_cast<const uint16_t*>(text), byteLength);
    452         case kUTF32_SkTextEncoding:
    453             return byteLength >> 2;
    454         case kGlyphID_SkTextEncoding:
    455             return byteLength >> 1;
    456     }
    457     SkASSERT(false);
    458     return 0;
    459 }
    460 
    461 void SkFontPriv::GlyphsToUnichars(const SkFont& font, const uint16_t glyphs[], int count,
    462                                   SkUnichar uni[]) {
    463     font.glyphsToUnichars(glyphs, count, uni);
    464 }
    465 
    466 ///////////////////////////////////////////////////////////////////////////////////////////////////
    467 #include "SkReadBuffer.h"
    468 #include "SkWriteBuffer.h"
    469 
    470 // packed int at the beginning of the serialized font:
    471 //
    472 //  control_bits:8 size_as_byte:8 flags:12 edging:2 hinting:2
    473 
    474 enum {
    475     kSize_Is_Byte_Bit   = 1 << 31,
    476     kHas_ScaleX_Bit     = 1 << 30,
    477     kHas_SkewX_Bit      = 1 << 29,
    478     kHas_Typeface_Bit   = 1 << 28,
    479 
    480     kShift_for_Size     = 16,
    481     kMask_For_Size      = 0xFF,
    482 
    483     kShift_For_Flags    = 4,
    484     kMask_For_Flags     = 0xFFF,
    485 
    486     kShift_For_Edging   = 2,
    487     kMask_For_Edging    = 0x3,
    488 
    489     kShift_For_Hinting  = 0,
    490     kMask_For_Hinting   = 0x3
    491 };
    492 
    493 static bool scalar_is_byte(SkScalar x) {
    494     int ix = (int)x;
    495     return ix == x && ix >= 0 && ix <= kMask_For_Size;
    496 }
    497 
    498 void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) {
    499     SkASSERT((font.fFlags & ~kMask_For_Flags) == 0);
    500     SkASSERT((font.fEdging & ~kMask_For_Edging) == 0);
    501     SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0);
    502 
    503     uint32_t packed = 0;
    504     packed |= font.fFlags << kShift_For_Flags;
    505     packed |= font.fEdging << kShift_For_Edging;
    506     packed |= font.fHinting << kShift_For_Hinting;
    507 
    508     if (scalar_is_byte(font.fSize)) {
    509         packed |= kSize_Is_Byte_Bit;
    510         packed |= (int)font.fSize << kShift_for_Size;
    511     }
    512     if (font.fScaleX != 1) {
    513         packed |= kHas_ScaleX_Bit;
    514     }
    515     if (font.fSkewX != 0) {
    516         packed |= kHas_SkewX_Bit;
    517     }
    518     if (font.fTypeface) {
    519         packed |= kHas_Typeface_Bit;
    520     }
    521 
    522     buffer.write32(packed);
    523     if (!(packed & kSize_Is_Byte_Bit)) {
    524         buffer.writeScalar(font.fSize);
    525     }
    526     if (packed & kHas_ScaleX_Bit) {
    527         buffer.writeScalar(font.fScaleX);
    528     }
    529     if (packed & kHas_SkewX_Bit) {
    530         buffer.writeScalar(font.fSkewX);
    531     }
    532     if (packed & kHas_Typeface_Bit) {
    533         buffer.writeTypeface(font.fTypeface.get());
    534     }
    535 }
    536 
    537 bool SkFontPriv::Unflatten(SkFont* font, SkReadBuffer& buffer) {
    538     const uint32_t packed = buffer.read32();
    539 
    540     if (packed & kSize_Is_Byte_Bit) {
    541         font->fSize = (packed >> kShift_for_Size) & kMask_For_Size;
    542     } else {
    543         font->fSize = buffer.readScalar();
    544     }
    545     if (packed & kHas_ScaleX_Bit) {
    546         font->fScaleX = buffer.readScalar();
    547     }
    548     if (packed & kHas_SkewX_Bit) {
    549         font->fSkewX = buffer.readScalar();
    550     }
    551     if (packed & kHas_Typeface_Bit) {
    552         font->fTypeface = buffer.readTypeface();
    553     }
    554 
    555     SkASSERT(SkFont::kAllFlags <= kMask_For_Flags);
    556     // we & with kAllFlags, to clear out any unknown flag bits
    557     font->fFlags = SkToU8((packed >> kShift_For_Flags) & SkFont::kAllFlags);
    558 
    559     unsigned edging = (packed >> kShift_For_Edging) & kMask_For_Edging;
    560     if (edging > (unsigned)SkFont::Edging::kSubpixelAntiAlias) {
    561         edging = 0;
    562     }
    563     font->fEdging = SkToU8(edging);
    564 
    565     unsigned hinting = (packed >> kShift_For_Hinting) & kMask_For_Hinting;
    566     if (hinting > (unsigned)kFull_SkFontHinting) {
    567         hinting = 0;
    568     }
    569     font->fHinting = SkToU8(hinting);
    570 
    571     return buffer.isValid();
    572 }
    573