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