update devicelooper to skip internal tiles that are empty, and unittests

BUG=

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

git-svn-id: http://skia.googlecode.com/svn/trunk@11331 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2013-09-17 20:03:43 +00:00
parent dcd36f3c9d
commit 636d87a3f4
4 changed files with 55 additions and 19 deletions

View File

@ -46,6 +46,7 @@
'../tests/DataRefTest.cpp',
'../tests/DeferredCanvasTest.cpp',
'../tests/DequeTest.cpp',
'../tests/DeviceLooperTest.cpp',
'../tests/DrawBitmapRectTest.cpp',
'../tests/DrawPathTest.cpp',
'../tests/DrawTextTest.cpp',

View File

@ -46,6 +46,18 @@ public:
*/
static SkSurface* NewRaster(const SkImage::Info&);
/**
* Helper version of NewRaster. It creates a SkImage::Info with the
* specified width and height, and populates the rest of info to match
* pixels in SkPMColor format.
*/
static SkSurface* NewRasterPMColor(int width, int height) {
SkImage::Info info = {
width, height, SkImage::kPMColor_ColorType, SkImage::kPremul_AlphaType
};
return NewRaster(info);
}
/**
* Return a new surface whose contents will be recorded into a picture.
* When this surface is drawn into another canvas, its contents will be

View File

@ -27,6 +27,7 @@
#include "SkXfermode.h"
#include "SkStream.h"
#include "SkSurface.h"
#include "SkXMLParser.h"
class PictFileView : public SampleView {
@ -53,6 +54,11 @@ class PictFileView : public SampleView {
SkDebugf("coun't load picture at \"path\"\n", path);
}
if (false) {
SkSurface* surf = SkSurface::NewRasterPMColor(pic->width(), pic->height());
surf->getCanvas()->drawPicture(*pic);
surf->unref();
}
if (false) { // re-record
SkPicture p2;
pic->draw(p2.beginRecording(pic->width(), pic->height()));

View File

@ -19,10 +19,14 @@ SkDeviceLooper::SkDeviceLooper(const SkBitmap& base,
fCurrBitmap = NULL;
fCurrRC = NULL;
SkIRect bitmapBounds = SkIRect::MakeWH(base.width(), base.height());
if (!fClippedBounds.intersect(bounds, bitmapBounds)) {
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(bounds)) {
} else if (this->fitsInDelta(fClippedBounds)) {
fState = kSimple_State;
} else {
// back up by 1 DX, so that next() will put us in a correct starting
@ -62,17 +66,35 @@ bool SkDeviceLooper::computeCurrBitmapAndClip() {
SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
fDelta, fDelta);
if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) {
fState = kDone_State;
return false;
fSubsetRC.setEmpty();
} else {
fSubsetBitmap.lockPixels();
fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
(void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta),
SkRegion::kIntersect_Op);
}
fSubsetBitmap.lockPixels();
fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
(void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), SkRegion::kIntersect_Op);
fCurrBitmap = &fSubsetBitmap;
fCurrRC = &fSubsetRC;
return true;
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() {
@ -97,18 +119,13 @@ bool SkDeviceLooper::next() {
// need to propogate fCurrOffset through clippedbounds
// left to right, until we wrap around and move down
if (fCurrOffset.x() + fDelta < fClippedBounds.right()) {
fCurrOffset.fX += fDelta;
return this->computeCurrBitmapAndClip();
}
fCurrOffset.fX = fClippedBounds.left();
if (fCurrOffset.y() + fDelta < fClippedBounds.bottom()) {
fCurrOffset.fY += fDelta;
return this->computeCurrBitmapAndClip();
while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) {
if (this->computeCurrBitmapAndClip()) {
return true;
}
}
break;
}
fState = kDone_State;
return false;
}