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