uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
return row + (x - fBounds.fLeft);
}
-
+
+ /**
+ * Return the address of the specified 32bit mask. In the debug build,
+ * this asserts that the mask's format is 32bits, and that (x,y)
+ * are contained in the mask's fBounds.
+ */
+ uint32_t* getAddr32(int x, int y) const {
+ SkASSERT(kLCD32_Format == fFormat || kARGB32_Format == fFormat);
+ SkASSERT(fBounds.contains(x, y));
+ SkASSERT(fImage != NULL);
+ uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes);
+ return row + (x - fBounds.fLeft);
+ }
+
/**
* Returns the address of the specified pixel, computing the pixel-size
* at runtime based on the mask format. This will be slightly slower than
mask.fRowBytes = glyph.rowBytes();
mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
mask.fImage = aa;
- state.fBlitter->blitMask(mask, *bounds);
+ state.blitMask(mask, *bounds);
}
static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
mask.fImage = (uint8_t*)aa;
do {
- state.fBlitter->blitMask(mask, cr);
+ state.blitMask(mask, cr);
clipper.next();
} while (!clipper.done());
}
mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
mask.fImage = (uint8_t*)aa;
do {
- state.fBlitter->blitMask(mask, cr);
+ state.blitMask(mask, cr);
clipper.next();
} while (!clipper.done());
}
}
SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
- SkGlyphCache* cache) {
+ SkGlyphCache* cache, const SkPaint& pnt) {
fDraw = draw;
fBounder = draw->fBounder;
fBlitter = blitter;
fCache = cache;
+ fPaint = &pnt;
if (cache->isSubpixel()) {
fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
}
}
+void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
+ SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
+
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config,
+ mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
+ bm.setPixels((SkPMColor*)mask.fImage);
+
+ fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
+}
+
///////////////////////////////////////////////////////////////////////////////
void SkDraw::drawText(const char text[], size_t byteLength,
SkAutoKern autokern;
SkDraw1Glyph d1g;
- SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache);
+ SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
SkFixed fxMask = ~0;
SkFixed fyMask = ~0;
const char* stop = text + byteLength;
AlignProc alignProc = pick_align_proc(paint.getTextAlign());
SkDraw1Glyph d1g;
- SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache);
+ SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
TextMapState tms(*fMatrix, constY);
TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
#ifndef SkDrawProcs_DEFINED
#define SkDrawProcs_DEFINED
+#include "SkBlitter.h"
#include "SkDraw.h"
class SkAAClip;
const SkAAClip* fAAClip;
SkBlitter* fBlitter;
SkGlyphCache* fCache;
+ const SkPaint* fPaint;
SkIRect fClipBounds;
/** Half the sampling frequency of the rasterized glyph in x. */
SkFixed fHalfSampleX;
*/
typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&);
- Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache);
+ Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
+ const SkPaint&);
+
+ // call this instead of fBlitter->blitMask() since this wrapper will handle
+ // the case when the mask is ARGB32_Format
+ //
+ void blitMask(const SkMask& mask, const SkIRect& clip) const {
+ if (SkMask::kARGB32_Format == mask.fFormat) {
+ this->blitMaskAsSprite(mask);
+ } else {
+ fBlitter->blitMask(mask, clip);
+ }
+ }
+
+ // mask must be kARGB32_Format
+ void blitMaskAsSprite(const SkMask& mask) const;
};
struct SkDrawProcs {
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;
}
}
+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);
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;
}
applyLUTToA8Mask(mask, fPreBlend.fG);
}
} else {
+ SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
generateMask(mask, devPath, fPreBlend);
}
} else {
// 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)) {