| Index: src/core/SkDeviceLooper.cpp
|
| diff --git a/src/core/SkDeviceLooper.cpp b/src/core/SkDeviceLooper.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4122fd7aaf30335fcb188b2c8a6d89e129b37ee1
|
| --- /dev/null
|
| +++ b/src/core/SkDeviceLooper.cpp
|
| @@ -0,0 +1,114 @@
|
| +/*
|
| + * 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);
|
| +
|
| + SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
|
| + fDelta, fDelta);
|
| + if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) {
|
| + fState = kDone_State;
|
| + return false;
|
| + }
|
| + 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;
|
| +}
|
| +
|
| +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 (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
|
| +
|
| + 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;
|
| + }
|
| +
|
| + fState = kDone_State;
|
| + return false;
|
| +}
|
|
|