1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkDeviceLooper.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,131 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkDeviceLooper.h" 1.12 + 1.13 +SkDeviceLooper::SkDeviceLooper(const SkBitmap& base, 1.14 + const SkRasterClip& rc, 1.15 + const SkIRect& bounds, bool aa) 1.16 +: fBaseBitmap(base) 1.17 +, fBaseRC(rc) 1.18 +, fDelta(aa ? kAA_Delta : kBW_Delta) 1.19 +{ 1.20 + // sentinels that next() has not yet been called, and so our mapper functions 1.21 + // should not be called either. 1.22 + fCurrBitmap = NULL; 1.23 + fCurrRC = NULL; 1.24 + 1.25 + if (!rc.isEmpty()) { 1.26 + // clip must be contained by the bitmap 1.27 + SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds())); 1.28 + } 1.29 + 1.30 + if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) { 1.31 + fState = kDone_State; 1.32 + } else if (this->fitsInDelta(fClippedBounds)) { 1.33 + fState = kSimple_State; 1.34 + } else { 1.35 + // back up by 1 DX, so that next() will put us in a correct starting 1.36 + // position. 1.37 + fCurrOffset.set(fClippedBounds.left() - fDelta, 1.38 + fClippedBounds.top()); 1.39 + fState = kComplex_State; 1.40 + } 1.41 +} 1.42 + 1.43 +SkDeviceLooper::~SkDeviceLooper() { 1.44 +} 1.45 + 1.46 +void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const { 1.47 + SkASSERT(kDone_State != fState); 1.48 + SkASSERT(fCurrBitmap); 1.49 + SkASSERT(fCurrRC); 1.50 + 1.51 + *dst = src; 1.52 + dst->offset(SkIntToScalar(-fCurrOffset.fX), 1.53 + SkIntToScalar(-fCurrOffset.fY)); 1.54 +} 1.55 + 1.56 +void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const { 1.57 + SkASSERT(kDone_State != fState); 1.58 + SkASSERT(fCurrBitmap); 1.59 + SkASSERT(fCurrRC); 1.60 + 1.61 + *dst = src; 1.62 + dst->postTranslate(SkIntToScalar(-fCurrOffset.fX), 1.63 + SkIntToScalar(-fCurrOffset.fY)); 1.64 +} 1.65 + 1.66 +bool SkDeviceLooper::computeCurrBitmapAndClip() { 1.67 + SkASSERT(kComplex_State == fState); 1.68 + 1.69 + SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(), 1.70 + fDelta, fDelta); 1.71 + if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) { 1.72 + fSubsetRC.setEmpty(); 1.73 + } else { 1.74 + fSubsetBitmap.lockPixels(); 1.75 + fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC); 1.76 + (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), 1.77 + SkRegion::kIntersect_Op); 1.78 + } 1.79 + 1.80 + fCurrBitmap = &fSubsetBitmap; 1.81 + fCurrRC = &fSubsetRC; 1.82 + return !fCurrRC->isEmpty(); 1.83 +} 1.84 + 1.85 +static bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) { 1.86 + // can we move to the right? 1.87 + if (offset->x() + delta < boundary.right()) { 1.88 + offset->fX += delta; 1.89 + return true; 1.90 + } 1.91 + 1.92 + // reset to the left, but move down a row 1.93 + offset->fX = boundary.left(); 1.94 + if (offset->y() + delta < boundary.bottom()) { 1.95 + offset->fY += delta; 1.96 + return true; 1.97 + } 1.98 + 1.99 + // offset is now outside of boundary, so we're done 1.100 + return false; 1.101 +} 1.102 + 1.103 +bool SkDeviceLooper::next() { 1.104 + switch (fState) { 1.105 + case kDone_State: 1.106 + // in theory, we should not get called here, since we must have 1.107 + // previously returned false, but we check anyway. 1.108 + break; 1.109 + 1.110 + case kSimple_State: 1.111 + // first time for simple 1.112 + if (NULL == fCurrBitmap) { 1.113 + fCurrBitmap = &fBaseBitmap; 1.114 + fCurrRC = &fBaseRC; 1.115 + fCurrOffset.set(0, 0); 1.116 + return true; 1.117 + } 1.118 + // 2nd time for simple, we are done 1.119 + break; 1.120 + 1.121 + case kComplex_State: 1.122 + // need to propogate fCurrOffset through clippedbounds 1.123 + // left to right, until we wrap around and move down 1.124 + 1.125 + while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) { 1.126 + if (this->computeCurrBitmapAndClip()) { 1.127 + return true; 1.128 + } 1.129 + } 1.130 + break; 1.131 + } 1.132 + fState = kDone_State; 1.133 + return false; 1.134 +}