aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkScalerContext.cpp
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-02 18:55:44 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-02 18:55:44 +0000
commit5bdfb331ac650cf464baa96a49e2473ee10a515c (patch)
treeffd328cfee5da4bc5fb29be5af06ed97e69086d0 /src/core/SkScalerContext.cpp
parentce3d223cfe1b9dbb694dba6b8826b1fb187e667f (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.cpp60
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)) {