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 "SkOrderedWriteBuffer.h"
     20 #include "SkPathEffect.h"
     21 #include "SkRasterizer.h"
     22 #include "SkRasterClip.h"
     23 #include "SkStroke.h"
     24 #include "SkThread.h"
     25 
     26 #ifdef SK_BUILD_FOR_ANDROID
     27     #include "SkTypeface_android.h"
     28 #endif
     29 
     30 #define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
     31 
     32 void SkGlyph::toMask(SkMask* mask) const {
     33     SkASSERT(mask);
     34 
     35     mask->fImage = (uint8_t*)fImage;
     36     mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
     37     mask->fRowBytes = this->rowBytes();
     38     mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
     39 }
     40 
     41 size_t SkGlyph::computeImageSize() const {
     42     const size_t size = this->rowBytes() * fHeight;
     43 
     44     switch (fMaskFormat) {
     45         case SkMask::k3D_Format:
     46             return 3 * size;
     47         default:
     48             return size;
     49     }
     50 }
     51 
     52 void SkGlyph::zeroMetrics() {
     53     fAdvanceX = 0;
     54     fAdvanceY = 0;
     55     fWidth    = 0;
     56     fHeight   = 0;
     57     fTop      = 0;
     58     fLeft     = 0;
     59     fRsbDelta = 0;
     60     fLsbDelta = 0;
     61 }
     62 
     63 ///////////////////////////////////////////////////////////////////////////////
     64 
     65 #ifdef SK_DEBUG
     66     #define DUMP_RECx
     67 #endif
     68 
     69 static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
     70     SkFlattenable*  obj = NULL;
     71     uint32_t        len;
     72     const void*     data = desc->findEntry(tag, &len);
     73 
     74     if (data) {
     75         SkOrderedReadBuffer   buffer(data, len);
     76         obj = buffer.readFlattenable();
     77         SkASSERT(buffer.offset() == buffer.size());
     78     }
     79     return obj;
     80 }
     81 
     82 SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc)
     83     : fRec(*static_cast<const Rec*>(desc->findEntry(kRec_SkDescriptorTag, NULL)))
     84 
     85     , fBaseGlyphCount(0)
     86     , fTypeface(SkRef(typeface))
     87     , fPathEffect(static_cast<SkPathEffect*>(load_flattenable(desc, kPathEffect_SkDescriptorTag)))
     88     , fMaskFilter(static_cast<SkMaskFilter*>(load_flattenable(desc, kMaskFilter_SkDescriptorTag)))
     89     , fRasterizer(static_cast<SkRasterizer*>(load_flattenable(desc, kRasterizer_SkDescriptorTag)))
     90 
     91       // Initialize based on our settings. Subclasses can also force this.
     92     , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL)
     93 
     94     , fNextContext(NULL)
     95 
     96     , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMaskPreBlend(fRec))
     97     , fPreBlendForFilter(fMaskFilter ? SkScalerContext::GetMaskPreBlend(fRec)
     98                                      : SkMaskGamma::PreBlend())
     99 {
    100 #ifdef DUMP_REC
    101     desc->assertChecksum();
    102     SkDebugf("SkScalarContext checksum %x count %d length %d\n",
    103              desc->getChecksum(), desc->getCount(), desc->getLength());
    104     SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
    105         rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
    106         rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
    107     SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
    108         rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
    109         rec->fMaskFormat, rec->fStrokeJoin);
    110     SkDebugf("  pathEffect %x maskFilter %x\n",
    111              desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
    112         desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
    113 #endif
    114 #ifdef SK_BUILD_FOR_ANDROID
    115     uint32_t len;
    116     const void* data = desc->findEntry(kAndroidOpts_SkDescriptorTag, &len);
    117     if (data) {
    118         SkOrderedReadBuffer buffer(data, len);
    119         fPaintOptionsAndroid.unflatten(buffer);
    120         SkASSERT(buffer.offset() == buffer.size());
    121     }
    122 #endif
    123 }
    124 
    125 SkScalerContext::~SkScalerContext() {
    126     SkDELETE(fNextContext);
    127 
    128     SkSafeUnref(fPathEffect);
    129     SkSafeUnref(fMaskFilter);
    130     SkSafeUnref(fRasterizer);
    131 }
    132 
    133 // Return the context associated with the next logical typeface, or NULL if
    134 // there are no more entries in the fallback chain.
    135 SkScalerContext* SkScalerContext::allocNextContext() const {
    136 #ifdef SK_BUILD_FOR_ANDROID
    137     SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID,
    138                                                        fRec.fOrigFontID,
    139                                                        fPaintOptionsAndroid);
    140     if (0 == newFace) {
    141         return NULL;
    142     }
    143 
    144     SkAutoTUnref<SkTypeface> aur(newFace);
    145     uint32_t newFontID = newFace->uniqueID();
    146 
    147     SkOrderedWriteBuffer androidBuffer(128);
    148     fPaintOptionsAndroid.flatten(androidBuffer);
    149 
    150     SkAutoDescriptor    ad(sizeof(fRec) + androidBuffer.size() + SkDescriptor::ComputeOverhead(2));
    151     SkDescriptor*       desc = ad.getDesc();
    152 
    153     desc->init();
    154     SkScalerContext::Rec* newRec =
    155     (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
    156                                           sizeof(fRec), &fRec);
    157     androidBuffer.writeToMemory(desc->addEntry(kAndroidOpts_SkDescriptorTag,
    158                                                androidBuffer.size(), NULL));
    159 
    160     newRec->fFontID = newFontID;
    161     desc->computeChecksum();
    162 
    163     return newFace->createScalerContext(desc);
    164 #else
    165     return NULL;
    166 #endif
    167 }
    168 
    169 /*  Return the next context, creating it if its not already created, but return
    170     NULL if the fonthost says there are no more fonts to fallback to.
    171  */
    172 SkScalerContext* SkScalerContext::getNextContext() {
    173     SkScalerContext* next = fNextContext;
    174     // if next is null, then either it isn't cached yet, or we're at the
    175     // end of our possible chain
    176     if (NULL == next) {
    177         next = this->allocNextContext();
    178         if (NULL == next) {
    179             return NULL;
    180         }
    181         // next's base is our base + our local count
    182         next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
    183         // cache the answer
    184         fNextContext = next;
    185     }
    186     return next;
    187 }
    188 
    189 SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
    190     unsigned glyphID = glyph.getGlyphID();
    191     SkScalerContext* ctx = this;
    192     for (;;) {
    193         unsigned count = ctx->getGlyphCount();
    194         if (glyphID < count) {
    195             break;
    196         }
    197         glyphID -= count;
    198         ctx = ctx->getNextContext();
    199         if (NULL == ctx) {
    200 //            SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
    201             // just return the original context (this)
    202             return this;
    203         }
    204     }
    205     return ctx;
    206 }
    207 
    208 SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni,
    209                                                      uint16_t* glyphID) {
    210     SkScalerContext* ctx = this;
    211     for (;;) {
    212         const uint16_t glyph = ctx->generateCharToGlyph(uni);
    213         if (glyph) {
    214             if (NULL != glyphID) {
    215                 *glyphID = glyph;
    216             }
    217             break;  // found it
    218         }
    219         ctx = ctx->getNextContext();
    220         if (NULL == ctx) {
    221             return NULL;
    222         }
    223     }
    224     return ctx;
    225 }
    226 
    227 #ifdef SK_BUILD_FOR_ANDROID
    228 SkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) {
    229     SkScalerContext* ctx = this->getContextFromChar(uni, NULL);
    230     if (NULL != ctx) {
    231         return ctx->fRec.fFontID;
    232     } else {
    233         return 0;
    234     }
    235 }
    236 
    237 /*  This loops through all available fallback contexts (if needed) until it
    238     finds some context that can handle the unichar and return it.
    239 
    240     As this is somewhat expensive operation, it should only be done on the first
    241     char of a run.
    242  */
    243 unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
    244     SkScalerContext* ctx = this->getContextFromChar(uni, NULL);
    245     if (NULL != ctx) {
    246         return ctx->fBaseGlyphCount;
    247     } else {
    248         SkDEBUGF(("--- no context for char %x\n", uni));
    249         return this->fBaseGlyphCount;
    250     }
    251 }
    252 #endif
    253 
    254 /*  This loops through all available fallback contexts (if needed) until it
    255     finds some context that can handle the unichar. If all fail, returns 0
    256  */
    257 uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
    258 
    259     uint16_t tempID;
    260     SkScalerContext* ctx = this->getContextFromChar(uni, &tempID);
    261     if (NULL == ctx) {
    262         return 0; // no more contexts, return missing glyph
    263     }
    264     // add the ctx's base, making glyphID unique for chain of contexts
    265     unsigned glyphID = tempID + ctx->fBaseGlyphCount;
    266     // check for overflow of 16bits, since our glyphID cannot exceed that
    267     if (glyphID > 0xFFFF) {
    268         glyphID = 0;
    269     }
    270     return SkToU16(glyphID);
    271 }
    272 
    273 SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
    274     SkScalerContext* ctx = this;
    275     unsigned rangeEnd = 0;
    276     do {
    277         unsigned rangeStart = rangeEnd;
    278 
    279         rangeEnd += ctx->getGlyphCount();
    280         if (rangeStart <= glyphID && glyphID < rangeEnd) {
    281             return ctx->generateGlyphToChar(glyphID - rangeStart);
    282         }
    283         ctx = ctx->getNextContext();
    284     } while (NULL != ctx);
    285     return 0;
    286 }
    287 
    288 void SkScalerContext::getAdvance(SkGlyph* glyph) {
    289     // mark us as just having a valid advance
    290     glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
    291     // we mark the format before making the call, in case the impl
    292     // internally ends up calling its generateMetrics, which is OK
    293     // albeit slower than strictly necessary
    294     this->getGlyphContext(*glyph)->generateAdvance(glyph);
    295 }
    296 
    297 void SkScalerContext::getMetrics(SkGlyph* glyph) {
    298     this->getGlyphContext(*glyph)->generateMetrics(glyph);
    299 
    300     // for now we have separate cache entries for devkerning on and off
    301     // in the future we might share caches, but make our measure/draw
    302     // code make the distinction. Thus we zap the values if the caller
    303     // has not asked for them.
    304     if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
    305         // no devkern, so zap the fields
    306         glyph->fLsbDelta = glyph->fRsbDelta = 0;
    307     }
    308 
    309     // if either dimension is empty, zap the image bounds of the glyph
    310     if (0 == glyph->fWidth || 0 == glyph->fHeight) {
    311         glyph->fWidth   = 0;
    312         glyph->fHeight  = 0;
    313         glyph->fTop     = 0;
    314         glyph->fLeft    = 0;
    315         glyph->fMaskFormat = 0;
    316         return;
    317     }
    318 
    319     if (fGenerateImageFromPath) {
    320         SkPath      devPath, fillPath;
    321         SkMatrix    fillToDevMatrix;
    322 
    323         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    324 
    325         if (fRasterizer) {
    326             SkMask  mask;
    327 
    328             if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    329                                        fMaskFilter, &mask,
    330                                        SkMask::kJustComputeBounds_CreateMode)) {
    331                 glyph->fLeft    = mask.fBounds.fLeft;
    332                 glyph->fTop     = mask.fBounds.fTop;
    333                 glyph->fWidth   = SkToU16(mask.fBounds.width());
    334                 glyph->fHeight  = SkToU16(mask.fBounds.height());
    335             } else {
    336                 goto SK_ERROR;
    337             }
    338         } else {
    339             // just use devPath
    340             SkIRect ir;
    341             devPath.getBounds().roundOut(&ir);
    342 
    343             if (ir.isEmpty() || !ir.is16Bit()) {
    344                 goto SK_ERROR;
    345             }
    346             glyph->fLeft    = ir.fLeft;
    347             glyph->fTop     = ir.fTop;
    348             glyph->fWidth   = SkToU16(ir.width());
    349             glyph->fHeight  = SkToU16(ir.height());
    350 
    351             if (glyph->fWidth > 0) {
    352             switch (fRec.fMaskFormat) {
    353             case SkMask::kLCD16_Format:
    354             case SkMask::kLCD32_Format:
    355                 glyph->fWidth += 2;
    356                 glyph->fLeft -= 1;
    357                 break;
    358             default:
    359                 break;
    360             }
    361     }
    362         }
    363     }
    364 
    365     if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
    366         glyph->fMaskFormat = fRec.fMaskFormat;
    367     }
    368 
    369     // If we are going to create the mask, then we cannot keep the color
    370     if ((fGenerateImageFromPath || fMaskFilter) &&
    371             SkMask::kARGB32_Format == glyph->fMaskFormat) {
    372         glyph->fMaskFormat = SkMask::kA8_Format;
    373     }
    374 
    375     if (fMaskFilter) {
    376         SkMask      src, dst;
    377         SkMatrix    matrix;
    378 
    379         glyph->toMask(&src);
    380         fRec.getMatrixFrom2x2(&matrix);
    381 
    382         src.fImage = NULL;  // only want the bounds from the filter
    383         if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
    384             if (dst.fBounds.isEmpty() || !dst.fBounds.is16Bit()) {
    385                 goto SK_ERROR;
    386             }
    387             SkASSERT(dst.fImage == NULL);
    388             glyph->fLeft    = dst.fBounds.fLeft;
    389             glyph->fTop     = dst.fBounds.fTop;
    390             glyph->fWidth   = SkToU16(dst.fBounds.width());
    391             glyph->fHeight  = SkToU16(dst.fBounds.height());
    392             glyph->fMaskFormat = dst.fFormat;
    393         }
    394     }
    395     return;
    396 
    397 SK_ERROR:
    398     // draw nothing 'cause we failed
    399     glyph->fLeft    = 0;
    400     glyph->fTop     = 0;
    401     glyph->fWidth   = 0;
    402     glyph->fHeight  = 0;
    403     // put a valid value here, in case it was earlier set to
    404     // MASK_FORMAT_JUST_ADVANCE
    405     glyph->fMaskFormat = fRec.fMaskFormat;
    406 }
    407 
    408 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
    409 
    410 static void applyLUTToA8Mask(const SkMask& mask, const uint8_t* lut) {
    411     uint8_t* SK_RESTRICT dst = (uint8_t*)mask.fImage;
    412     unsigned rowBytes = mask.fRowBytes;
    413 
    414     for (int y = mask.fBounds.height() - 1; y >= 0; --y) {
    415         for (int x = mask.fBounds.width() - 1; x >= 0; --x) {
    416             dst[x] = lut[dst[x]];
    417         }
    418         dst += rowBytes;
    419     }
    420 }
    421 
    422 template<bool APPLY_PREBLEND>
    423 static void pack4xHToLCD16(const SkBitmap& src, const SkMask& dst,
    424                            const SkMaskGamma::PreBlend& maskPreBlend) {
    425 #define SAMPLES_PER_PIXEL 4
    426 #define LCD_PER_PIXEL 3
    427     SkASSERT(SkBitmap::kA8_Config == src.config());
    428     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
    429 
    430     const int sample_width = src.width();
    431     const int height = src.height();
    432 
    433     uint16_t* dstP = (uint16_t*)dst.fImage;
    434     size_t dstRB = dst.fRowBytes;
    435     // An N tap FIR is defined by
    436     // out[n] = coeff[0]*x[n] + coeff[1]*x[n-1] + ... + coeff[N]*x[n-N]
    437     // or
    438     // out[n] = sum(i, 0, N, coeff[i]*x[n-i])
    439 
    440     // The strategy is to use one FIR (different coefficients) for each of r, g, and b.
    441     // This means using every 4th FIR output value of each FIR and discarding the rest.
    442     // The FIRs are aligned, and the coefficients reach 5 samples to each side of their 'center'.
    443     // (For r and b this is technically incorrect, but the coeffs outside round to zero anyway.)
    444 
    445     // These are in some fixed point repesentation.
    446     // Adding up to more than one simulates ink spread.
    447     // For implementation reasons, these should never add up to more than two.
    448 
    449     // Coefficients determined by a gausian where 5 samples = 3 std deviations (0x110 'contrast').
    450     // Calculated using tools/generate_fir_coeff.py
    451     // With this one almost no fringing is ever seen, but it is imperceptibly blurry.
    452     // The lcd smoothed text is almost imperceptibly different from gray,
    453     // but is still sharper on small stems and small rounded corners than gray.
    454     // This also seems to be about as wide as one can get and only have a three pixel kernel.
    455     // TODO: caculate these at runtime so parameters can be adjusted (esp contrast).
    456     static const unsigned int coefficients[LCD_PER_PIXEL][SAMPLES_PER_PIXEL*3] = {
    457         //The red subpixel is centered inside the first sample (at 1/6 pixel), and is shifted.
    458         { 0x03, 0x0b, 0x1c, 0x33,  0x40, 0x39, 0x24, 0x10,  0x05, 0x01, 0x00, 0x00, },
    459         //The green subpixel is centered between two samples (at 1/2 pixel), so is symetric
    460         { 0x00, 0x02, 0x08, 0x16,  0x2b, 0x3d, 0x3d, 0x2b,  0x16, 0x08, 0x02, 0x00, },
    461         //The blue subpixel is centered inside the last sample (at 5/6 pixel), and is shifted.
    462         { 0x00, 0x00, 0x01, 0x05,  0x10, 0x24, 0x39, 0x40,  0x33, 0x1c, 0x0b, 0x03, },
    463     };
    464 
    465     for (int y = 0; y < height; ++y) {
    466         const uint8_t* srcP = src.getAddr8(0, y);
    467 
    468         // TODO: this fir filter implementation is straight forward, but slow.
    469         // It should be possible to make it much faster.
    470         for (int sample_x = -4, pixel_x = 0; sample_x < sample_width + 4; sample_x += 4, ++pixel_x) {
    471             int fir[LCD_PER_PIXEL] = { 0 };
    472             for (int sample_index = SkMax32(0, sample_x - 4), coeff_index = sample_index - (sample_x - 4)
    473                 ; sample_index < SkMin32(sample_x + 8, sample_width)
    474                 ; ++sample_index, ++coeff_index)
    475             {
    476                 int sample_value = srcP[sample_index];
    477                 for (int subpxl_index = 0; subpxl_index < LCD_PER_PIXEL; ++subpxl_index) {
    478                     fir[subpxl_index] += coefficients[subpxl_index][coeff_index] * sample_value;
    479                 }
    480             }
    481             for (int subpxl_index = 0; subpxl_index < LCD_PER_PIXEL; ++subpxl_index) {
    482                 fir[subpxl_index] /= 0x100;
    483                 fir[subpxl_index] = SkMin32(fir[subpxl_index], 255);
    484             }
    485 
    486             U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(fir[0], maskPreBlend.fR);
    487             U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(fir[1], maskPreBlend.fG);
    488             U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(fir[2], maskPreBlend.fB);
    489 #if SK_SHOW_TEXT_BLIT_COVERAGE
    490             r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
    491 #endif
    492             dstP[pixel_x] = SkPack888ToRGB16(r, g, b);
    493         }
    494         dstP = (uint16_t*)((char*)dstP + dstRB);
    495     }
    496 }
    497 
    498 template<bool APPLY_PREBLEND>
    499 static void pack4xHToLCD32(const SkBitmap& src, const SkMask& dst,
    500                            const SkMaskGamma::PreBlend& maskPreBlend) {
    501     SkASSERT(SkBitmap::kA8_Config == src.config());
    502     SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
    503 
    504     const int width = dst.fBounds.width();
    505     const int height = dst.fBounds.height();
    506     SkPMColor* dstP = (SkPMColor*)dst.fImage;
    507     size_t dstRB = dst.fRowBytes;
    508 
    509     for (int y = 0; y < height; ++y) {
    510         const uint8_t* srcP = src.getAddr8(0, y);
    511 
    512         // TODO: need to use fir filter here as well.
    513         for (int x = 0; x < width; ++x) {
    514             U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fR);
    515             U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fG);
    516             U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fB);
    517             dstP[x] = SkPackARGB32(0xFF, r, g, b);
    518         }
    519         dstP = (SkPMColor*)((char*)dstP + dstRB);
    520     }
    521 }
    522 
    523 static void generateMask(const SkMask& mask, const SkPath& path,
    524                          const SkMaskGamma::PreBlend& maskPreBlend) {
    525     SkBitmap::Config config;
    526     SkPaint     paint;
    527 
    528     int srcW = mask.fBounds.width();
    529     int srcH = mask.fBounds.height();
    530     int dstW = srcW;
    531     int dstH = srcH;
    532     int dstRB = mask.fRowBytes;
    533 
    534     SkMatrix matrix;
    535     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
    536                         -SkIntToScalar(mask.fBounds.fTop));
    537 
    538     if (SkMask::kBW_Format == mask.fFormat) {
    539         config = SkBitmap::kA1_Config;
    540         paint.setAntiAlias(false);
    541     } else {
    542         config = SkBitmap::kA8_Config;
    543         paint.setAntiAlias(true);
    544         switch (mask.fFormat) {
    545             case SkMask::kA8_Format:
    546                 break;
    547             case SkMask::kLCD16_Format:
    548             case SkMask::kLCD32_Format:
    549                 // TODO: trigger off LCD orientation
    550                 dstW = 4*dstW - 8;
    551                 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1),
    552                                     -SkIntToScalar(mask.fBounds.fTop));
    553                 matrix.postScale(SkIntToScalar(4), SK_Scalar1);
    554                 dstRB = 0;  // signals we need a copy
    555                 break;
    556             default:
    557                 SkDEBUGFAIL("unexpected mask format");
    558         }
    559     }
    560 
    561     SkRasterClip clip;
    562     clip.setRect(SkIRect::MakeWH(dstW, dstH));
    563 
    564     SkBitmap bm;
    565     bm.setConfig(config, dstW, dstH, dstRB);
    566 
    567     if (0 == dstRB) {
    568         if (!bm.allocPixels()) {
    569             // can't allocate offscreen, so empty the mask and return
    570             sk_bzero(mask.fImage, mask.computeImageSize());
    571             return;
    572         }
    573         bm.lockPixels();
    574     } else {
    575         bm.setPixels(mask.fImage);
    576     }
    577     sk_bzero(bm.getPixels(), bm.getSafeSize());
    578 
    579     SkDraw  draw;
    580     draw.fRC    = &clip;
    581     draw.fClip  = &clip.bwRgn();
    582     draw.fMatrix = &matrix;
    583     draw.fBitmap = &bm;
    584     draw.drawPath(path, paint);
    585 
    586     switch (mask.fFormat) {
    587         case SkMask::kA8_Format:
    588             if (maskPreBlend.isApplicable()) {
    589                 applyLUTToA8Mask(mask, maskPreBlend.fG);
    590             }
    591             break;
    592         case SkMask::kLCD16_Format:
    593             if (maskPreBlend.isApplicable()) {
    594                 pack4xHToLCD16<true>(bm, mask, maskPreBlend);
    595             } else {
    596                 pack4xHToLCD16<false>(bm, mask, maskPreBlend);
    597             }
    598             break;
    599         case SkMask::kLCD32_Format:
    600             if (maskPreBlend.isApplicable()) {
    601                 pack4xHToLCD32<true>(bm, mask, maskPreBlend);
    602             } else {
    603                 pack4xHToLCD32<false>(bm, mask, maskPreBlend);
    604             }
    605             break;
    606         default:
    607             break;
    608     }
    609 }
    610 
    611 static void extract_alpha(const SkMask& dst,
    612                           const SkPMColor* srcRow, size_t srcRB) {
    613     int width = dst.fBounds.width();
    614     int height = dst.fBounds.height();
    615     int dstRB = dst.fRowBytes;
    616     uint8_t* dstRow = dst.fImage;
    617 
    618     for (int y = 0; y < height; ++y) {
    619         for (int x = 0; x < width; ++x) {
    620             dstRow[x] = SkGetPackedA32(srcRow[x]);
    621         }
    622         // zero any padding on each row
    623         for (int x = width; x < dstRB; ++x) {
    624             dstRow[x] = 0;
    625         }
    626         dstRow += dstRB;
    627         srcRow = (const SkPMColor*)((const char*)srcRow + srcRB);
    628     }
    629 }
    630 
    631 void SkScalerContext::getImage(const SkGlyph& origGlyph) {
    632     const SkGlyph*  glyph = &origGlyph;
    633     SkGlyph         tmpGlyph;
    634 
    635     // in case we need to call generateImage on a mask-format that is different
    636     // (i.e. larger) than what our caller allocated by looking at origGlyph.
    637     SkAutoMalloc tmpGlyphImageStorage;
    638 
    639     // If we are going to draw-from-path, then we cannot generate color, since
    640     // the path only makes a mask. This case should have been caught up in
    641     // generateMetrics().
    642     SkASSERT(!fGenerateImageFromPath ||
    643              SkMask::kARGB32_Format != origGlyph.fMaskFormat);
    644 
    645     if (fMaskFilter) {   // restore the prefilter bounds
    646         tmpGlyph.init(origGlyph.fID);
    647 
    648         // need the original bounds, sans our maskfilter
    649         SkMaskFilter* mf = fMaskFilter;
    650         fMaskFilter = NULL;             // temp disable
    651         this->getMetrics(&tmpGlyph);
    652         fMaskFilter = mf;               // restore
    653 
    654         // we need the prefilter bounds to be <= filter bounds
    655         SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
    656         SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
    657 
    658         if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat) {
    659             tmpGlyph.fImage = origGlyph.fImage;
    660         } else {
    661             tmpGlyphImageStorage.reset(tmpGlyph.computeImageSize());
    662             tmpGlyph.fImage = tmpGlyphImageStorage.get();
    663         }
    664         glyph = &tmpGlyph;
    665     }
    666 
    667     if (fGenerateImageFromPath) {
    668         SkPath      devPath, fillPath;
    669         SkMatrix    fillToDevMatrix;
    670         SkMask      mask;
    671 
    672         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    673         glyph->toMask(&mask);
    674 
    675         if (fRasterizer) {
    676             mask.fFormat = SkMask::kA8_Format;
    677             sk_bzero(glyph->fImage, mask.computeImageSize());
    678 
    679             if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    680                                         fMaskFilter, &mask,
    681                                         SkMask::kJustRenderImage_CreateMode)) {
    682                 return;
    683             }
    684             if (fPreBlend.isApplicable()) {
    685                 applyLUTToA8Mask(mask, fPreBlend.fG);
    686             }
    687         } else {
    688             SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
    689             generateMask(mask, devPath, fPreBlend);
    690         }
    691     } else {
    692         this->getGlyphContext(*glyph)->generateImage(*glyph);
    693     }
    694 
    695     if (fMaskFilter) {
    696         SkMask      srcM, dstM;
    697         SkMatrix    matrix;
    698 
    699         // the src glyph image shouldn't be 3D
    700         SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
    701 
    702         SkAutoSMalloc<32*32> a8storage;
    703         glyph->toMask(&srcM);
    704         if (SkMask::kARGB32_Format == srcM.fFormat) {
    705             // now we need to extract the alpha-channel from the glyph's image
    706             // and copy it into a temp buffer, and then point srcM at that temp.
    707             srcM.fFormat = SkMask::kA8_Format;
    708             srcM.fRowBytes = SkAlign4(srcM.fBounds.width());
    709             size_t size = srcM.computeImageSize();
    710             a8storage.reset(size);
    711             srcM.fImage = (uint8_t*)a8storage.get();
    712             extract_alpha(srcM,
    713                           (const SkPMColor*)glyph->fImage, glyph->rowBytes());
    714         }
    715 
    716         fRec.getMatrixFrom2x2(&matrix);
    717 
    718         if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
    719             int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
    720             int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
    721             int dstRB = origGlyph.rowBytes();
    722             int srcRB = dstM.fRowBytes;
    723 
    724             const uint8_t* src = (const uint8_t*)dstM.fImage;
    725             uint8_t* dst = (uint8_t*)origGlyph.fImage;
    726 
    727             if (SkMask::k3D_Format == dstM.fFormat) {
    728                 // we have to copy 3 times as much
    729                 height *= 3;
    730             }
    731 
    732             // clean out our glyph, since it may be larger than dstM
    733             //sk_bzero(dst, height * dstRB);
    734 
    735             while (--height >= 0) {
    736                 memcpy(dst, src, width);
    737                 src += srcRB;
    738                 dst += dstRB;
    739             }
    740             SkMask::FreeImage(dstM.fImage);
    741 
    742             if (fPreBlendForFilter.isApplicable()) {
    743                 applyLUTToA8Mask(srcM, fPreBlendForFilter.fG);
    744             }
    745         }
    746     }
    747 }
    748 
    749 void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
    750     this->internalGetPath(glyph, NULL, path, NULL);
    751 }
    752 
    753 void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* fm) {
    754     // All of this complexity should go away when we change generateFontMetrics
    755     // to just take one parameter (since it knows if it is vertical or not)
    756     SkPaint::FontMetrics* mx = NULL;
    757     SkPaint::FontMetrics* my = NULL;
    758     if (fRec.fFlags & kVertical_Flag) {
    759         mx = fm;
    760     } else {
    761         my = fm;
    762     }
    763     this->generateFontMetrics(mx, my);
    764 }
    765 
    766 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
    767     return 0;
    768 }
    769 
    770 ///////////////////////////////////////////////////////////////////////////////
    771 
    772 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
    773                                   SkPath* devPath, SkMatrix* fillToDevMatrix) {
    774     SkPath  path;
    775 
    776     this->getGlyphContext(glyph)->generatePath(glyph, &path);
    777 
    778     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
    779         SkFixed dx = glyph.getSubXFixed();
    780         SkFixed dy = glyph.getSubYFixed();
    781         if (dx | dy) {
    782             path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
    783         }
    784     }
    785 
    786     if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
    787         // need the path in user-space, with only the point-size applied
    788         // so that our stroking and effects will operate the same way they
    789         // would if the user had extracted the path themself, and then
    790         // called drawPath
    791         SkPath      localPath;
    792         SkMatrix    matrix, inverse;
    793 
    794         fRec.getMatrixFrom2x2(&matrix);
    795         if (!matrix.invert(&inverse)) {
    796             // assume fillPath and devPath are already empty.
    797             return;
    798         }
    799         path.transform(inverse, &localPath);
    800         // now localPath is only affected by the paint settings, and not the canvas matrix
    801 
    802         SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
    803 
    804         if (fRec.fFrameWidth > 0) {
    805             rec.setStrokeStyle(fRec.fFrameWidth,
    806                                SkToBool(fRec.fFlags & kFrameAndFill_Flag));
    807             // glyphs are always closed contours, so cap type is ignored,
    808             // so we just pass something.
    809             rec.setStrokeParams(SkPaint::kButt_Cap,
    810                                 (SkPaint::Join)fRec.fStrokeJoin,
    811                                 fRec.fMiterLimit);
    812         }
    813 
    814         if (fPathEffect) {
    815             SkPath effectPath;
    816             if (fPathEffect->filterPath(&effectPath, localPath, &rec, NULL)) {
    817                 localPath.swap(effectPath);
    818             }
    819         }
    820 
    821         if (rec.needToApply()) {
    822             SkPath strokePath;
    823             if (rec.applyToPath(&strokePath, localPath)) {
    824                 localPath.swap(strokePath);
    825             }
    826         }
    827 
    828         // now return stuff to the caller
    829         if (fillToDevMatrix) {
    830             *fillToDevMatrix = matrix;
    831         }
    832         if (devPath) {
    833             localPath.transform(matrix, devPath);
    834         }
    835         if (fillPath) {
    836             fillPath->swap(localPath);
    837         }
    838     } else {   // nothing tricky to do
    839         if (fillToDevMatrix) {
    840             fillToDevMatrix->reset();
    841         }
    842         if (devPath) {
    843             if (fillPath == NULL) {
    844                 devPath->swap(path);
    845             } else {
    846                 *devPath = path;
    847             }
    848         }
    849 
    850         if (fillPath) {
    851             fillPath->swap(path);
    852         }
    853     }
    854 
    855     if (devPath) {
    856         devPath->updateBoundsCache();
    857     }
    858     if (fillPath) {
    859         fillPath->updateBoundsCache();
    860     }
    861 }
    862 
    863 
    864 void SkScalerContextRec::getMatrixFrom2x2(SkMatrix* dst) const {
    865     dst->setAll(fPost2x2[0][0], fPost2x2[0][1], 0,
    866                 fPost2x2[1][0], fPost2x2[1][1], 0,
    867                 0,              0,              SkScalarToPersp(SK_Scalar1));
    868 }
    869 
    870 void SkScalerContextRec::getLocalMatrix(SkMatrix* m) const {
    871     SkPaint::SetTextMatrix(m, fTextSize, fPreScaleX, fPreSkewX);
    872 }
    873 
    874 void SkScalerContextRec::getSingleMatrix(SkMatrix* m) const {
    875     this->getLocalMatrix(m);
    876 
    877     //  now concat the device matrix
    878     SkMatrix    deviceMatrix;
    879     this->getMatrixFrom2x2(&deviceMatrix);
    880     m->postConcat(deviceMatrix);
    881 }
    882 
    883 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
    884     SkASSERT(!matrix.hasPerspective());
    885 
    886     if (0 == matrix[SkMatrix::kMSkewY]) {
    887         return kX_SkAxisAlignment;
    888     }
    889     if (0 == matrix[SkMatrix::kMScaleX]) {
    890         return kY_SkAxisAlignment;
    891     }
    892     return kNone_SkAxisAlignment;
    893 }
    894 
    895 ///////////////////////////////////////////////////////////////////////////////
    896 
    897 #include "SkFontHost.h"
    898 
    899 class SkScalerContext_Empty : public SkScalerContext {
    900 public:
    901     SkScalerContext_Empty(SkTypeface* face, const SkDescriptor* desc)
    902         : SkScalerContext(face, desc) {}
    903 
    904 protected:
    905     virtual unsigned generateGlyphCount() SK_OVERRIDE {
    906         return 0;
    907     }
    908     virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE {
    909         return 0;
    910     }
    911     virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE {
    912         glyph->zeroMetrics();
    913     }
    914     virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE {
    915         glyph->zeroMetrics();
    916     }
    917     virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE {}
    918     virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE {}
    919     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
    920                                      SkPaint::FontMetrics* my) SK_OVERRIDE {
    921         if (mx) {
    922             sk_bzero(mx, sizeof(*mx));
    923         }
    924         if (my) {
    925             sk_bzero(my, sizeof(*my));
    926         }
    927     }
    928 };
    929 
    930 extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
    931 
    932 SkScalerContext* SkTypeface::createScalerContext(const SkDescriptor* desc,
    933                                                  bool allowFailure) const {
    934     SkScalerContext* c = this->onCreateScalerContext(desc);
    935 
    936     if (!c && !allowFailure) {
    937         c = SkNEW_ARGS(SkScalerContext_Empty,
    938                        (const_cast<SkTypeface*>(this), desc));
    939     }
    940     return c;
    941 }
    942