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