diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-02 18:55:44 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-02 18:55:44 +0000 |
commit | 5bdfb331ac650cf464baa96a49e2473ee10a515c (patch) | |
tree | ffd328cfee5da4bc5fb29be5af06ed97e69086d0 /src/core/SkScalerContext.cpp | |
parent | ce3d223cfe1b9dbb694dba6b8826b1fb187e667f (diff) |
Detect color masks, and divert to draw-sprite instead of maskblitters.
Review URL: https://codereview.chromium.org/14637007
git-svn-id: http://skia.googlecode.com/svn/trunk@8967 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkScalerContext.cpp')
-rw-r--r-- | src/core/SkScalerContext.cpp | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index c02dbca93b..fa4f863cee 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -337,6 +337,12 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) { glyph->fMaskFormat = fRec.fMaskFormat; } + // If we are going to create the mask, then we cannot keep the color + if ((fGenerateImageFromPath || fMaskFilter) && + SkMask::kARGB32_Format == glyph->fMaskFormat) { + glyph->fMaskFormat = SkMask::kA8_Format; + } + if (fMaskFilter) { SkMask src, dst; SkMatrix matrix; @@ -515,10 +521,40 @@ static void generateMask(const SkMask& mask, const SkPath& path, } } +static void extract_alpha(const SkMask& dst, + const SkPMColor* srcRow, size_t srcRB) { + int width = dst.fBounds.width(); + int height = dst.fBounds.height(); + int dstRB = dst.fRowBytes; + uint8_t* dstRow = dst.fImage; + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + dstRow[x] = SkGetPackedA32(srcRow[x]); + } + // zero any padding on each row + for (int x = width; x < dstRB; ++x) { + dstRow[x] = 0; + } + dstRow += dstRB; + srcRow = (const SkPMColor*)((const char*)srcRow + srcRB); + } +} + void SkScalerContext::getImage(const SkGlyph& origGlyph) { const SkGlyph* glyph = &origGlyph; SkGlyph tmpGlyph; + // in case we need to call generateImage on a mask-format that is different + // (i.e. larger) than what our caller allocated by looking at origGlyph. + SkAutoMalloc tmpGlyphImageStorage; + + // If we are going to draw-from-path, then we cannot generate color, since + // the path only makes a mask. This case should have been caught up in + // generateMetrics(). + SkASSERT(!fGenerateImageFromPath || + SkMask::kARGB32_Format != origGlyph.fMaskFormat); + if (fMaskFilter) { // restore the prefilter bounds tmpGlyph.init(origGlyph.fID); @@ -528,11 +564,16 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { this->getMetrics(&tmpGlyph); fMaskFilter = mf; // restore - tmpGlyph.fImage = origGlyph.fImage; - // we need the prefilter bounds to be <= filter bounds SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth); SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight); + + if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat) { + tmpGlyph.fImage = origGlyph.fImage; + } else { + tmpGlyphImageStorage.reset(tmpGlyph.computeImageSize()); + tmpGlyph.fImage = tmpGlyphImageStorage.get(); + } glyph = &tmpGlyph; } @@ -557,6 +598,7 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { applyLUTToA8Mask(mask, fPreBlend.fG); } } else { + SkASSERT(SkMask::kARGB32_Format != mask.fFormat); generateMask(mask, devPath, fPreBlend); } } else { @@ -569,7 +611,21 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { // the src glyph image shouldn't be 3D SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat); + + SkAutoSMalloc<32*32> a8storage; glyph->toMask(&srcM); + if (SkMask::kARGB32_Format == srcM.fFormat) { + // now we need to extract the alpha-channel from the glyph's image + // and copy it into a temp buffer, and then point srcM at that temp. + srcM.fFormat = SkMask::kA8_Format; + srcM.fRowBytes = SkAlign4(srcM.fBounds.width()); + size_t size = srcM.computeImageSize(); + a8storage.reset(size); + srcM.fImage = (uint8_t*)a8storage.get(); + extract_alpha(srcM, + (const SkPMColor*)glyph->fImage, glyph->rowBytes()); + } + fRec.getMatrixFrom2x2(&matrix); if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) { |