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