diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/core/SkDeviceLooper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/core/SkDeviceLooper.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,131 @@ +/* + * 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; + + 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(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)) { + fSubsetRC.setEmpty(); + } else { + fSubsetBitmap.lockPixels(); + fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC); + (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), + SkRegion::kIntersect_Op); + } + + fCurrBitmap = &fSubsetBitmap; + 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 (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 + + while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) { + if (this->computeCurrBitmapAndClip()) { + return true; + } + } + break; + } + fState = kDone_State; + return false; +}