Home | History | Annotate | Download | only in core
      1 /* libs/graphics/sgl/SkPaint.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkPaint.h"
     19 #include "SkColorFilter.h"
     20 #include "SkDrawLooper.h"
     21 #include "SkFontHost.h"
     22 #include "SkMaskFilter.h"
     23 #include "SkPathEffect.h"
     24 #include "SkRasterizer.h"
     25 #include "SkShader.h"
     26 #include "SkScalar.h"
     27 #include "SkScalerContext.h"
     28 #include "SkStroke.h"
     29 #include "SkTextFormatParams.h"
     30 #include "SkTypeface.h"
     31 #include "SkXfermode.h"
     32 #include "SkAutoKern.h"
     33 
     34 #define SK_DefaultTextSize      SkIntToScalar(12)
     35 
     36 #define SK_DefaultFlags         0   //(kNativeHintsText_Flag)
     37 
     38 #ifdef ANDROID
     39 #define GEN_ID_INC                  fGenerationID++
     40 #define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
     41 #else
     42 #define GEN_ID_INC
     43 #define GEN_ID_INC_EVAL(expression)
     44 #endif
     45 
     46 SkPaint::SkPaint() {
     47     // since we may have padding, we zero everything so that our memcmp() call
     48     // in operator== will work correctly.
     49     // with this, we can skip 0 and null individual initializations
     50     sk_bzero(this, sizeof(*this));
     51 
     52 #if 0   // not needed with the bzero call above
     53     fTypeface   = NULL;
     54     fTextSkewX  = 0;
     55     fPathEffect  = NULL;
     56     fShader      = NULL;
     57     fXfermode    = NULL;
     58     fMaskFilter  = NULL;
     59     fColorFilter = NULL;
     60     fRasterizer  = NULL;
     61     fLooper      = NULL;
     62     fWidth      = 0;
     63 #endif
     64 
     65     fTextSize   = SK_DefaultTextSize;
     66     fTextScaleX = SK_Scalar1;
     67     fColor      = SK_ColorBLACK;
     68     fMiterLimit = SK_DefaultMiterLimit;
     69     fFlags      = SK_DefaultFlags;
     70     fCapType    = kDefault_Cap;
     71     fJoinType   = kDefault_Join;
     72     fTextAlign  = kLeft_Align;
     73     fStyle      = kFill_Style;
     74     fTextEncoding = kUTF8_TextEncoding;
     75     fHinting    = kNormal_Hinting;
     76 #ifdef ANDROID
     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 }
     93 
     94 SkPaint::~SkPaint() {
     95     SkSafeUnref(fTypeface);
     96     SkSafeUnref(fPathEffect);
     97     SkSafeUnref(fShader);
     98     SkSafeUnref(fXfermode);
     99     SkSafeUnref(fMaskFilter);
    100     SkSafeUnref(fColorFilter);
    101     SkSafeUnref(fRasterizer);
    102     SkSafeUnref(fLooper);
    103 }
    104 
    105 SkPaint& SkPaint::operator=(const SkPaint& src) {
    106     SkASSERT(&src);
    107 
    108     SkSafeRef(src.fTypeface);
    109     SkSafeRef(src.fPathEffect);
    110     SkSafeRef(src.fShader);
    111     SkSafeRef(src.fXfermode);
    112     SkSafeRef(src.fMaskFilter);
    113     SkSafeRef(src.fColorFilter);
    114     SkSafeRef(src.fRasterizer);
    115     SkSafeRef(src.fLooper);
    116 
    117     SkSafeUnref(fTypeface);
    118     SkSafeUnref(fPathEffect);
    119     SkSafeUnref(fShader);
    120     SkSafeUnref(fXfermode);
    121     SkSafeUnref(fMaskFilter);
    122     SkSafeUnref(fColorFilter);
    123     SkSafeUnref(fRasterizer);
    124     SkSafeUnref(fLooper);
    125 
    126 #ifdef ANDROID
    127     uint32_t oldGenerationID = fGenerationID;
    128 #endif
    129     memcpy(this, &src, sizeof(src));
    130 #ifdef ANDROID
    131     fGenerationID = oldGenerationID + 1;
    132 #endif
    133 
    134     return *this;
    135 }
    136 
    137 int operator==(const SkPaint& a, const SkPaint& b) {
    138     return memcmp(&a, &b, sizeof(a)) == 0;
    139 }
    140 
    141 void SkPaint::reset() {
    142     SkPaint init;
    143 
    144 #ifdef ANDROID
    145     uint32_t oldGenerationID = fGenerationID;
    146 #endif
    147     *this = init;
    148 #ifdef ANDROID
    149     fGenerationID = oldGenerationID + 1;
    150 #endif
    151 }
    152 
    153 #ifdef ANDROID
    154 uint32_t SkPaint::getGenerationID() const {
    155     return fGenerationID;
    156 }
    157 #endif
    158 
    159 void SkPaint::setHinting(Hinting hintingLevel) {
    160     GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
    161     fHinting = hintingLevel;
    162 }
    163 
    164 void SkPaint::setFlags(uint32_t flags) {
    165     GEN_ID_INC_EVAL(fFlags != flags);
    166     fFlags = flags;
    167 }
    168 
    169 void SkPaint::setAntiAlias(bool doAA) {
    170     GEN_ID_INC_EVAL(doAA != isAntiAlias());
    171     this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
    172 }
    173 
    174 void SkPaint::setDither(bool doDither) {
    175     GEN_ID_INC_EVAL(doDither != isDither());
    176     this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
    177 }
    178 
    179 void SkPaint::setSubpixelText(bool doSubpixel) {
    180     GEN_ID_INC_EVAL(doSubpixel != isSubpixelText());
    181     this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
    182 }
    183 
    184 void SkPaint::setLCDRenderText(bool doLCDRender) {
    185     GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText());
    186     this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
    187 }
    188 
    189 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
    190     GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText());
    191     this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
    192 }
    193 
    194 void SkPaint::setAutohinted(bool useAutohinter) {
    195     GEN_ID_INC_EVAL(useAutohinter != isAutohinted());
    196     this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
    197 }
    198 
    199 void SkPaint::setLinearText(bool doLinearText) {
    200     GEN_ID_INC_EVAL(doLinearText != isLinearText());
    201     this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
    202 }
    203 
    204 void SkPaint::setUnderlineText(bool doUnderline) {
    205     GEN_ID_INC_EVAL(doUnderline != isUnderlineText());
    206     this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
    207 }
    208 
    209 void SkPaint::setStrikeThruText(bool doStrikeThru) {
    210     GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText());
    211     this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
    212 }
    213 
    214 void SkPaint::setFakeBoldText(bool doFakeBold) {
    215     GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText());
    216     this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
    217 }
    218 
    219 void SkPaint::setDevKernText(bool doDevKern) {
    220     GEN_ID_INC_EVAL(doDevKern != isDevKernText());
    221     this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
    222 }
    223 
    224 void SkPaint::setFilterBitmap(bool doFilter) {
    225     GEN_ID_INC_EVAL(doFilter != isFilterBitmap());
    226     this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
    227 }
    228 
    229 void SkPaint::setStyle(Style style) {
    230     if ((unsigned)style < kStyleCount) {
    231         GEN_ID_INC_EVAL((unsigned)style != fStyle);
    232         fStyle = style;
    233     } else {
    234         SkDEBUGCODE(SkDebugf("SkPaint::setStyle(%d) out of range\n", style);)
    235     }
    236 }
    237 
    238 void SkPaint::setColor(SkColor color) {
    239     GEN_ID_INC_EVAL(color != fColor);
    240     fColor = color;
    241 }
    242 
    243 void SkPaint::setAlpha(U8CPU a) {
    244     this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
    245                                   SkColorGetG(fColor), SkColorGetB(fColor)));
    246 }
    247 
    248 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
    249     this->setColor(SkColorSetARGB(a, r, g, b));
    250 }
    251 
    252 void SkPaint::setStrokeWidth(SkScalar width) {
    253     if (width >= 0) {
    254         GEN_ID_INC_EVAL(width != fWidth);
    255         fWidth = width;
    256     } else {
    257         SkDEBUGCODE(SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");)
    258     }
    259 }
    260 
    261 void SkPaint::setStrokeMiter(SkScalar limit) {
    262     if (limit >= 0) {
    263         GEN_ID_INC_EVAL(limit != fMiterLimit);
    264         fMiterLimit = limit;
    265     } else {
    266         SkDEBUGCODE(SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");)
    267     }
    268 }
    269 
    270 void SkPaint::setStrokeCap(Cap ct) {
    271     if ((unsigned)ct < kCapCount) {
    272         GEN_ID_INC_EVAL((unsigned)ct != fCapType);
    273         fCapType = SkToU8(ct);
    274     } else {
    275         SkDEBUGCODE(SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);)
    276     }
    277 }
    278 
    279 void SkPaint::setStrokeJoin(Join jt) {
    280     if ((unsigned)jt < kJoinCount) {
    281         GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
    282         fJoinType = SkToU8(jt);
    283     } else {
    284         SkDEBUGCODE(SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);)
    285     }
    286 }
    287 
    288 ///////////////////////////////////////////////////////////////////////////////
    289 
    290 void SkPaint::setTextAlign(Align align) {
    291     if ((unsigned)align < kAlignCount) {
    292         GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
    293         fTextAlign = SkToU8(align);
    294     } else {
    295         SkDEBUGCODE(SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);)
    296     }
    297 }
    298 
    299 void SkPaint::setTextSize(SkScalar ts) {
    300     if (ts > 0) {
    301         GEN_ID_INC_EVAL(ts != fTextSize);
    302         fTextSize = ts;
    303     } else {
    304         SkDEBUGCODE(SkDebugf("SkPaint::setTextSize() called with negative value\n");)
    305     }
    306 }
    307 
    308 void SkPaint::setTextScaleX(SkScalar scaleX) {
    309     GEN_ID_INC_EVAL(scaleX != fTextScaleX);
    310     fTextScaleX = scaleX;
    311 }
    312 
    313 void SkPaint::setTextSkewX(SkScalar skewX) {
    314     GEN_ID_INC_EVAL(skewX != fTextSkewX);
    315     fTextSkewX = skewX;
    316 }
    317 
    318 void SkPaint::setTextEncoding(TextEncoding encoding) {
    319     if ((unsigned)encoding <= kGlyphID_TextEncoding) {
    320         GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
    321         fTextEncoding = encoding;
    322     } else {
    323         SkDEBUGCODE(SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);)
    324     }
    325 }
    326 
    327 ///////////////////////////////////////////////////////////////////////////////
    328 
    329 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
    330     SkRefCnt_SafeAssign(fTypeface, font);
    331     GEN_ID_INC;
    332     return font;
    333 }
    334 
    335 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
    336     SkRefCnt_SafeAssign(fRasterizer, r);
    337     GEN_ID_INC;
    338     return r;
    339 }
    340 
    341 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
    342     SkRefCnt_SafeAssign(fLooper, looper);
    343     GEN_ID_INC;
    344     return looper;
    345 }
    346 
    347 ///////////////////////////////////////////////////////////////////////////////
    348 
    349 #include "SkGlyphCache.h"
    350 #include "SkUtils.h"
    351 
    352 static void DetachDescProc(const SkDescriptor* desc, void* context) {
    353     *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
    354 }
    355 
    356 #ifdef ANDROID
    357 const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) {
    358     SkGlyphCache* cache;
    359     descriptorProc(NULL, DetachDescProc, &cache, true);
    360 
    361     const SkGlyph& glyph = cache->getUnicharMetrics(text);
    362 
    363     SkGlyphCache::AttachCache(cache);
    364     return glyph;
    365 }
    366 
    367 const SkGlyph& SkPaint::getGlyphMetrics(uint16_t glyphId) {
    368     SkGlyphCache* cache;
    369     descriptorProc(NULL, DetachDescProc, &cache, true);
    370 
    371     const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphId);
    372 
    373     SkGlyphCache::AttachCache(cache);
    374     return glyph;
    375 }
    376 
    377 const void* SkPaint::findImage(const SkGlyph& glyph) {
    378     // See ::detachCache()
    379     SkGlyphCache* cache;
    380     descriptorProc(NULL, DetachDescProc, &cache, true);
    381 
    382     const void* image = cache->findImage(glyph);
    383 
    384     SkGlyphCache::AttachCache(cache);
    385     return image;
    386 }
    387 #endif
    388 
    389 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
    390                           uint16_t glyphs[]) const {
    391     if (byteLength == 0) {
    392         return 0;
    393     }
    394 
    395     SkASSERT(textData != NULL);
    396 
    397     if (NULL == glyphs) {
    398         switch (this->getTextEncoding()) {
    399         case kUTF8_TextEncoding:
    400             return SkUTF8_CountUnichars((const char*)textData, byteLength);
    401         case kUTF16_TextEncoding:
    402             return SkUTF16_CountUnichars((const uint16_t*)textData,
    403                                          byteLength >> 1);
    404         case kGlyphID_TextEncoding:
    405             return byteLength >> 1;
    406         default:
    407             SkASSERT(!"unknown text encoding");
    408         }
    409         return 0;
    410     }
    411 
    412     // if we get here, we have a valid glyphs[] array, so time to fill it in
    413 
    414     // handle this encoding before the setup for the glyphcache
    415     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
    416         // we want to ignore the low bit of byteLength
    417         memcpy(glyphs, textData, byteLength >> 1 << 1);
    418         return byteLength >> 1;
    419     }
    420 
    421     SkAutoGlyphCache autoCache(*this, NULL);
    422     SkGlyphCache*    cache = autoCache.getCache();
    423 
    424     const char* text = (const char*)textData;
    425     const char* stop = text + byteLength;
    426     uint16_t*   gptr = glyphs;
    427 
    428     switch (this->getTextEncoding()) {
    429         case SkPaint::kUTF8_TextEncoding:
    430             while (text < stop) {
    431                 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
    432             }
    433             break;
    434         case SkPaint::kUTF16_TextEncoding: {
    435             const uint16_t* text16 = (const uint16_t*)text;
    436             const uint16_t* stop16 = (const uint16_t*)stop;
    437             while (text16 < stop16) {
    438                 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
    439             }
    440             break;
    441         }
    442         default:
    443             SkASSERT(!"unknown text encoding");
    444     }
    445     return gptr - glyphs;
    446 }
    447 
    448 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
    449     if (0 == byteLength) {
    450         return true;
    451     }
    452 
    453     SkASSERT(textData != NULL);
    454 
    455     // handle this encoding before the setup for the glyphcache
    456     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
    457         const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
    458         size_t count = byteLength >> 1;
    459         for (size_t i = 0; i < count; i++) {
    460             if (0 == glyphID[i]) {
    461                 return false;
    462             }
    463         }
    464         return true;
    465     }
    466 
    467     SkAutoGlyphCache autoCache(*this, NULL);
    468     SkGlyphCache*    cache = autoCache.getCache();
    469 
    470     switch (this->getTextEncoding()) {
    471         case SkPaint::kUTF8_TextEncoding: {
    472             const char* text = static_cast<const char*>(textData);
    473             const char* stop = text + byteLength;
    474             while (text < stop) {
    475                 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
    476                     return false;
    477                 }
    478             }
    479             break;
    480         }
    481         case SkPaint::kUTF16_TextEncoding: {
    482             const uint16_t* text = static_cast<const uint16_t*>(textData);
    483             const uint16_t* stop = text + (byteLength >> 1);
    484             while (text < stop) {
    485                 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
    486                     return false;
    487                 }
    488             }
    489             break;
    490         }
    491         default:
    492             SkASSERT(!"unknown text encoding");
    493             return false;
    494     }
    495     return true;
    496 }
    497 
    498 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
    499                                SkUnichar textData[]) const {
    500     if (count <= 0) {
    501         return;
    502     }
    503 
    504     SkASSERT(glyphs != NULL);
    505     SkASSERT(textData != NULL);
    506 
    507     SkAutoGlyphCache autoCache(*this, NULL);
    508     SkGlyphCache*    cache = autoCache.getCache();
    509 
    510     for (int index = 0; index < count; index++) {
    511         textData[index] = cache->glyphToUnichar(glyphs[index]);
    512     }
    513 }
    514 
    515 ///////////////////////////////////////////////////////////////////////////////
    516 
    517 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
    518                                               const char** text) {
    519     SkASSERT(cache != NULL);
    520     SkASSERT(text != NULL);
    521 
    522     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
    523 }
    524 
    525 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
    526                                               const char** text) {
    527     SkASSERT(cache != NULL);
    528     SkASSERT(text != NULL);
    529 
    530     return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
    531 }
    532 
    533 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
    534                                                const char** text) {
    535     SkASSERT(cache != NULL);
    536     SkASSERT(text != NULL);
    537 
    538     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
    539 }
    540 
    541 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
    542                                                const char** text) {
    543     SkASSERT(cache != NULL);
    544     SkASSERT(text != NULL);
    545 
    546     return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
    547 }
    548 
    549 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
    550                                                const char** text) {
    551     SkASSERT(cache != NULL);
    552     SkASSERT(text != NULL);
    553 
    554     const uint16_t* ptr = *(const uint16_t**)text;
    555     unsigned glyphID = *ptr;
    556     ptr += 1;
    557     *text = (const char*)ptr;
    558     return cache->getGlyphIDMetrics(glyphID);
    559 }
    560 
    561 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
    562                                                const char** text) {
    563     SkASSERT(cache != NULL);
    564     SkASSERT(text != NULL);
    565 
    566     const uint16_t* ptr = *(const uint16_t**)text;
    567     ptr -= 1;
    568     unsigned glyphID = *ptr;
    569     *text = (const char*)ptr;
    570     return cache->getGlyphIDMetrics(glyphID);
    571 }
    572 
    573 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
    574                                               const char** text) {
    575     SkASSERT(cache != NULL);
    576     SkASSERT(text != NULL);
    577 
    578     return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
    579 }
    580 
    581 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
    582                                               const char** text) {
    583     SkASSERT(cache != NULL);
    584     SkASSERT(text != NULL);
    585 
    586     return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
    587 }
    588 
    589 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
    590                                                const char** text) {
    591     SkASSERT(cache != NULL);
    592     SkASSERT(text != NULL);
    593 
    594     return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
    595 }
    596 
    597 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
    598                                                const char** text) {
    599     SkASSERT(cache != NULL);
    600     SkASSERT(text != NULL);
    601 
    602     return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
    603 }
    604 
    605 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
    606                                                const char** text) {
    607     SkASSERT(cache != NULL);
    608     SkASSERT(text != NULL);
    609 
    610     const uint16_t* ptr = *(const uint16_t**)text;
    611     unsigned glyphID = *ptr;
    612     ptr += 1;
    613     *text = (const char*)ptr;
    614     return cache->getGlyphIDAdvance(glyphID);
    615 }
    616 
    617 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
    618                                                const char** text) {
    619     SkASSERT(cache != NULL);
    620     SkASSERT(text != NULL);
    621 
    622     const uint16_t* ptr = *(const uint16_t**)text;
    623     ptr -= 1;
    624     unsigned glyphID = *ptr;
    625     *text = (const char*)ptr;
    626     return cache->getGlyphIDAdvance(glyphID);
    627 }
    628 
    629 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
    630                                                 bool needFullMetrics) const {
    631     static const SkMeasureCacheProc gMeasureCacheProcs[] = {
    632         sk_getMetrics_utf8_next,
    633         sk_getMetrics_utf16_next,
    634         sk_getMetrics_glyph_next,
    635 
    636         sk_getMetrics_utf8_prev,
    637         sk_getMetrics_utf16_prev,
    638         sk_getMetrics_glyph_prev,
    639 
    640         sk_getAdvance_utf8_next,
    641         sk_getAdvance_utf16_next,
    642         sk_getAdvance_glyph_next,
    643 
    644         sk_getAdvance_utf8_prev,
    645         sk_getAdvance_utf16_prev,
    646         sk_getAdvance_glyph_prev
    647     };
    648 
    649     unsigned index = this->getTextEncoding();
    650 
    651     if (kBackward_TextBufferDirection == tbd) {
    652         index += 3;
    653     }
    654     if (!needFullMetrics && !this->isDevKernText()) {
    655         index += 6;
    656     }
    657 
    658     SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
    659     return gMeasureCacheProcs[index];
    660 }
    661 
    662 ///////////////////////////////////////////////////////////////////////////////
    663 
    664 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
    665                                         const char** text, SkFixed, SkFixed) {
    666     SkASSERT(cache != NULL);
    667     SkASSERT(text != NULL);
    668 
    669     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
    670 }
    671 
    672 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
    673                                     const char** text, SkFixed x, SkFixed y) {
    674     SkASSERT(cache != NULL);
    675     SkASSERT(text != NULL);
    676 
    677     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
    678 }
    679 
    680 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
    681                                         const char** text, SkFixed, SkFixed) {
    682     SkASSERT(cache != NULL);
    683     SkASSERT(text != NULL);
    684 
    685     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
    686 }
    687 
    688 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
    689                                      const char** text, SkFixed x, SkFixed y) {
    690     SkASSERT(cache != NULL);
    691     SkASSERT(text != NULL);
    692 
    693     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
    694                                     x, y);
    695 }
    696 
    697 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
    698                                          const char** text, SkFixed, SkFixed) {
    699     SkASSERT(cache != NULL);
    700     SkASSERT(text != NULL);
    701 
    702     const uint16_t* ptr = *(const uint16_t**)text;
    703     unsigned glyphID = *ptr;
    704     ptr += 1;
    705     *text = (const char*)ptr;
    706     return cache->getGlyphIDMetrics(glyphID);
    707 }
    708 
    709 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
    710                                      const char** text, SkFixed x, SkFixed y) {
    711     SkASSERT(cache != NULL);
    712     SkASSERT(text != NULL);
    713 
    714     const uint16_t* ptr = *(const uint16_t**)text;
    715     unsigned glyphID = *ptr;
    716     ptr += 1;
    717     *text = (const char*)ptr;
    718     return cache->getGlyphIDMetrics(glyphID, x, y);
    719 }
    720 
    721 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
    722     static const SkDrawCacheProc gDrawCacheProcs[] = {
    723         sk_getMetrics_utf8_00,
    724         sk_getMetrics_utf16_00,
    725         sk_getMetrics_glyph_00,
    726 
    727         sk_getMetrics_utf8_xy,
    728         sk_getMetrics_utf16_xy,
    729         sk_getMetrics_glyph_xy
    730     };
    731 
    732     unsigned index = this->getTextEncoding();
    733     if (fFlags & kSubpixelText_Flag) {
    734         index += 3;
    735     }
    736 
    737     SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
    738     return gDrawCacheProcs[index];
    739 }
    740 
    741 ///////////////////////////////////////////////////////////////////////////////
    742 
    743 class SkAutoRestorePaintTextSizeAndFrame {
    744 public:
    745     SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint)
    746             : fPaint((SkPaint*)paint) {
    747         fTextSize = paint->getTextSize();
    748         fStyle = paint->getStyle();
    749         fPaint->setStyle(SkPaint::kFill_Style);
    750     }
    751 
    752     ~SkAutoRestorePaintTextSizeAndFrame() {
    753         fPaint->setStyle(fStyle);
    754         fPaint->setTextSize(fTextSize);
    755     }
    756 
    757 private:
    758     SkPaint*        fPaint;
    759     SkScalar        fTextSize;
    760     SkPaint::Style  fStyle;
    761 };
    762 
    763 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
    764     bounds->set(SkIntToScalar(g.fLeft),
    765                 SkIntToScalar(g.fTop),
    766                 SkIntToScalar(g.fLeft + g.fWidth),
    767                 SkIntToScalar(g.fTop + g.fHeight));
    768 }
    769 
    770 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
    771 // we don't overflow along the way
    772 typedef int64_t Sk48Dot16;
    773 
    774 #ifdef SK_SCALAR_IS_FLOAT
    775     static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
    776         return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
    777     }
    778 #else
    779     static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) {
    780         // just return the low 32bits
    781         return static_cast<SkFixed>(x);
    782     }
    783 #endif
    784 
    785 static void join_bounds(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
    786     SkScalar sx = Sk48Dot16ToScalar(dx);
    787     bounds->join(SkIntToScalar(g.fLeft) + sx,
    788                  SkIntToScalar(g.fTop),
    789                  SkIntToScalar(g.fLeft + g.fWidth) + sx,
    790                  SkIntToScalar(g.fTop + g.fHeight));
    791 }
    792 
    793 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
    794                                const char* text, size_t byteLength,
    795                                int* count, SkRect* bounds) const {
    796     SkASSERT(count);
    797     if (byteLength == 0) {
    798         *count = 0;
    799         if (bounds) {
    800             bounds->setEmpty();
    801         }
    802         return 0;
    803     }
    804 
    805     SkMeasureCacheProc glyphCacheProc;
    806     glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
    807                                                NULL != bounds);
    808 
    809     int         n = 1;
    810     const char* stop = (const char*)text + byteLength;
    811     const SkGlyph* g = &glyphCacheProc(cache, &text);
    812     // our accumulated fixed-point advances might overflow 16.16, so we use
    813     // a 48.16 (64bit) accumulator, and then convert that to scalar at the
    814     // very end.
    815     Sk48Dot16 x = g->fAdvanceX;
    816 
    817     SkAutoKern  autokern;
    818 
    819     if (NULL == bounds) {
    820         if (this->isDevKernText()) {
    821             int rsb;
    822             for (; text < stop; n++) {
    823                 rsb = g->fRsbDelta;
    824                 g = &glyphCacheProc(cache, &text);
    825                 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX;
    826             }
    827         } else {
    828             for (; text < stop; n++) {
    829                 x += glyphCacheProc(cache, &text).fAdvanceX;
    830             }
    831         }
    832     } else {
    833         set_bounds(*g, bounds);
    834         if (this->isDevKernText()) {
    835             int rsb;
    836             for (; text < stop; n++) {
    837                 rsb = g->fRsbDelta;
    838                 g = &glyphCacheProc(cache, &text);
    839                 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
    840                 join_bounds(*g, bounds, x);
    841                 x += g->fAdvanceX;
    842             }
    843         } else {
    844             for (; text < stop; n++) {
    845                 g = &glyphCacheProc(cache, &text);
    846                 join_bounds(*g, bounds, x);
    847                 x += g->fAdvanceX;
    848             }
    849         }
    850     }
    851     SkASSERT(text == stop);
    852 
    853     *count = n;
    854     return Sk48Dot16ToScalar(x);
    855 }
    856 
    857 SkScalar SkPaint::measureText(const void* textData, size_t length,
    858                               SkRect* bounds, SkScalar zoom) const {
    859     const char* text = (const char*)textData;
    860     SkASSERT(text != NULL || length == 0);
    861 
    862     SkScalar                            scale = 0;
    863     SkAutoRestorePaintTextSizeAndFrame  restore(this);
    864 
    865     if (this->isLinearText()) {
    866         scale = fTextSize / kCanonicalTextSizeForPaths;
    867         // this gets restored by restore
    868         ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
    869     }
    870 
    871     SkMatrix zoomMatrix, *zoomPtr = NULL;
    872     if (zoom) {
    873         zoomMatrix.setScale(zoom, zoom);
    874         zoomPtr = &zoomMatrix;
    875     }
    876 
    877     SkAutoGlyphCache    autoCache(*this, zoomPtr);
    878     SkGlyphCache*       cache = autoCache.getCache();
    879 
    880     SkScalar width = 0;
    881 
    882     if (length > 0) {
    883         int tempCount;
    884 
    885         width = this->measure_text(cache, text, length, &tempCount, bounds);
    886         if (scale) {
    887             width = SkScalarMul(width, scale);
    888             if (bounds) {
    889                 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
    890                 bounds->fTop = SkScalarMul(bounds->fTop, scale);
    891                 bounds->fRight = SkScalarMul(bounds->fRight, scale);
    892                 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
    893             }
    894         }
    895     }
    896     return width;
    897 }
    898 
    899 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
    900 
    901 static bool forward_textBufferPred(const char* text, const char* stop) {
    902     return text < stop;
    903 }
    904 
    905 static bool backward_textBufferPred(const char* text, const char* stop) {
    906     return text > stop;
    907 }
    908 
    909 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
    910                                              const char** text, size_t length,
    911                                              const char** stop) {
    912     if (SkPaint::kForward_TextBufferDirection == tbd) {
    913         *stop = *text + length;
    914         return forward_textBufferPred;
    915     } else {
    916         // text should point to the end of the buffer, and stop to the beginning
    917         *stop = *text;
    918         *text += length;
    919         return backward_textBufferPred;
    920     }
    921 }
    922 
    923 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
    924                           SkScalar* measuredWidth,
    925                           TextBufferDirection tbd) const {
    926     if (0 == length || 0 >= maxWidth) {
    927         if (measuredWidth) {
    928             *measuredWidth = 0;
    929         }
    930         return 0;
    931     }
    932 
    933     SkASSERT(textD != NULL);
    934     const char* text = (const char*)textD;
    935 
    936     SkScalar                            scale = 0;
    937     SkAutoRestorePaintTextSizeAndFrame  restore(this);
    938 
    939     if (this->isLinearText()) {
    940         scale = fTextSize / kCanonicalTextSizeForPaths;
    941         maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
    942         // this gets restored by restore
    943         ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
    944     }
    945 
    946     SkAutoGlyphCache    autoCache(*this, NULL);
    947     SkGlyphCache*       cache = autoCache.getCache();
    948 
    949     SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
    950     const char*      stop;
    951     SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
    952     // use 64bits for our accumulator, to avoid overflowing 16.16
    953     Sk48Dot16        max = SkScalarToFixed(maxWidth);
    954     Sk48Dot16        width = 0;
    955 
    956     SkAutoKern  autokern;
    957 
    958     if (this->isDevKernText()) {
    959         int rsb = 0;
    960         while (pred(text, stop)) {
    961             const char* curr = text;
    962             const SkGlyph& g = glyphCacheProc(cache, &text);
    963             SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
    964             if ((width += x) > max) {
    965                 width -= x;
    966                 text = curr;
    967                 break;
    968             }
    969             rsb = g.fRsbDelta;
    970         }
    971     } else {
    972         while (pred(text, stop)) {
    973             const char* curr = text;
    974             SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
    975             if ((width += x) > max) {
    976                 width -= x;
    977                 text = curr;
    978                 break;
    979             }
    980         }
    981     }
    982 
    983     if (measuredWidth) {
    984         SkScalar scalarWidth = Sk48Dot16ToScalar(width);
    985         if (scale) {
    986             scalarWidth = SkScalarMul(scalarWidth, scale);
    987         }
    988         *measuredWidth = scalarWidth;
    989     }
    990 
    991     // return the number of bytes measured
    992     return (kForward_TextBufferDirection == tbd) ?
    993                 text - stop + length : stop - text + length;
    994 }
    995 
    996 ///////////////////////////////////////////////////////////////////////////////
    997 
    998 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
    999     *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
   1000     return false;   // don't detach the cache
   1001 }
   1002 
   1003 static void FontMetricsDescProc(const SkDescriptor* desc, void* context) {
   1004     SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
   1005 }
   1006 
   1007 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
   1008     SkScalar                            scale = 0;
   1009     SkAutoRestorePaintTextSizeAndFrame  restore(this);
   1010 
   1011     if (this->isLinearText()) {
   1012         scale = fTextSize / kCanonicalTextSizeForPaths;
   1013         // this gets restored by restore
   1014         ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
   1015     }
   1016 
   1017     SkMatrix zoomMatrix, *zoomPtr = NULL;
   1018     if (zoom) {
   1019         zoomMatrix.setScale(zoom, zoom);
   1020         zoomPtr = &zoomMatrix;
   1021     }
   1022 
   1023 #if 0
   1024     SkAutoGlyphCache    autoCache(*this, zoomPtr);
   1025     SkGlyphCache*       cache = autoCache.getCache();
   1026     const FontMetrics&  my = cache->getFontMetricsY();
   1027 #endif
   1028     FontMetrics storage;
   1029     if (NULL == metrics) {
   1030         metrics = &storage;
   1031     }
   1032 
   1033     this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
   1034 
   1035     if (scale) {
   1036         metrics->fTop = SkScalarMul(metrics->fTop, scale);
   1037         metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
   1038         metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
   1039         metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
   1040         metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
   1041     }
   1042     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
   1043 }
   1044 
   1045 ///////////////////////////////////////////////////////////////////////////////
   1046 
   1047 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
   1048     bounds->set(g.fLeft * scale,
   1049                 g.fTop * scale,
   1050                 (g.fLeft + g.fWidth) * scale,
   1051                 (g.fTop + g.fHeight) * scale);
   1052 }
   1053 
   1054 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
   1055                            SkScalar widths[], SkRect bounds[]) const {
   1056     if (0 == byteLength) {
   1057         return 0;
   1058     }
   1059 
   1060     SkASSERT(NULL != textData);
   1061 
   1062     if (NULL == widths && NULL == bounds) {
   1063         return this->countText(textData, byteLength);
   1064     }
   1065 
   1066     SkAutoRestorePaintTextSizeAndFrame  restore(this);
   1067     SkScalar                            scale = 0;
   1068 
   1069     if (this->isLinearText()) {
   1070         scale = fTextSize / kCanonicalTextSizeForPaths;
   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     SkMeasureCacheProc  glyphCacheProc;
   1078     glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
   1079                                                NULL != bounds);
   1080 
   1081     const char* text = (const char*)textData;
   1082     const char* stop = text + byteLength;
   1083     int         count = 0;
   1084 
   1085     if (this->isDevKernText()) {
   1086         // we adjust the widths returned here through auto-kerning
   1087         SkAutoKern  autokern;
   1088         SkFixed     prevWidth = 0;
   1089 
   1090         if (scale) {
   1091             while (text < stop) {
   1092                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1093                 if (widths) {
   1094                     SkFixed  adjust = autokern.adjust(g);
   1095 
   1096                     if (count > 0) {
   1097                         SkScalar w = SkFixedToScalar(prevWidth + adjust);
   1098                         *widths++ = SkScalarMul(w, scale);
   1099                     }
   1100                     prevWidth = g.fAdvanceX;
   1101                 }
   1102                 if (bounds) {
   1103                     set_bounds(g, bounds++, scale);
   1104                 }
   1105                 ++count;
   1106             }
   1107             if (count > 0 && widths) {
   1108                 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
   1109             }
   1110         } else {
   1111             while (text < stop) {
   1112                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1113                 if (widths) {
   1114                     SkFixed  adjust = autokern.adjust(g);
   1115 
   1116                     if (count > 0) {
   1117                         *widths++ = SkFixedToScalar(prevWidth + adjust);
   1118                     }
   1119                     prevWidth = g.fAdvanceX;
   1120                 }
   1121                 if (bounds) {
   1122                     set_bounds(g, bounds++);
   1123                 }
   1124                 ++count;
   1125             }
   1126             if (count > 0 && widths) {
   1127                 *widths = SkFixedToScalar(prevWidth);
   1128             }
   1129         }
   1130     } else {    // no devkern
   1131         if (scale) {
   1132             while (text < stop) {
   1133                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1134                 if (widths) {
   1135                     *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
   1136                                             scale);
   1137                 }
   1138                 if (bounds) {
   1139                     set_bounds(g, bounds++, scale);
   1140                 }
   1141                 ++count;
   1142             }
   1143         } else {
   1144             while (text < stop) {
   1145                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1146                 if (widths) {
   1147                     *widths++ = SkFixedToScalar(g.fAdvanceX);
   1148                 }
   1149                 if (bounds) {
   1150                     set_bounds(g, bounds++);
   1151                 }
   1152                 ++count;
   1153             }
   1154         }
   1155     }
   1156 
   1157     SkASSERT(text == stop);
   1158     return count;
   1159 }
   1160 
   1161 ///////////////////////////////////////////////////////////////////////////////
   1162 
   1163 #include "SkDraw.h"
   1164 
   1165 void SkPaint::getTextPath(const void* textData, size_t length,
   1166                           SkScalar x, SkScalar y, SkPath* path) const {
   1167     SkASSERT(length == 0 || textData != NULL);
   1168 
   1169     const char* text = (const char*)textData;
   1170     if (text == NULL || length == 0 || path == NULL) {
   1171         return;
   1172     }
   1173 
   1174     SkTextToPathIter    iter(text, length, *this, false, true);
   1175     SkMatrix            matrix;
   1176     SkScalar            prevXPos = 0;
   1177 
   1178     matrix.setScale(iter.getPathScale(), iter.getPathScale());
   1179     matrix.postTranslate(x, y);
   1180     path->reset();
   1181 
   1182     SkScalar        xpos;
   1183     const SkPath*   iterPath;
   1184     while ((iterPath = iter.next(&xpos)) != NULL) {
   1185         matrix.postTranslate(xpos - prevXPos, 0);
   1186         path->addPath(*iterPath, matrix);
   1187         prevXPos = xpos;
   1188     }
   1189 }
   1190 
   1191 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
   1192                             SkFlattenableWriteBuffer* buffer) {
   1193     buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
   1194 }
   1195 
   1196 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
   1197     uint32_t flags = paint.getFlags();
   1198 
   1199     // Antialiasing being disabled trumps all other settings.
   1200     if (!(flags & SkPaint::kAntiAlias_Flag)) {
   1201         return SkMask::kBW_Format;
   1202     }
   1203 
   1204 #if defined(SK_SUPPORT_LCDTEXT)
   1205     if (flags & SkPaint::kLCDRenderText_Flag) {
   1206         return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
   1207                    SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
   1208     }
   1209 #else
   1210     if (flags & SkPaint::kLCDRenderText_Flag) {
   1211         return SkMask::kLCD16_Format;
   1212     }
   1213 #endif
   1214 
   1215     return SkMask::kA8_Format;
   1216 }
   1217 
   1218 // if linear-text is on, then we force hinting to be off (since that's sort of
   1219 // the point of linear-text.
   1220 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
   1221     SkPaint::Hinting h = paint.getHinting();
   1222     if (paint.isLinearText()) {
   1223         h = SkPaint::kNo_Hinting;
   1224     }
   1225     return h;
   1226 }
   1227 
   1228 /*
   1229  *  Return the scalar with only limited fractional precision. Used to consolidate matrices
   1230  *  that vary only slightly when we create our key into the font cache, since the font scaler
   1231  *  typically returns the same looking resuts for tiny changes in the matrix.
   1232  */
   1233 static SkScalar sk_relax(SkScalar x) {
   1234 #ifdef SK_SCALAR_IS_FLOAT
   1235     int n = sk_float_round2int(x * 1024);
   1236     return n / 1024.0f;
   1237 #else
   1238     // round to the nearest 10 fractional bits
   1239     return (x + (1 << 5)) & ~(1024 - 1);
   1240 #endif
   1241 }
   1242 
   1243 void SkScalerContext::MakeRec(const SkPaint& paint,
   1244                               const SkMatrix* deviceMatrix, Rec* rec) {
   1245     SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
   1246 
   1247     rec->fOrigFontID = SkTypeface::UniqueID(paint.getTypeface());
   1248     rec->fFontID = rec->fOrigFontID;
   1249     rec->fTextSize = paint.getTextSize();
   1250     rec->fPreScaleX = paint.getTextScaleX();
   1251     rec->fPreSkewX  = paint.getTextSkewX();
   1252 
   1253     if (deviceMatrix) {
   1254         rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
   1255         rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
   1256         rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
   1257         rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
   1258     } else {
   1259         rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
   1260         rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
   1261     }
   1262 
   1263     SkPaint::Style  style = paint.getStyle();
   1264     SkScalar        strokeWidth = paint.getStrokeWidth();
   1265 
   1266     unsigned flags = SkFontHost::ComputeGammaFlag(paint);
   1267 
   1268     if (paint.isFakeBoldText()) {
   1269 #ifdef SK_USE_FREETYPE_EMBOLDEN
   1270         flags |= SkScalerContext::kEmbolden_Flag;
   1271 #else
   1272         SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
   1273                                                     kStdFakeBoldInterpKeys,
   1274                                                     kStdFakeBoldInterpValues,
   1275                                                     kStdFakeBoldInterpLength);
   1276         SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
   1277 
   1278         if (style == SkPaint::kFill_Style) {
   1279             style = SkPaint::kStrokeAndFill_Style;
   1280             strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
   1281         } else {
   1282             strokeWidth += extra;
   1283         }
   1284 #endif
   1285     }
   1286 
   1287     if (paint.isDevKernText()) {
   1288         flags |= SkScalerContext::kDevKernText_Flag;
   1289     }
   1290 
   1291     if (style != SkPaint::kFill_Style && strokeWidth > 0) {
   1292         rec->fFrameWidth = strokeWidth;
   1293         rec->fMiterLimit = paint.getStrokeMiter();
   1294         rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
   1295 
   1296         if (style == SkPaint::kStrokeAndFill_Style) {
   1297             flags |= SkScalerContext::kFrameAndFill_Flag;
   1298         }
   1299     } else {
   1300         rec->fFrameWidth = 0;
   1301         rec->fMiterLimit = 0;
   1302         rec->fStrokeJoin = 0;
   1303     }
   1304 
   1305     rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
   1306 
   1307     if (SkMask::kLCD16_Format == rec->fMaskFormat) {
   1308         SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
   1309         SkFontHost::LCDOrientation orient = SkFontHost::GetSubpixelOrientation();
   1310         if (SkFontHost::kNONE_LCDOrder == order) {
   1311             // eeek, can't support LCD
   1312             rec->fMaskFormat = SkMask::kA8_Format;
   1313         } else {
   1314             if (SkFontHost::kVertical_LCDOrientation == orient) {
   1315                 flags |= SkScalerContext::kLCD_Vertical_Flag;
   1316             }
   1317             if (SkFontHost::kBGR_LCDOrder == order) {
   1318                 flags |= SkScalerContext::kLCD_BGROrder_Flag;
   1319             }
   1320         }
   1321     }
   1322 
   1323     if (paint.isEmbeddedBitmapText()) {
   1324         flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
   1325     }
   1326     if (paint.isSubpixelText()) {
   1327         flags |= SkScalerContext::kSubpixelPositioning_Flag;
   1328     }
   1329     if (paint.isAutohinted()) {
   1330         flags |= SkScalerContext::kAutohinting_Flag;
   1331     }
   1332     rec->fFlags = SkToU16(flags);
   1333 
   1334     // setHinting modifies fFlags, so do this last
   1335     rec->setHinting(computeHinting(paint));
   1336 
   1337     /*  Allow the fonthost to modify our rec before we use it as a key into the
   1338         cache. This way if we're asking for something that they will ignore,
   1339         they can modify our rec up front, so we don't create duplicate cache
   1340         entries.
   1341      */
   1342     SkFontHost::FilterRec(rec);
   1343 }
   1344 
   1345 #define MIN_SIZE_FOR_EFFECT_BUFFER  1024
   1346 
   1347 #ifdef SK_DEBUG
   1348     #define TEST_DESC
   1349 #endif
   1350 
   1351 void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
   1352                              void (*proc)(const SkDescriptor*, void*),
   1353                              void* context, bool ignoreGamma) const {
   1354     SkScalerContext::Rec    rec;
   1355 
   1356     SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
   1357     if (ignoreGamma) {
   1358         rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag |
   1359                 SkScalerContext::kGammaForWhite_Flag);
   1360     }
   1361 
   1362     size_t          descSize = sizeof(rec);
   1363     int             entryCount = 1;
   1364     SkPathEffect*   pe = this->getPathEffect();
   1365     SkMaskFilter*   mf = this->getMaskFilter();
   1366     SkRasterizer*   ra = this->getRasterizer();
   1367 
   1368     SkFlattenableWriteBuffer    peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
   1369     SkFlattenableWriteBuffer    mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
   1370     SkFlattenableWriteBuffer    raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
   1371 
   1372     if (pe) {
   1373         peBuffer.writeFlattenable(pe);
   1374         descSize += peBuffer.size();
   1375         entryCount += 1;
   1376         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
   1377         // seems like we could support kLCD as well at this point...
   1378     }
   1379     if (mf) {
   1380         mfBuffer.writeFlattenable(mf);
   1381         descSize += mfBuffer.size();
   1382         entryCount += 1;
   1383         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
   1384     }
   1385     if (ra) {
   1386         raBuffer.writeFlattenable(ra);
   1387         descSize += raBuffer.size();
   1388         entryCount += 1;
   1389         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
   1390     }
   1391     descSize += SkDescriptor::ComputeOverhead(entryCount);
   1392 
   1393     SkAutoDescriptor    ad(descSize);
   1394     SkDescriptor*       desc = ad.getDesc();
   1395 
   1396     desc->init();
   1397     desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1398 
   1399     if (pe) {
   1400         add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
   1401     }
   1402     if (mf) {
   1403         add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
   1404     }
   1405     if (ra) {
   1406         add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
   1407     }
   1408 
   1409     SkASSERT(descSize == desc->getLength());
   1410     desc->computeChecksum();
   1411 
   1412 #ifdef TEST_DESC
   1413     {
   1414         // Check that we completely write the bytes in desc (our key), and that
   1415         // there are no uninitialized bytes. If there were, then we would get
   1416         // false-misses (or worse, false-hits) in our fontcache.
   1417         //
   1418         // We do this buy filling 2 others, one with 0s and the other with 1s
   1419         // and create those, and then check that all 3 are identical.
   1420         SkAutoDescriptor    ad1(descSize);
   1421         SkAutoDescriptor    ad2(descSize);
   1422         SkDescriptor*       desc1 = ad1.getDesc();
   1423         SkDescriptor*       desc2 = ad2.getDesc();
   1424 
   1425         memset(desc1, 0x00, descSize);
   1426         memset(desc2, 0xFF, descSize);
   1427 
   1428         desc1->init();
   1429         desc2->init();
   1430         desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1431         desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1432 
   1433         if (pe) {
   1434             add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
   1435             add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
   1436         }
   1437         if (mf) {
   1438             add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
   1439             add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
   1440         }
   1441         if (ra) {
   1442             add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
   1443             add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
   1444         }
   1445 
   1446         SkASSERT(descSize == desc1->getLength());
   1447         SkASSERT(descSize == desc2->getLength());
   1448         desc1->computeChecksum();
   1449         desc2->computeChecksum();
   1450         SkASSERT(!memcmp(desc, desc1, descSize));
   1451         SkASSERT(!memcmp(desc, desc2, descSize));
   1452     }
   1453 #endif
   1454 
   1455     proc(desc, context);
   1456 }
   1457 
   1458 SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const {
   1459     SkGlyphCache* cache;
   1460     this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
   1461     return cache;
   1462 }
   1463 
   1464 ///////////////////////////////////////////////////////////////////////////////
   1465 
   1466 #include "SkStream.h"
   1467 
   1468 static uintptr_t asint(const void* p) {
   1469     return reinterpret_cast<uintptr_t>(p);
   1470 }
   1471 
   1472 union Scalar32 {
   1473     SkScalar    fScalar;
   1474     uint32_t    f32;
   1475 };
   1476 
   1477 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
   1478     SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
   1479     Scalar32 tmp;
   1480     tmp.fScalar = value;
   1481     *ptr = tmp.f32;
   1482     return ptr + 1;
   1483 }
   1484 
   1485 static SkScalar read_scalar(const uint32_t*& ptr) {
   1486     SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
   1487     Scalar32 tmp;
   1488     tmp.f32 = *ptr++;
   1489     return tmp.fScalar;
   1490 }
   1491 
   1492 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
   1493     SkASSERT(a == (uint8_t)a);
   1494     SkASSERT(b == (uint8_t)b);
   1495     SkASSERT(c == (uint8_t)c);
   1496     SkASSERT(d == (uint8_t)d);
   1497     return (a << 24) | (b << 16) | (c << 8) | d;
   1498 }
   1499 
   1500 enum FlatFlags {
   1501     kHasTypeface_FlatFlag   = 0x01,
   1502     kHasEffects_FlatFlag    = 0x02
   1503 };
   1504 
   1505 // The size of a flat paint's POD fields
   1506 static const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
   1507                                         1 * sizeof(SkColor) +
   1508                                         1 * sizeof(uint16_t) +
   1509                                         6 * sizeof(uint8_t);
   1510 
   1511 /*  To save space/time, we analyze the paint, and write a truncated version of
   1512     it if there are not tricky elements like shaders, etc.
   1513  */
   1514 void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
   1515     uint8_t flatFlags = 0;
   1516     if (this->getTypeface()) {
   1517         flatFlags |= kHasTypeface_FlatFlag;
   1518     }
   1519     if (asint(this->getPathEffect()) |
   1520         asint(this->getShader()) |
   1521         asint(this->getXfermode()) |
   1522         asint(this->getMaskFilter()) |
   1523         asint(this->getColorFilter()) |
   1524         asint(this->getRasterizer()) |
   1525         asint(this->getLooper())) {
   1526         flatFlags |= kHasEffects_FlatFlag;
   1527     }
   1528 
   1529     SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
   1530     uint32_t* ptr = buffer.reserve(kPODPaintSize);
   1531 
   1532     ptr = write_scalar(ptr, this->getTextSize());
   1533     ptr = write_scalar(ptr, this->getTextScaleX());
   1534     ptr = write_scalar(ptr, this->getTextSkewX());
   1535     ptr = write_scalar(ptr, this->getStrokeWidth());
   1536     ptr = write_scalar(ptr, this->getStrokeMiter());
   1537     *ptr++ = this->getColor();
   1538     *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
   1539     *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
   1540                     this->getStyle(), this->getTextEncoding());
   1541 
   1542     // now we're done with ptr and the (pre)reserved space. If we need to write
   1543     // additional fields, use the buffer directly
   1544     if (flatFlags & kHasTypeface_FlatFlag) {
   1545         buffer.writeTypeface(this->getTypeface());
   1546     }
   1547     if (flatFlags & kHasEffects_FlatFlag) {
   1548         buffer.writeFlattenable(this->getPathEffect());
   1549         buffer.writeFlattenable(this->getShader());
   1550         buffer.writeFlattenable(this->getXfermode());
   1551         buffer.writeFlattenable(this->getMaskFilter());
   1552         buffer.writeFlattenable(this->getColorFilter());
   1553         buffer.writeFlattenable(this->getRasterizer());
   1554         buffer.writeFlattenable(this->getLooper());
   1555     }
   1556 }
   1557 
   1558 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
   1559     SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
   1560     const void* podData = buffer.skip(kPODPaintSize);
   1561     const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
   1562 
   1563     // the order we read must match the order we wrote in flatten()
   1564     this->setTextSize(read_scalar(pod));
   1565     this->setTextScaleX(read_scalar(pod));
   1566     this->setTextSkewX(read_scalar(pod));
   1567     this->setStrokeWidth(read_scalar(pod));
   1568     this->setStrokeMiter(read_scalar(pod));
   1569     this->setColor(*pod++);
   1570 
   1571     uint32_t tmp = *pod++;
   1572     this->setFlags(tmp >> 16);
   1573     this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
   1574     uint8_t flatFlags = tmp & 0xFF;
   1575 
   1576     tmp = *pod++;
   1577     this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
   1578     this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
   1579     this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
   1580     this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
   1581 
   1582     if (flatFlags & kHasTypeface_FlatFlag) {
   1583         this->setTypeface(buffer.readTypeface());
   1584     } else {
   1585         this->setTypeface(NULL);
   1586     }
   1587 
   1588     if (flatFlags & kHasEffects_FlatFlag) {
   1589         SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable()));
   1590         SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable()));
   1591         SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable()));
   1592         SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable()));
   1593         SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable()));
   1594         SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
   1595         SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
   1596     } else {
   1597         this->setPathEffect(NULL);
   1598         this->setShader(NULL);
   1599         this->setXfermode(NULL);
   1600         this->setMaskFilter(NULL);
   1601         this->setColorFilter(NULL);
   1602         this->setRasterizer(NULL);
   1603         this->setLooper(NULL);
   1604     }
   1605 }
   1606 
   1607 ///////////////////////////////////////////////////////////////////////////////
   1608 
   1609 SkShader* SkPaint::setShader(SkShader* shader) {
   1610     GEN_ID_INC_EVAL(shader != fShader);
   1611     SkRefCnt_SafeAssign(fShader, shader);
   1612     return shader;
   1613 }
   1614 
   1615 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
   1616     GEN_ID_INC_EVAL(filter != fColorFilter);
   1617     SkRefCnt_SafeAssign(fColorFilter, filter);
   1618     return filter;
   1619 }
   1620 
   1621 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
   1622     GEN_ID_INC_EVAL(mode != fXfermode);
   1623     SkRefCnt_SafeAssign(fXfermode, mode);
   1624     return mode;
   1625 }
   1626 
   1627 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
   1628     SkSafeUnref(fXfermode);
   1629     fXfermode = SkXfermode::Create(mode);
   1630     GEN_ID_INC;
   1631     return fXfermode;
   1632 }
   1633 
   1634 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
   1635     GEN_ID_INC_EVAL(effect != fPathEffect);
   1636     SkRefCnt_SafeAssign(fPathEffect, effect);
   1637     return effect;
   1638 }
   1639 
   1640 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
   1641     GEN_ID_INC_EVAL(filter != fMaskFilter);
   1642     SkRefCnt_SafeAssign(fMaskFilter, filter);
   1643     return filter;
   1644 }
   1645 
   1646 ///////////////////////////////////////////////////////////////////////////////
   1647 
   1648 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
   1649     SkPath          effectPath, strokePath;
   1650     const SkPath*   path = &src;
   1651 
   1652     SkScalar width = this->getStrokeWidth();
   1653 
   1654     switch (this->getStyle()) {
   1655         case SkPaint::kFill_Style:
   1656             width = -1; // mark it as no-stroke
   1657             break;
   1658         case SkPaint::kStrokeAndFill_Style:
   1659             if (width == 0) {
   1660                 width = -1; // mark it as no-stroke
   1661             }
   1662             break;
   1663         case SkPaint::kStroke_Style:
   1664             break;
   1665         default:
   1666             SkASSERT(!"unknown paint style");
   1667     }
   1668 
   1669     if (this->getPathEffect()) {
   1670         // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
   1671         if (this->getStyle() == SkPaint::kStrokeAndFill_Style) {
   1672             width = -1; // mark it as no-stroke
   1673         }
   1674 
   1675         if (this->getPathEffect()->filterPath(&effectPath, src, &width)) {
   1676             path = &effectPath;
   1677         }
   1678 
   1679         // restore the width if we earlier had to lie, and if we're still set to no-stroke
   1680         // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
   1681         // and we want to respect that (i.e. don't overwrite their setting for width)
   1682         if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) {
   1683             width = this->getStrokeWidth();
   1684             if (width == 0) {
   1685                 width = -1;
   1686             }
   1687         }
   1688     }
   1689 
   1690     if (width > 0 && !path->isEmpty()) {
   1691         SkStroke stroker(*this, width);
   1692         stroker.strokePath(*path, &strokePath);
   1693         path = &strokePath;
   1694     }
   1695 
   1696     if (path == &src) {
   1697         *dst = src;
   1698     } else {
   1699         SkASSERT(path == &effectPath || path == &strokePath);
   1700         dst->swap(*(SkPath*)path);
   1701     }
   1702 
   1703     return width != 0;  // return true if we're filled, or false if we're hairline (width == 0)
   1704 }
   1705 
   1706 const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
   1707                                                SkRect* storage) const {
   1708     SkASSERT(storage);
   1709     SkASSERT(this->getStyle() != SkPaint::kFill_Style);
   1710 
   1711     // since we're stroked, outset the rect by the radius (and join type)
   1712     SkScalar radius = SkScalarHalf(this->getStrokeWidth());
   1713     if (0 == radius) {  // hairline
   1714         radius = SK_Scalar1;
   1715     } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
   1716         SkScalar scale = this->getStrokeMiter();
   1717         if (scale > SK_Scalar1) {
   1718             radius = SkScalarMul(radius, scale);
   1719         }
   1720     }
   1721     storage->set(src.fLeft - radius, src.fTop - radius,
   1722                  src.fRight + radius, src.fBottom + radius);
   1723     return *storage;
   1724 }
   1725 
   1726 ///////////////////////////////////////////////////////////////////////////////
   1727 
   1728 static bool has_thick_frame(const SkPaint& paint) {
   1729     return  paint.getStrokeWidth() > 0 &&
   1730             paint.getStyle() != SkPaint::kFill_Style;
   1731 }
   1732 
   1733 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
   1734                                     const SkPaint& paint,
   1735                                     bool applyStrokeAndPathEffects,
   1736                                     bool forceLinearTextOn) : fPaint(paint) {
   1737     fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
   1738                                                 true);
   1739 
   1740     if (forceLinearTextOn) {
   1741         fPaint.setLinearText(true);
   1742     }
   1743     fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
   1744 
   1745     if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
   1746         applyStrokeAndPathEffects = false;
   1747     }
   1748 
   1749     // can't use our canonical size if we need to apply patheffects/strokes
   1750     if (fPaint.isLinearText() && !applyStrokeAndPathEffects) {
   1751         fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
   1752         fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
   1753     } else {
   1754         fScale = SK_Scalar1;
   1755     }
   1756 
   1757     if (!applyStrokeAndPathEffects) {
   1758         fPaint.setStyle(SkPaint::kFill_Style);
   1759         fPaint.setPathEffect(NULL);
   1760     }
   1761 
   1762     fCache = fPaint.detachCache(NULL);
   1763 
   1764     SkPaint::Style  style = SkPaint::kFill_Style;
   1765     SkPathEffect*   pe = NULL;
   1766 
   1767     if (!applyStrokeAndPathEffects) {
   1768         style = paint.getStyle();   // restore
   1769         pe = paint.getPathEffect();     // restore
   1770     }
   1771     fPaint.setStyle(style);
   1772     fPaint.setPathEffect(pe);
   1773     fPaint.setMaskFilter(paint.getMaskFilter());    // restore
   1774 
   1775     // now compute fXOffset if needed
   1776 
   1777     SkScalar xOffset = 0;
   1778     if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
   1779         int      count;
   1780         SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
   1781                                                          &count, NULL), fScale);
   1782         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   1783             width = SkScalarHalf(width);
   1784         }
   1785         xOffset = -width;
   1786     }
   1787     fXPos = xOffset;
   1788     fPrevAdvance = 0;
   1789 
   1790     fText = text;
   1791     fStop = text + length;
   1792 }
   1793 
   1794 SkTextToPathIter::~SkTextToPathIter() {
   1795     SkGlyphCache::AttachCache(fCache);
   1796 }
   1797 
   1798 const SkPath* SkTextToPathIter::next(SkScalar* xpos) {
   1799     while (fText < fStop) {
   1800         const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
   1801 
   1802         fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
   1803         fPrevAdvance = glyph.fAdvanceX;   // + fPaint.getTextTracking();
   1804 
   1805         if (glyph.fWidth) {
   1806             if (xpos) {
   1807                 *xpos = fXPos;
   1808             }
   1809             return fCache->findPath(glyph);
   1810         }
   1811     }
   1812     return NULL;
   1813 }
   1814