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