michael@0: michael@0: /* michael@0: * Copyright 2011 The Android Open Source Project 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: michael@0: #ifndef SkDrawLooper_DEFINED michael@0: #define SkDrawLooper_DEFINED michael@0: michael@0: #include "SkFlattenable.h" michael@0: michael@0: class SkCanvas; michael@0: class SkPaint; michael@0: struct SkRect; michael@0: class SkString; michael@0: michael@0: /** \class SkDrawLooper michael@0: Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are, michael@0: and something is drawn to a canvas with that paint, the looper subclass will michael@0: be called, allowing it to modify the canvas and/or paint for that draw call. michael@0: More than that, via the next() method, the looper can modify the draw to be michael@0: invoked multiple times (hence the name loop-er), allow it to perform effects michael@0: like shadows or frame/fills, that require more than one pass. michael@0: */ michael@0: class SK_API SkDrawLooper : public SkFlattenable { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkDrawLooper) michael@0: michael@0: /** michael@0: * Holds state during a draw. Users call next() until it returns false. michael@0: * michael@0: * Subclasses of SkDrawLooper should create a subclass of this object to michael@0: * hold state specific to their subclass. michael@0: */ michael@0: class SK_API Context : public SkNoncopyable { michael@0: public: michael@0: Context() {} michael@0: virtual ~Context() {} michael@0: michael@0: /** michael@0: * Called in a loop on objects returned by SkDrawLooper::createContext(). michael@0: * Each time true is returned, the object is drawn (possibly with a modified michael@0: * canvas and/or paint). When false is finally returned, drawing for the object michael@0: * stops. michael@0: * michael@0: * On each call, the paint will be in its original state, but the michael@0: * canvas will be as it was following the previous call to next() or michael@0: * createContext(). michael@0: * michael@0: * The implementation must ensure that, when next() finally returns michael@0: * false, the canvas has been restored to the state it was michael@0: * initially, before createContext() was first called. michael@0: */ michael@0: virtual bool next(SkCanvas* canvas, SkPaint* paint) = 0; michael@0: }; michael@0: michael@0: /** michael@0: * Called right before something is being drawn. Returns a Context michael@0: * whose next() method should be called until it returns false. michael@0: * The caller has to ensure that the storage pointer provides enough michael@0: * memory for the Context. The required size can be queried by calling michael@0: * contextSize(). It is also the caller's responsibility to destroy the michael@0: * object after use. michael@0: */ michael@0: virtual Context* createContext(SkCanvas*, void* storage) const = 0; michael@0: michael@0: /** michael@0: * Returns the number of bytes needed to store subclasses of Context (belonging to the michael@0: * corresponding SkDrawLooper subclass). michael@0: */ michael@0: virtual size_t contextSize() const = 0; michael@0: michael@0: michael@0: /** michael@0: * The fast bounds functions are used to enable the paint to be culled early michael@0: * in the drawing pipeline. If a subclass can support this feature it must michael@0: * return true for the canComputeFastBounds() function. If that function michael@0: * returns false then computeFastBounds behavior is undefined otherwise it michael@0: * is expected to have the following behavior. Given the parent paint and michael@0: * the parent's bounding rect the subclass must fill in and return the michael@0: * storage rect, where the storage rect is with the union of the src rect michael@0: * and the looper's bounding rect. michael@0: */ michael@0: virtual bool canComputeFastBounds(const SkPaint& paint) const; michael@0: virtual void computeFastBounds(const SkPaint& paint, michael@0: const SkRect& src, SkRect* dst) const; michael@0: michael@0: SK_TO_STRING_PUREVIRT() michael@0: SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper) michael@0: michael@0: protected: michael@0: SkDrawLooper() {} michael@0: SkDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {} michael@0: michael@0: private: michael@0: typedef SkFlattenable INHERITED; michael@0: }; michael@0: michael@0: #endif