1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkDeviceLooper.h" 9 10 SkDeviceLooper::SkDeviceLooper(const SkBitmap& base, 11 const SkRasterClip& rc, 12 const SkIRect& bounds, bool aa) 13 : fBaseBitmap(base) 14 , fBaseRC(rc) 15 , fSubsetRC(rc.isForceConservativeRects()) 16 , fDelta(aa ? kAA_Delta : kBW_Delta) 17 { 18 // sentinels that next() has not yet been called, and so our mapper functions 19 // should not be called either. 20 fCurrBitmap = NULL; 21 fCurrRC = NULL; 22 23 if (!rc.isEmpty()) { 24 // clip must be contained by the bitmap 25 SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds())); 26 } 27 28 if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) { 29 fState = kDone_State; 30 } else if (this->fitsInDelta(fClippedBounds)) { 31 fState = kSimple_State; 32 } else { 33 // back up by 1 DX, so that next() will put us in a correct starting 34 // position. 35 fCurrOffset.set(fClippedBounds.left() - fDelta, 36 fClippedBounds.top()); 37 fState = kComplex_State; 38 } 39 } 40 41 SkDeviceLooper::~SkDeviceLooper() { 42 } 43 44 void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const { 45 SkASSERT(kDone_State != fState); 46 SkASSERT(fCurrBitmap); 47 SkASSERT(fCurrRC); 48 49 *dst = src; 50 dst->offset(SkIntToScalar(-fCurrOffset.fX), 51 SkIntToScalar(-fCurrOffset.fY)); 52 } 53 54 void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const { 55 SkASSERT(kDone_State != fState); 56 SkASSERT(fCurrBitmap); 57 SkASSERT(fCurrRC); 58 59 *dst = src; 60 dst->postTranslate(SkIntToScalar(-fCurrOffset.fX), 61 SkIntToScalar(-fCurrOffset.fY)); 62 } 63 64 bool SkDeviceLooper::computeCurrBitmapAndClip() { 65 SkASSERT(kComplex_State == fState); 66 67 SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(), 68 fDelta, fDelta); 69 if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) { 70 fSubsetRC.setEmpty(); 71 } else { 72 fSubsetBitmap.lockPixels(); 73 fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC); 74 (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), 75 SkRegion::kIntersect_Op); 76 } 77 78 fCurrBitmap = &fSubsetBitmap; 79 fCurrRC = &fSubsetRC; 80 return !fCurrRC->isEmpty(); 81 } 82 83 static bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) { 84 // can we move to the right? 85 if (offset->x() + delta < boundary.right()) { 86 offset->fX += delta; 87 return true; 88 } 89 90 // reset to the left, but move down a row 91 offset->fX = boundary.left(); 92 if (offset->y() + delta < boundary.bottom()) { 93 offset->fY += delta; 94 return true; 95 } 96 97 // offset is now outside of boundary, so we're done 98 return false; 99 } 100 101 bool SkDeviceLooper::next() { 102 switch (fState) { 103 case kDone_State: 104 // in theory, we should not get called here, since we must have 105 // previously returned false, but we check anyway. 106 break; 107 108 case kSimple_State: 109 // first time for simple 110 if (NULL == fCurrBitmap) { 111 fCurrBitmap = &fBaseBitmap; 112 fCurrRC = &fBaseRC; 113 fCurrOffset.set(0, 0); 114 return true; 115 } 116 // 2nd time for simple, we are done 117 break; 118 119 case kComplex_State: 120 // need to propogate fCurrOffset through clippedbounds 121 // left to right, until we wrap around and move down 122 123 while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) { 124 if (this->computeCurrBitmapAndClip()) { 125 return true; 126 } 127 } 128 break; 129 } 130 fState = kDone_State; 131 return false; 132 } 133