Revert of Simplify draw one glyph (patchset #3 id:40001 of https://codereview.chromiu...
authorherb <herb@google.com>
Tue, 1 Dec 2015 22:14:17 +0000 (14:14 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 1 Dec 2015 22:14:17 +0000 (14:14 -0800)
Reason for revert:
This seems to break nexus 9 release.

Original issue's description:
> Replace D1G with a simpler implementation.
>
> Committed: https://skia.googlesource.com/skia/+/001e74426672e00f3f2783ccf728031662d4a358

TBR=bungeman@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1486723004

src/core/SkDraw.cpp

index 2fa6273112cf0975623755f6a4b04b4a8c386b45..e1a49d39b4a582265dda15c430ffbf95578bc297 100644 (file)
@@ -1423,120 +1423,170 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
-
-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;
+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;
+    }
 
-        int left = Sk48Dot16FloorToInt(fx);
-        int top  = Sk48Dot16FloorToInt(fy);
-        SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
+    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()));
 
-        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;
-        mask.fBounds.set(left, top, right, bottom);
+    SkMask        mask;
+    SkIRect        storage;
+    SkIRect*    bounds = &mask.fBounds;
 
-        if (fUseRegionToDraw) {
-            SkRegion::Cliperator clipper(*fClip, mask.fBounds);
+    mask.fBounds.set(left, top, right, bottom);
 
-            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;
-            }
+    // 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 (this->getImageData(glyph, &mask)) {
-                this->blitMask(mask, *bounds);
-            }
+    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
         }
     }
 
-private:
-    static bool UsingRegionToDraw(const SkRasterClip* rClip) {
-        return rClip->isBW() && !rClip->isRect();
-    }
+    mask.fRowBytes = glyph.rowBytes();
+    mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
+    mask.fImage = aa;
+    state.blitMask(mask, *bounds);
+}
 
-    static SkIRect PickClipBounds(const SkDraw& draw) {
-        const SkRasterClip& rasterClip = *draw.fRC;
+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());
 
-        if (rasterClip.isBW()) {
-            return rasterClip.bwRgn().getBounds();
-        } else {
-            return rasterClip.aaRgn().getBounds();
-        }
-    }
+    SkMask  mask;
 
-    bool getImageData(const SkGlyph& glyph, SkMask* mask) {
-        uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph));
-        if (nullptr == bits) {
-            return false;  // can't rasterize glyph
+    left += glyph.fLeft;
+    top  += glyph.fTop;
+
+    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
+    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
+
+    if (!clipper.done()) {
+        const SkIRect&  cr = clipper.rect();
+        const uint8_t* aa = (uint8_t*)state.fCache->findImage(glyph);
+        if (nullptr == aa) {
+            return;
         }
-        mask->fImage    = bits;
-        mask->fRowBytes = glyph.rowBytes();
-        mask->fFormat   = static_cast<SkMask::Format>(glyph.fMaskFormat);
-        return true;
+
+        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());
     }
+}
 
-    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);
+SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
+                                      const SkPaint& pnt) {
+    fDraw = draw;
+    fBlitter = blitter;
+    fCache = cache;
+    fPaint = &pnt;
 
-            fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint);
+    if (cache->isSubpixel()) {
+        fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
+    } else {
+        fHalfSampleX = fHalfSampleY = SK_ScalarHalf;
+    }
+
+    if (draw->fRC->isBW()) {
+        fAAClip = nullptr;
+        fClip = &draw->fRC->bwRgn();
+        fClipBounds = fClip->getBounds();
+        if (fClip->isRect()) {
+            return D1G_RectClip;
         } else {
-            fBlitter->blitMask(mask, clip);
+            return D1G_RgnClip;
         }
+    } else {    // aaclip
+        fAAClip = &draw->fRC->aaRgn();
+        fClip = nullptr;
+        fClipBounds = fAAClip->getBounds();
+        return D1G_RectClip;
     }
+}
 
-    const bool            fUseRegionToDraw;
-    SkGlyphCache  * const fGlyphCache;
-    SkBlitter     * const fBlitter;
-    const SkRegion* const fClip;
-    const SkDraw&         fDraw;
-    const SkPaint&        fPaint;
-    const SkIRect         fClipBounds;
-};
+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);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 void SkDraw::drawText(const char text[], size_t byteLength,
                       SkScalar x, SkScalar y, const SkPaint& paint) const {
@@ -1556,17 +1606,25 @@ 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());
-    DrawOneGlyph           drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
+
+    SkDraw1Glyph        d1g;
+    SkDraw1Glyph::Proc  proc = d1g.init(this, wrapper.getBlitter(), cache, paint);
 
     SkFindAndPlaceGlyph::ProcessText(
         paint.getTextEncoding(), text, byteLength,
-        {x, y}, *fMatrix, paint.getTextAlign(), cache, drawOneGlyph);
+        {x, y}, *fMatrix, paint.getTextAlign(), cache,
+        [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
+            position += rounding;
+            proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
+        }
+    );
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1638,18 +1696,24 @@ 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());
-    DrawOneGlyph           drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
-    SkPaint::Align         textAlignment = paint.getTextAlign();
+
+    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();
 
     SkFindAndPlaceGlyph::ProcessPosText(
         paint.getTextEncoding(), text, byteLength,
-        offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, drawOneGlyph);
+        offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache,
+        [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
+            position += rounding;
+            proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
+        }
+    );
 }
 
 #if defined _WIN32 && _MSC_VER >= 1300