/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDeviceLooper_DEFINED
#define SkDeviceLooper_DEFINED
#include "SkBitmap.h"
#include "SkMatrix.h"
#include "SkRasterClip.h"
/**
* Helper class to manage "tiling" a large coordinate space into managable
* chunks, where managable means areas that are <= some max critical coordinate
* size.
*
* The constructor takes an antialiasing bool, which affects what this maximum
* allowable size is: If we're drawing BW, then we need coordinates to stay
* safely within fixed-point range (we use +- 16K, to give ourselves room to
* add/subtract two fixed values and still be in range. If we're drawing AA,
* then we reduce that size by the amount that the supersampler scan converter
* needs (at the moment, that is 4X, so the "safe" range is +- 4K).
*
* For performance reasons, the class first checks to see if any help is needed
* at all, and if not (i.e. the specified bounds and base bitmap area already
* in the safe-zone, then the class does nothing (effectively).
*/
class SkDeviceLooper {
public:
SkDeviceLooper(const SkBitmap& base, const SkRasterClip&,
const SkIRect& bounds, bool aa);
~SkDeviceLooper();
const SkBitmap& getBitmap() const {
SkASSERT(kDone_State != fState);
SkASSERT(fCurrBitmap);
return *fCurrBitmap;
}
const SkRasterClip& getRC() const {
SkASSERT(kDone_State != fState);
SkASSERT(fCurrRC);
return *fCurrRC;
}
void mapRect(SkRect* dst, const SkRect& src) const;
void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
/**
* Call next to setup the looper to return a valid coordinate chunk.
* Each time this returns true, it is safe to call mapRect() and
* mapMatrix(), to convert from "global" coordinate values to ones that
* are local to this chunk.
*
* When next() returns false, the list of chunks is done, and mapRect()
* and mapMatrix() should no longer be called.
*/
bool next();
private:
const SkBitmap& fBaseBitmap;
const SkRasterClip& fBaseRC;
enum State {
kDone_State, // iteration is complete, getters will assert
kSimple_State, // no translate/clip mods needed
kComplex_State
};
// storage for our tiled versions. Perhaps could use SkTLazy
SkBitmap fSubsetBitmap;
SkRasterClip fSubsetRC;
const SkBitmap* fCurrBitmap;
const SkRasterClip* fCurrRC;
SkIRect fClippedBounds;
SkIPoint fCurrOffset;
int fDelta;
State fState;
enum Delta {
kBW_Delta = 1 << 14, // 16K, gives room to spare for fixedpoint
kAA_Delta = kBW_Delta >> 2 // supersample 4x
};
bool fitsInDelta(const SkIRect& r) const {
return r.right() < fDelta && r.bottom() < fDelta;
}
bool computeCurrBitmapAndClip();
};
#endif