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