Chromium Code Reviews| Index: src/core/SkDeviceLooper.cpp |
| diff --git a/src/core/SkDeviceLooper.cpp b/src/core/SkDeviceLooper.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3d64fe0f9bf9304fdb711bd3c7f4a7d6d7f0dd24 |
| --- /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 bee called, and so our mapper functions |
|
tomhudson
2013/08/28 15:01:21
Nit: bee -> been
reed1
2013/08/28 15:11:30
Done.
|
| + // 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; |
| +} |