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         maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
    910         // this gets restored by restore
    911         ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
    912     }
    913 
    914     SkAutoGlyphCache    autoCache(*this, NULL);
    915     SkGlyphCache*       cache = autoCache.getCache();
    916 
    917     SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
    918     const char*      stop;
    919     SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
    920     // use 64bits for our accumulator, to avoid overflowing 16.16
    921     Sk48Dot16        max = SkScalarToFixed(maxWidth);
    922     Sk48Dot16        width = 0;
    923 
    924     SkAutoKern  autokern;
    925 
    926     if (this->isDevKernText())
    927     {
    928         int rsb = 0;
    929         while (pred(text, stop))
    930         {
    931             const char* curr = text;
    932             const SkGlyph& g = glyphCacheProc(cache, &text);
    933             SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
    934             if ((width += x) > max)
    935             {
    936                 width -= x;
    937                 text = curr;
    938                 break;
    939             }
    940             rsb = g.fRsbDelta;
    941         }
    942     }
    943     else
    944     {
    945         while (pred(text, stop))
    946         {
    947             const char* curr = text;
    948             SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
    949             if ((width += x) > max)
    950             {
    951                 width -= x;
    952                 text = curr;
    953                 break;
    954             }
    955         }
    956     }
    957 
    958     if (measuredWidth)
    959     {
    960 
    961         SkScalar scalarWidth = Sk48Dot16ToScalar(width);
    962         if (scale)
    963             scalarWidth = SkScalarMul(scalarWidth, scale);
    964         *measuredWidth = scalarWidth;
    965     }
    966 
    967     // return the number of bytes measured
    968     return (kForward_TextBufferDirection == tbd) ?
    969                 text - stop + length : stop - text + length;
    970 }
    971 
    972 ///////////////////////////////////////////////////////////////////////////////
    973 
    974 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context)
    975 {
    976     *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
    977     return false;   // don't detach the cache
    978 }
    979 
    980 static void FontMetricsDescProc(const SkDescriptor* desc, void* context)
    981 {
    982     SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
    983 }
    984 
    985 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const
    986 {
    987     SkScalar                            scale = 0;
    988     SkAutoRestorePaintTextSizeAndFrame  restore(this);
    989 
    990     if (this->isLinearText())
    991     {
    992         scale = fTextSize / kCanonicalTextSizeForPaths;
    993         // this gets restored by restore
    994         ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
    995     }
    996 
    997     SkMatrix    zoomMatrix, *zoomPtr = NULL;
    998     if (zoom)
    999     {
   1000         zoomMatrix.setScale(zoom, zoom);
   1001         zoomPtr = &zoomMatrix;
   1002     }
   1003 
   1004 #if 0
   1005     SkAutoGlyphCache    autoCache(*this, zoomPtr);
   1006     SkGlyphCache*       cache = autoCache.getCache();
   1007     const FontMetrics&  my = cache->getFontMetricsY();
   1008 #endif
   1009     FontMetrics storage;
   1010     if (NULL == metrics)
   1011         metrics = &storage;
   1012 
   1013     this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
   1014 
   1015     if (scale)
   1016     {
   1017         metrics->fTop = SkScalarMul(metrics->fTop, scale);
   1018         metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
   1019         metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
   1020         metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
   1021         metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
   1022     }
   1023     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
   1024 }
   1025 
   1026 ////////////////////////////////////////////////////////////////////////////////////////////
   1027 
   1028 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale)
   1029 {
   1030     bounds->set(g.fLeft * scale,
   1031                 g.fTop * scale,
   1032                 (g.fLeft + g.fWidth) * scale,
   1033                 (g.fTop + g.fHeight) * scale);
   1034 }
   1035 
   1036 int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[],
   1037                            SkRect bounds[]) const
   1038 {
   1039     if (0 == byteLength)
   1040         return 0;
   1041 
   1042     SkASSERT(NULL != textData);
   1043 
   1044     if (NULL == widths && NULL == bounds)
   1045         return this->countText(textData, byteLength);
   1046 
   1047     SkAutoRestorePaintTextSizeAndFrame  restore(this);
   1048     SkScalar                            scale = 0;
   1049 
   1050     if (this->isLinearText())
   1051     {
   1052         scale = fTextSize / kCanonicalTextSizeForPaths;
   1053         // this gets restored by restore
   1054         ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
   1055     }
   1056 
   1057     SkAutoGlyphCache    autoCache(*this, NULL);
   1058     SkGlyphCache*       cache = autoCache.getCache();
   1059     SkMeasureCacheProc  glyphCacheProc;
   1060     glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
   1061                                                NULL != bounds);
   1062 
   1063     const char* text = (const char*)textData;
   1064     const char* stop = text + byteLength;
   1065     int         count = 0;
   1066 
   1067     if (this->isDevKernText())
   1068     {
   1069         // we adjust the widths returned here through auto-kerning
   1070         SkAutoKern  autokern;
   1071         SkFixed     prevWidth = 0;
   1072 
   1073         if (scale) {
   1074             while (text < stop) {
   1075                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1076                 if (widths) {
   1077                     SkFixed  adjust = autokern.adjust(g);
   1078 
   1079                     if (count > 0) {
   1080                         SkScalar w = SkFixedToScalar(prevWidth + adjust);
   1081                         *widths++ = SkScalarMul(w, scale);
   1082                     }
   1083                     prevWidth = g.fAdvanceX;
   1084                 }
   1085                 if (bounds) {
   1086                     set_bounds(g, bounds++, scale);
   1087                 }
   1088                 ++count;
   1089             }
   1090             if (count > 0 && widths) {
   1091                 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
   1092             }
   1093         } else {
   1094             while (text < stop) {
   1095                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1096                 if (widths) {
   1097                     SkFixed  adjust = autokern.adjust(g);
   1098 
   1099                     if (count > 0) {
   1100                         *widths++ = SkFixedToScalar(prevWidth + adjust);
   1101                     }
   1102                     prevWidth = g.fAdvanceX;
   1103                 }
   1104                 if (bounds) {
   1105                     set_bounds(g, bounds++);
   1106                 }
   1107                 ++count;
   1108             }
   1109             if (count > 0 && widths) {
   1110                 *widths = SkFixedToScalar(prevWidth);
   1111             }
   1112         }
   1113     } else {    // no devkern
   1114         if (scale) {
   1115             while (text < stop) {
   1116                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1117                 if (widths) {
   1118                     *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
   1119                                             scale);
   1120                 }
   1121                 if (bounds) {
   1122                     set_bounds(g, bounds++, scale);
   1123                 }
   1124                 ++count;
   1125             }
   1126         } else {
   1127             while (text < stop) {
   1128                 const SkGlyph& g = glyphCacheProc(cache, &text);
   1129                 if (widths) {
   1130                     *widths++ = SkFixedToScalar(g.fAdvanceX);
   1131                 }
   1132                 if (bounds) {
   1133                     set_bounds(g, bounds++);
   1134                 }
   1135                 ++count;
   1136             }
   1137         }
   1138     }
   1139 
   1140     SkASSERT(text == stop);
   1141     return count;
   1142 }
   1143 
   1144 ////////////////////////////////////////////////////////////////////////////////////////////
   1145 
   1146 #include "SkDraw.h"
   1147 
   1148 void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const
   1149 {
   1150     const char* text = (const char*)textData;
   1151     SkASSERT(length == 0 || text != NULL);
   1152     if (text == NULL || length == 0 || path == NULL)
   1153         return;
   1154 
   1155     SkTextToPathIter    iter(text, length, *this, false, true);
   1156     SkMatrix            matrix;
   1157     SkScalar            prevXPos = 0;
   1158 
   1159     matrix.setScale(iter.getPathScale(), iter.getPathScale());
   1160     matrix.postTranslate(x, y);
   1161     path->reset();
   1162 
   1163     SkScalar        xpos;
   1164     const SkPath*   iterPath;
   1165     while ((iterPath = iter.next(&xpos)) != NULL)
   1166     {
   1167         matrix.postTranslate(xpos - prevXPos, 0);
   1168         path->addPath(*iterPath, matrix);
   1169         prevXPos = xpos;
   1170     }
   1171 }
   1172 
   1173 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
   1174                             SkFlattenableWriteBuffer* buffer) {
   1175     buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
   1176 }
   1177 
   1178 /*
   1179  *  interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i])
   1180     inspired by a desire to change the multiplier for thickness in fakebold
   1181     therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient
   1182     repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if
   1183         key is the value of a repeated scalar in keys, the first one will be used
   1184     - this may change if a binary search is used
   1185     - also, this ensures that there is no divide by zero (an assert also checks for that)
   1186 */
   1187 static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length)
   1188 {
   1189 
   1190     SkASSERT(length > 0);
   1191     SkASSERT(keys != NULL);
   1192     SkASSERT(values != NULL);
   1193 #ifdef SK_DEBUG
   1194     for (int i = 1; i < length; i++)
   1195         SkASSERT(keys[i] >= keys[i-1]);
   1196 #endif
   1197     int right = 0;
   1198     while (right < length && key > keys[right])
   1199         right++;
   1200     //could use sentinal values to eliminate conditionals
   1201     //i assume i am not in control of input values, so i want to make it simple
   1202     if (length == right)
   1203         return values[length-1];
   1204     if (0 == right)
   1205         return values[0];
   1206     //otherwise, we interpolate between right-1 and right
   1207     SkScalar rVal = values[right];
   1208     SkScalar lVal = values[right-1];
   1209     SkScalar rightKey = keys[right];
   1210     SkScalar leftKey = keys[right-1];
   1211     SkASSERT(rightKey != leftKey);
   1212     //fractional amount which we will multiply by the difference in the left value and right value
   1213     SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey);
   1214     return lVal + SkScalarMul(fract, rVal-lVal);
   1215 }
   1216 
   1217 //used for interpolating in fakeBold
   1218 static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) };
   1219 static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 };
   1220 
   1221 static SkMask::Format computeMaskFormat(const SkPaint& paint)
   1222 {
   1223     uint32_t flags = paint.getFlags();
   1224 
   1225     // Antialiasing being disabled trumps all other settings.
   1226     if (!(flags & SkPaint::kAntiAlias_Flag))
   1227         return SkMask::kBW_Format;
   1228 
   1229 #if defined(SK_SUPPORT_LCDTEXT)
   1230     if (flags & SkPaint::kLCDRenderText_Flag)
   1231         return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
   1232                    SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
   1233 #endif
   1234 
   1235     return SkMask::kA8_Format;
   1236 }
   1237 
   1238 // if linear-text is on, then we force hinting to be off (since that's sort of
   1239 // the point of linear-text.
   1240 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
   1241     SkPaint::Hinting h = paint.getHinting();
   1242     if (paint.isLinearText()) {
   1243         h = SkPaint::kNo_Hinting;
   1244     }
   1245     return h;
   1246 }
   1247 
   1248 void SkScalerContext::MakeRec(const SkPaint& paint,
   1249                               const SkMatrix* deviceMatrix, Rec* rec)
   1250 {
   1251     SkASSERT(deviceMatrix == NULL ||
   1252              (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
   1253 
   1254     rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
   1255     rec->fTextSize = paint.getTextSize();
   1256     rec->fPreScaleX = paint.getTextScaleX();
   1257     rec->fPreSkewX  = paint.getTextSkewX();
   1258 
   1259     if (deviceMatrix)
   1260     {
   1261         rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
   1262         rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
   1263         rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
   1264         rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
   1265     }
   1266     else
   1267     {
   1268         rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
   1269         rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
   1270     }
   1271 
   1272     SkPaint::Style  style = paint.getStyle();
   1273     SkScalar        strokeWidth = paint.getStrokeWidth();
   1274 
   1275     unsigned flags = SkFontHost::ComputeGammaFlag(paint);
   1276 
   1277     if (paint.isFakeBoldText())
   1278     {
   1279 #ifdef SK_USE_FREETYPE_EMBOLDEN
   1280         flags |= SkScalerContext::kEmbolden_Flag;
   1281 #else
   1282         SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2);
   1283         SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
   1284 
   1285         if (style == SkPaint::kFill_Style)
   1286         {
   1287             style = SkPaint::kStrokeAndFill_Style;
   1288             strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
   1289         }
   1290         else
   1291             strokeWidth += extra;
   1292 #endif
   1293     }
   1294 
   1295     if (paint.isDevKernText())
   1296         flags |= SkScalerContext::kDevKernText_Flag;
   1297 
   1298     if (style != SkPaint::kFill_Style && strokeWidth > 0)
   1299     {
   1300         rec->fFrameWidth = strokeWidth;
   1301         rec->fMiterLimit = paint.getStrokeMiter();
   1302         rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
   1303 
   1304         if (style == SkPaint::kStrokeAndFill_Style)
   1305             flags |= SkScalerContext::kFrameAndFill_Flag;
   1306     }
   1307     else
   1308     {
   1309         rec->fFrameWidth = 0;
   1310         rec->fMiterLimit = 0;
   1311         rec->fStrokeJoin = 0;
   1312     }
   1313 
   1314     rec->fSubpixelPositioning = paint.isSubpixelText();
   1315     rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
   1316     rec->fFlags = SkToU8(flags);
   1317     rec->setHinting(computeHinting(paint));
   1318     if (paint.isEmbeddedBitmapText())
   1319         rec->fFlags |= SkScalerContext::kEmbeddedBitmapText_Flag;
   1320 
   1321     /*  Allow the fonthost to modify our rec before we use it as a key into the
   1322         cache. This way if we're asking for something that they will ignore,
   1323         they can modify our rec up front, so we don't create duplicate cache
   1324         entries.
   1325      */
   1326     SkFontHost::FilterRec(rec);
   1327 }
   1328 
   1329 #define MIN_SIZE_FOR_EFFECT_BUFFER  1024
   1330 
   1331 void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
   1332                              void (*proc)(const SkDescriptor*, void*),
   1333                              void* context) const
   1334 {
   1335     SkScalerContext::Rec    rec;
   1336 
   1337     SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
   1338 
   1339     size_t          descSize = sizeof(rec);
   1340     int             entryCount = 1;
   1341     SkPathEffect*   pe = this->getPathEffect();
   1342     SkMaskFilter*   mf = this->getMaskFilter();
   1343     SkRasterizer*   ra = this->getRasterizer();
   1344 
   1345     SkFlattenableWriteBuffer    peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
   1346     SkFlattenableWriteBuffer    mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
   1347     SkFlattenableWriteBuffer    raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
   1348 
   1349     if (pe) {
   1350         peBuffer.writeFlattenable(pe);
   1351         descSize += peBuffer.size();
   1352         entryCount += 1;
   1353         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
   1354         // seems like we could support kLCD as well at this point...
   1355     }
   1356     if (mf) {
   1357         mfBuffer.writeFlattenable(mf);
   1358         descSize += mfBuffer.size();
   1359         entryCount += 1;
   1360         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
   1361     }
   1362     if (ra) {
   1363         raBuffer.writeFlattenable(ra);
   1364         descSize += raBuffer.size();
   1365         entryCount += 1;
   1366         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
   1367     }
   1368     descSize += SkDescriptor::ComputeOverhead(entryCount);
   1369 
   1370     SkAutoDescriptor    ad(descSize);
   1371     SkDescriptor*       desc = ad.getDesc();
   1372 
   1373     desc->init();
   1374     desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
   1375 
   1376     if (pe) {
   1377         add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
   1378     }
   1379     if (mf) {
   1380         add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
   1381     }
   1382     if (ra) {
   1383         add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
   1384     }
   1385 
   1386     SkASSERT(descSize == desc->getLength());
   1387     desc->computeChecksum();
   1388 
   1389     proc(desc, context);
   1390 }
   1391 
   1392 static void DetachDescProc(const SkDescriptor* desc, void* context)
   1393 {
   1394     *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
   1395 }
   1396 
   1397 SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
   1398 {
   1399     SkGlyphCache* cache;
   1400     this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
   1401     return cache;
   1402 }
   1403 
   1404 ///////////////////////////////////////////////////////////////////////////////
   1405 
   1406 #include "SkStream.h"
   1407 
   1408 static uintptr_t asint(const void* p) {
   1409     return reinterpret_cast<uintptr_t>(p);
   1410 }
   1411 
   1412 union Scalar32 {
   1413     SkScalar    fScalar;
   1414     uint32_t    f32;
   1415 };
   1416 
   1417 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
   1418     SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
   1419     Scalar32 tmp;
   1420     tmp.fScalar = value;
   1421     *ptr = tmp.f32;
   1422     return ptr + 1;
   1423 }
   1424 
   1425 static SkScalar read_scalar(const uint32_t*& ptr) {
   1426     SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
   1427     Scalar32 tmp;
   1428     tmp.f32 = *ptr++;
   1429     return tmp.fScalar;
   1430 }
   1431 
   1432 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
   1433     SkASSERT(a == (uint8_t)a);
   1434     SkASSERT(b == (uint8_t)b);
   1435     SkASSERT(c == (uint8_t)c);
   1436     SkASSERT(d == (uint8_t)d);
   1437     return (a << 24) | (b << 16) | (c << 8) | d;
   1438 }
   1439 
   1440 enum FlatFlags {
   1441     kHasTypeface_FlatFlag   = 0x01,
   1442     kHasEffects_FlatFlag    = 0x02
   1443 };
   1444 
   1445 // The size of a flat paint's POD fields
   1446 static const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
   1447                                         1 * sizeof(SkColor) +
   1448                                         1 * sizeof(uint16_t) +
   1449                                         6 * sizeof(uint8_t);
   1450 
   1451 /*  To save space/time, we analyze the paint, and write a truncated version of
   1452     it if there are not tricky elements like shaders, etc.
   1453  */
   1454 void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
   1455     uint8_t flatFlags = 0;
   1456     if (this->getTypeface()) {
   1457         flatFlags |= kHasTypeface_FlatFlag;
   1458     }
   1459     if (asint(this->getPathEffect()) |
   1460         asint(this->getShader()) |
   1461         asint(this->getXfermode()) |
   1462         asint(this->getMaskFilter()) |
   1463         asint(this->getColorFilter()) |
   1464         asint(this->getRasterizer()) |
   1465         asint(this->getLooper())) {
   1466         flatFlags |= kHasEffects_FlatFlag;
   1467     }
   1468 
   1469     SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
   1470     uint32_t* ptr = buffer.reserve(kPODPaintSize);
   1471 
   1472     ptr = write_scalar(ptr, this->getTextSize());
   1473     ptr = write_scalar(ptr, this->getTextScaleX());
   1474     ptr = write_scalar(ptr, this->getTextSkewX());
   1475     ptr = write_scalar(ptr, this->getStrokeWidth());
   1476     ptr = write_scalar(ptr, this->getStrokeMiter());
   1477     *ptr++ = this->getColor();
   1478     *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
   1479     *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
   1480                     this->getStyle(), this->getTextEncoding());
   1481 
   1482     // now we're done with ptr and the (pre)reserved space. If we need to write
   1483     // additional fields, use the buffer directly
   1484     if (flatFlags & kHasTypeface_FlatFlag) {
   1485         buffer.writeTypeface(this->getTypeface());
   1486     }
   1487     if (flatFlags & kHasEffects_FlatFlag) {
   1488         buffer.writeFlattenable(this->getPathEffect());
   1489         buffer.writeFlattenable(this->getShader());
   1490         buffer.writeFlattenable(this->getXfermode());
   1491         buffer.writeFlattenable(this->getMaskFilter());
   1492         buffer.writeFlattenable(this->getColorFilter());
   1493         buffer.writeFlattenable(this->getRasterizer());
   1494         buffer.writeFlattenable(this->getLooper());
   1495     }
   1496 }
   1497 
   1498 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
   1499     SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
   1500     const void* podData = buffer.skip(kPODPaintSize);
   1501     const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
   1502 
   1503     // the order we read must match the order we wrote in flatten()
   1504     this->setTextSize(read_scalar(pod));
   1505     this->setTextScaleX(read_scalar(pod));
   1506     this->setTextSkewX(read_scalar(pod));
   1507     this->setStrokeWidth(read_scalar(pod));
   1508     this->setStrokeMiter(read_scalar(pod));
   1509     this->setColor(*pod++);
   1510 
   1511     uint32_t tmp = *pod++;
   1512     this->setFlags(tmp >> 16);
   1513     this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
   1514     uint8_t flatFlags = tmp & 0xFF;
   1515 
   1516     tmp = *pod++;
   1517     this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
   1518     this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
   1519     this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
   1520     this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
   1521 
   1522     if (flatFlags & kHasTypeface_FlatFlag) {
   1523         this->setTypeface(buffer.readTypeface());
   1524     } else {
   1525         this->setTypeface(NULL);
   1526     }
   1527 
   1528     if (flatFlags & kHasEffects_FlatFlag) {
   1529         this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
   1530         this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
   1531         this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
   1532         this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
   1533         this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
   1534         this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
   1535         this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
   1536     } else {
   1537         this->setPathEffect(NULL);
   1538         this->setShader(NULL);
   1539         this->setXfermode(NULL);
   1540         this->setMaskFilter(NULL);
   1541         this->setColorFilter(NULL);
   1542         this->setRasterizer(NULL);
   1543         this->setLooper(NULL);
   1544     }
   1545 }
   1546 
   1547 ///////////////////////////////////////////////////////////////////////////////
   1548 
   1549 SkShader* SkPaint::setShader(SkShader* shader)
   1550 {
   1551     SkRefCnt_SafeAssign(fShader, shader);
   1552     return shader;
   1553 }
   1554 
   1555 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter)
   1556 {
   1557     SkRefCnt_SafeAssign(fColorFilter, filter);
   1558     return filter;
   1559 }
   1560 
   1561 SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
   1562 {
   1563     SkRefCnt_SafeAssign(fXfermode, mode);
   1564     return mode;
   1565 }
   1566 
   1567 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
   1568     SkSafeUnref(fXfermode);
   1569     fXfermode = SkXfermode::Create(mode);
   1570     return fXfermode;
   1571 }
   1572 
   1573 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
   1574 {
   1575     SkRefCnt_SafeAssign(fPathEffect, effect);
   1576     return effect;
   1577 }
   1578 
   1579 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter)
   1580 {
   1581     SkRefCnt_SafeAssign(fMaskFilter, filter);
   1582     return filter;
   1583 }
   1584 
   1585 ////////////////////////////////////////////////////////////////////////////////////////
   1586 
   1587 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
   1588 {
   1589     SkPath          effectPath, strokePath;
   1590     const SkPath*   path = &src;
   1591 
   1592     SkScalar width = this->getStrokeWidth();
   1593 
   1594     switch (this->getStyle()) {
   1595     case SkPaint::kFill_Style:
   1596         width = -1; // mark it as no-stroke
   1597         break;
   1598     case SkPaint::kStrokeAndFill_Style:
   1599         if (width == 0)
   1600             width = -1; // mark it as no-stroke
   1601         break;
   1602     case SkPaint::kStroke_Style:
   1603         break;
   1604     default:
   1605         SkASSERT(!"unknown paint style");
   1606     }
   1607 
   1608     if (this->getPathEffect())
   1609     {
   1610         // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
   1611         if (this->getStyle() == SkPaint::kStrokeAndFill_Style)
   1612             width = -1; // mark it as no-stroke
   1613 
   1614         if (this->getPathEffect()->filterPath(&effectPath, src, &width))
   1615             path = &effectPath;
   1616 
   1617         // restore the width if we earlier had to lie, and if we're still set to no-stroke
   1618         // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
   1619         // and we want to respect that (i.e. don't overwrite their setting for width)
   1620         if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0)
   1621         {
   1622             width = this->getStrokeWidth();
   1623             if (width == 0)
   1624                 width = -1;
   1625         }
   1626     }
   1627 
   1628     if (width > 0 && !path->isEmpty())
   1629     {
   1630         SkStroke stroker(*this, width);
   1631         stroker.strokePath(*path, &strokePath);
   1632         path = &strokePath;
   1633     }
   1634 
   1635     if (path == &src)
   1636         *dst = src;
   1637     else
   1638     {
   1639         SkASSERT(path == &effectPath || path == &strokePath);
   1640         dst->swap(*(SkPath*)path);
   1641     }
   1642 
   1643     return width != 0;  // return true if we're filled, or false if we're hairline (width == 0)
   1644 }
   1645 
   1646 const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
   1647                                                SkRect* storage) const {
   1648     SkASSERT(storage);
   1649     SkASSERT(this->getStyle() != SkPaint::kFill_Style);
   1650 
   1651     // since we're stroked, outset the rect by the radius (and join type)
   1652     SkScalar radius = SkScalarHalf(this->getStrokeWidth());
   1653     if (0 == radius) {  // hairline
   1654         radius = SK_Scalar1;
   1655     } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
   1656         SkScalar scale = this->getStrokeMiter();
   1657         if (scale > SK_Scalar1) {
   1658             radius = SkScalarMul(radius, scale);
   1659         }
   1660     }
   1661     storage->set(src.fLeft - radius, src.fTop - radius,
   1662                  src.fRight + radius, src.fBottom + radius);
   1663     return *storage;
   1664 }
   1665 
   1666 ////////////////////////////////////////////////////////////////////////////////////////
   1667 
   1668 static bool has_thick_frame(const SkPaint& paint)
   1669 {
   1670     return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style;
   1671 }
   1672 
   1673 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
   1674                                     const SkPaint& paint,
   1675                                     bool applyStrokeAndPathEffects,
   1676                                     bool forceLinearTextOn)
   1677                                     : fPaint(paint) /* make a copy of the paint */
   1678 {
   1679     fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
   1680                                                 true);
   1681 
   1682     if (forceLinearTextOn)
   1683         fPaint.setLinearText(true);
   1684     fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
   1685 
   1686     if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint))
   1687         applyStrokeAndPathEffects = false;
   1688 
   1689     // can't use our canonical size if we need to apply patheffects/strokes
   1690     if (fPaint.isLinearText() && !applyStrokeAndPathEffects)
   1691     {
   1692         fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
   1693         fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
   1694     }
   1695     else
   1696         fScale = SK_Scalar1;
   1697 
   1698     if (!applyStrokeAndPathEffects)
   1699     {
   1700         fPaint.setStyle(SkPaint::kFill_Style);
   1701         fPaint.setPathEffect(NULL);
   1702     }
   1703 
   1704     fCache = fPaint.detachCache(NULL);
   1705 
   1706     SkPaint::Style  style = SkPaint::kFill_Style;
   1707     SkPathEffect*   pe = NULL;
   1708 
   1709     if (!applyStrokeAndPathEffects)
   1710     {
   1711         style = paint.getStyle();   // restore
   1712         pe = paint.getPathEffect();     // restore
   1713     }
   1714     fPaint.setStyle(style);
   1715     fPaint.setPathEffect(pe);
   1716     fPaint.setMaskFilter(paint.getMaskFilter());    // restore
   1717 
   1718     // now compute fXOffset if needed
   1719 
   1720     SkScalar xOffset = 0;
   1721     if (paint.getTextAlign() != SkPaint::kLeft_Align)   // need to measure first
   1722     {
   1723         int      count;
   1724         SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale);
   1725         if (paint.getTextAlign() == SkPaint::kCenter_Align)
   1726             width = SkScalarHalf(width);
   1727         xOffset = -width;
   1728     }
   1729     fXPos = xOffset;
   1730     fPrevAdvance = 0;
   1731 
   1732     fText = text;
   1733     fStop = text + length;
   1734 }
   1735 
   1736 SkTextToPathIter::~SkTextToPathIter()
   1737 {
   1738     SkGlyphCache::AttachCache(fCache);
   1739 }
   1740 
   1741 const SkPath* SkTextToPathIter::next(SkScalar* xpos)
   1742 {
   1743     while (fText < fStop)
   1744     {
   1745         const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
   1746 
   1747         fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
   1748         fPrevAdvance = glyph.fAdvanceX;   // + fPaint.getTextTracking();
   1749 
   1750         if (glyph.fWidth)
   1751         {
   1752             if (xpos)
   1753                 *xpos = fXPos;
   1754             return fCache->findPath(glyph);
   1755         }
   1756     }
   1757     return NULL;
   1758 }
   1759