2013-08-28 15:23:19 +00:00
|
|
|
/*
|
|
|
|
* 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 SkBitmap& base,
|
|
|
|
const SkRasterClip& rc,
|
|
|
|
const SkIRect& bounds, bool aa)
|
|
|
|
: fBaseBitmap(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.
|
|
|
|
fCurrBitmap = NULL;
|
|
|
|
fCurrRC = NULL;
|
|
|
|
|
|
|
|
SkIRect bitmapBounds = SkIRect::MakeWH(base.width(), base.height());
|
|
|
|
if (!fClippedBounds.intersect(bounds, bitmapBounds)) {
|
|
|
|
fState = kDone_State;
|
|
|
|
} else if (this->fitsInDelta(bounds)) {
|
|
|
|
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(fCurrBitmap);
|
|
|
|
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(fCurrBitmap);
|
|
|
|
SkASSERT(fCurrRC);
|
|
|
|
|
|
|
|
*dst = src;
|
|
|
|
dst->postTranslate(SkIntToScalar(-fCurrOffset.fX),
|
|
|
|
SkIntToScalar(-fCurrOffset.fY));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SkDeviceLooper::computeCurrBitmapAndClip() {
|
|
|
|
SkASSERT(kComplex_State == fState);
|
2013-08-29 07:01:20 +00:00
|
|
|
|
2013-08-28 15:23:19 +00:00
|
|
|
SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
|
|
|
|
fDelta, fDelta);
|
|
|
|
if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) {
|
|
|
|
fState = kDone_State;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fSubsetBitmap.lockPixels();
|
2013-08-29 07:01:20 +00:00
|
|
|
|
2013-08-28 15:23:19 +00:00
|
|
|
fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
|
|
|
|
(void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), SkRegion::kIntersect_Op);
|
2013-08-29 07:01:20 +00:00
|
|
|
|
2013-08-28 15:23:19 +00:00
|
|
|
fCurrBitmap = &fSubsetBitmap;
|
|
|
|
fCurrRC = &fSubsetRC;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2013-08-29 07:01:20 +00:00
|
|
|
|
2013-08-28 15:23:19 +00:00
|
|
|
case kSimple_State:
|
|
|
|
// first time for simple
|
|
|
|
if (NULL == fCurrBitmap) {
|
|
|
|
fCurrBitmap = &fBaseBitmap;
|
|
|
|
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
|
2013-08-29 07:01:20 +00:00
|
|
|
|
2013-08-28 15:23:19 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2013-08-29 07:01:20 +00:00
|
|
|
|
2013-08-28 15:23:19 +00:00
|
|
|
fState = kDone_State;
|
|
|
|
return false;
|
|
|
|
}
|