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 #ifndef SkDeviceLooper_DEFINED
9 #define SkDeviceLooper_DEFINED
10 
11 #include "SkBitmap.h"
12 #include "SkMatrix.h"
13 #include "SkRasterClip.h"
14 
15 /**
16  *  Helper class to manage "tiling" a large coordinate space into managable
17  *  chunks, where managable means areas that are <= some max critical coordinate
18  *  size.
19  *
20  *  The constructor takes an antialiasing bool, which affects what this maximum
21  *  allowable size is: If we're drawing BW, then we need coordinates to stay
22  *  safely within fixed-point range (we use +- 16K, to give ourselves room to
23  *  add/subtract two fixed values and still be in range. If we're drawing AA,
24  *  then we reduce that size by the amount that the supersampler scan converter
25  *  needs (at the moment, that is 4X, so the "safe" range is +- 4K).
26  *
27  *  For performance reasons, the class first checks to see if any help is needed
28  *  at all, and if not (i.e. the specified bounds and base bitmap area already
29  *  in the safe-zone, then the class does nothing (effectively).
30  */
31 class SkDeviceLooper {
32 public:
33     SkDeviceLooper(const SkPixmap& base, const SkRasterClip&, const SkIRect& bounds, bool aa);
34     ~SkDeviceLooper();
35 
getPixmap()36     const SkPixmap& getPixmap() const {
37         SkASSERT(kDone_State != fState);
38         SkASSERT(fCurrDst);
39         return *fCurrDst;
40     }
41 
getRC()42     const SkRasterClip& getRC() const {
43         SkASSERT(kDone_State != fState);
44         SkASSERT(fCurrRC);
45         return *fCurrRC;
46     }
47 
48     void mapRect(SkRect* dst, const SkRect& src) const;
49     void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
50 
51     /**
52      *  Call next to setup the looper to return a valid coordinate chunk.
53      *  Each time this returns true, it is safe to call mapRect() and
54      *  mapMatrix(), to convert from "global" coordinate values to ones that
55      *  are local to this chunk.
56      *
57      *  When next() returns false, the list of chunks is done, and mapRect()
58      *  and mapMatrix() should no longer be called.
59      */
60     bool next();
61 
62 private:
63     const SkPixmap&     fBaseDst;
64     const SkRasterClip& fBaseRC;
65 
66     enum State {
67         kDone_State,    // iteration is complete, getters will assert
68         kSimple_State,  // no translate/clip mods needed
69         kComplex_State
70     };
71 
72     // storage for our tiled versions. Perhaps could use SkTLazy
73     SkPixmap            fSubsetDst;
74     SkRasterClip        fSubsetRC;
75 
76     const SkPixmap*     fCurrDst;
77     const SkRasterClip* fCurrRC;
78     SkIRect             fClippedBounds;
79     SkIPoint            fCurrOffset;
80     int                 fDelta;
81     State               fState;
82 
83     enum Delta {
84         kBW_Delta = 1 << 14,        // 16K, gives room to spare for fixedpoint
85         kAA_Delta = kBW_Delta >> 2  // supersample 4x
86     };
87 
fitsInDelta(const SkIRect & r)88     bool fitsInDelta(const SkIRect& r) const {
89         return r.right() < fDelta && r.bottom() < fDelta;
90     }
91 
92     bool computeCurrBitmapAndClip();
93 };
94 
95 #endif
96