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