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