Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 "SkPaint.h"
      9 #include "SkPaintPriv.h"
     10 #include "SkAutoKern.h"
     11 #include "SkColorFilter.h"
     12 #include "SkData.h"
     13 #include "SkDraw.h"
     14 #include "SkFontDescriptor.h"
     15 #include "SkGlyphCache.h"
     16 #include "SkImageFilter.h"
     17 #include "SkMaskFilter.h"
     18 #include "SkMaskGamma.h"
     19 #include "SkMutex.h"
     20 #include "SkReadBuffer.h"
     21 #include "SkWriteBuffer.h"
     22 #include "SkOpts.h"
     23 #include "SkPaintDefaults.h"
     24 #include "SkPathEffect.h"
     25 #include "SkRasterizer.h"
     26 #include "SkScalar.h"
     27 #include "SkScalerContext.h"
     28 #include "SkShader.h"
     29 #include "SkStringUtils.h"
     30 #include "SkStroke.h"
     31 #include "SkStrokeRec.h"
     32 #include "SkSurfacePriv.h"
     33 #include "SkTextBlob.h"
     34 #include "SkTextBlobRunIterator.h"
     35 #include "SkTextFormatParams.h"
     36 #include "SkTextToPathIter.h"
     37 #include "SkTLazy.h"
     38 #include "SkTypeface.h"
     39 
     40 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) {
     41     return cond ? bits | mask : bits & ~mask;
     42 }
     43 
     44 // define this to get a printf for out-of-range parameter in setters
     45 // e.g. setTextSize(-1)
     46 //#define SK_REPORT_API_RANGE_CHECK
     47 
     48 SkPaint::SkPaint() {
     49     fTextSize   = SkPaintDefaults_TextSize;
     50     fTextScaleX = SK_Scalar1;
     51     fTextSkewX  = 0;
     52     fColor      = SK_ColorBLACK;
     53     fWidth      = 0;
     54     fMiterLimit = SkPaintDefaults_MiterLimit;
     55     fBlendMode  = (unsigned)SkBlendMode::kSrcOver;
     56 
     57     // Zero all bitfields, then set some non-zero defaults.
     58     fBitfieldsUInt           = 0;
     59     fBitfields.fFlags        = SkPaintDefaults_Flags;
     60     fBitfields.fCapType      = kDefault_Cap;
     61     fBitfields.fJoinType     = kDefault_Join;
     62     fBitfields.fTextAlign    = kLeft_Align;
     63     fBitfields.fStyle        = kFill_Style;
     64     fBitfields.fTextEncoding = kUTF8_TextEncoding;
     65     fBitfields.fHinting      = SkPaintDefaults_Hinting;
     66 }
     67 
     68 SkPaint::SkPaint(const SkPaint& src)
     69 #define COPY(field) field(src.field)
     70     : COPY(fTypeface)
     71     , COPY(fPathEffect)
     72     , COPY(fShader)
     73     , COPY(fMaskFilter)
     74     , COPY(fColorFilter)
     75     , COPY(fRasterizer)
     76     , COPY(fDrawLooper)
     77     , COPY(fImageFilter)
     78     , COPY(fTextSize)
     79     , COPY(fTextScaleX)
     80     , COPY(fTextSkewX)
     81     , COPY(fColor)
     82     , COPY(fWidth)
     83     , COPY(fMiterLimit)
     84     , COPY(fBlendMode)
     85     , COPY(fBitfields)
     86 #undef COPY
     87 {}
     88 
     89 SkPaint::SkPaint(SkPaint&& src) {
     90 #define MOVE(field) field = std::move(src.field)
     91     MOVE(fTypeface);
     92     MOVE(fPathEffect);
     93     MOVE(fShader);
     94     MOVE(fMaskFilter);
     95     MOVE(fColorFilter);
     96     MOVE(fRasterizer);
     97     MOVE(fDrawLooper);
     98     MOVE(fImageFilter);
     99     MOVE(fTextSize);
    100     MOVE(fTextScaleX);
    101     MOVE(fTextSkewX);
    102     MOVE(fColor);
    103     MOVE(fWidth);
    104     MOVE(fMiterLimit);
    105     MOVE(fBlendMode);
    106     MOVE(fBitfields);
    107 #undef MOVE
    108 }
    109 
    110 SkPaint::~SkPaint() {}
    111 
    112 SkPaint& SkPaint::operator=(const SkPaint& src) {
    113     if (this == &src) {
    114         return *this;
    115     }
    116 
    117 #define ASSIGN(field) field = src.field
    118     ASSIGN(fTypeface);
    119     ASSIGN(fPathEffect);
    120     ASSIGN(fShader);
    121     ASSIGN(fMaskFilter);
    122     ASSIGN(fColorFilter);
    123     ASSIGN(fRasterizer);
    124     ASSIGN(fDrawLooper);
    125     ASSIGN(fImageFilter);
    126     ASSIGN(fTextSize);
    127     ASSIGN(fTextScaleX);
    128     ASSIGN(fTextSkewX);
    129     ASSIGN(fColor);
    130     ASSIGN(fWidth);
    131     ASSIGN(fMiterLimit);
    132     ASSIGN(fBlendMode);
    133     ASSIGN(fBitfields);
    134 #undef ASSIGN
    135 
    136     return *this;
    137 }
    138 
    139 SkPaint& SkPaint::operator=(SkPaint&& src) {
    140     if (this == &src) {
    141         return *this;
    142     }
    143 
    144 #define MOVE(field) field = std::move(src.field)
    145     MOVE(fTypeface);
    146     MOVE(fPathEffect);
    147     MOVE(fShader);
    148     MOVE(fMaskFilter);
    149     MOVE(fColorFilter);
    150     MOVE(fRasterizer);
    151     MOVE(fDrawLooper);
    152     MOVE(fImageFilter);
    153     MOVE(fTextSize);
    154     MOVE(fTextScaleX);
    155     MOVE(fTextSkewX);
    156     MOVE(fColor);
    157     MOVE(fWidth);
    158     MOVE(fMiterLimit);
    159     MOVE(fBlendMode);
    160     MOVE(fBitfields);
    161 #undef MOVE
    162 
    163     return *this;
    164 }
    165 
    166 bool operator==(const SkPaint& a, const SkPaint& b) {
    167 #define EQUAL(field) (a.field == b.field)
    168     return EQUAL(fTypeface)
    169         && EQUAL(fPathEffect)
    170         && EQUAL(fShader)
    171         && EQUAL(fMaskFilter)
    172         && EQUAL(fColorFilter)
    173         && EQUAL(fRasterizer)
    174         && EQUAL(fDrawLooper)
    175         && EQUAL(fImageFilter)
    176         && EQUAL(fTextSize)
    177         && EQUAL(fTextScaleX)
    178         && EQUAL(fTextSkewX)
    179         && EQUAL(fColor)
    180         && EQUAL(fWidth)
    181         && EQUAL(fMiterLimit)
    182         && EQUAL(fBlendMode)
    183         && EQUAL(fBitfieldsUInt)
    184         ;
    185 #undef EQUAL
    186 }
    187 
    188 #define DEFINE_REF_FOO(type)    sk_sp<Sk##type> SkPaint::ref##type() const { return f##type; }
    189 DEFINE_REF_FOO(ColorFilter)
    190 DEFINE_REF_FOO(DrawLooper)
    191 DEFINE_REF_FOO(ImageFilter)
    192 DEFINE_REF_FOO(MaskFilter)
    193 DEFINE_REF_FOO(PathEffect)
    194 DEFINE_REF_FOO(Rasterizer)
    195 DEFINE_REF_FOO(Shader)
    196 DEFINE_REF_FOO(Typeface)
    197 #undef DEFINE_REF_FOO
    198 
    199 void SkPaint::reset() {
    200     SkPaint init;
    201     *this = init;
    202 }
    203 
    204 void SkPaint::setFilterQuality(SkFilterQuality quality) {
    205     fBitfields.fFilterQuality = quality;
    206 }
    207 
    208 void SkPaint::setHinting(Hinting hintingLevel) {
    209     fBitfields.fHinting = hintingLevel;
    210 }
    211 
    212 void SkPaint::setFlags(uint32_t flags) {
    213     fBitfields.fFlags = flags;
    214 }
    215 
    216 void SkPaint::setAntiAlias(bool doAA) {
    217     this->setFlags(set_clear_mask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
    218 }
    219 
    220 void SkPaint::setDither(bool doDither) {
    221     this->setFlags(set_clear_mask(fBitfields.fFlags, doDither, kDither_Flag));
    222 }
    223 
    224 void SkPaint::setSubpixelText(bool doSubpixel) {
    225     this->setFlags(set_clear_mask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
    226 }
    227 
    228 void SkPaint::setLCDRenderText(bool doLCDRender) {
    229     this->setFlags(set_clear_mask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
    230 }
    231 
    232 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
    233     this->setFlags(set_clear_mask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
    234 }
    235 
    236 void SkPaint::setAutohinted(bool useAutohinter) {
    237     this->setFlags(set_clear_mask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
    238 }
    239 
    240 void SkPaint::setLinearText(bool doLinearText) {
    241     this->setFlags(set_clear_mask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
    242 }
    243 
    244 void SkPaint::setVerticalText(bool doVertical) {
    245     this->setFlags(set_clear_mask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
    246 }
    247 
    248 void SkPaint::setFakeBoldText(bool doFakeBold) {
    249     this->setFlags(set_clear_mask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
    250 }
    251 
    252 void SkPaint::setDevKernText(bool doDevKern) {
    253     this->setFlags(set_clear_mask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
    254 }
    255 
    256 void SkPaint::setStyle(Style style) {
    257     if ((unsigned)style < kStyleCount) {
    258         fBitfields.fStyle = style;
    259     } else {
    260 #ifdef SK_REPORT_API_RANGE_CHECK
    261         SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
    262 #endif
    263     }
    264 }
    265 
    266 void SkPaint::setColor(SkColor color) {
    267     fColor = color;
    268 }
    269 
    270 void SkPaint::setAlpha(U8CPU a) {
    271     this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
    272                                   SkColorGetG(fColor), SkColorGetB(fColor)));
    273 }
    274 
    275 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
    276     this->setColor(SkColorSetARGB(a, r, g, b));
    277 }
    278 
    279 void SkPaint::setStrokeWidth(SkScalar width) {
    280     if (width >= 0) {
    281         fWidth = width;
    282     } else {
    283 #ifdef SK_REPORT_API_RANGE_CHECK
    284         SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
    285 #endif
    286     }
    287 }
    288 
    289 void SkPaint::setStrokeMiter(SkScalar limit) {
    290     if (limit >= 0) {
    291         fMiterLimit = limit;
    292     } else {
    293 #ifdef SK_REPORT_API_RANGE_CHECK
    294         SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
    295 #endif
    296     }
    297 }
    298 
    299 void SkPaint::setStrokeCap(Cap ct) {
    300     if ((unsigned)ct < kCapCount) {
    301         fBitfields.fCapType = SkToU8(ct);
    302     } else {
    303 #ifdef SK_REPORT_API_RANGE_CHECK
    304         SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
    305 #endif
    306     }
    307 }
    308 
    309 void SkPaint::setStrokeJoin(Join jt) {
    310     if ((unsigned)jt < kJoinCount) {
    311         fBitfields.fJoinType = SkToU8(jt);
    312     } else {
    313 #ifdef SK_REPORT_API_RANGE_CHECK
    314         SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
    315 #endif
    316     }
    317 }
    318 
    319 ///////////////////////////////////////////////////////////////////////////////
    320 
    321 void SkPaint::setTextAlign(Align align) {
    322     if ((unsigned)align < kAlignCount) {
    323         fBitfields.fTextAlign = SkToU8(align);
    324     } else {
    325 #ifdef SK_REPORT_API_RANGE_CHECK
    326         SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
    327 #endif
    328     }
    329 }
    330 
    331 void SkPaint::setTextSize(SkScalar ts) {
    332     if (ts >= 0) {
    333         fTextSize = ts;
    334     } else {
    335 #ifdef SK_REPORT_API_RANGE_CHECK
    336         SkDebugf("SkPaint::setTextSize() called with negative value\n");
    337 #endif
    338     }
    339 }
    340 
    341 void SkPaint::setTextScaleX(SkScalar scaleX) {
    342     fTextScaleX = scaleX;
    343 }
    344 
    345 void SkPaint::setTextSkewX(SkScalar skewX) {
    346     fTextSkewX = skewX;
    347 }
    348 
    349 void SkPaint::setTextEncoding(TextEncoding encoding) {
    350     if ((unsigned)encoding <= kGlyphID_TextEncoding) {
    351         fBitfields.fTextEncoding = encoding;
    352     } else {
    353 #ifdef SK_REPORT_API_RANGE_CHECK
    354         SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
    355 #endif
    356     }
    357 }
    358 
    359 ///////////////////////////////////////////////////////////////////////////////
    360 
    361 #define MOVE_FIELD(Field) void SkPaint::set##Field(sk_sp<Sk##Field> f) { f##Field = std::move(f); }
    362 MOVE_FIELD(Typeface)
    363 MOVE_FIELD(Rasterizer)
    364 MOVE_FIELD(ImageFilter)
    365 MOVE_FIELD(Shader)
    366 MOVE_FIELD(ColorFilter)
    367 MOVE_FIELD(PathEffect)
    368 MOVE_FIELD(MaskFilter)
    369 MOVE_FIELD(DrawLooper)
    370 #undef MOVE_FIELD
    371 void SkPaint::setLooper(sk_sp<SkDrawLooper> looper) { fDrawLooper = std::move(looper); }
    372 
    373 ///////////////////////////////////////////////////////////////////////////////
    374 
    375 static SkScalar mag2(SkScalar x, SkScalar y) {
    376     return x * x + y * y;
    377 }
    378 
    379 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
    380     return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
    381             ||
    382             mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
    383 }
    384 
    385 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
    386     SkASSERT(!ctm.hasPerspective());
    387     SkASSERT(!textM.hasPerspective());
    388 
    389     SkMatrix matrix;
    390     matrix.setConcat(ctm, textM);
    391     return tooBig(matrix, MaxCacheSize2());
    392 }
    393 
    394 
    395 ///////////////////////////////////////////////////////////////////////////////
    396 
    397 #include "SkGlyphCache.h"
    398 #include "SkUtils.h"
    399 
    400 static void DetachDescProc(SkTypeface* typeface, const SkScalerContextEffects& effects,
    401                            const SkDescriptor* desc, void* context) {
    402     *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, effects, desc);
    403 }
    404 
    405 int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const {
    406     if (byteLength == 0) {
    407         return 0;
    408     }
    409 
    410     SkASSERT(textData != nullptr);
    411 
    412     if (nullptr == glyphs) {
    413         switch (this->getTextEncoding()) {
    414         case kUTF8_TextEncoding:
    415             return SkUTF8_CountUnichars((const char*)textData, byteLength);
    416         case kUTF16_TextEncoding:
    417             return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
    418         case kUTF32_TextEncoding:
    419             return SkToInt(byteLength >> 2);
    420         case kGlyphID_TextEncoding:
    421             return SkToInt(byteLength >> 1);
    422         default:
    423             SkDEBUGFAIL("unknown text encoding");
    424         }
    425         return 0;
    426     }
    427 
    428     // if we get here, we have a valid glyphs[] array, so time to fill it in
    429 
    430     // handle this encoding before the setup for the glyphcache
    431     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
    432         // we want to ignore the low bit of byteLength
    433         memcpy(glyphs, textData, byteLength >> 1 << 1);
    434         return SkToInt(byteLength >> 1);
    435     }
    436 
    437     SkAutoGlyphCache autoCache(*this, nullptr, nullptr);
    438     SkGlyphCache*    cache = autoCache.getCache();
    439 
    440     const char* text = (const char*)textData;
    441     const char* stop = text + byteLength;
    442     uint16_t*   gptr = glyphs;
    443 
    444     switch (this->getTextEncoding()) {
    445         case SkPaint::kUTF8_TextEncoding:
    446             while (text < stop) {
    447                 SkUnichar u = SkUTF8_NextUnicharWithError(&text, stop);
    448                 if (u < 0) {
    449                     return 0;  // bad UTF-8 sequence
    450                 }
    451                 *gptr++ = cache->unicharToGlyph(u);
    452             }
    453             break;
    454         case SkPaint::kUTF16_TextEncoding: {
    455             const uint16_t* text16 = (const uint16_t*)text;
    456             const uint16_t* stop16 = (const uint16_t*)stop;
    457             while (text16 < stop16) {
    458                 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
    459             }
    460             break;
    461         }
    462         case kUTF32_TextEncoding: {
    463             const int32_t* text32 = (const int32_t*)text;
    464             const int32_t* stop32 = (const int32_t*)stop;
    465             while (text32 < stop32) {
    466                 *gptr++ = cache->unicharToGlyph(*text32++);
    467             }
    468             break;
    469         }
    470         default:
    471             SkDEBUGFAIL("unknown text encoding");
    472     }
    473     return SkToInt(gptr - glyphs);
    474 }
    475 
    476 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
    477     if (0 == byteLength) {
    478         return true;
    479     }
    480 
    481     SkASSERT(textData != nullptr);
    482 
    483     // handle this encoding before the setup for the glyphcache
    484     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
    485         const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
    486         size_t count = byteLength >> 1;
    487         for (size_t i = 0; i < count; i++) {
    488             if (0 == glyphID[i]) {
    489                 return false;
    490             }
    491         }
    492         return true;
    493     }
    494 
    495     SkAutoGlyphCache autoCache(*this, nullptr, nullptr);
    496     SkGlyphCache*    cache = autoCache.getCache();
    497 
    498     switch (this->getTextEncoding()) {
    499         case SkPaint::kUTF8_TextEncoding: {
    500             const char* text = static_cast<const char*>(textData);
    501             const char* stop = text + byteLength;
    502             while (text < stop) {
    503                 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
    504                     return false;
    505                 }
    506             }
    507             break;
    508         }
    509         case SkPaint::kUTF16_TextEncoding: {
    510             const uint16_t* text = static_cast<const uint16_t*>(textData);
    511             const uint16_t* stop = text + (byteLength >> 1);
    512             while (text < stop) {
    513                 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
    514                     return false;
    515                 }
    516             }
    517             break;
    518         }
    519         case SkPaint::kUTF32_TextEncoding: {
    520             const int32_t* text = static_cast<const int32_t*>(textData);
    521             const int32_t* stop = text + (byteLength >> 2);
    522             while (text < stop) {
    523                 if (0 == cache->unicharToGlyph(*text++)) {
    524                     return false;
    525                 }
    526             }
    527             break;
    528         }
    529         default:
    530             SkDEBUGFAIL("unknown text encoding");
    531             return false;
    532     }
    533     return true;
    534 }
    535 
    536 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count, SkUnichar textData[]) const {
    537     if (count <= 0) {
    538         return;
    539     }
    540 
    541     SkASSERT(glyphs != nullptr);
    542     SkASSERT(textData != nullptr);
    543 
    544     SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
    545     SkAutoGlyphCache autoCache(*this, &props, nullptr);
    546     SkGlyphCache*    cache = autoCache.getCache();
    547 
    548     for (int index = 0; index < count; index++) {
    549         textData[index] = cache->glyphToUnichar(glyphs[index]);
    550     }
    551 }
    552 
    553 ///////////////////////////////////////////////////////////////////////////////
    554 
    555 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
    556                                               const char** text) {
    557     SkASSERT(cache != nullptr);
    558     SkASSERT(text != nullptr);
    559 
    560     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
    561 }
    562 
    563 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
    564                                                const char** text) {
    565     SkASSERT(cache != nullptr);
    566     SkASSERT(text != nullptr);
    567 
    568     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
    569 }
    570 
    571 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
    572                                                const char** text) {
    573     SkASSERT(cache != nullptr);
    574     SkASSERT(text != nullptr);
    575 
    576     const int32_t* ptr = *(const int32_t**)text;
    577     SkUnichar uni = *ptr++;
    578     *text = (const char*)ptr;
    579     return cache->getUnicharMetrics(uni);
    580 }
    581 
    582 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
    583                                                const char** text) {
    584     SkASSERT(cache != nullptr);
    585     SkASSERT(text != nullptr);
    586 
    587     const uint16_t* ptr = *(const uint16_t**)text;
    588     unsigned glyphID = *ptr;
    589     ptr += 1;
    590     *text = (const char*)ptr;
    591     return cache->getGlyphIDMetrics(glyphID);
    592 }
    593 
    594 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
    595                                               const char** text) {
    596     SkASSERT(cache != nullptr);
    597     SkASSERT(text != nullptr);
    598 
    599     return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
    600 }
    601 
    602 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
    603                                                const char** text) {
    604     SkASSERT(cache != nullptr);
    605     SkASSERT(text != nullptr);
    606 
    607     return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
    608 }
    609 
    610 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
    611                                                const char** text) {
    612     SkASSERT(cache != nullptr);
    613     SkASSERT(text != nullptr);
    614 
    615     const int32_t* ptr = *(const int32_t**)text;
    616     SkUnichar uni = *ptr++;
    617     *text = (const char*)ptr;
    618     return cache->getUnicharAdvance(uni);
    619 }
    620 
    621 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
    622                                                const char** text) {
    623     SkASSERT(cache != nullptr);
    624     SkASSERT(text != nullptr);
    625 
    626     const uint16_t* ptr = *(const uint16_t**)text;
    627     unsigned glyphID = *ptr;
    628     ptr += 1;
    629     *text = (const char*)ptr;
    630     return cache->getGlyphIDAdvance(glyphID);
    631 }
    632 
    633 SkPaint::GlyphCacheProc SkPaint::GetGlyphCacheProc(TextEncoding encoding,
    634                                                    bool isDevKern,
    635                                                    bool needFullMetrics) {
    636     static const GlyphCacheProc gGlyphCacheProcs[] = {
    637         sk_getMetrics_utf8_next,
    638         sk_getMetrics_utf16_next,
    639         sk_getMetrics_utf32_next,
    640         sk_getMetrics_glyph_next,
    641 
    642         sk_getAdvance_utf8_next,
    643         sk_getAdvance_utf16_next,
    644         sk_getAdvance_utf32_next,
    645         sk_getAdvance_glyph_next,
    646     };
    647 
    648     unsigned index = encoding;
    649 
    650     if (!needFullMetrics && !isDevKern) {
    651         index += 4;
    652     }
    653 
    654     SkASSERT(index < SK_ARRAY_COUNT(gGlyphCacheProcs));
    655     return gGlyphCacheProcs[index];
    656 }
    657 
    658 ///////////////////////////////////////////////////////////////////////////////
    659 
    660 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
    661 SkPaint::kDevKernText_Flag          |       \
    662 SkPaint::kLinearText_Flag           |       \
    663 SkPaint::kLCDRenderText_Flag        |       \
    664 SkPaint::kEmbeddedBitmapText_Flag   |       \
    665 SkPaint::kAutoHinting_Flag          |       \
    666 SkPaint::kGenA8FromLCD_Flag )
    667 
    668 SkScalar SkPaint::setupForAsPaths() {
    669     uint32_t flags = this->getFlags();
    670     // clear the flags we don't care about
    671     flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
    672     // set the flags we do care about
    673     flags |= SkPaint::kSubpixelText_Flag;
    674 
    675     this->setFlags(flags);
    676     this->setHinting(SkPaint::kNo_Hinting);
    677 
    678     SkScalar textSize = fTextSize;
    679     this->setTextSize(kCanonicalTextSizeForPaths);
    680     return textSize / kCanonicalTextSizeForPaths;
    681 }
    682 
    683 class SkCanonicalizePaint {
    684 public:
    685     SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
    686         if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
    687             SkPaint* p = fLazy.set(paint);
    688             fScale = p->setupForAsPaths();
    689             fPaint = p;
    690         }
    691     }
    692 
    693     const SkPaint& getPaint() const { return *fPaint; }
    694 
    695     /**
    696      *  Returns 0 if the paint was unmodified, or the scale factor need to
    697      *  the original textSize
    698      */
    699     SkScalar getScale() const { return fScale; }
    700 
    701 private:
    702     const SkPaint*   fPaint;
    703     SkScalar         fScale;
    704     SkTLazy<SkPaint> fLazy;
    705 };
    706 
    707 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
    708     bounds->set(SkIntToScalar(g.fLeft),
    709                 SkIntToScalar(g.fTop),
    710                 SkIntToScalar(g.fLeft + g.fWidth),
    711                 SkIntToScalar(g.fTop + g.fHeight));
    712 }
    713 
    714 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, SkScalar dx) {
    715     bounds->join(SkIntToScalar(g.fLeft) + dx,
    716                  SkIntToScalar(g.fTop),
    717                  SkIntToScalar(g.fLeft + g.fWidth) + dx,
    718                  SkIntToScalar(g.fTop + g.fHeight));
    719 }
    720 
    721 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, SkScalar dy) {
    722     bounds->join(SkIntToScalar(g.fLeft),
    723                  SkIntToScalar(g.fTop) + dy,
    724                  SkIntToScalar(g.fLeft + g.fWidth),
    725                  SkIntToScalar(g.fTop + g.fHeight) + dy);
    726 }
    727 
    728 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, SkScalar);
    729 
    730 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
    731 static SkScalar advance(const SkGlyph& glyph, int xyIndex) {
    732     SkASSERT(0 == xyIndex || 1 == xyIndex);
    733     return SkFloatToScalar((&glyph.fAdvanceX)[xyIndex]);
    734 }
    735 
    736 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
    737                                const char* text, size_t byteLength,
    738                                int* count, SkRect* bounds) const {
    739     SkASSERT(count);
    740     if (byteLength == 0) {
    741         *count = 0;
    742         if (bounds) {
    743             bounds->setEmpty();
    744         }
    745         return 0;
    746     }
    747 
    748     GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(this->getTextEncoding(),
    749                                                                this->isDevKernText(),
    750                                                                nullptr != bounds);
    751 
    752     int xyIndex;
    753     JoinBoundsProc joinBoundsProc;
    754     if (this->isVerticalText()) {
    755         xyIndex = 1;
    756         joinBoundsProc = join_bounds_y;
    757     } else {
    758         xyIndex = 0;
    759         joinBoundsProc = join_bounds_x;
    760     }
    761 
    762     int         n = 1;
    763     const char* stop = (const char*)text + byteLength;
    764     const SkGlyph* g = &glyphCacheProc(cache, &text);
    765     SkScalar x = advance(*g, xyIndex);
    766 
    767     if (nullptr == bounds) {
    768         if (this->isDevKernText()) {
    769             for (; text < stop; n++) {
    770                 const int rsb = g->fRsbDelta;
    771                 g = &glyphCacheProc(cache, &text);
    772                 x += SkAutoKern_Adjust(rsb, g->fLsbDelta) + advance(*g, xyIndex);
    773             }
    774         } else {
    775             for (; text < stop; n++) {
    776                 x += advance(glyphCacheProc(cache, &text), xyIndex);
    777             }
    778         }
    779     } else {
    780         set_bounds(*g, bounds);
    781         if (this->isDevKernText()) {
    782             for (; text < stop; n++) {
    783                 const int rsb = g->fRsbDelta;
    784                 g = &glyphCacheProc(cache, &text);
    785                 x += SkAutoKern_Adjust(rsb, g->fLsbDelta);
    786                 joinBoundsProc(*g, bounds, x);
    787                 x += advance(*g, xyIndex);
    788             }
    789         } else {
    790             for (; text < stop; n++) {
    791                 g = &glyphCacheProc(cache, &text);
    792                 joinBoundsProc(*g, bounds, x);
    793                 x += advance(*g, xyIndex);
    794             }
    795         }
    796     }
    797     SkASSERT(text == stop);
    798 
    799     *count = n;
    800     return x;
    801 }
    802 
    803 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
    804     const char* text = (const char*)textData;
    805     SkASSERT(text != nullptr || length == 0);
    806 
    807     SkCanonicalizePaint canon(*this);
    808     const SkPaint& paint = canon.getPaint();
    809     SkScalar scale = canon.getScale();
    810 
    811     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
    812     SkGlyphCache*       cache = autoCache.getCache();
    813 
    814     SkScalar width = 0;
    815 
    816     if (length > 0) {
    817         int tempCount;
    818 
    819         width = paint.measure_text(cache, text, length, &tempCount, bounds);
    820         if (scale) {
    821             width *= scale;
    822             if (bounds) {
    823                 bounds->fLeft *= scale;
    824                 bounds->fTop *= scale;
    825                 bounds->fRight *= scale;
    826                 bounds->fBottom *= scale;
    827             }
    828         }
    829     } else if (bounds) {
    830         // ensure that even if we don't measure_text we still update the bounds
    831         bounds->setEmpty();
    832     }
    833     return width;
    834 }
    835 
    836 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
    837                           SkScalar* measuredWidth) const {
    838     if (0 == length || 0 >= maxWidth) {
    839         if (measuredWidth) {
    840             *measuredWidth = 0;
    841         }
    842         return 0;
    843     }
    844 
    845     if (0 == fTextSize) {
    846         if (measuredWidth) {
    847             *measuredWidth = 0;
    848         }
    849         return length;
    850     }
    851 
    852     SkASSERT(textD != nullptr);
    853     const char* text = (const char*)textD;
    854     const char* stop = text + length;
    855 
    856     SkCanonicalizePaint canon(*this);
    857     const SkPaint& paint = canon.getPaint();
    858     SkScalar scale = canon.getScale();
    859 
    860     // adjust max in case we changed the textSize in paint
    861     if (scale) {
    862         maxWidth /= scale;
    863     }
    864 
    865     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
    866     SkGlyphCache*       cache = autoCache.getCache();
    867 
    868     GlyphCacheProc   glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
    869                                                                  paint.isDevKernText(),
    870                                                                  false);
    871     const int        xyIndex = paint.isVerticalText() ? 1 : 0;
    872     SkScalar         width = 0;
    873 
    874     if (this->isDevKernText()) {
    875         int rsb = 0;
    876         while (text < stop) {
    877             const char* curr = text;
    878             const SkGlyph& g = glyphCacheProc(cache, &text);
    879             SkScalar x = SkAutoKern_Adjust(rsb, g.fLsbDelta) + advance(g, xyIndex);
    880             if ((width += x) > maxWidth) {
    881                 width -= x;
    882                 text = curr;
    883                 break;
    884             }
    885             rsb = g.fRsbDelta;
    886         }
    887     } else {
    888         while (text < stop) {
    889             const char* curr = text;
    890             SkScalar x = advance(glyphCacheProc(cache, &text), xyIndex);
    891             if ((width += x) > maxWidth) {
    892                 width -= x;
    893                 text = curr;
    894                 break;
    895             }
    896         }
    897     }
    898 
    899     if (measuredWidth) {
    900         if (scale) {
    901             width *= scale;
    902         }
    903         *measuredWidth = width;
    904     }
    905 
    906     // return the number of bytes measured
    907     return text - stop + length;
    908 }
    909 
    910 ///////////////////////////////////////////////////////////////////////////////
    911 
    912 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
    913     *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
    914     return false;   // don't detach the cache
    915 }
    916 
    917 static void FontMetricsDescProc(SkTypeface* typeface, const SkScalerContextEffects& effects,
    918                                 const SkDescriptor* desc, void* context) {
    919     SkGlyphCache::VisitCache(typeface, effects, desc, FontMetricsCacheProc, context);
    920 }
    921 
    922 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
    923     SkCanonicalizePaint canon(*this);
    924     const SkPaint& paint = canon.getPaint();
    925     SkScalar scale = canon.getScale();
    926 
    927     SkMatrix zoomMatrix, *zoomPtr = nullptr;
    928     if (zoom) {
    929         zoomMatrix.setScale(zoom, zoom);
    930         zoomPtr = &zoomMatrix;
    931     }
    932 
    933     FontMetrics storage;
    934     if (nullptr == metrics) {
    935         metrics = &storage;
    936     }
    937 
    938     paint.descriptorProc(nullptr, kNone_ScalerContextFlags, zoomPtr, FontMetricsDescProc, metrics);
    939 
    940     if (scale) {
    941         SkPaintPriv::ScaleFontMetrics(metrics, scale);
    942     }
    943     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
    944 }
    945 
    946 ///////////////////////////////////////////////////////////////////////////////
    947 
    948 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
    949     bounds->set(g.fLeft * scale,
    950                 g.fTop * scale,
    951                 (g.fLeft + g.fWidth) * scale,
    952                 (g.fTop + g.fHeight) * scale);
    953 }
    954 
    955 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
    956                            SkScalar widths[], SkRect bounds[]) const {
    957     if (0 == byteLength) {
    958         return 0;
    959     }
    960 
    961     SkASSERT(textData);
    962 
    963     if (nullptr == widths && nullptr == bounds) {
    964         return this->countText(textData, byteLength);
    965     }
    966 
    967     SkCanonicalizePaint canon(*this);
    968     const SkPaint& paint = canon.getPaint();
    969     SkScalar scale = canon.getScale();
    970 
    971     SkAutoGlyphCache    autoCache(paint, nullptr, nullptr);
    972     SkGlyphCache*       cache = autoCache.getCache();
    973     GlyphCacheProc      glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
    974                                                                     paint.isDevKernText(),
    975                                                                     nullptr != bounds);
    976 
    977     const char* text = (const char*)textData;
    978     const char* stop = text + byteLength;
    979     int         count = 0;
    980     const int   xyIndex = paint.isVerticalText() ? 1 : 0;
    981 
    982     if (this->isDevKernText()) {
    983         // we adjust the widths returned here through auto-kerning
    984         SkAutoKern  autokern;
    985         SkScalar    prevWidth = 0;
    986 
    987         if (scale) {
    988             while (text < stop) {
    989                 const SkGlyph& g = glyphCacheProc(cache, &text);
    990                 if (widths) {
    991                     SkScalar adjust = autokern.adjust(g);
    992 
    993                     if (count > 0) {
    994                         *widths++ = (prevWidth + adjust) * scale;
    995                     }
    996                     prevWidth = advance(g, xyIndex);
    997                 }
    998                 if (bounds) {
    999                     set_bounds(g, bounds++, scale);
   1000                 }
   1001                 ++count;
   1002             }
   1003             if (count > 0 && widths) {
   1004                 *widths = prevWidth * scale;
   1005             }
   1006         } else {
   1007             while (text < stop) {
   1008                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1009                 if (widths) {
   1010                     SkScalar adjust = autokern.adjust(g);
   1011 
   1012                     if (count > 0) {
   1013                         *widths++ = prevWidth + adjust;
   1014                     }
   1015                     prevWidth = advance(g, xyIndex);
   1016                 }
   1017                 if (bounds) {
   1018                     set_bounds(g, bounds++);
   1019                 }
   1020                 ++count;
   1021             }
   1022             if (count > 0 && widths) {
   1023                 *widths = prevWidth;
   1024             }
   1025         }
   1026     } else {    // no devkern
   1027         if (scale) {
   1028             while (text < stop) {
   1029                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1030                 if (widths) {
   1031                     *widths++ = advance(g, xyIndex) * scale;
   1032                 }
   1033                 if (bounds) {
   1034                     set_bounds(g, bounds++, scale);
   1035                 }
   1036                 ++count;
   1037             }
   1038         } else {
   1039             while (text < stop) {
   1040                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1041                 if (widths) {
   1042                     *widths++ = advance(g, xyIndex);
   1043                 }
   1044                 if (bounds) {
   1045                     set_bounds(g, bounds++);
   1046                 }
   1047                 ++count;
   1048             }
   1049         }
   1050     }
   1051 
   1052     SkASSERT(text == stop);
   1053     return count;
   1054 }
   1055 
   1056 ///////////////////////////////////////////////////////////////////////////////
   1057 
   1058 #include "SkDraw.h"
   1059 
   1060 void SkPaint::getTextPath(const void* textData, size_t length,
   1061                           SkScalar x, SkScalar y, SkPath* path) const {
   1062     SkASSERT(length == 0 || textData != nullptr);
   1063 
   1064     const char* text = (const char*)textData;
   1065     if (text == nullptr || length == 0 || path == nullptr) {
   1066         return;
   1067     }
   1068 
   1069     SkTextToPathIter    iter(text, length, *this, false);
   1070     SkMatrix            matrix;
   1071     SkScalar            prevXPos = 0;
   1072 
   1073     matrix.setScale(iter.getPathScale(), iter.getPathScale());
   1074     matrix.postTranslate(x, y);
   1075     path->reset();
   1076 
   1077     SkScalar        xpos;
   1078     const SkPath*   iterPath;
   1079     while (iter.next(&iterPath, &xpos)) {
   1080         matrix.postTranslate(xpos - prevXPos, 0);
   1081         if (iterPath) {
   1082             path->addPath(*iterPath, matrix);
   1083         }
   1084         prevXPos = xpos;
   1085     }
   1086 }
   1087 
   1088 void SkPaint::getPosTextPath(const void* textData, size_t length,
   1089                              const SkPoint pos[], SkPath* path) const {
   1090     SkASSERT(length == 0 || textData != nullptr);
   1091 
   1092     const char* text = (const char*)textData;
   1093     if (text == nullptr || length == 0 || path == nullptr) {
   1094         return;
   1095     }
   1096 
   1097     SkTextToPathIter    iter(text, length, *this, false);
   1098     SkMatrix            matrix;
   1099     SkPoint             prevPos;
   1100     prevPos.set(0, 0);
   1101 
   1102     matrix.setScale(iter.getPathScale(), iter.getPathScale());
   1103     path->reset();
   1104 
   1105     unsigned int    i = 0;
   1106     const SkPath*   iterPath;
   1107     while (iter.next(&iterPath, nullptr)) {
   1108         matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
   1109         if (iterPath) {
   1110             path->addPath(*iterPath, matrix);
   1111         }
   1112         prevPos = pos[i];
   1113         i++;
   1114     }
   1115 }
   1116 
   1117 template <SkTextInterceptsIter::TextType TextType, typename Func>
   1118 int GetTextIntercepts(const SkPaint& paint, const void* text, size_t length,
   1119                       const SkScalar bounds[2], SkScalar* array, Func posMaker) {
   1120     SkASSERT(length == 0 || text != nullptr);
   1121     if (!length) {
   1122         return 0;
   1123     }
   1124 
   1125     const SkPoint pos0 = posMaker(0);
   1126     SkTextInterceptsIter iter(static_cast<const char*>(text), length, paint, bounds,
   1127                               pos0.x(), pos0.y(), TextType);
   1128 
   1129     int i = 0;
   1130     int count = 0;
   1131     while (iter.next(array, &count)) {
   1132         if (TextType == SkTextInterceptsIter::TextType::kPosText) {
   1133             const SkPoint pos = posMaker(++i);
   1134             iter.setPosition(pos.x(), pos.y());
   1135         }
   1136     }
   1137 
   1138     return count;
   1139 }
   1140 
   1141 int SkPaint::getTextIntercepts(const void* textData, size_t length,
   1142                                SkScalar x, SkScalar y, const SkScalar bounds[2],
   1143                                SkScalar* array) const {
   1144 
   1145     return GetTextIntercepts<SkTextInterceptsIter::TextType::kText>(
   1146         *this, textData, length, bounds, array, [&x, &y] (int) -> SkPoint {
   1147             return SkPoint::Make(x, y);
   1148         });
   1149 }
   1150 
   1151 int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[],
   1152                                   const SkScalar bounds[2], SkScalar* array) const {
   1153 
   1154     return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
   1155         *this, textData, length, bounds, array, [&pos] (int i) -> SkPoint {
   1156             return pos[i];
   1157         });
   1158 }
   1159 
   1160 int SkPaint::getPosTextHIntercepts(const void* textData, size_t length, const SkScalar xpos[],
   1161                                    SkScalar constY, const SkScalar bounds[2],
   1162                                    SkScalar* array) const {
   1163 
   1164     return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
   1165         *this, textData, length, bounds, array, [&xpos, &constY] (int i) -> SkPoint {
   1166             return SkPoint::Make(xpos[i], constY);
   1167         });
   1168 }
   1169 
   1170 int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
   1171                                    SkScalar* intervals) const {
   1172     int count = 0;
   1173     SkPaint runPaint(*this);
   1174 
   1175     SkTextBlobRunIterator it(blob);
   1176     while (!it.done()) {
   1177         it.applyFontToPaint(&runPaint);
   1178         const size_t runByteCount = it.glyphCount() * sizeof(SkGlyphID);
   1179         SkScalar* runIntervals = intervals ? intervals + count : nullptr;
   1180 
   1181         switch (it.positioning()) {
   1182         case SkTextBlob::kDefault_Positioning:
   1183             count += runPaint.getTextIntercepts(it.glyphs(), runByteCount, it.offset().x(),
   1184                                                 it.offset().y(), bounds, runIntervals);
   1185             break;
   1186         case SkTextBlob::kHorizontal_Positioning:
   1187             count += runPaint.getPosTextHIntercepts(it.glyphs(), runByteCount, it.pos(),
   1188                                                     it.offset().y(), bounds, runIntervals);
   1189             break;
   1190         case SkTextBlob::kFull_Positioning:
   1191             count += runPaint.getPosTextIntercepts(it.glyphs(), runByteCount,
   1192                                                    reinterpret_cast<const SkPoint*>(it.pos()),
   1193                                                    bounds, runIntervals);
   1194             break;
   1195         }
   1196 
   1197         it.next();
   1198     }
   1199 
   1200     return count;
   1201 }
   1202 
   1203 SkRect SkPaint::getFontBounds() const {
   1204     SkMatrix m;
   1205     m.setScale(fTextSize * fTextScaleX, fTextSize);
   1206     m.postSkew(fTextSkewX, 0);
   1207 
   1208     SkTypeface* typeface = this->getTypeface();
   1209     if (nullptr == typeface) {
   1210         typeface = SkTypeface::GetDefaultTypeface();
   1211     }
   1212 
   1213     SkRect bounds;
   1214     m.mapRect(&bounds, typeface->getBounds());
   1215     return bounds;
   1216 }
   1217 
   1218 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
   1219                             SkBinaryWriteBuffer* buffer) {
   1220     buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr));
   1221 }
   1222 
   1223 static SkMask::Format compute_mask_format(const SkPaint& paint) {
   1224     uint32_t flags = paint.getFlags();
   1225 
   1226     // Antialiasing being disabled trumps all other settings.
   1227     if (!(flags & SkPaint::kAntiAlias_Flag)) {
   1228         return SkMask::kBW_Format;
   1229     }
   1230 
   1231     if (flags & SkPaint::kLCDRenderText_Flag) {
   1232         return SkMask::kLCD16_Format;
   1233     }
   1234 
   1235     return SkMask::kA8_Format;
   1236 }
   1237 
   1238 // if linear-text is on, then we force hinting to be off (since that's sort of
   1239 // the point of linear-text.
   1240 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
   1241     SkPaint::Hinting h = paint.getHinting();
   1242     if (paint.isLinearText()) {
   1243         h = SkPaint::kNo_Hinting;
   1244     }
   1245     return h;
   1246 }
   1247 
   1248 // return true if the paint is just a single color (i.e. not a shader). If its
   1249 // a shader, then we can't compute a const luminance for it :(
   1250 static bool justAColor(const SkPaint& paint, SkColor* color) {
   1251     SkColor c = paint.getColor();
   1252 
   1253     SkShader* shader = paint.getShader();
   1254     if (shader && !shader->asLuminanceColor(&c)) {
   1255         return false;
   1256     }
   1257     if (paint.getColorFilter()) {
   1258         c = paint.getColorFilter()->filterColor(c);
   1259     }
   1260     if (color) {
   1261         *color = c;
   1262     }
   1263     return true;
   1264 }
   1265 
   1266 SkColor SkPaint::computeLuminanceColor() const {
   1267     SkColor c;
   1268     if (!justAColor(*this, &c)) {
   1269         c = SkColorSetRGB(0x7F, 0x80, 0x7F);
   1270     }
   1271     return c;
   1272 }
   1273 
   1274 #define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
   1275 
   1276 // Beyond this size, LCD doesn't appreciably improve quality, but it always
   1277 // cost more RAM and draws slower, so we set a cap.
   1278 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
   1279     #define SK_MAX_SIZE_FOR_LCDTEXT    48
   1280 #endif
   1281 
   1282 const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
   1283 
   1284 static bool too_big_for_lcd(const SkScalerContext::Rec& rec, bool checkPost2x2) {
   1285     if (checkPost2x2) {
   1286         SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
   1287                         rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
   1288         area *= rec.fTextSize * rec.fTextSize;
   1289         return area > gMaxSize2ForLCDText;
   1290     } else {
   1291         return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
   1292     }
   1293 }
   1294 
   1295 /*
   1296  *  Return the scalar with only limited fractional precision. Used to consolidate matrices
   1297  *  that vary only slightly when we create our key into the font cache, since the font scaler
   1298  *  typically returns the same looking resuts for tiny changes in the matrix.
   1299  */
   1300 static SkScalar sk_relax(SkScalar x) {
   1301     SkScalar n = SkScalarRoundToScalar(x * 1024);
   1302     return n / 1024.0f;
   1303 }
   1304 
   1305 void SkScalerContext::MakeRec(const SkPaint& paint,
   1306                               const SkSurfaceProps* surfaceProps,
   1307                               const SkMatrix* deviceMatrix,
   1308                               Rec* rec) {
   1309     SkASSERT(deviceMatrix == nullptr || !deviceMatrix->hasPerspective());
   1310 
   1311     SkTypeface* typeface = paint.getTypeface();
   1312     if (nullptr == typeface) {
   1313         typeface = SkTypeface::GetDefaultTypeface();
   1314     }
   1315     rec->fFontID = typeface->uniqueID();
   1316     rec->fTextSize = paint.getTextSize();
   1317     rec->fPreScaleX = paint.getTextScaleX();
   1318     rec->fPreSkewX  = paint.getTextSkewX();
   1319 
   1320     bool checkPost2x2 = false;
   1321 
   1322     if (deviceMatrix) {
   1323         const SkMatrix::TypeMask mask = deviceMatrix->getType();
   1324         if (mask & SkMatrix::kScale_Mask) {
   1325             rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
   1326             rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
   1327             checkPost2x2 = true;
   1328         } else {
   1329             rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
   1330         }
   1331         if (mask & SkMatrix::kAffine_Mask) {
   1332             rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
   1333             rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
   1334             checkPost2x2 = true;
   1335         } else {
   1336             rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
   1337         }
   1338     } else {
   1339         rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
   1340         rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
   1341     }
   1342 
   1343     SkPaint::Style  style = paint.getStyle();
   1344     SkScalar        strokeWidth = paint.getStrokeWidth();
   1345 
   1346     unsigned flags = 0;
   1347 
   1348     if (paint.isFakeBoldText()) {
   1349 #ifdef SK_USE_FREETYPE_EMBOLDEN
   1350         flags |= SkScalerContext::kEmbolden_Flag;
   1351 #else
   1352         SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
   1353                                                     kStdFakeBoldInterpKeys,
   1354                                                     kStdFakeBoldInterpValues,
   1355                                                     kStdFakeBoldInterpLength);
   1356         SkScalar extra = paint.getTextSize() * fakeBoldScale;
   1357 
   1358         if (style == SkPaint::kFill_Style) {
   1359             style = SkPaint::kStrokeAndFill_Style;
   1360             strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
   1361         } else {
   1362             strokeWidth += extra;
   1363         }
   1364 #endif
   1365     }
   1366 
   1367     if (paint.isDevKernText()) {
   1368         flags |= SkScalerContext::kDevKernText_Flag;
   1369     }
   1370 
   1371     if (style != SkPaint::kFill_Style && strokeWidth > 0) {
   1372         rec->fFrameWidth = strokeWidth;
   1373         rec->fMiterLimit = paint.getStrokeMiter();
   1374         rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
   1375         rec->fStrokeCap = SkToU8(paint.getStrokeCap());
   1376 
   1377         if (style == SkPaint::kStrokeAndFill_Style) {
   1378             flags |= SkScalerContext::kFrameAndFill_Flag;
   1379         }
   1380     } else {
   1381         rec->fFrameWidth = 0;
   1382         rec->fMiterLimit = 0;
   1383         rec->fStrokeJoin = 0;
   1384         rec->fStrokeCap = 0;
   1385     }
   1386 
   1387     rec->fMaskFormat = SkToU8(compute_mask_format(paint));
   1388 
   1389     if (SkMask::kLCD16_Format == rec->fMaskFormat) {
   1390         if (too_big_for_lcd(*rec, checkPost2x2)) {
   1391             rec->fMaskFormat = SkMask::kA8_Format;
   1392             flags |= SkScalerContext::kGenA8FromLCD_Flag;
   1393         } else {
   1394             SkPixelGeometry geometry = surfaceProps
   1395                                      ? surfaceProps->pixelGeometry()
   1396                                      : SkSurfacePropsDefaultPixelGeometry();
   1397             switch (geometry) {
   1398                 case kUnknown_SkPixelGeometry:
   1399                     // eeek, can't support LCD
   1400                     rec->fMaskFormat = SkMask::kA8_Format;
   1401                     flags |= SkScalerContext::kGenA8FromLCD_Flag;
   1402                     break;
   1403                 case kRGB_H_SkPixelGeometry:
   1404                     // our default, do nothing.
   1405                     break;
   1406                 case kBGR_H_SkPixelGeometry:
   1407                     flags |= SkScalerContext::kLCD_BGROrder_Flag;
   1408                     break;
   1409                 case kRGB_V_SkPixelGeometry:
   1410                     flags |= SkScalerContext::kLCD_Vertical_Flag;
   1411                     break;
   1412                 case kBGR_V_SkPixelGeometry:
   1413                     flags |= SkScalerContext::kLCD_Vertical_Flag;
   1414                     flags |= SkScalerContext::kLCD_BGROrder_Flag;
   1415                     break;
   1416             }
   1417         }
   1418     }
   1419 
   1420     if (paint.isEmbeddedBitmapText()) {
   1421         flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
   1422     }
   1423     if (paint.isSubpixelText()) {
   1424         flags |= SkScalerContext::kSubpixelPositioning_Flag;
   1425     }
   1426     if (paint.isAutohinted()) {
   1427         flags |= SkScalerContext::kForceAutohinting_Flag;
   1428     }
   1429     if (paint.isVerticalText()) {
   1430         flags |= SkScalerContext::kVertical_Flag;
   1431     }
   1432     if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
   1433         flags |= SkScalerContext::kGenA8FromLCD_Flag;
   1434     }
   1435     rec->fFlags = SkToU16(flags);
   1436 
   1437     // these modify fFlags, so do them after assigning fFlags
   1438     rec->setHinting(computeHinting(paint));
   1439 
   1440     rec->setLuminanceColor(paint.computeLuminanceColor());
   1441 
   1442     //For now always set the paint gamma equal to the device gamma.
   1443     //The math in SkMaskGamma can handle them being different,
   1444     //but it requires superluminous masks when
   1445     //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
   1446     rec->setDeviceGamma(SK_GAMMA_EXPONENT);
   1447     rec->setPaintGamma(SK_GAMMA_EXPONENT);
   1448 
   1449 #ifdef SK_GAMMA_CONTRAST
   1450     rec->setContrast(SK_GAMMA_CONTRAST);
   1451 #else
   1452     /**
   1453      * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
   1454      * With lower values small text appears washed out (though correctly so).
   1455      * With higher values lcd fringing is worse and the smoothing effect of
   1456      * partial coverage is diminished.
   1457      */
   1458     rec->setContrast(0.5f);
   1459 #endif
   1460 
   1461     rec->fReservedAlign = 0;
   1462 
   1463     /*  Allow the fonthost to modify our rec before we use it as a key into the
   1464         cache. This way if we're asking for something that they will ignore,
   1465         they can modify our rec up front, so we don't create duplicate cache
   1466         entries.
   1467      */
   1468     typeface->onFilterRec(rec);
   1469 
   1470     // be sure to call PostMakeRec(rec) before you actually use it!
   1471 }
   1472 
   1473 /**
   1474  * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
   1475  * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
   1476  * to hold it until the returned pointer is refed or forgotten.
   1477  */
   1478 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
   1479 
   1480 static SkMaskGamma* gLinearMaskGamma = nullptr;
   1481 static SkMaskGamma* gMaskGamma = nullptr;
   1482 static SkScalar gContrast = SK_ScalarMin;
   1483 static SkScalar gPaintGamma = SK_ScalarMin;
   1484 static SkScalar gDeviceGamma = SK_ScalarMin;
   1485 /**
   1486  * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
   1487  * the returned SkMaskGamma pointer is refed or forgotten.
   1488  */
   1489 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
   1490     gMaskGammaCacheMutex.assertHeld();
   1491     if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
   1492         if (nullptr == gLinearMaskGamma) {
   1493             gLinearMaskGamma = new SkMaskGamma;
   1494         }
   1495         return *gLinearMaskGamma;
   1496     }
   1497     if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
   1498         SkSafeUnref(gMaskGamma);
   1499         gMaskGamma = new SkMaskGamma(contrast, paintGamma, deviceGamma);
   1500         gContrast = contrast;
   1501         gPaintGamma = paintGamma;
   1502         gDeviceGamma = deviceGamma;
   1503     }
   1504     return *gMaskGamma;
   1505 }
   1506 
   1507 /**
   1508  *  We ensure that the rec is self-consistent and efficient (where possible)
   1509  */
   1510 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
   1511     /**
   1512      *  If we're asking for A8, we force the colorlum to be gray, since that
   1513      *  limits the number of unique entries, and the scaler will only look at
   1514      *  the lum of one of them.
   1515      */
   1516     switch (rec->fMaskFormat) {
   1517         case SkMask::kLCD16_Format: {
   1518             // filter down the luminance color to a finite number of bits
   1519             SkColor color = rec->getLuminanceColor();
   1520             rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
   1521             break;
   1522         }
   1523         case SkMask::kA8_Format: {
   1524             // filter down the luminance to a single component, since A8 can't
   1525             // use per-component information
   1526             SkColor color = rec->getLuminanceColor();
   1527             U8CPU lum = SkComputeLuminance(SkColorGetR(color),
   1528                                            SkColorGetG(color),
   1529                                            SkColorGetB(color));
   1530             // reduce to our finite number of bits
   1531             color = SkColorSetRGB(lum, lum, lum);
   1532             rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
   1533             break;
   1534         }
   1535         case SkMask::kBW_Format:
   1536             // No need to differentiate gamma or apply contrast if we're BW
   1537             rec->ignorePreBlend();
   1538             break;
   1539     }
   1540 }
   1541 
   1542 #define MIN_SIZE_FOR_EFFECT_BUFFER  1024
   1543 
   1544 #ifdef SK_DEBUG
   1545     #define TEST_DESC
   1546 #endif
   1547 
   1548 static void write_out_descriptor(SkDescriptor* desc, const SkScalerContext::Rec& rec,
   1549                                  const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
   1550                                  const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
   1551                                  const SkRasterizer* ra, SkBinaryWriteBuffer* raBuffer,
   1552                                  size_t descSize) {
   1553     desc->init();
   1554     desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1555 
   1556     if (pe) {
   1557         add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer);
   1558     }
   1559     if (mf) {
   1560         add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer);
   1561     }
   1562     if (ra) {
   1563         add_flattenable(desc, kRasterizer_SkDescriptorTag, raBuffer);
   1564     }
   1565 
   1566     desc->computeChecksum();
   1567 }
   1568 
   1569 static size_t fill_out_rec(const SkPaint& paint, SkScalerContext::Rec* rec,
   1570                            const SkSurfaceProps* surfaceProps,
   1571                            bool fakeGamma, bool boostContrast,
   1572                            const SkMatrix* deviceMatrix,
   1573                            const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
   1574                            const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
   1575                            const SkRasterizer* ra, SkBinaryWriteBuffer* raBuffer) {
   1576     SkScalerContext::MakeRec(paint, surfaceProps, deviceMatrix, rec);
   1577     if (!fakeGamma) {
   1578         rec->ignoreGamma();
   1579     }
   1580     if (!boostContrast) {
   1581         rec->setContrast(0);
   1582     }
   1583 
   1584     int entryCount = 1;
   1585     size_t descSize = sizeof(*rec);
   1586 
   1587     if (pe) {
   1588         pe->flatten(*peBuffer);
   1589         descSize += peBuffer->bytesWritten();
   1590         entryCount += 1;
   1591         rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
   1592         // seems like we could support kLCD as well at this point...
   1593     }
   1594     if (mf) {
   1595         mf->flatten(*mfBuffer);
   1596         descSize += mfBuffer->bytesWritten();
   1597         entryCount += 1;
   1598         rec->fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
   1599         /* Pre-blend is not currently applied to filtered text.
   1600            The primary filter is blur, for which contrast makes no sense,
   1601            and for which the destination guess error is more visible.
   1602            Also, all existing users of blur have calibrated for linear. */
   1603         rec->ignorePreBlend();
   1604     }
   1605     if (ra) {
   1606         ra->flatten(*raBuffer);
   1607         descSize += raBuffer->bytesWritten();
   1608         entryCount += 1;
   1609         rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
   1610     }
   1611 
   1612     ///////////////////////////////////////////////////////////////////////////
   1613     // Now that we're done tweaking the rec, call the PostMakeRec cleanup
   1614     SkScalerContext::PostMakeRec(paint, rec);
   1615 
   1616     descSize += SkDescriptor::ComputeOverhead(entryCount);
   1617     return descSize;
   1618 }
   1619 
   1620 #ifdef TEST_DESC
   1621 static void test_desc(const SkScalerContext::Rec& rec,
   1622                       const SkPathEffect* pe, SkBinaryWriteBuffer* peBuffer,
   1623                       const SkMaskFilter* mf, SkBinaryWriteBuffer* mfBuffer,
   1624                       const SkRasterizer* ra, SkBinaryWriteBuffer* raBuffer,
   1625                       const SkDescriptor* desc, size_t descSize) {
   1626     // Check that we completely write the bytes in desc (our key), and that
   1627     // there are no uninitialized bytes. If there were, then we would get
   1628     // false-misses (or worse, false-hits) in our fontcache.
   1629     //
   1630     // We do this buy filling 2 others, one with 0s and the other with 1s
   1631     // and create those, and then check that all 3 are identical.
   1632     SkAutoDescriptor    ad1(descSize);
   1633     SkAutoDescriptor    ad2(descSize);
   1634     SkDescriptor*       desc1 = ad1.getDesc();
   1635     SkDescriptor*       desc2 = ad2.getDesc();
   1636 
   1637     memset(desc1, 0x00, descSize);
   1638     memset(desc2, 0xFF, descSize);
   1639 
   1640     desc1->init();
   1641     desc2->init();
   1642     desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1643     desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1644 
   1645     if (pe) {
   1646         add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
   1647         add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
   1648     }
   1649     if (mf) {
   1650         add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
   1651         add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
   1652     }
   1653     if (ra) {
   1654         add_flattenable(desc1, kRasterizer_SkDescriptorTag, raBuffer);
   1655         add_flattenable(desc2, kRasterizer_SkDescriptorTag, raBuffer);
   1656     }
   1657 
   1658     SkASSERT(descSize == desc1->getLength());
   1659     SkASSERT(descSize == desc2->getLength());
   1660     desc1->computeChecksum();
   1661     desc2->computeChecksum();
   1662     SkASSERT(!memcmp(desc, desc1, descSize));
   1663     SkASSERT(!memcmp(desc, desc2, descSize));
   1664 }
   1665 #endif
   1666 
   1667 /* see the note on ignoreGamma on descriptorProc */
   1668 void SkPaint::getScalerContextDescriptor(SkScalerContextEffects* effects,
   1669                                          SkAutoDescriptor* ad,
   1670                                          const SkSurfaceProps& surfaceProps,
   1671                                          uint32_t scalerContextFlags,
   1672                                          const SkMatrix* deviceMatrix) const {
   1673     SkScalerContext::Rec    rec;
   1674 
   1675     SkPathEffect*   pe = this->getPathEffect();
   1676     SkMaskFilter*   mf = this->getMaskFilter();
   1677     SkRasterizer*   ra = this->getRasterizer();
   1678 
   1679     SkBinaryWriteBuffer   peBuffer, mfBuffer, raBuffer;
   1680     size_t descSize = fill_out_rec(*this, &rec, &surfaceProps,
   1681                                    SkToBool(scalerContextFlags & kFakeGamma_ScalerContextFlag),
   1682                                    SkToBool(scalerContextFlags & kBoostContrast_ScalerContextFlag),
   1683                                    deviceMatrix, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
   1684 
   1685     ad->reset(descSize);
   1686     SkDescriptor* desc = ad->getDesc();
   1687 
   1688     write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
   1689 
   1690     SkASSERT(descSize == desc->getLength());
   1691 
   1692 #ifdef TEST_DESC
   1693     test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
   1694 #endif
   1695 
   1696     effects->fPathEffect = pe;
   1697     effects->fMaskFilter = mf;
   1698     effects->fRasterizer = ra;
   1699 }
   1700 
   1701 /*
   1702  *  ignoreGamma tells us that the caller just wants metrics that are unaffected
   1703  *  by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
   1704  *  contrast = 0, luminanceColor = transparent black.
   1705  */
   1706 void SkPaint::descriptorProc(const SkSurfaceProps* surfaceProps,
   1707                              uint32_t scalerContextFlags,
   1708                              const SkMatrix* deviceMatrix,
   1709                              void (*proc)(SkTypeface*, const SkScalerContextEffects&,
   1710                                           const SkDescriptor*, void*),
   1711                              void* context) const {
   1712     SkScalerContext::Rec    rec;
   1713 
   1714     SkPathEffect*   pe = this->getPathEffect();
   1715     SkMaskFilter*   mf = this->getMaskFilter();
   1716     SkRasterizer*   ra = this->getRasterizer();
   1717 
   1718     SkBinaryWriteBuffer   peBuffer, mfBuffer, raBuffer;
   1719     size_t descSize = fill_out_rec(*this, &rec, surfaceProps,
   1720                                    SkToBool(scalerContextFlags & kFakeGamma_ScalerContextFlag),
   1721                                    SkToBool(scalerContextFlags & kBoostContrast_ScalerContextFlag),
   1722                                    deviceMatrix, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
   1723 
   1724     SkAutoDescriptor    ad(descSize);
   1725     SkDescriptor*       desc = ad.getDesc();
   1726 
   1727     write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
   1728 
   1729     SkASSERT(descSize == desc->getLength());
   1730 
   1731 #ifdef TEST_DESC
   1732     test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
   1733 #endif
   1734 
   1735     proc(fTypeface.get(), { pe, mf, ra }, desc, context);
   1736 }
   1737 
   1738 SkGlyphCache* SkPaint::detachCache(const SkSurfaceProps* surfaceProps,
   1739                                    uint32_t scalerContextFlags,
   1740                                    const SkMatrix* deviceMatrix) const {
   1741     SkGlyphCache* cache;
   1742     this->descriptorProc(surfaceProps, scalerContextFlags, deviceMatrix, DetachDescProc, &cache);
   1743     return cache;
   1744 }
   1745 
   1746 /**
   1747  * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
   1748  */
   1749 //static
   1750 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
   1751     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
   1752     const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
   1753                                                    rec.getPaintGamma(),
   1754                                                    rec.getDeviceGamma());
   1755     return maskGamma.preBlend(rec.getLuminanceColor());
   1756 }
   1757 
   1758 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
   1759                                         SkScalar deviceGamma, int* width, int* height) {
   1760     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
   1761     const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
   1762                                                    paintGamma,
   1763                                                    deviceGamma);
   1764 
   1765     maskGamma.getGammaTableDimensions(width, height);
   1766     size_t size = (*width)*(*height)*sizeof(uint8_t);
   1767 
   1768     return size;
   1769 }
   1770 
   1771 void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
   1772                                       void* data) {
   1773     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
   1774     const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
   1775                                                    paintGamma,
   1776                                                    deviceGamma);
   1777     int width, height;
   1778     maskGamma.getGammaTableDimensions(&width, &height);
   1779     size_t size = width*height*sizeof(uint8_t);
   1780     const uint8_t* gammaTables = maskGamma.getGammaTables();
   1781     memcpy(data, gammaTables, size);
   1782 }
   1783 
   1784 
   1785 ///////////////////////////////////////////////////////////////////////////////
   1786 
   1787 #include "SkStream.h"
   1788 
   1789 static uintptr_t asint(const void* p) {
   1790     return reinterpret_cast<uintptr_t>(p);
   1791 }
   1792 
   1793 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
   1794     SkASSERT(a == (uint8_t)a);
   1795     SkASSERT(b == (uint8_t)b);
   1796     SkASSERT(c == (uint8_t)c);
   1797     SkASSERT(d == (uint8_t)d);
   1798     return (a << 24) | (b << 16) | (c << 8) | d;
   1799 }
   1800 
   1801 #ifdef SK_DEBUG
   1802     static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
   1803         SkASSERT(bitCount > 0 && bitCount <= 32);
   1804         uint32_t mask = ~0U;
   1805         mask >>= (32 - bitCount);
   1806         SkASSERT(0 == (value & ~mask));
   1807     }
   1808 #else
   1809     #define ASSERT_FITS_IN(value, bitcount)
   1810 #endif
   1811 
   1812 enum FlatFlags {
   1813     kHasTypeface_FlatFlag = 0x1,
   1814     kHasEffects_FlatFlag  = 0x2,
   1815 
   1816     kFlatFlagMask         = 0x3,
   1817 };
   1818 
   1819 enum BitsPerField {
   1820     kFlags_BPF  = 16,
   1821     kHint_BPF   = 2,
   1822     kAlign_BPF  = 2,
   1823     kFilter_BPF = 2,
   1824     kFlatFlags_BPF  = 3,
   1825 };
   1826 
   1827 static inline int BPF_Mask(int bits) {
   1828     return (1 << bits) - 1;
   1829 }
   1830 
   1831 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
   1832                                  unsigned filter, unsigned flatFlags) {
   1833     ASSERT_FITS_IN(flags, kFlags_BPF);
   1834     ASSERT_FITS_IN(hint, kHint_BPF);
   1835     ASSERT_FITS_IN(align, kAlign_BPF);
   1836     ASSERT_FITS_IN(filter, kFilter_BPF);
   1837     ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
   1838 
   1839     // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
   1840     // add more bits in the future.
   1841     return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
   1842 }
   1843 
   1844 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
   1845     paint->setFlags(packed >> 16);
   1846     paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
   1847     paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
   1848     paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
   1849     return (FlatFlags)(packed & kFlatFlagMask);
   1850 }
   1851 
   1852 /*  To save space/time, we analyze the paint, and write a truncated version of
   1853     it if there are not tricky elements like shaders, etc.
   1854  */
   1855 void SkPaint::flatten(SkWriteBuffer& buffer) const {
   1856     uint8_t flatFlags = 0;
   1857     if (this->getTypeface()) {
   1858         flatFlags |= kHasTypeface_FlatFlag;
   1859     }
   1860     if (asint(this->getPathEffect()) |
   1861         asint(this->getShader()) |
   1862         asint(this->getMaskFilter()) |
   1863         asint(this->getColorFilter()) |
   1864         asint(this->getRasterizer()) |
   1865         asint(this->getLooper()) |
   1866         asint(this->getImageFilter())) {
   1867         flatFlags |= kHasEffects_FlatFlag;
   1868     }
   1869 
   1870     buffer.writeScalar(this->getTextSize());
   1871     buffer.writeScalar(this->getTextScaleX());
   1872     buffer.writeScalar(this->getTextSkewX());
   1873     buffer.writeScalar(this->getStrokeWidth());
   1874     buffer.writeScalar(this->getStrokeMiter());
   1875     buffer.writeColor(this->getColor());
   1876 
   1877     buffer.writeUInt(pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
   1878                                       this->getFilterQuality(), flatFlags));
   1879     buffer.writeUInt(pack_4(this->getStrokeCap(), this->getStrokeJoin(),
   1880                             (this->getStyle() << 4) | this->getTextEncoding(),
   1881                             fBlendMode));
   1882 
   1883     // now we're done with ptr and the (pre)reserved space. If we need to write
   1884     // additional fields, use the buffer directly
   1885     if (flatFlags & kHasTypeface_FlatFlag) {
   1886         buffer.writeTypeface(this->getTypeface());
   1887     }
   1888     if (flatFlags & kHasEffects_FlatFlag) {
   1889         buffer.writeFlattenable(this->getPathEffect());
   1890         buffer.writeFlattenable(this->getShader());
   1891         buffer.writeFlattenable(this->getMaskFilter());
   1892         buffer.writeFlattenable(this->getColorFilter());
   1893         buffer.writeFlattenable(this->getRasterizer());
   1894         buffer.writeFlattenable(this->getLooper());
   1895         buffer.writeFlattenable(this->getImageFilter());
   1896     }
   1897 }
   1898 
   1899 void SkPaint::unflatten(SkReadBuffer& buffer) {
   1900     this->setTextSize(buffer.readScalar());
   1901     this->setTextScaleX(buffer.readScalar());
   1902     this->setTextSkewX(buffer.readScalar());
   1903     this->setStrokeWidth(buffer.readScalar());
   1904     this->setStrokeMiter(buffer.readScalar());
   1905     this->setColor(buffer.readColor());
   1906 
   1907     unsigned flatFlags = unpack_paint_flags(this, buffer.readUInt());
   1908 
   1909     uint32_t tmp = buffer.readUInt();
   1910     this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
   1911     this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
   1912     if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) {
   1913         this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
   1914         this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
   1915     } else {
   1916         this->setStyle(static_cast<Style>((tmp >> 12) & 0xF));
   1917         this->setTextEncoding(static_cast<TextEncoding>((tmp >> 8) & 0xF));
   1918         this->setBlendMode((SkBlendMode)(tmp & 0xFF));
   1919     }
   1920 
   1921     if (flatFlags & kHasTypeface_FlatFlag) {
   1922         this->setTypeface(buffer.readTypeface());
   1923     } else {
   1924         this->setTypeface(nullptr);
   1925     }
   1926 
   1927     if (flatFlags & kHasEffects_FlatFlag) {
   1928         this->setPathEffect(buffer.readPathEffect());
   1929         this->setShader(buffer.readShader());
   1930         if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) {
   1931             sk_sp<SkXfermode> xfer = buffer.readXfermode();
   1932             this->setBlendMode(xfer ? xfer->blend() : SkBlendMode::kSrcOver);
   1933         }
   1934         this->setMaskFilter(buffer.readMaskFilter());
   1935         this->setColorFilter(buffer.readColorFilter());
   1936         this->setRasterizer(buffer.readRasterizer());
   1937         this->setLooper(buffer.readDrawLooper());
   1938         this->setImageFilter(buffer.readImageFilter());
   1939 
   1940         if (buffer.isVersionLT(SkReadBuffer::kAnnotationsMovedToCanvas_Version)) {
   1941             // We used to store annotations here (string+skdata) if this bool was true
   1942             if (buffer.readBool()) {
   1943                 // Annotations have moved to drawAnnotation, so we just drop this one on the floor.
   1944                 SkString key;
   1945                 buffer.readString(&key);
   1946                 (void)buffer.readByteArrayAsData();
   1947             }
   1948         }
   1949     } else {
   1950         this->setPathEffect(nullptr);
   1951         this->setShader(nullptr);
   1952         this->setMaskFilter(nullptr);
   1953         this->setColorFilter(nullptr);
   1954         this->setRasterizer(nullptr);
   1955         this->setLooper(nullptr);
   1956         this->setImageFilter(nullptr);
   1957     }
   1958 }
   1959 
   1960 ///////////////////////////////////////////////////////////////////////////////
   1961 
   1962 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
   1963                           SkScalar resScale) const {
   1964     SkStrokeRec rec(*this, resScale);
   1965 
   1966     const SkPath* srcPtr = &src;
   1967     SkPath tmpPath;
   1968 
   1969     if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
   1970         srcPtr = &tmpPath;
   1971     }
   1972 
   1973     if (!rec.applyToPath(dst, *srcPtr)) {
   1974         if (srcPtr == &tmpPath) {
   1975             // If path's were copy-on-write, this trick would not be needed.
   1976             // As it is, we want to save making a deep-copy from tmpPath -> dst
   1977             // since we know we're just going to delete tmpPath when we return,
   1978             // so the swap saves that copy.
   1979             dst->swap(tmpPath);
   1980         } else {
   1981             *dst = *srcPtr;
   1982         }
   1983     }
   1984     return !rec.isHairlineStyle();
   1985 }
   1986 
   1987 bool SkPaint::canComputeFastBounds() const {
   1988     if (this->getLooper()) {
   1989         return this->getLooper()->canComputeFastBounds(*this);
   1990     }
   1991     if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) {
   1992         return false;
   1993     }
   1994     return !this->getRasterizer();
   1995 }
   1996 
   1997 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
   1998                                            SkRect* storage,
   1999                                            Style style) const {
   2000     SkASSERT(storage);
   2001 
   2002     const SkRect* src = &origSrc;
   2003 
   2004     if (this->getLooper()) {
   2005         SkASSERT(this->getLooper()->canComputeFastBounds(*this));
   2006         this->getLooper()->computeFastBounds(*this, *src, storage);
   2007         return *storage;
   2008     }
   2009 
   2010     SkRect tmpSrc;
   2011     if (this->getPathEffect()) {
   2012         this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
   2013         src = &tmpSrc;
   2014     }
   2015 
   2016     SkScalar radius = SkStrokeRec::GetInflationRadius(*this, style);
   2017     *storage = src->makeOutset(radius, radius);
   2018 
   2019     if (this->getMaskFilter()) {
   2020         this->getMaskFilter()->computeFastBounds(*storage, storage);
   2021     }
   2022 
   2023     if (this->getImageFilter()) {
   2024         *storage = this->getImageFilter()->computeFastBounds(*storage);
   2025     }
   2026 
   2027     return *storage;
   2028 }
   2029 
   2030 #ifndef SK_IGNORE_TO_STRING
   2031 
   2032 void SkPaint::toString(SkString* str) const {
   2033     str->append("<dl><dt>SkPaint:</dt><dd><dl>");
   2034 
   2035     SkTypeface* typeface = this->getTypeface();
   2036     if (typeface) {
   2037         SkDynamicMemoryWStream ostream;
   2038         typeface->serialize(&ostream);
   2039         std::unique_ptr<SkStreamAsset> istream(ostream.detachAsStream());
   2040 
   2041         SkFontDescriptor descriptor;
   2042         if (!SkFontDescriptor::Deserialize(istream.get(), &descriptor)) {
   2043             str->append("<dt>FontDescriptor deserialization failed</dt>");
   2044         } else {
   2045             str->append("<dt>Font Family Name:</dt><dd>");
   2046             str->append(descriptor.getFamilyName());
   2047             str->append("</dd><dt>Font Full Name:</dt><dd>");
   2048             str->append(descriptor.getFullName());
   2049             str->append("</dd><dt>Font PS Name:</dt><dd>");
   2050             str->append(descriptor.getPostscriptName());
   2051             str->append("</dd>");
   2052         }
   2053     }
   2054 
   2055     str->append("<dt>TextSize:</dt><dd>");
   2056     str->appendScalar(this->getTextSize());
   2057     str->append("</dd>");
   2058 
   2059     str->append("<dt>TextScaleX:</dt><dd>");
   2060     str->appendScalar(this->getTextScaleX());
   2061     str->append("</dd>");
   2062 
   2063     str->append("<dt>TextSkewX:</dt><dd>");
   2064     str->appendScalar(this->getTextSkewX());
   2065     str->append("</dd>");
   2066 
   2067     SkPathEffect* pathEffect = this->getPathEffect();
   2068     if (pathEffect) {
   2069         str->append("<dt>PathEffect:</dt><dd>");
   2070         pathEffect->toString(str);
   2071         str->append("</dd>");
   2072     }
   2073 
   2074     SkShader* shader = this->getShader();
   2075     if (shader) {
   2076         str->append("<dt>Shader:</dt><dd>");
   2077         shader->toString(str);
   2078         str->append("</dd>");
   2079     }
   2080 
   2081     if (!this->isSrcOver()) {
   2082         str->appendf("<dt>Xfermode:</dt><dd>%d</dd>", fBlendMode);
   2083     }
   2084 
   2085     SkMaskFilter* maskFilter = this->getMaskFilter();
   2086     if (maskFilter) {
   2087         str->append("<dt>MaskFilter:</dt><dd>");
   2088         maskFilter->toString(str);
   2089         str->append("</dd>");
   2090     }
   2091 
   2092     SkColorFilter* colorFilter = this->getColorFilter();
   2093     if (colorFilter) {
   2094         str->append("<dt>ColorFilter:</dt><dd>");
   2095         colorFilter->toString(str);
   2096         str->append("</dd>");
   2097     }
   2098 
   2099     SkRasterizer* rasterizer = this->getRasterizer();
   2100     if (rasterizer) {
   2101         str->append("<dt>Rasterizer:</dt><dd>");
   2102         str->append("</dd>");
   2103     }
   2104 
   2105     SkDrawLooper* looper = this->getLooper();
   2106     if (looper) {
   2107         str->append("<dt>DrawLooper:</dt><dd>");
   2108         looper->toString(str);
   2109         str->append("</dd>");
   2110     }
   2111 
   2112     SkImageFilter* imageFilter = this->getImageFilter();
   2113     if (imageFilter) {
   2114         str->append("<dt>ImageFilter:</dt><dd>");
   2115         imageFilter->toString(str);
   2116         str->append("</dd>");
   2117     }
   2118 
   2119     str->append("<dt>Color:</dt><dd>0x");
   2120     SkColor color = this->getColor();
   2121     str->appendHex(color);
   2122     str->append("</dd>");
   2123 
   2124     str->append("<dt>Stroke Width:</dt><dd>");
   2125     str->appendScalar(this->getStrokeWidth());
   2126     str->append("</dd>");
   2127 
   2128     str->append("<dt>Stroke Miter:</dt><dd>");
   2129     str->appendScalar(this->getStrokeMiter());
   2130     str->append("</dd>");
   2131 
   2132     str->append("<dt>Flags:</dt><dd>(");
   2133     if (this->getFlags()) {
   2134         bool needSeparator = false;
   2135         SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
   2136         SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
   2137         SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
   2138         SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
   2139         SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
   2140         SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
   2141         SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
   2142         SkAddFlagToString(str, this->isEmbeddedBitmapText(),
   2143                           "EmbeddedBitmapText", &needSeparator);
   2144         SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
   2145         SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
   2146         SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
   2147                           "GenA8FromLCD", &needSeparator);
   2148     } else {
   2149         str->append("None");
   2150     }
   2151     str->append(")</dd>");
   2152 
   2153     str->append("<dt>FilterLevel:</dt><dd>");
   2154     static const char* gFilterQualityStrings[] = { "None", "Low", "Medium", "High" };
   2155     str->append(gFilterQualityStrings[this->getFilterQuality()]);
   2156     str->append("</dd>");
   2157 
   2158     str->append("<dt>TextAlign:</dt><dd>");
   2159     static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
   2160     str->append(gTextAlignStrings[this->getTextAlign()]);
   2161     str->append("</dd>");
   2162 
   2163     str->append("<dt>CapType:</dt><dd>");
   2164     static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
   2165     str->append(gStrokeCapStrings[this->getStrokeCap()]);
   2166     str->append("</dd>");
   2167 
   2168     str->append("<dt>JoinType:</dt><dd>");
   2169     static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
   2170     str->append(gJoinStrings[this->getStrokeJoin()]);
   2171     str->append("</dd>");
   2172 
   2173     str->append("<dt>Style:</dt><dd>");
   2174     static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
   2175     str->append(gStyleStrings[this->getStyle()]);
   2176     str->append("</dd>");
   2177 
   2178     str->append("<dt>TextEncoding:</dt><dd>");
   2179     static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
   2180     str->append(gTextEncodingStrings[this->getTextEncoding()]);
   2181     str->append("</dd>");
   2182 
   2183     str->append("<dt>Hinting:</dt><dd>");
   2184     static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
   2185     str->append(gHintingStrings[this->getHinting()]);
   2186     str->append("</dd>");
   2187 
   2188     str->append("</dd></dl></dl>");
   2189 }
   2190 #endif
   2191 
   2192 ///////////////////////////////////////////////////////////////////////////////
   2193 
   2194 static bool has_thick_frame(const SkPaint& paint) {
   2195     return  paint.getStrokeWidth() > 0 &&
   2196             paint.getStyle() != SkPaint::kFill_Style;
   2197 }
   2198 
   2199 SkTextBaseIter::SkTextBaseIter(const char text[], size_t length,
   2200                                    const SkPaint& paint,
   2201                                    bool applyStrokeAndPathEffects)
   2202     : fPaint(paint) {
   2203     fGlyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(),
   2204                                                  paint.isDevKernText(),
   2205                                                  true);
   2206 
   2207     fPaint.setLinearText(true);
   2208     fPaint.setMaskFilter(nullptr);   // don't want this affecting our path-cache lookup
   2209 
   2210     if (fPaint.getPathEffect() == nullptr && !has_thick_frame(fPaint)) {
   2211         applyStrokeAndPathEffects = false;
   2212     }
   2213 
   2214     // can't use our canonical size if we need to apply patheffects
   2215     if (fPaint.getPathEffect() == nullptr) {
   2216         fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
   2217         fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
   2218         if (has_thick_frame(fPaint)) {
   2219             fPaint.setStrokeWidth(fPaint.getStrokeWidth() / fScale);
   2220         }
   2221     } else {
   2222         fScale = SK_Scalar1;
   2223     }
   2224 
   2225     if (!applyStrokeAndPathEffects) {
   2226         fPaint.setStyle(SkPaint::kFill_Style);
   2227         fPaint.setPathEffect(nullptr);
   2228     }
   2229 
   2230     // SRGBTODO: Is this correct?
   2231     fCache = fPaint.detachCache(nullptr, SkPaint::kFakeGammaAndBoostContrast_ScalerContextFlags,
   2232                                 nullptr);
   2233 
   2234     SkPaint::Style  style = SkPaint::kFill_Style;
   2235     sk_sp<SkPathEffect> pe;
   2236 
   2237     if (!applyStrokeAndPathEffects) {
   2238         style = paint.getStyle();       // restore
   2239         pe = paint.refPathEffect();     // restore
   2240     }
   2241     fPaint.setStyle(style);
   2242     fPaint.setPathEffect(pe);
   2243     fPaint.setMaskFilter(paint.refMaskFilter());    // restore
   2244 
   2245     // now compute fXOffset if needed
   2246 
   2247     SkScalar xOffset = 0;
   2248     if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
   2249         int      count;
   2250         SkScalar width = fPaint.measure_text(fCache, text, length, &count, nullptr) * fScale;
   2251         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   2252             width = SkScalarHalf(width);
   2253         }
   2254         xOffset = -width;
   2255     }
   2256     fXPos = xOffset;
   2257     fPrevAdvance = 0;
   2258 
   2259     fText = text;
   2260     fStop = text + length;
   2261 
   2262     fXYIndex = paint.isVerticalText() ? 1 : 0;
   2263 }
   2264 
   2265 SkTextBaseIter::~SkTextBaseIter() {
   2266     SkGlyphCache::AttachCache(fCache);
   2267 }
   2268 
   2269 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
   2270     if (fText < fStop) {
   2271         const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
   2272 
   2273         fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
   2274         fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
   2275 
   2276         if (glyph.fWidth) {
   2277             if (path) {
   2278                 *path = fCache->findPath(glyph);
   2279             }
   2280         } else {
   2281             if (path) {
   2282                 *path = nullptr;
   2283             }
   2284         }
   2285         if (xpos) {
   2286             *xpos = fXPos;
   2287         }
   2288         return true;
   2289     }
   2290     return false;
   2291 }
   2292 
   2293 bool SkTextInterceptsIter::next(SkScalar* array, int* count) {
   2294     const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
   2295     fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
   2296     fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
   2297     if (fCache->findPath(glyph)) {
   2298         fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex),
   2299                 const_cast<SkGlyph*>(&glyph), array, count);
   2300     }
   2301     return fText < fStop;
   2302 }
   2303 
   2304 ///////////////////////////////////////////////////////////////////////////////
   2305 
   2306 // return true if the filter exists, and may affect alpha
   2307 static bool affects_alpha(const SkColorFilter* cf) {
   2308     return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
   2309 }
   2310 
   2311 // return true if the filter exists, and may affect alpha
   2312 static bool affects_alpha(const SkImageFilter* imf) {
   2313     // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
   2314     // ala colorfilters
   2315     return imf != nullptr;
   2316 }
   2317 
   2318 bool SkPaint::nothingToDraw() const {
   2319     if (fDrawLooper) {
   2320         return false;
   2321     }
   2322     switch ((SkBlendMode)fBlendMode) {
   2323         case SkBlendMode::kSrcOver:
   2324         case SkBlendMode::kSrcATop:
   2325         case SkBlendMode::kDstOut:
   2326         case SkBlendMode::kDstOver:
   2327         case SkBlendMode::kPlus:
   2328             if (0 == this->getAlpha()) {
   2329                 return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
   2330             }
   2331             break;
   2332         case SkBlendMode::kDst:
   2333             return true;
   2334         default:
   2335             break;
   2336     }
   2337     return false;
   2338 }
   2339 
   2340 uint32_t SkPaint::getHash() const {
   2341     // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
   2342     // so fBitfields should be 10 pointers and 6 32-bit values from the start.
   2343     static_assert(offsetof(SkPaint, fBitfields) == 8 * sizeof(void*) + 7 * sizeof(uint32_t),
   2344                   "SkPaint_notPackedTightly");
   2345     return SkOpts::hash(reinterpret_cast<const uint32_t*>(this),
   2346                         offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
   2347 }
   2348