aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-03-07 14:16:52 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-07 19:39:00 +0000
commitb5e1f7558052cc60deaf23ccc2c898d1c6c94c09 (patch)
treeb3ee26c7341dc9757ed02e91e3d30b4de32c2b90
parentd2e9f767bbb1a7664e9ee83d0755d7e4327cb7b2 (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.cpp33
-rw-r--r--gn/core.gni1
-rw-r--r--gn/tests.gni1
-rw-r--r--src/core/SkBitmapDevice.cpp160
-rw-r--r--src/core/SkBitmapDevice.h1
-rw-r--r--src/core/SkDeviceLooper.cpp126
-rw-r--r--src/core/SkDeviceLooper.h95
-rw-r--r--src/core/SkDraw.cpp74
-rw-r--r--tests/DeviceLooperTest.cpp139
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);
-}