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