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