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