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