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 SkPixmap& base, const SkRasterClip&, const SkIRect& bounds, bool aa);
34    ~SkDeviceLooper();
35
36    const SkPixmap& getPixmap() const {
37        SkASSERT(kDone_State != fState);
38        SkASSERT(fCurrDst);
39        return *fCurrDst;
40    }
41
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
62private:
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
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