11c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com/*
21c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * Copyright 2013 Google Inc.
31c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *
41c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * Use of this source code is governed by a BSD-style license that can be
51c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com * found in the LICENSE file.
61c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com */
71c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
81c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#ifndef SkDeviceLooper_DEFINED
91c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#define SkDeviceLooper_DEFINED
101c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
111c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkBitmap.h"
121c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkMatrix.h"
131c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkRasterClip.h"
141c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
151c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com/**
161c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  Helper class to manage "tiling" a large coordinate space into managable
171c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  chunks, where managable means areas that are <= some max critical coordinate
181c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  size.
191c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *
201c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  The constructor takes an antialiasing bool, which affects what this maximum
211c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  allowable size is: If we're drawing BW, then we need coordinates to stay
221c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  safely within fixed-point range (we use +- 16K, to give ourselves room to
231c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  add/subtract two fixed values and still be in range. If we're drawing AA,
241c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  then we reduce that size by the amount that the supersampler scan converter
251c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  needs (at the moment, that is 4X, so the "safe" range is +- 4K).
261c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *
271c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  For performance reasons, the class first checks to see if any help is needed
281c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  at all, and if not (i.e. the specified bounds and base bitmap area already
291c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com *  in the safe-zone, then the class does nothing (effectively).
301c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com */
311c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.comclass SkDeviceLooper {
321c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.compublic:
331c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    SkDeviceLooper(const SkBitmap& base, const SkRasterClip&,
341c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com                   const SkIRect& bounds, bool aa);
351c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    ~SkDeviceLooper();
361c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
371c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    const SkBitmap& getBitmap() const {
381c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        SkASSERT(kDone_State != fState);
391c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        SkASSERT(fCurrBitmap);
401c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        return *fCurrBitmap;
411c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    }
421c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
431c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    const SkRasterClip& getRC() const {
441c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        SkASSERT(kDone_State != fState);
451c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        SkASSERT(fCurrRC);
461c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        return *fCurrRC;
471c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    }
481c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
491c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    void mapRect(SkRect* dst, const SkRect& src) const;
501c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
511c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
521c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    /**
531c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     *  Call next to setup the looper to return a valid coordinate chunk.
546b00a1ec2ad525cae559d6b6e2157786686b2953skia.committer@gmail.com     *  Each time this returns true, it is safe to call mapRect() and
551c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     *  mapMatrix(), to convert from "global" coordinate values to ones that
561c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     *  are local to this chunk.
571c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     *
581c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     *  When next() returns false, the list of chunks is done, and mapRect()
591c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     *  and mapMatrix() should no longer be called.
601c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com     */
611c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    bool next();
621c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
631c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.comprivate:
641c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    const SkBitmap&     fBaseBitmap;
651c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    const SkRasterClip& fBaseRC;
661c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
671c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    enum State {
681c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        kDone_State,    // iteration is complete, getters will assert
691c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        kSimple_State,  // no translate/clip mods needed
701c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        kComplex_State
711c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    };
721c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
731c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    // storage for our tiled versions. Perhaps could use SkTLazy
741c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    SkBitmap            fSubsetBitmap;
751c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    SkRasterClip        fSubsetRC;
761c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
771c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    const SkBitmap*     fCurrBitmap;
781c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    const SkRasterClip* fCurrRC;
791c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    SkIRect             fClippedBounds;
801c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    SkIPoint            fCurrOffset;
811c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    int                 fDelta;
821c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    State               fState;
831c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
841c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    enum Delta {
851c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        kBW_Delta = 1 << 14,        // 16K, gives room to spare for fixedpoint
861c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        kAA_Delta = kBW_Delta >> 2  // supersample 4x
871c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    };
881c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
891c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    bool fitsInDelta(const SkIRect& r) const {
901c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com        return r.right() < fDelta && r.bottom() < fDelta;
911c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    }
926b00a1ec2ad525cae559d6b6e2157786686b2953skia.committer@gmail.com
931c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    bool computeCurrBitmapAndClip();
941c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com};
951c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com
961c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#endif
97