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 */
31class SkDeviceLooper {
32public:
33    SkDeviceLooper(const SkBitmap& base, const SkRasterClip&,
34                   const SkIRect& bounds, bool aa);
35    ~SkDeviceLooper();
36
37    const SkBitmap& getBitmap() const {
38        SkASSERT(kDone_State != fState);
39        SkASSERT(fCurrBitmap);
40        return *fCurrBitmap;
41    }
42
43    const SkRasterClip& getRC() const {
44        SkASSERT(kDone_State != fState);
45        SkASSERT(fCurrRC);
46        return *fCurrRC;
47    }
48
49    void mapRect(SkRect* dst, const SkRect& src) const;
50    void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
51
52    /**
53     *  Call next to setup the looper to return a valid coordinate chunk.
54     *  Each time this returns true, it is safe to call mapRect() and
55     *  mapMatrix(), to convert from "global" coordinate values to ones that
56     *  are local to this chunk.
57     *
58     *  When next() returns false, the list of chunks is done, and mapRect()
59     *  and mapMatrix() should no longer be called.
60     */
61    bool next();
62
63private:
64    const SkBitmap&     fBaseBitmap;
65    const SkRasterClip& fBaseRC;
66
67    enum State {
68        kDone_State,    // iteration is complete, getters will assert
69        kSimple_State,  // no translate/clip mods needed
70        kComplex_State
71    };
72
73    // storage for our tiled versions. Perhaps could use SkTLazy
74    SkBitmap            fSubsetBitmap;
75    SkRasterClip        fSubsetRC;
76
77    const SkBitmap*     fCurrBitmap;
78    const SkRasterClip* fCurrRC;
79    SkIRect             fClippedBounds;
80    SkIPoint            fCurrOffset;
81    int                 fDelta;
82    State               fState;
83
84    enum Delta {
85        kBW_Delta = 1 << 14,        // 16K, gives room to spare for fixedpoint
86        kAA_Delta = kBW_Delta >> 2  // supersample 4x
87    };
88
89    bool fitsInDelta(const SkIRect& r) const {
90        return r.right() < fDelta && r.bottom() < fDelta;
91    }
92
93    bool computeCurrBitmapAndClip();
94};
95
96#endif
97