Index: src/core/SkDraw.cpp |
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp |
index e1a49d39b4a582265dda15c430ffbf95578bc297..2fa6273112cf0975623755f6a4b04b4a8c386b45 100644 |
--- a/src/core/SkDraw.cpp |
+++ b/src/core/SkDraw.cpp |
@@ -1423,170 +1423,120 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength, |
#endif |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
-struct SkDraw1Glyph { |
- const SkDraw* fDraw; |
- const SkRegion* fClip; |
- const SkAAClip* fAAClip; |
- SkBlitter* fBlitter; |
- SkGlyphCache* fCache; |
- const SkPaint* fPaint; |
- SkIRect fClipBounds; |
- /** Half the sampling frequency of the rasterized glyph in x. */ |
- SkScalar fHalfSampleX; |
- /** Half the sampling frequency of the rasterized glyph in y. */ |
- SkScalar fHalfSampleY; |
- |
- /** Draws one glyph. |
- * |
- * The x and y are pre-biased, so implementations may just truncate them. |
- * i.e. half the sampling frequency has been added. |
- * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added. |
- * This added bias can be found in fHalfSampleX,Y. |
- */ |
- typedef void (*Proc)(const SkDraw1Glyph&, Sk48Dot16 x, Sk48Dot16 y, const SkGlyph&); |
- |
- 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; |
-}; |
-static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, |
- const SkGlyph& glyph) { |
- // Prevent glyphs from being drawn outside of or straddling the edge of device space. |
- if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || |
- (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) || |
- (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || |
- (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) |
- { |
- return; |
- } |
+class DrawOneGlyph { |
+public: |
+ DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter) |
+ : fUseRegionToDraw(UsingRegionToDraw(draw.fRC)) |
+ , fGlyphCache(cache) |
+ , fBlitter(blitter) |
+ , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr) |
+ , fDraw(draw) |
+ , fPaint(paint) |
+ , fClipBounds(PickClipBounds(draw)) { } |
+ |
+ void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) { |
+ position += rounding; |
+ Sk48Dot16 fx = SkScalarTo48Dot16(position.fX); |
+ Sk48Dot16 fy = SkScalarTo48Dot16(position.fY); |
+ // Prevent glyphs from being drawn outside of or straddling the edge of device space. |
+ if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || |
+ (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) || |
+ (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || |
+ (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) { |
+ return; |
+ } |
- int left = Sk48Dot16FloorToInt(fx); |
- int top = Sk48Dot16FloorToInt(fy); |
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); |
- SkASSERT((nullptr == state.fClip && state.fAAClip) || |
- (state.fClip && nullptr == state.fAAClip && state.fClip->isRect())); |
+ int left = Sk48Dot16FloorToInt(fx); |
+ int top = Sk48Dot16FloorToInt(fy); |
+ SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); |
- left += glyph.fLeft; |
- top += glyph.fTop; |
+ left += glyph.fLeft; |
+ top += glyph.fTop; |
- int right = left + glyph.fWidth; |
- int bottom = top + glyph.fHeight; |
+ int right = left + glyph.fWidth; |
+ int bottom = top + glyph.fHeight; |
- SkMask mask; |
- SkIRect storage; |
- SkIRect* bounds = &mask.fBounds; |
+ SkMask mask; |
+ mask.fBounds.set(left, top, right, bottom); |
- mask.fBounds.set(left, top, right, bottom); |
+ if (fUseRegionToDraw) { |
+ SkRegion::Cliperator clipper(*fClip, mask.fBounds); |
- // this extra test is worth it, assuming that most of the time it succeeds |
- // since we can avoid writing to storage |
- if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { |
- if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) |
- return; |
- bounds = &storage; |
- } |
+ if (!clipper.done() && this->getImageData(glyph, &mask)) { |
+ const SkIRect& cr = clipper.rect(); |
+ do { |
+ this->blitMask(mask, cr); |
+ clipper.next(); |
+ } while (!clipper.done()); |
+ } |
+ } else { |
+ SkIRect storage; |
+ SkIRect* bounds = &mask.fBounds; |
+ |
+ // this extra test is worth it, assuming that most of the time it succeeds |
+ // since we can avoid writing to storage |
+ if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) { |
+ if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds)) |
+ return; |
+ bounds = &storage; |
+ } |
- uint8_t* aa = (uint8_t*)glyph.fImage; |
- if (nullptr == aa) { |
- aa = (uint8_t*)state.fCache->findImage(glyph); |
- if (nullptr == aa) { |
- return; // can't rasterize glyph |
+ if (this->getImageData(glyph, &mask)) { |
+ this->blitMask(mask, *bounds); |
+ } |
} |
} |
- mask.fRowBytes = glyph.rowBytes(); |
- mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); |
- mask.fImage = aa; |
- state.blitMask(mask, *bounds); |
-} |
- |
-static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, |
- const SkGlyph& glyph) { |
- int left = Sk48Dot16FloorToInt(fx); |
- int top = Sk48Dot16FloorToInt(fy); |
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); |
- SkASSERT(!state.fClip->isRect()); |
- |
- SkMask mask; |
- |
- left += glyph.fLeft; |
- top += glyph.fTop; |
+private: |
+ static bool UsingRegionToDraw(const SkRasterClip* rClip) { |
+ return rClip->isBW() && !rClip->isRect(); |
+ } |
- mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); |
- SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); |
+ static SkIRect PickClipBounds(const SkDraw& draw) { |
+ const SkRasterClip& rasterClip = *draw.fRC; |
- if (!clipper.done()) { |
- const SkIRect& cr = clipper.rect(); |
- const uint8_t* aa = (uint8_t*)state.fCache->findImage(glyph); |
- if (nullptr == aa) { |
- return; |
+ if (rasterClip.isBW()) { |
+ return rasterClip.bwRgn().getBounds(); |
+ } else { |
+ return rasterClip.aaRgn().getBounds(); |
} |
- |
- mask.fRowBytes = glyph.rowBytes(); |
- mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); |
- mask.fImage = (uint8_t*)aa; |
- do { |
- state.blitMask(mask, cr); |
- clipper.next(); |
- } while (!clipper.done()); |
} |
-} |
- |
-SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, |
- const SkPaint& pnt) { |
- fDraw = draw; |
- fBlitter = blitter; |
- fCache = cache; |
- fPaint = &pnt; |
- if (cache->isSubpixel()) { |
- fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); |
- } else { |
- fHalfSampleX = fHalfSampleY = SK_ScalarHalf; |
+ bool getImageData(const SkGlyph& glyph, SkMask* mask) { |
+ uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph)); |
+ if (nullptr == bits) { |
+ return false; // can't rasterize glyph |
+ } |
+ mask->fImage = bits; |
+ mask->fRowBytes = glyph.rowBytes(); |
+ mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); |
+ return true; |
} |
- if (draw->fRC->isBW()) { |
- fAAClip = nullptr; |
- fClip = &draw->fRC->bwRgn(); |
- fClipBounds = fClip->getBounds(); |
- if (fClip->isRect()) { |
- return D1G_RectClip; |
+ void blitMask(const SkMask& mask, const SkIRect& clip) const { |
+ if (SkMask::kARGB32_Format == mask.fFormat) { |
+ SkBitmap bm; |
+ bm.installPixels( |
+ SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), |
+ (SkPMColor*)mask.fImage, mask.fRowBytes); |
+ |
+ fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint); |
} else { |
- return D1G_RgnClip; |
+ fBlitter->blitMask(mask, clip); |
} |
- } else { // aaclip |
- fAAClip = &draw->fRC->aaRgn(); |
- fClip = nullptr; |
- fClipBounds = fAAClip->getBounds(); |
- return D1G_RectClip; |
} |
-} |
- |
-void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const { |
- SkASSERT(SkMask::kARGB32_Format == mask.fFormat); |
- SkBitmap bm; |
- bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), |
- (SkPMColor*)mask.fImage, mask.fRowBytes); |
- |
- fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint); |
-} |
+ const bool fUseRegionToDraw; |
+ SkGlyphCache * const fGlyphCache; |
+ SkBlitter * const fBlitter; |
+ const SkRegion* const fClip; |
+ const SkDraw& fDraw; |
+ const SkPaint& fPaint; |
+ const SkIRect fClipBounds; |
+}; |
-/////////////////////////////////////////////////////////////////////////////// |
+//////////////////////////////////////////////////////////////////////////////////////////////////// |
void SkDraw::drawText(const char text[], size_t byteLength, |
SkScalar x, SkScalar y, const SkPaint& paint) const { |
@@ -1606,25 +1556,17 @@ void SkDraw::drawText(const char text[], size_t byteLength, |
return; |
} |
- SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); |
- SkGlyphCache* cache = autoCache.getCache(); |
- |
+ SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); |
+ SkGlyphCache* cache = autoCache.getCache(); |
// The Blitter Choose needs to be live while using the blitter below. |
SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); |
SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); |
- |
- SkDraw1Glyph d1g; |
- SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint); |
+ DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter()); |
SkFindAndPlaceGlyph::ProcessText( |
paint.getTextEncoding(), text, byteLength, |
- {x, y}, *fMatrix, paint.getTextAlign(), cache, |
- [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { |
- position += rounding; |
- proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph); |
- } |
- ); |
+ {x, y}, *fMatrix, paint.getTextAlign(), cache, drawOneGlyph); |
} |
////////////////////////////////////////////////////////////////////////////// |
@@ -1696,24 +1638,18 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, |
return; |
} |
+ SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); |
+ SkGlyphCache* cache = autoCache.getCache(); |
+ |
// The Blitter Choose needs to be live while using the blitter below. |
SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); |
SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); |
- |
- SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); |
- SkGlyphCache* cache = autoCache.getCache(); |
- SkDraw1Glyph d1g; |
- SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint); |
- SkPaint::Align textAlignment = paint.getTextAlign(); |
+ DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter()); |
+ SkPaint::Align textAlignment = paint.getTextAlign(); |
SkFindAndPlaceGlyph::ProcessPosText( |
paint.getTextEncoding(), text, byteLength, |
- offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, |
- [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { |
- position += rounding; |
- proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph); |
- } |
- ); |
+ offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, drawOneGlyph); |
} |
#if defined _WIN32 && _MSC_VER >= 1300 |