11c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com/* 21c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * Copyright 2013 Google Inc. 31c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * 41c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * Use of this source code is governed by a BSD-style license that can be 51c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * found in the LICENSE file. 61c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com */ 71c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 81c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkDeviceLooper.h" 91c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 101c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.comSkDeviceLooper::SkDeviceLooper(const SkBitmap& base, 111c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com const SkRasterClip& rc, 121c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com const SkIRect& bounds, bool aa) 13d954498c01ccf0417feacf89e45d0c62a06a813breed : fBaseBitmap(base) 14d954498c01ccf0417feacf89e45d0c62a06a813breed , fBaseRC(rc) 15d954498c01ccf0417feacf89e45d0c62a06a813breed , fSubsetRC(rc.isForceConservativeRects()) 16d954498c01ccf0417feacf89e45d0c62a06a813breed , fDelta(aa ? kAA_Delta : kBW_Delta) 171c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com{ 181c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // sentinels that next() has not yet been called, and so our mapper functions 191c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // should not be called either. 201c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrBitmap = NULL; 211c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrRC = NULL; 221c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 23636d87a3f411507020a21c6b0641da795eb5d275reed@google.com if (!rc.isEmpty()) { 24636d87a3f411507020a21c6b0641da795eb5d275reed@google.com // clip must be contained by the bitmap 25636d87a3f411507020a21c6b0641da795eb5d275reed@google.com SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds())); 26636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } 27636d87a3f411507020a21c6b0641da795eb5d275reed@google.com 28636d87a3f411507020a21c6b0641da795eb5d275reed@google.com if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) { 291c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fState = kDone_State; 30636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } else if (this->fitsInDelta(fClippedBounds)) { 311c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fState = kSimple_State; 321c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 331c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // back up by 1 DX, so that next() will put us in a correct starting 341c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // position. 351c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrOffset.set(fClippedBounds.left() - fDelta, 361c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fClippedBounds.top()); 371c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fState = kComplex_State; 381c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 391c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com} 401c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 411c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.comSkDeviceLooper::~SkDeviceLooper() { 421c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com} 431c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 441c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.comvoid SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const { 451c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(kDone_State != fState); 461c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(fCurrBitmap); 471c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(fCurrRC); 481c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 491c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *dst = src; 501c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com dst->offset(SkIntToScalar(-fCurrOffset.fX), 511c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkIntToScalar(-fCurrOffset.fY)); 521c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com} 531c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 541c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.comvoid SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const { 551c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(kDone_State != fState); 561c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(fCurrBitmap); 571c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(fCurrRC); 581c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 591c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *dst = src; 601c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com dst->postTranslate(SkIntToScalar(-fCurrOffset.fX), 611c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkIntToScalar(-fCurrOffset.fY)); 621c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com} 631c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 641c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.combool SkDeviceLooper::computeCurrBitmapAndClip() { 651c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkASSERT(kComplex_State == fState); 666b00a1ec2ad525cae559d6b6e2157786686b2953skia.committer@gmail.com 671c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(), 681c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fDelta, fDelta); 691c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) { 70636d87a3f411507020a21c6b0641da795eb5d275reed@google.com fSubsetRC.setEmpty(); 71636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } else { 72636d87a3f411507020a21c6b0641da795eb5d275reed@google.com fSubsetBitmap.lockPixels(); 73636d87a3f411507020a21c6b0641da795eb5d275reed@google.com fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC); 74636d87a3f411507020a21c6b0641da795eb5d275reed@google.com (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), 75636d87a3f411507020a21c6b0641da795eb5d275reed@google.com SkRegion::kIntersect_Op); 761c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 776b00a1ec2ad525cae559d6b6e2157786686b2953skia.committer@gmail.com 781c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrBitmap = &fSubsetBitmap; 791c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrRC = &fSubsetRC; 80636d87a3f411507020a21c6b0641da795eb5d275reed@google.com return !fCurrRC->isEmpty(); 81636d87a3f411507020a21c6b0641da795eb5d275reed@google.com} 82636d87a3f411507020a21c6b0641da795eb5d275reed@google.com 83636d87a3f411507020a21c6b0641da795eb5d275reed@google.comstatic bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) { 84636d87a3f411507020a21c6b0641da795eb5d275reed@google.com // can we move to the right? 85636d87a3f411507020a21c6b0641da795eb5d275reed@google.com if (offset->x() + delta < boundary.right()) { 86636d87a3f411507020a21c6b0641da795eb5d275reed@google.com offset->fX += delta; 87636d87a3f411507020a21c6b0641da795eb5d275reed@google.com return true; 88636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } 89636d87a3f411507020a21c6b0641da795eb5d275reed@google.com 90636d87a3f411507020a21c6b0641da795eb5d275reed@google.com // reset to the left, but move down a row 91636d87a3f411507020a21c6b0641da795eb5d275reed@google.com offset->fX = boundary.left(); 92636d87a3f411507020a21c6b0641da795eb5d275reed@google.com if (offset->y() + delta < boundary.bottom()) { 93636d87a3f411507020a21c6b0641da795eb5d275reed@google.com offset->fY += delta; 94636d87a3f411507020a21c6b0641da795eb5d275reed@google.com return true; 95636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } 962291e72b998244f3b4426b7307967b096ab13b1askia.committer@gmail.com 97636d87a3f411507020a21c6b0641da795eb5d275reed@google.com // offset is now outside of boundary, so we're done 98636d87a3f411507020a21c6b0641da795eb5d275reed@google.com return false; 991c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com} 1001c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 1011c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.combool SkDeviceLooper::next() { 1021c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com switch (fState) { 1031c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kDone_State: 1041c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // in theory, we should not get called here, since we must have 1051c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // previously returned false, but we check anyway. 1061c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 1076b00a1ec2ad525cae559d6b6e2157786686b2953skia.committer@gmail.com 1081c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kSimple_State: 1091c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // first time for simple 1101c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (NULL == fCurrBitmap) { 1111c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrBitmap = &fBaseBitmap; 1121c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrRC = &fBaseRC; 1131c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fCurrOffset.set(0, 0); 1141c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com return true; 1151c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 1161c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // 2nd time for simple, we are done 1171c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 1181c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 1191c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kComplex_State: 1201c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // need to propogate fCurrOffset through clippedbounds 1211c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // left to right, until we wrap around and move down 1226b00a1ec2ad525cae559d6b6e2157786686b2953skia.committer@gmail.com 123636d87a3f411507020a21c6b0641da795eb5d275reed@google.com while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) { 124636d87a3f411507020a21c6b0641da795eb5d275reed@google.com if (this->computeCurrBitmapAndClip()) { 125636d87a3f411507020a21c6b0641da795eb5d275reed@google.com return true; 126636d87a3f411507020a21c6b0641da795eb5d275reed@google.com } 1271c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 1281c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 1291c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 1301c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com fState = kDone_State; 1311c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com return false; 1321c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com} 133