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