/* * 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