gfx/skia/trunk/src/core/SkScalerContext.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial