diff options
author | Mike Reed <reed@google.com> | 2018-03-07 14:16:52 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-03-07 19:39:00 +0000 |
commit | b5e1f7558052cc60deaf23ccc2c898d1c6c94c09 (patch) | |
tree | b3ee26c7341dc9757ed02e91e3d30b4de32c2b90 | |
parent | d2e9f767bbb1a7664e9ee83d0755d7e4327cb7b2 (diff) |
Revert "Revert "add tiler for SkDraw""
This reverts commit 461ef7af88cc966007c464130a971ec86c803f1d.
Prev CL to SkScan_Hairline.cpp fixed the bug that caused the earlier revert.
Bug: skia:
Change-Id: Ifd9a364c7546175be292f726e19465b72196b45e
Reviewed-on: https://skia-review.googlesource.com/112723
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
-rw-r--r-- | gm/hugepath.cpp | 33 | ||||
-rw-r--r-- | gn/core.gni | 1 | ||||
-rw-r--r-- | gn/tests.gni | 1 | ||||
-rw-r--r-- | src/core/SkBitmapDevice.cpp | 160 | ||||
-rw-r--r-- | src/core/SkBitmapDevice.h | 1 | ||||
-rw-r--r-- | src/core/SkDeviceLooper.cpp | 126 | ||||
-rw-r--r-- | src/core/SkDeviceLooper.h | 95 | ||||
-rw-r--r-- | src/core/SkDraw.cpp | 74 | ||||
-rw-r--r-- | tests/DeviceLooperTest.cpp | 139 |
9 files changed, 198 insertions, 432 deletions
diff --git a/gm/hugepath.cpp b/gm/hugepath.cpp index 83dff9ec3e..4a691b8182 100644 --- a/gm/hugepath.cpp +++ b/gm/hugepath.cpp @@ -8,6 +8,7 @@ #include "gm.h" #include "SkCanvas.h" #include "SkPath.h" +#include "SkSurface.h" DEF_SIMPLE_GM(path_huge_crbug_800804, canvas, 50, 600) { SkPaint paint; @@ -35,3 +36,35 @@ DEF_SIMPLE_GM(path_huge_crbug_800804, canvas, 50, 600) { } } +// Test that we can draw into a huge surface ( > 64K ) and still retain paths and antialiasing. +DEF_SIMPLE_GM(path_huge_aa, canvas, 200, 200) { + auto proc = [](SkCanvas* canvas, int w, int h) { + SkAutoCanvasRestore acr(canvas, true); + + auto surf = SkSurface::MakeRasterN32Premul(w, h); + auto can = surf->getCanvas(); + + SkPaint paint; + SkPath path; + path.addRoundRect(SkRect::MakeXYWH(4, 4, w - 8, h - 8), 12, 12); + + canvas->save(); + canvas->clipRect(SkRect::MakeXYWH(4, 4, 64, 64)); + can->drawPath(path, paint); + surf->draw(canvas, 64 - w, 0, nullptr); + canvas->restore(); + + canvas->translate(80, 0); + canvas->save(); + canvas->clipRect(SkRect::MakeXYWH(4, 4, 64, 64)); + can->clear(0); + paint.setAntiAlias(true); + can->drawPath(path, paint); + surf->draw(canvas, 64 - w, 0, nullptr); + canvas->restore(); + }; + + proc(canvas, 100, 60); + canvas->translate(0, 80); + proc(canvas, 100 * 1024, 60); +} diff --git a/gn/core.gni b/gn/core.gni index 12a74ae93b..3d1b399313 100644 --- a/gn/core.gni +++ b/gn/core.gni @@ -106,7 +106,6 @@ skia_core_sources = [ "$_src/core/SkDescriptor.h", "$_src/core/SkDevice.cpp", "$_src/core/SkDevice.h", - "$_src/core/SkDeviceLooper.cpp", "$_src/core/SkDeviceProfile.cpp", "$_src/core/SkDiscardableMemory.h", "$_src/lazy/SkDiscardableMemoryPool.cpp", diff --git a/gn/tests.gni b/gn/tests.gni index 50cca5487e..cde24b0ea3 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -53,7 +53,6 @@ tests_sources = [ "$_tests/DeferredDisplayListTest.cpp", "$_tests/DequeTest.cpp", "$_tests/DetermineDomainModeTest.cpp", - "$_tests/DeviceLooperTest.cpp", "$_tests/DeviceTest.cpp", "$_tests/DFPathRendererTest.cpp", "$_tests/DiscardableMemoryPoolTest.cpp", diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 3d66ba6dfc..219724451a 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -23,6 +23,116 @@ #include "SkTLazy.h" #include "SkVertices.h" +class SkDrawTiler { + enum { + // 8K is 1 too big, since 8K << supersample == 32768 which is too big for SkFixed + kMaxDim = 8192 - 1 + }; + + SkBitmapDevice* fDevice; + SkPixmap fRootPixmap; + + // Used for tiling and non-tiling + SkDraw fDraw; + + // fCurr... are only used if fNeedTiling + SkMatrix fTileMatrix; + SkRasterClip fTileRC; + SkIPoint fCurrOrigin, fOrigin; + + bool fDone, fNeedsTiling; + +public: + SkDrawTiler(SkBitmapDevice* dev) : fDevice(dev) { + // we need fDst to be set, and if we're actually drawing, to dirty the genID + if (!dev->accessPixels(&fRootPixmap)) { + // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels + fRootPixmap.reset(dev->imageInfo(), nullptr, 0); + } + + fDone = false; + fNeedsTiling = fRootPixmap.width() > kMaxDim || fRootPixmap.height() > kMaxDim; + fOrigin.set(0, 0); + fCurrOrigin = fOrigin; + + if (fNeedsTiling) { + // fDraw.fDst is reset each time in setupTileDraw() + fDraw.fMatrix = &fTileMatrix; + fDraw.fRC = &fTileRC; + } else { + fDraw.fDst = fRootPixmap; + fDraw.fMatrix = &dev->ctm(); + fDraw.fRC = &dev->fRCStack.rc(); + } + } + + bool needsTiling() const { return fNeedsTiling; } + + const SkDraw* next() { + if (fDone) { + return nullptr; + } + if (fNeedsTiling) { + do { + this->setupTileDraw(); // might set the clip to empty + this->stepOrigin(); // might set fDone to true + } while (!fDone && fTileRC.isEmpty()); + // if we exit the loop and we're still empty, we're (past) done + if (fTileRC.isEmpty()) { + SkASSERT(fDone); + return nullptr; + } + SkASSERT(!fTileRC.isEmpty()); + } else { + fDone = true; // only draw untiled once + } + return &fDraw; + } + + int curr_x() const { return fCurrOrigin.x(); } + int curr_y() const { return fCurrOrigin.y(); } + +private: + void setupTileDraw() { + SkASSERT(!fDone); + SkIRect bounds = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), kMaxDim, kMaxDim); + SkASSERT(!bounds.isEmpty()); + bool success = fRootPixmap.extractSubset(&fDraw.fDst, bounds); + SkASSERT_RELEASE(success); + // now don't use bounds, since fDst has the clipped dimensions. + + fTileMatrix = fDevice->ctm(); + fTileMatrix.postTranslate(SkIntToScalar(-fOrigin.x()), SkIntToScalar(-fOrigin.y())); + fDevice->fRCStack.rc().translate(-fOrigin.x(), -fOrigin.y(), &fTileRC); + fTileRC.op(SkIRect::MakeWH(fDraw.fDst.width(), fDraw.fDst.height()), + SkRegion::kIntersect_Op); + + fCurrOrigin = fOrigin; + } + + void stepOrigin() { + SkASSERT(!fDone); + SkASSERT(fNeedsTiling); + fOrigin.fX += kMaxDim; + if (fOrigin.fX >= fRootPixmap.width()) { // too far + fOrigin.fX = 0; + fOrigin.fY += kMaxDim; + if (fOrigin.fY >= fRootPixmap.height()) { + fDone = true; // way too far + } + } + } +}; + +#define LOOP_TILER(code) \ + SkDrawTiler priv_tiler(this); \ + while (const SkDraw* priv_draw = priv_tiler.next()) { \ + priv_draw->code; \ + } +#define TILER_X(x) (x) - priv_tiler.curr_x() +#define TILER_Y(y) (y) - priv_tiler.curr_y() + + class SkColorTable; static bool valid_for_bitmap_device(const SkImageInfo& info, @@ -173,30 +283,17 @@ bool SkBitmapDevice::onReadPixels(const SkPixmap& pm, int x, int y) { /////////////////////////////////////////////////////////////////////////////// -class SkBitmapDevice::BDDraw : public SkDraw { -public: - BDDraw(SkBitmapDevice* dev) { - // we need fDst to be set, and if we're actually drawing, to dirty the genID - if (!dev->accessPixels(&fDst)) { - // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels - fDst.reset(dev->imageInfo(), nullptr, 0); - } - fMatrix = &dev->ctm(); - fRC = &dev->fRCStack.rc(); - } -}; - void SkBitmapDevice::drawPaint(const SkPaint& paint) { - BDDraw(this).drawPaint(paint); + LOOP_TILER( drawPaint(paint)) } void SkBitmapDevice::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { - BDDraw(this).drawPoints(mode, count, pts, paint, nullptr); + LOOP_TILER( drawPoints(mode, count, pts, paint, nullptr)) } void SkBitmapDevice::drawRect(const SkRect& r, const SkPaint& paint) { - BDDraw(this).drawRect(r, paint); + LOOP_TILER( drawRect(r, paint)) } void SkBitmapDevice::drawOval(const SkRect& oval, const SkPaint& paint) { @@ -216,21 +313,27 @@ void SkBitmapDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) { // required to override drawRRect. this->drawPath(path, paint, nullptr, true); #else - BDDraw(this).drawRRect(rrect, paint); + LOOP_TILER( drawRRect(rrect, paint)) #endif } void SkBitmapDevice::drawPath(const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) { - BDDraw(this).drawPath(path, paint, prePathMatrix, pathIsMutable); + SkDrawTiler tiler(this); + if (tiler.needsTiling()) { + pathIsMutable = false; + } + while (const SkDraw* draw = tiler.next()) { + draw->drawPath(path, paint, prePathMatrix, pathIsMutable); + } } void SkBitmapDevice::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint& paint) { SkMatrix matrix = SkMatrix::MakeTrans(x, y); LogDrawScaleFactor(SkMatrix::Concat(this->ctm(), matrix), paint.getFilterQuality()); - BDDraw(this).drawBitmap(bitmap, matrix, nullptr, paint); + LOOP_TILER( drawBitmap(bitmap, matrix, nullptr, paint)) } static inline bool CanApplyDstMatrixAsCTM(const SkMatrix& m, const SkPaint& paint) { @@ -325,7 +428,7 @@ void SkBitmapDevice::drawBitmapRect(const SkBitmap& bitmap, // matrix with the CTM, and try to call drawSprite if it can. If not, // it will make a shader and call drawRect, as we do below. if (CanApplyDstMatrixAsCTM(matrix, paint)) { - BDDraw(this).drawBitmap(*bitmapPtr, matrix, dstPtr, paint); + LOOP_TILER( drawBitmap(*bitmapPtr, matrix, dstPtr, paint)) return; } } @@ -354,25 +457,25 @@ void SkBitmapDevice::drawBitmapRect(const SkBitmap& bitmap, } void SkBitmapDevice::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& paint) { - BDDraw(this).drawSprite(bitmap, x, y, paint); + LOOP_TILER( drawSprite(bitmap, TILER_X(x), TILER_Y(y), paint)) } void SkBitmapDevice::drawText(const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { - BDDraw(this).drawText((const char*)text, len, x, y, paint, &fSurfaceProps); + LOOP_TILER( drawText((const char*)text, len, x, y, paint, &fSurfaceProps)) } void SkBitmapDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[], int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) { - BDDraw(this).drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint, - &fSurfaceProps); + LOOP_TILER( drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint, + &fSurfaceProps)) } void SkBitmapDevice::drawVertices(const SkVertices* vertices, SkBlendMode bmode, const SkPaint& paint) { - BDDraw(this).drawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(), - vertices->texCoords(), vertices->colors(), bmode, - vertices->indices(), vertices->indexCount(), paint); + LOOP_TILER( drawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(), + vertices->texCoords(), vertices->colors(), bmode, + vertices->indices(), vertices->indexCount(), paint)) } void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPaint& origPaint) { @@ -384,7 +487,8 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm())); } - BDDraw(this).drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, *paint); + LOOP_TILER( drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, + TILER_X(x), TILER_Y(y), *paint)) } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkBitmapDevice.h b/src/core/SkBitmapDevice.h index b890066da6..dbe04fa1cc 100644 --- a/src/core/SkBitmapDevice.h +++ b/src/core/SkBitmapDevice.h @@ -142,6 +142,7 @@ private: friend struct DeviceCM; //for setMatrixClip friend class SkDraw; friend class SkDrawIter; + friend class SkDrawTiler; friend class SkDeviceFilteredPaint; friend class SkSurface_Raster; friend class SkThreadedBMPDevice; // to copy fRCStack diff --git a/src/core/SkDeviceLooper.cpp b/src/core/SkDeviceLooper.cpp deleted file mode 100644 index cea92704ef..0000000000 --- a/src/core/SkDeviceLooper.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkDeviceLooper.h" - -SkDeviceLooper::SkDeviceLooper(const SkPixmap& base, const SkRasterClip& rc, const SkIRect& bounds, - bool aa) - : fBaseDst(base) - , fBaseRC(rc) - , fDelta(aa ? kAA_Delta : kBW_Delta) -{ - // sentinels that next() has not yet been called, and so our mapper functions - // should not be called either. - fCurrDst = nullptr; - fCurrRC = nullptr; - - if (!rc.isEmpty()) { - // clip must be contained by the bitmap - SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds())); - } - - if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) { - fState = kDone_State; - } else if (this->fitsInDelta(fClippedBounds)) { - fState = kSimple_State; - } else { - // back up by 1 DX, so that next() will put us in a correct starting - // position. - fCurrOffset.set(fClippedBounds.left() - fDelta, - fClippedBounds.top()); - fState = kComplex_State; - } -} - -SkDeviceLooper::~SkDeviceLooper() {} - -void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const { - SkASSERT(kDone_State != fState); - SkASSERT(fCurrDst); - SkASSERT(fCurrRC); - - *dst = src; - dst->offset(SkIntToScalar(-fCurrOffset.fX), - SkIntToScalar(-fCurrOffset.fY)); -} - -void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const { - SkASSERT(kDone_State != fState); - SkASSERT(fCurrDst); - SkASSERT(fCurrRC); - - *dst = src; - dst->postTranslate(SkIntToScalar(-fCurrOffset.fX), SkIntToScalar(-fCurrOffset.fY)); -} - -bool SkDeviceLooper::computeCurrBitmapAndClip() { - SkASSERT(kComplex_State == fState); - - SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(), - fDelta, fDelta); - if (!fBaseDst.extractSubset(&fSubsetDst, r)) { - fSubsetRC.setEmpty(); - } else { - fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC); - (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), SkRegion::kIntersect_Op); - } - - fCurrDst = &fSubsetDst; - fCurrRC = &fSubsetRC; - return !fCurrRC->isEmpty(); -} - -static bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) { - // can we move to the right? - if (offset->x() + delta < boundary.right()) { - offset->fX += delta; - return true; - } - - // reset to the left, but move down a row - offset->fX = boundary.left(); - if (offset->y() + delta < boundary.bottom()) { - offset->fY += delta; - return true; - } - - // offset is now outside of boundary, so we're done - return false; -} - -bool SkDeviceLooper::next() { - switch (fState) { - case kDone_State: - // in theory, we should not get called here, since we must have - // previously returned false, but we check anyway. - break; - - case kSimple_State: - // first time for simple - if (nullptr == fCurrDst) { - fCurrDst = &fBaseDst; - fCurrRC = &fBaseRC; - fCurrOffset.set(0, 0); - return true; - } - // 2nd time for simple, we are done - break; - - case kComplex_State: - // need to propogate fCurrOffset through clippedbounds - // left to right, until we wrap around and move down - - while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) { - if (this->computeCurrBitmapAndClip()) { - return true; - } - } - break; - } - fState = kDone_State; - return false; -} diff --git a/src/core/SkDeviceLooper.h b/src/core/SkDeviceLooper.h deleted file mode 100644 index dd346d7445..0000000000 --- a/src/core/SkDeviceLooper.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkDeviceLooper_DEFINED -#define SkDeviceLooper_DEFINED - -#include "SkBitmap.h" -#include "SkMatrix.h" -#include "SkRasterClip.h" - -/** - * Helper class to manage "tiling" a large coordinate space into managable - * chunks, where managable means areas that are <= some max critical coordinate - * size. - * - * The constructor takes an antialiasing bool, which affects what this maximum - * allowable size is: If we're drawing BW, then we need coordinates to stay - * safely within fixed-point range (we use +- 16K, to give ourselves room to - * add/subtract two fixed values and still be in range. If we're drawing AA, - * then we reduce that size by the amount that the supersampler scan converter - * needs (at the moment, that is 4X, so the "safe" range is +- 4K). - * - * For performance reasons, the class first checks to see if any help is needed - * at all, and if not (i.e. the specified bounds and base bitmap area already - * in the safe-zone, then the class does nothing (effectively). - */ -class SkDeviceLooper { -public: - SkDeviceLooper(const SkPixmap& base, const SkRasterClip&, const SkIRect& bounds, bool aa); - ~SkDeviceLooper(); - - const SkPixmap& getPixmap() const { - SkASSERT(kDone_State != fState); - SkASSERT(fCurrDst); - return *fCurrDst; - } - - const SkRasterClip& getRC() const { - SkASSERT(kDone_State != fState); - SkASSERT(fCurrRC); - return *fCurrRC; - } - - void mapRect(SkRect* dst, const SkRect& src) const; - void mapMatrix(SkMatrix* dst, const SkMatrix& src) const; - - /** - * Call next to setup the looper to return a valid coordinate chunk. - * Each time this returns true, it is safe to call mapRect() and - * mapMatrix(), to convert from "global" coordinate values to ones that - * are local to this chunk. - * - * When next() returns false, the list of chunks is done, and mapRect() - * and mapMatrix() should no longer be called. - */ - bool next(); - -private: - const SkPixmap& fBaseDst; - const SkRasterClip& fBaseRC; - - enum State { - kDone_State, // iteration is complete, getters will assert - kSimple_State, // no translate/clip mods needed - kComplex_State - }; - - // storage for our tiled versions. Perhaps could use SkTLazy - SkPixmap fSubsetDst; - SkRasterClip fSubsetRC; - - const SkPixmap* fCurrDst; - const SkRasterClip* fCurrRC; - SkIRect fClippedBounds; - SkIPoint fCurrOffset; - int fDelta; - State fState; - - enum Delta { - kBW_Delta = 1 << 14, // 16K, gives room to spare for fixedpoint - kAA_Delta = kBW_Delta >> 2 // supersample 4x - }; - - bool fitsInDelta(const SkIRect& r) const { - return r.right() < fDelta && r.bottom() < fDelta; - } - - bool computeCurrBitmapAndClip(); -}; - -#endif diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 21a89ae5a9..cf06b7b3b5 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -14,7 +14,6 @@ #include "SkCanvas.h" #include "SkColorData.h" #include "SkDevice.h" -#include "SkDeviceLooper.h" #include "SkDraw.h" #include "SkDrawProcs.h" #include "SkFindAndPlaceGlyph.h" @@ -785,8 +784,7 @@ void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, } } - if (!SkRectPriv::MakeLargeS32().contains(bbox)) { - // bbox.roundOut() is undefined; use slow path. + if (!SkRectPriv::FitsInFixed(bbox) && rtype != kHair_RectType) { draw_rect_as_path(*this, prePaintRect, paint, matrix); return; } @@ -796,45 +794,37 @@ void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, return; } - SkDeviceLooper looper(fDst, *fRC, ir, paint.isAntiAlias()); - while (looper.next()) { - SkRect localDevRect; - looper.mapRect(&localDevRect, devRect); - SkMatrix localMatrix; - looper.mapMatrix(&localMatrix, *matrix); - - SkAutoBlitterChoose blitterStorage(looper.getPixmap(), localMatrix, paint); - const SkRasterClip& clip = looper.getRC(); - SkBlitter* blitter = blitterStorage.get(); - - // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter - // case we are also hairline (if we've gotten to here), which devolves to - // effectively just kFill - switch (rtype) { - case kFill_RectType: - if (paint.isAntiAlias()) { - SkScan::AntiFillRect(localDevRect, clip, blitter); - } else { - SkScan::FillRect(localDevRect, clip, blitter); - } - break; - case kStroke_RectType: - if (paint.isAntiAlias()) { - SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); - } else { - SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); - } - break; - case kHair_RectType: - if (paint.isAntiAlias()) { - SkScan::AntiHairRect(localDevRect, clip, blitter); - } else { - SkScan::HairRect(localDevRect, clip, blitter); - } - break; - default: - SkDEBUGFAIL("bad rtype"); - } + SkAutoBlitterChoose blitterStorage(fDst, *matrix, paint); + const SkRasterClip& clip = *fRC; + SkBlitter* blitter = blitterStorage.get(); + + // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter + // case we are also hairline (if we've gotten to here), which devolves to + // effectively just kFill + switch (rtype) { + case kFill_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFillRect(devRect, clip, blitter); + } else { + SkScan::FillRect(devRect, clip, blitter); + } + break; + case kStroke_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter); + } else { + SkScan::FrameRect(devRect, strokeSize, clip, blitter); + } + break; + case kHair_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiHairRect(devRect, clip, blitter); + } else { + SkScan::HairRect(devRect, clip, blitter); + } + break; + default: + SkDEBUGFAIL("bad rtype"); } } diff --git a/tests/DeviceLooperTest.cpp b/tests/DeviceLooperTest.cpp deleted file mode 100644 index c8eb3c7b75..0000000000 --- a/tests/DeviceLooperTest.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkAutoPixmapStorage.h" -#include "SkDeviceLooper.h" -#include "SkRasterClip.h" -#include "Test.h" - -static void make_pm(SkAutoPixmapStorage* pixmap, int w, int h) { - pixmap->alloc(SkImageInfo::Make(w, h, kAlpha_8_SkColorType, kPremul_SkAlphaType)); -} - -static bool equal(const SkRasterClip& a, const SkRasterClip& b) { - if (a.isBW()) { - return b.isBW() && a.bwRgn() == b.bwRgn(); - } else { - return a.isAA() && a.aaRgn() == b.aaRgn(); - } -} - -static const struct { - SkISize fDevSize; - SkIRect fRCBounds; - SkIRect fRect; -} gRec[] = { - { { 4000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 4000, 4000 } }, - { { 10, 4000 }, { 0, 0, 10, 4000 }, { 0, 0, 4000, 4000 } }, - // very large devce, small rect - { { 32000, 10 }, { 0, 0, 32000, 10 }, { 0, 0, 4000, 4000 } }, - { { 10, 32000 }, { 0, 0, 10, 32000 }, { 0, 0, 4000, 4000 } }, - // very large device, small clip - { { 32000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 32000, 32000 } }, - { { 10, 32000 }, { 0, 0, 10, 4000 }, { 0, 0, 32000, 32000 } }, -}; - -static void test_simple(skiatest::Reporter* reporter) { - - for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { - SkAutoPixmapStorage pmap; - make_pm(&pmap, gRec[i].fDevSize.width(), gRec[i].fDevSize.height()); - - SkRasterClip rc(gRec[i].fRCBounds); - - for (int aa = 0; aa <= 1; ++aa) { - SkDeviceLooper looper(pmap, rc, gRec[i].fRect, SkToBool(aa)); - - bool valid = looper.next(); - REPORTER_ASSERT(reporter, valid); - if (valid) { - REPORTER_ASSERT(reporter, looper.getPixmap().width() == pmap.width()); - REPORTER_ASSERT(reporter, looper.getPixmap().height() == pmap.height()); - REPORTER_ASSERT(reporter, equal(looper.getRC(), rc)); - - REPORTER_ASSERT(reporter, !looper.next()); - } - } - // test that a rect that doesn't intersect returns no loops - { - SkIRect r = rc.getBounds(); - r.offset(r.width(), 0); - SkDeviceLooper looper(pmap, rc, r, false); - REPORTER_ASSERT(reporter, !looper.next()); - } - } -} - -// mask-bits are interpreted as the areas where the clip is visible -// [ 0x01 0x02 ] -// [ 0x04 0x08 ] -// -static void make_rgn(SkRegion* rgn, int w, int h, unsigned mask) { - SkASSERT(SkAlign2(w)); - SkASSERT(SkAlign2(h)); - w >>= 1; - h >>= 1; - const SkIRect baseR = SkIRect::MakeWH(w, h); - - int bit = 1; - for (int y = 0; y <= 1; ++y) { - for (int x = 0; x <= 1; ++x) { - if (mask & bit) { - SkIRect r = baseR; - r.offset(x * w, y * h); - rgn->op(r, SkRegion::kUnion_Op); - } - bit <<= 1; - } - } -} - -static void test_complex(skiatest::Reporter* reporter) { - // choose size values that will result in 4 quadrants, given fAA setting - const int BW_SIZE = 17 * 1000; - const int AA_SIZE = 7 * 1000; - - struct { - SkISize fSize; - bool fAA; - } const gRec[] = { - { { BW_SIZE, BW_SIZE }, false }, - { { AA_SIZE, AA_SIZE }, true }, - }; - - for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { - const int w = gRec[i].fSize.width(); - const int h = gRec[i].fSize.height(); - - SkAutoPixmapStorage pmap; - make_pm(&pmap, w, h); - - const SkIRect rect = SkIRect::MakeWH(w, h); - - // mask-bits are interpreted as the areas where the clip is visible - // [ 0x01 0x02 ] - // [ 0x04 0x08 ] - // - for (int mask = 0; mask <= 15; ++mask) { - SkRegion rgn; - make_rgn(&rgn, w, h, mask); - - SkRasterClip rc; - rc.op(rgn, SkRegion::kReplace_Op); - - SkDeviceLooper looper(pmap, rc, rect, gRec[i].fAA); - while (looper.next()) { - REPORTER_ASSERT(reporter, !looper.getRC().isEmpty()); - } - } - } -} - -DEF_TEST(DeviceLooper, reporter) { - test_simple(reporter); - test_complex(reporter); -} |