Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkScalerContext.h"
     11 #include "SkColorPriv.h"
     12 #include "SkDescriptor.h"
     13 #include "SkDraw.h"
     14 #include "SkFontHost.h"
     15 #include "SkMaskFilter.h"
     16 #include "SkPathEffect.h"
     17 #include "SkRasterizer.h"
     18 #include "SkRasterClip.h"
     19 #include "SkStroke.h"
     20 #include "SkThread.h"
     21 
     22 #define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
     23 
     24 void SkGlyph::toMask(SkMask* mask) const {
     25     SkASSERT(mask);
     26 
     27     mask->fImage = (uint8_t*)fImage;
     28     mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
     29     mask->fRowBytes = this->rowBytes();
     30     mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
     31 }
     32 
     33 size_t SkGlyph::computeImageSize() const {
     34     const size_t size = this->rowBytes() * fHeight;
     35 
     36     switch (fMaskFormat) {
     37         case SkMask::k3D_Format:
     38             return 3 * size;
     39         default:
     40             return size;
     41     }
     42 }
     43 
     44 void SkGlyph::zeroMetrics() {
     45     fAdvanceX = 0;
     46     fAdvanceY = 0;
     47     fWidth    = 0;
     48     fHeight   = 0;
     49     fTop      = 0;
     50     fLeft     = 0;
     51     fRsbDelta = 0;
     52     fLsbDelta = 0;
     53 }
     54 
     55 ///////////////////////////////////////////////////////////////////////////////
     56 
     57 #ifdef SK_DEBUG
     58     #define DUMP_RECx
     59 #endif
     60 
     61 static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
     62     SkFlattenable*  obj = NULL;
     63     uint32_t        len;
     64     const void*     data = desc->findEntry(tag, &len);
     65 
     66     if (data) {
     67         SkFlattenableReadBuffer   buffer(data, len);
     68         obj = buffer.readFlattenable();
     69         SkASSERT(buffer.offset() == buffer.size());
     70     }
     71     return obj;
     72 }
     73 
     74 SkScalerContext::SkScalerContext(const SkDescriptor* desc)
     75     : fPathEffect(NULL), fMaskFilter(NULL)
     76 {
     77     fBaseGlyphCount = 0;
     78     fNextContext = NULL;
     79 
     80     const Rec* rec = (const Rec*)desc->findEntry(kRec_SkDescriptorTag, NULL);
     81     SkASSERT(rec);
     82 
     83     fRec = *rec;
     84 
     85 #ifdef DUMP_REC
     86     desc->assertChecksum();
     87     SkDebugf("SkScalarContext checksum %x count %d length %d\n",
     88              desc->getChecksum(), desc->getCount(), desc->getLength());
     89     SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
     90         rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
     91         rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
     92     SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
     93         rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
     94         rec->fMaskFormat, rec->fStrokeJoin);
     95     SkDebugf("  pathEffect %x maskFilter %x\n",
     96              desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
     97         desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
     98 #endif
     99 
    100     fPathEffect = (SkPathEffect*)load_flattenable(desc, kPathEffect_SkDescriptorTag);
    101     fMaskFilter = (SkMaskFilter*)load_flattenable(desc, kMaskFilter_SkDescriptorTag);
    102     fRasterizer = (SkRasterizer*)load_flattenable(desc, kRasterizer_SkDescriptorTag);
    103 
    104     // initialize based on our settings. subclasses can also force this
    105     fGenerateImageFromPath = fRec.fFrameWidth > 0 || fPathEffect != NULL ||
    106                              fRasterizer != NULL;
    107 }
    108 
    109 SkScalerContext::~SkScalerContext() {
    110     SkDELETE(fNextContext);
    111 
    112     SkSafeUnref(fPathEffect);
    113     SkSafeUnref(fMaskFilter);
    114     SkSafeUnref(fRasterizer);
    115 }
    116 
    117 static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
    118     // fonthost will determine the next possible font to search, based
    119     // on the current font in fRec. It will return NULL if ctx is our
    120     // last font that can be searched (i.e. ultimate fallback font)
    121     uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
    122     if (0 == newFontID) {
    123         return NULL;
    124     }
    125 
    126     SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
    127     SkDescriptor*       desc = ad.getDesc();
    128 
    129     desc->init();
    130     SkScalerContext::Rec* newRec =
    131     (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
    132                                           sizeof(rec), &rec);
    133     newRec->fFontID = newFontID;
    134     desc->computeChecksum();
    135 
    136     return SkFontHost::CreateScalerContext(desc);
    137 }
    138 
    139 /*  Return the next context, creating it if its not already created, but return
    140     NULL if the fonthost says there are no more fonts to fallback to.
    141  */
    142 SkScalerContext* SkScalerContext::getNextContext() {
    143     SkScalerContext* next = fNextContext;
    144     // if next is null, then either it isn't cached yet, or we're at the
    145     // end of our possible chain
    146     if (NULL == next) {
    147         next = allocNextContext(fRec);
    148         if (NULL == next) {
    149             return NULL;
    150         }
    151         // next's base is our base + our local count
    152         next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
    153         // cache the answer
    154         fNextContext = next;
    155     }
    156     return next;
    157 }
    158 
    159 SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
    160     unsigned glyphID = glyph.getGlyphID();
    161     SkScalerContext* ctx = this;
    162     for (;;) {
    163         unsigned count = ctx->getGlyphCount();
    164         if (glyphID < count) {
    165             break;
    166         }
    167         glyphID -= count;
    168         ctx = ctx->getNextContext();
    169         if (NULL == ctx) {
    170             SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
    171             // just return the original context (this)
    172             return this;
    173         }
    174     }
    175     return ctx;
    176 }
    177 
    178 #ifdef SK_BUILD_FOR_ANDROID
    179 /*  This loops through all available fallback contexts (if needed) until it
    180     finds some context that can handle the unichar and return it.
    181 
    182     As this is somewhat expensive operation, it should only be done on the first
    183     char of a run.
    184  */
    185 unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
    186     SkScalerContext* ctx = this;
    187     unsigned glyphID;
    188     for (;;) {
    189         glyphID = ctx->generateCharToGlyph(uni);
    190         if (glyphID) {
    191             break;  // found it
    192         }
    193         ctx = ctx->getNextContext();
    194         if (NULL == ctx) {
    195             SkDebugf("--- no context for char %x\n", uni);
    196             // just return the original context (this)
    197             return this->fBaseGlyphCount;
    198         }
    199     }
    200     return ctx->fBaseGlyphCount;
    201 }
    202 #endif
    203 
    204 /*  This loops through all available fallback contexts (if needed) until it
    205     finds some context that can handle the unichar. If all fail, returns 0
    206  */
    207 uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
    208     SkScalerContext* ctx = this;
    209     unsigned glyphID;
    210     for (;;) {
    211         glyphID = ctx->generateCharToGlyph(uni);
    212         if (glyphID) {
    213             break;  // found it
    214         }
    215         ctx = ctx->getNextContext();
    216         if (NULL == ctx) {
    217             return 0;   // no more contexts, return missing glyph
    218         }
    219     }
    220     // add the ctx's base, making glyphID unique for chain of contexts
    221     glyphID += ctx->fBaseGlyphCount;
    222     // check for overflow of 16bits, since our glyphID cannot exceed that
    223     if (glyphID > 0xFFFF) {
    224         glyphID = 0;
    225     }
    226     return SkToU16(glyphID);
    227 }
    228 
    229 SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
    230     SkScalerContext* ctx = this;
    231     unsigned rangeEnd = 0;
    232     do {
    233         unsigned rangeStart = rangeEnd;
    234 
    235         rangeEnd += ctx->getGlyphCount();
    236         if (rangeStart <= glyphID && glyphID < rangeEnd) {
    237             return ctx->generateGlyphToChar(glyphID - rangeStart);
    238         }
    239         ctx = ctx->getNextContext();
    240     } while (NULL != ctx);
    241     return 0;
    242 }
    243 
    244 void SkScalerContext::getAdvance(SkGlyph* glyph) {
    245     // mark us as just having a valid advance
    246     glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
    247     // we mark the format before making the call, in case the impl
    248     // internally ends up calling its generateMetrics, which is OK
    249     // albeit slower than strictly necessary
    250     this->getGlyphContext(*glyph)->generateAdvance(glyph);
    251 }
    252 
    253 void SkScalerContext::getMetrics(SkGlyph* glyph) {
    254     this->getGlyphContext(*glyph)->generateMetrics(glyph);
    255 
    256     // for now we have separate cache entries for devkerning on and off
    257     // in the future we might share caches, but make our measure/draw
    258     // code make the distinction. Thus we zap the values if the caller
    259     // has not asked for them.
    260     if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
    261         // no devkern, so zap the fields
    262         glyph->fLsbDelta = glyph->fRsbDelta = 0;
    263     }
    264 
    265     // if either dimension is empty, zap the image bounds of the glyph
    266     if (0 == glyph->fWidth || 0 == glyph->fHeight) {
    267         glyph->fWidth   = 0;
    268         glyph->fHeight  = 0;
    269         glyph->fTop     = 0;
    270         glyph->fLeft    = 0;
    271         glyph->fMaskFormat = 0;
    272         return;
    273     }
    274 
    275     if (fGenerateImageFromPath) {
    276         SkPath      devPath, fillPath;
    277         SkMatrix    fillToDevMatrix;
    278 
    279         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    280 
    281         if (fRasterizer) {
    282             SkMask  mask;
    283 
    284             if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    285                                        fMaskFilter, &mask,
    286                                        SkMask::kJustComputeBounds_CreateMode)) {
    287                 glyph->fLeft    = mask.fBounds.fLeft;
    288                 glyph->fTop     = mask.fBounds.fTop;
    289                 glyph->fWidth   = SkToU16(mask.fBounds.width());
    290                 glyph->fHeight  = SkToU16(mask.fBounds.height());
    291             } else {
    292                 goto SK_ERROR;
    293             }
    294         } else {
    295             // just use devPath
    296             SkIRect ir;
    297             devPath.getBounds().roundOut(&ir);
    298 
    299             if (ir.isEmpty() || !ir.is16Bit()) {
    300                 goto SK_ERROR;
    301             }
    302             glyph->fLeft    = ir.fLeft;
    303             glyph->fTop     = ir.fTop;
    304             glyph->fWidth   = SkToU16(ir.width());
    305             glyph->fHeight  = SkToU16(ir.height());
    306         }
    307     }
    308 
    309 	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
    310 		glyph->fMaskFormat = fRec.fMaskFormat;
    311 	}
    312 
    313     if (fMaskFilter) {
    314         SkMask      src, dst;
    315         SkMatrix    matrix;
    316 
    317         glyph->toMask(&src);
    318         fRec.getMatrixFrom2x2(&matrix);
    319 
    320         src.fImage = NULL;  // only want the bounds from the filter
    321         if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
    322             SkASSERT(dst.fImage == NULL);
    323             glyph->fLeft    = dst.fBounds.fLeft;
    324             glyph->fTop     = dst.fBounds.fTop;
    325             glyph->fWidth   = SkToU16(dst.fBounds.width());
    326             glyph->fHeight  = SkToU16(dst.fBounds.height());
    327             glyph->fMaskFormat = dst.fFormat;
    328         }
    329     }
    330     return;
    331 
    332 SK_ERROR:
    333     // draw nothing 'cause we failed
    334     glyph->fLeft    = 0;
    335     glyph->fTop     = 0;
    336     glyph->fWidth   = 0;
    337     glyph->fHeight  = 0;
    338     // put a valid value here, in case it was earlier set to
    339     // MASK_FORMAT_JUST_ADVANCE
    340     glyph->fMaskFormat = fRec.fMaskFormat;
    341 }
    342 
    343 static bool isLCD(const SkScalerContext::Rec& rec) {
    344     return SkMask::kLCD16_Format == rec.fMaskFormat ||
    345            SkMask::kLCD32_Format == rec.fMaskFormat;
    346 }
    347 
    348 static uint16_t a8_to_rgb565(unsigned a8) {
    349     return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
    350 }
    351 
    352 static void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
    353     SkASSERT(SkBitmap::kA8_Config == src.config());
    354     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
    355 
    356     const int width = dst.fBounds.width();
    357     const int height = dst.fBounds.height();
    358     const uint8_t* srcP = src.getAddr8(0, 0);
    359     size_t srcRB = src.rowBytes();
    360     uint16_t* dstP = (uint16_t*)dst.fImage;
    361     size_t dstRB = dst.fRowBytes;
    362     for (int y = 0; y < height; ++y) {
    363         for (int x = 0; x < width; ++x) {
    364             dstP[x] = a8_to_rgb565(srcP[x]);
    365         }
    366         srcP += srcRB;
    367         dstP = (uint16_t*)((char*)dstP + dstRB);
    368     }
    369 }
    370 
    371 #define SK_FREETYPE_LCD_LERP    160
    372 
    373 static int lerp(int start, int end) {
    374     SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
    375     return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
    376 }
    377 
    378 static uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
    379     if (SK_FREETYPE_LCD_LERP) {
    380         // want (a+b+c)/3, but we approx to avoid the divide
    381         unsigned ave = (5 * (r + g + b) + g) >> 4;
    382         r = lerp(r, ave);
    383         g = lerp(g, ave);
    384         b = lerp(b, ave);
    385     }
    386     return SkPackRGB16(r >> 3, g >> 2, b >> 3);
    387 }
    388 
    389 static void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst) {
    390     SkASSERT(SkBitmap::kA8_Config == src.config());
    391     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
    392 
    393     const int width = dst.fBounds.width();
    394     const int height = dst.fBounds.height();
    395     uint16_t* dstP = (uint16_t*)dst.fImage;
    396     size_t dstRB = dst.fRowBytes;
    397     for (int y = 0; y < height; ++y) {
    398         const uint8_t* srcP = src.getAddr8(0, y);
    399         for (int x = 0; x < width; ++x) {
    400             unsigned r = *srcP++;
    401             unsigned g = *srcP++;
    402             unsigned b = *srcP++;
    403             dstP[x] = packLCD16(r, g, b);
    404         }
    405         dstP = (uint16_t*)((char*)dstP + dstRB);
    406     }
    407 }
    408 
    409 static void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst) {
    410     SkASSERT(SkBitmap::kA8_Config == src.config());
    411     SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
    412 
    413     const int width = dst.fBounds.width();
    414     const int height = dst.fBounds.height();
    415     SkPMColor* dstP = (SkPMColor*)dst.fImage;
    416     size_t dstRB = dst.fRowBytes;
    417     for (int y = 0; y < height; ++y) {
    418         const uint8_t* srcP = src.getAddr8(0, y);
    419         for (int x = 0; x < width; ++x) {
    420             unsigned r = *srcP++;
    421             unsigned g = *srcP++;
    422             unsigned b = *srcP++;
    423             unsigned a = SkMax32(SkMax32(r, g), b);
    424             dstP[x] = SkPackARGB32(a, r, g, b);
    425         }
    426         dstP = (SkPMColor*)((char*)dstP + dstRB);
    427     }
    428 }
    429 
    430 static void generateMask(const SkMask& mask, const SkPath& path) {
    431     SkBitmap::Config config;
    432     SkPaint     paint;
    433 
    434     int srcW = mask.fBounds.width();
    435     int srcH = mask.fBounds.height();
    436     int dstW = srcW;
    437     int dstH = srcH;
    438     int dstRB = mask.fRowBytes;
    439 
    440     SkMatrix matrix;
    441     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
    442                         -SkIntToScalar(mask.fBounds.fTop));
    443 
    444     if (SkMask::kBW_Format == mask.fFormat) {
    445         config = SkBitmap::kA1_Config;
    446         paint.setAntiAlias(false);
    447     } else {
    448         config = SkBitmap::kA8_Config;
    449         paint.setAntiAlias(true);
    450         switch (mask.fFormat) {
    451             case SkMask::kA8_Format:
    452                 break;
    453             case SkMask::kLCD16_Format:
    454             case SkMask::kLCD32_Format:
    455                 // TODO: trigger off LCD orientation
    456                 dstW *= 3;
    457                 matrix.postScale(SkIntToScalar(3), SK_Scalar1);
    458                 dstRB = 0;  // signals we need a copy
    459                 break;
    460             default:
    461                 SkDEBUGFAIL("unexpected mask format");
    462         }
    463     }
    464 
    465     SkRasterClip clip;
    466     clip.setRect(SkIRect::MakeWH(dstW, dstH));
    467 
    468     SkBitmap bm;
    469     bm.setConfig(config, dstW, dstH, dstRB);
    470 
    471     if (0 == dstRB) {
    472         bm.allocPixels();
    473         bm.lockPixels();
    474     } else {
    475         bm.setPixels(mask.fImage);
    476     }
    477     sk_bzero(bm.getPixels(), bm.getSafeSize());
    478 
    479     SkDraw  draw;
    480     sk_bzero(&draw, sizeof(draw));
    481     draw.fRC    = &clip;
    482     draw.fClip  = &clip.bwRgn();
    483     draw.fMatrix = &matrix;
    484     draw.fBitmap = &bm;
    485     draw.drawPath(path, paint);
    486 
    487     if (0 == dstRB) {
    488         switch (mask.fFormat) {
    489             case SkMask::kLCD16_Format:
    490                 pack3xHToLCD16(bm, mask);
    491                 break;
    492             case SkMask::kLCD32_Format:
    493                 pack3xHToLCD32(bm, mask);
    494                 break;
    495             default:
    496                 SkDEBUGFAIL("bad format for copyback");
    497         }
    498     }
    499 }
    500 
    501 void SkScalerContext::getImage(const SkGlyph& origGlyph) {
    502     const SkGlyph*  glyph = &origGlyph;
    503     SkGlyph         tmpGlyph;
    504 
    505     if (fMaskFilter) {   // restore the prefilter bounds
    506         tmpGlyph.init(origGlyph.fID);
    507 
    508         // need the original bounds, sans our maskfilter
    509         SkMaskFilter* mf = fMaskFilter;
    510         fMaskFilter = NULL;             // temp disable
    511         this->getMetrics(&tmpGlyph);
    512         fMaskFilter = mf;               // restore
    513 
    514         tmpGlyph.fImage = origGlyph.fImage;
    515 
    516         // we need the prefilter bounds to be <= filter bounds
    517         SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
    518         SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
    519         glyph = &tmpGlyph;
    520     }
    521 
    522     if (fGenerateImageFromPath) {
    523         SkPath      devPath, fillPath;
    524         SkMatrix    fillToDevMatrix;
    525         SkMask      mask;
    526 
    527         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    528         glyph->toMask(&mask);
    529 
    530         if (fRasterizer) {
    531             mask.fFormat = SkMask::kA8_Format;
    532             sk_bzero(glyph->fImage, mask.computeImageSize());
    533 
    534             if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    535                                         fMaskFilter, &mask,
    536                                         SkMask::kJustRenderImage_CreateMode)) {
    537                 return;
    538             }
    539         } else {
    540             generateMask(mask, devPath);
    541         }
    542     } else {
    543         this->getGlyphContext(*glyph)->generateImage(*glyph);
    544     }
    545 
    546     if (fMaskFilter) {
    547         SkMask      srcM, dstM;
    548         SkMatrix    matrix;
    549 
    550         // the src glyph image shouldn't be 3D
    551         SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
    552         glyph->toMask(&srcM);
    553         fRec.getMatrixFrom2x2(&matrix);
    554 
    555         if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
    556             int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
    557             int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
    558             int dstRB = origGlyph.rowBytes();
    559             int srcRB = dstM.fRowBytes;
    560 
    561             const uint8_t* src = (const uint8_t*)dstM.fImage;
    562             uint8_t* dst = (uint8_t*)origGlyph.fImage;
    563 
    564             if (SkMask::k3D_Format == dstM.fFormat) {
    565                 // we have to copy 3 times as much
    566                 height *= 3;
    567             }
    568 
    569             // clean out our glyph, since it may be larger than dstM
    570             //sk_bzero(dst, height * dstRB);
    571 
    572             while (--height >= 0) {
    573                 memcpy(dst, src, width);
    574                 src += srcRB;
    575                 dst += dstRB;
    576             }
    577             SkMask::FreeImage(dstM.fImage);
    578         }
    579     }
    580 }
    581 
    582 void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
    583     this->internalGetPath(glyph, NULL, path, NULL);
    584 }
    585 
    586 void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
    587                                      SkPaint::FontMetrics* my) {
    588     this->generateFontMetrics(mx, my);
    589 }
    590 
    591 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
    592     return 0;
    593 }
    594 
    595 ///////////////////////////////////////////////////////////////////////////////
    596 
    597 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
    598                                   SkPath* devPath, SkMatrix* fillToDevMatrix) {
    599     SkPath  path;
    600 
    601     this->getGlyphContext(glyph)->generatePath(glyph, &path);
    602 
    603     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
    604         SkFixed dx = glyph.getSubXFixed();
    605         SkFixed dy = glyph.getSubYFixed();
    606         if (dx | dy) {
    607             path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
    608         }
    609     }
    610 
    611     if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
    612         // need the path in user-space, with only the point-size applied
    613         // so that our stroking and effects will operate the same way they
    614         // would if the user had extracted the path themself, and then
    615         // called drawPath
    616         SkPath      localPath;
    617         SkMatrix    matrix, inverse;
    618 
    619         fRec.getMatrixFrom2x2(&matrix);
    620         matrix.invert(&inverse);
    621         path.transform(inverse, &localPath);
    622         // now localPath is only affected by the paint settings, and not the canvas matrix
    623 
    624         SkScalar width = fRec.fFrameWidth;
    625 
    626         if (fPathEffect) {
    627             SkPath effectPath;
    628 
    629             if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
    630                 localPath.swap(effectPath);
    631             }
    632         }
    633 
    634         if (width > 0) {
    635             SkStroke    stroker;
    636             SkPath      outline;
    637 
    638             stroker.setWidth(width);
    639             stroker.setMiterLimit(fRec.fMiterLimit);
    640             stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
    641             stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
    642             stroker.strokePath(localPath, &outline);
    643             localPath.swap(outline);
    644         }
    645 
    646         // now return stuff to the caller
    647         if (fillToDevMatrix) {
    648             *fillToDevMatrix = matrix;
    649         }
    650         if (devPath) {
    651             localPath.transform(matrix, devPath);
    652         }
    653         if (fillPath) {
    654             fillPath->swap(localPath);
    655         }
    656     } else {   // nothing tricky to do
    657         if (fillToDevMatrix) {
    658             fillToDevMatrix->reset();
    659         }
    660         if (devPath) {
    661             if (fillPath == NULL) {
    662                 devPath->swap(path);
    663             } else {
    664                 *devPath = path;
    665             }
    666         }
    667 
    668         if (fillPath) {
    669             fillPath->swap(path);
    670         }
    671     }
    672 
    673     if (devPath) {
    674         devPath->updateBoundsCache();
    675     }
    676     if (fillPath) {
    677         fillPath->updateBoundsCache();
    678     }
    679 }
    680 
    681 
    682 void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const {
    683     dst->reset();
    684     dst->setScaleX(fPost2x2[0][0]);
    685     dst->setSkewX( fPost2x2[0][1]);
    686     dst->setSkewY( fPost2x2[1][0]);
    687     dst->setScaleY(fPost2x2[1][1]);
    688 }
    689 
    690 void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const {
    691     m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
    692     if (fPreSkewX) {
    693         m->postSkew(fPreSkewX, 0);
    694     }
    695 }
    696 
    697 void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const {
    698     this->getLocalMatrix(m);
    699 
    700     //  now concat the device matrix
    701     SkMatrix    deviceMatrix;
    702     this->getMatrixFrom2x2(&deviceMatrix);
    703     m->postConcat(deviceMatrix);
    704 }
    705 
    706 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
    707     SkASSERT(!matrix.hasPerspective());
    708 
    709     if (0 == matrix[SkMatrix::kMSkewY]) {
    710         return kX_SkAxisAlignment;
    711     }
    712     if (0 == matrix[SkMatrix::kMScaleX]) {
    713         return kY_SkAxisAlignment;
    714     }
    715     return kNone_SkAxisAlignment;
    716 }
    717 
    718 ///////////////////////////////////////////////////////////////////////////////
    719 
    720 #include "SkFontHost.h"
    721 
    722 class SkScalerContext_Empty : public SkScalerContext {
    723 public:
    724     SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
    725 
    726 protected:
    727     virtual unsigned generateGlyphCount() {
    728         return 0;
    729     }
    730     virtual uint16_t generateCharToGlyph(SkUnichar uni) {
    731         return 0;
    732     }
    733     virtual void generateAdvance(SkGlyph* glyph) {
    734         glyph->zeroMetrics();
    735     }
    736     virtual void generateMetrics(SkGlyph* glyph) {
    737         glyph->zeroMetrics();
    738     }
    739     virtual void generateImage(const SkGlyph& glyph) {}
    740     virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
    741     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
    742                                      SkPaint::FontMetrics* my) {
    743         if (mx) {
    744             sk_bzero(mx, sizeof(*mx));
    745         }
    746         if (my) {
    747             sk_bzero(my, sizeof(*my));
    748         }
    749     }
    750 };
    751 
    752 extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
    753 
    754 SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
    755 	SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
    756 	if (NULL == c) {
    757 		c = SkFontHost::CreateScalerContext(desc);
    758 	}
    759     if (NULL == c) {
    760         c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
    761     }
    762     return c;
    763 }
    764 
    765