10a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger/*
20a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * Copyright 2013 Google Inc.
30a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *
40a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
50a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger * found in the LICENSE file.
60a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger */
70a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
80a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifndef SkDeviceLooper_DEFINED
90a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#define SkDeviceLooper_DEFINED
100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkBitmap.h"
120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkMatrix.h"
130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#include "SkRasterClip.h"
140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger/**
160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  Helper class to manage "tiling" a large coordinate space into managable
170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  chunks, where managable means areas that are <= some max critical coordinate
180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  size.
190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *
200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  The constructor takes an antialiasing bool, which affects what this maximum
210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  allowable size is: If we're drawing BW, then we need coordinates to stay
220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  safely within fixed-point range (we use +- 16K, to give ourselves room to
230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  add/subtract two fixed values and still be in range. If we're drawing AA,
240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  then we reduce that size by the amount that the supersampler scan converter
250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  needs (at the moment, that is 4X, so the "safe" range is +- 4K).
260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *
270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  For performance reasons, the class first checks to see if any help is needed
280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  at all, and if not (i.e. the specified bounds and base bitmap area already
290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger *  in the safe-zone, then the class does nothing (effectively).
300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger */
310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerclass SkDeviceLooper {
320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerpublic:
330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkDeviceLooper(const SkBitmap& base, const SkRasterClip&,
340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                   const SkIRect& bounds, bool aa);
350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    ~SkDeviceLooper();
360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkBitmap& getBitmap() const {
380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(kDone_State != fState);
390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(fCurrBitmap);
400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        return *fCurrBitmap;
410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkRasterClip& getRC() const {
440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(kDone_State != fState);
450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        SkASSERT(fCurrRC);
460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        return *fCurrRC;
470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    void mapRect(SkRect* dst, const SkRect& src) const;
500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    /**
530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *  Call next to setup the looper to return a valid coordinate chunk.
540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *  Each time this returns true, it is safe to call mapRect() and
550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *  mapMatrix(), to convert from "global" coordinate values to ones that
560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *  are local to this chunk.
570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *
580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *  When next() returns false, the list of chunks is done, and mapRect()
590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     *  and mapMatrix() should no longer be called.
600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger     */
610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    bool next();
620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerprivate:
640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkBitmap&     fBaseBitmap;
650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkRasterClip& fBaseRC;
660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    enum State {
680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kDone_State,    // iteration is complete, getters will assert
690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kSimple_State,  // no translate/clip mods needed
700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kComplex_State
710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    };
720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // storage for our tiled versions. Perhaps could use SkTLazy
740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkBitmap            fSubsetBitmap;
750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkRasterClip        fSubsetRC;
760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkBitmap*     fCurrBitmap;
780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkRasterClip* fCurrRC;
790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkIRect             fClippedBounds;
800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    SkIPoint            fCurrOffset;
810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    int                 fDelta;
820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    State               fState;
830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    enum Delta {
850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kBW_Delta = 1 << 14,        // 16K, gives room to spare for fixedpoint
860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        kAA_Delta = kBW_Delta >> 2  // supersample 4x
870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    };
880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    bool fitsInDelta(const SkIRect& r) const {
900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        return r.right() < fDelta && r.bottom() < fDelta;
910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    bool computeCurrBitmapAndClip();
940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger};
950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#endif
97