| 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
|
|
|