gfx/skia/skia/include/core/SkDrawLooper.h
author Wes Kocher <wkocher@mozilla.com>
Wed, 10 May 2017 10:01:18 -0700
changeset 407965 ce2218406119c36a551e3faea4e192186ee46cc5
parent 407937 af6f19870b2a00759ac1d83dedc3db57213abfee
child 408167 0ded74baeaf23d7985401fe9bbabdb3d9385ac22
permissions -rw-r--r--
Backed out 9 changesets (bug 1340627) for graphical glitches a=backout Backed out changeset 0b1371055c7f (bug 1340627) Backed out changeset f152be1fadb7 (bug 1340627) Backed out changeset c691e2ab6a0c (bug 1340627) Backed out changeset 3cb4bceb8d79 (bug 1340627) Backed out changeset 026aadd76d06 (bug 1340627) Backed out changeset fdbd5d281287 (bug 1340627) Backed out changeset 75fb0d9858a9 (bug 1340627) Backed out changeset 0d4ec7d38a00 (bug 1340627) Backed out changeset af6f19870b2a (bug 1340627) MozReview-Commit-ID: 9dHr7xMZezY


/*
 * Copyright 2011 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkDrawLooper_DEFINED
#define SkDrawLooper_DEFINED

#include "SkBlurTypes.h"
#include "SkFlattenable.h"
#include "SkPoint.h"
#include "SkColor.h"

class SkCanvas;
class SkPaint;
struct SkRect;
class SkString;

/** \class SkDrawLooper
    Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
    and something is drawn to a canvas with that paint, the looper subclass will
    be called, allowing it to modify the canvas and/or paint for that draw call.
    More than that, via the next() method, the looper can modify the draw to be
    invoked multiple times (hence the name loop-er), allow it to perform effects
    like shadows or frame/fills, that require more than one pass.
*/
class SK_API SkDrawLooper : public SkFlattenable {
public:
    /**
     *  Holds state during a draw. Users call next() until it returns false.
     *
     *  Subclasses of SkDrawLooper should create a subclass of this object to
     *  hold state specific to their subclass.
     */
    class SK_API Context : ::SkNoncopyable {
    public:
        Context() {}
        virtual ~Context() {}

        /**
         *  Called in a loop on objects returned by SkDrawLooper::createContext().
         *  Each time true is returned, the object is drawn (possibly with a modified
         *  canvas and/or paint). When false is finally returned, drawing for the object
         *  stops.
         *
         *  On each call, the paint will be in its original state, but the
         *  canvas will be as it was following the previous call to next() or
         *  createContext().
         *
         *  The implementation must ensure that, when next() finally returns
         *  false, the canvas has been restored to the state it was
         *  initially, before createContext() was first called.
         */
        virtual bool next(SkCanvas* canvas, SkPaint* paint) = 0;
    };

    /**
     *  Called right before something is being drawn. Returns a Context
     *  whose next() method should be called until it returns false.
     *  The caller has to ensure that the storage pointer provides enough
     *  memory for the Context. The required size can be queried by calling
     *  contextSize(). It is also the caller's responsibility to destroy the
     *  object after use.
     */
    virtual Context* createContext(SkCanvas*, void* storage) const = 0;

    /**
      *  Returns the number of bytes needed to store subclasses of Context (belonging to the
      *  corresponding SkDrawLooper subclass).
      */
    virtual size_t contextSize() const = 0;


    /**
     * The fast bounds functions are used to enable the paint to be culled early
     * in the drawing pipeline. If a subclass can support this feature it must
     * return true for the canComputeFastBounds() function.  If that function
     * returns false then computeFastBounds behavior is undefined otherwise it
     * is expected to have the following behavior. Given the parent paint and
     * the parent's bounding rect the subclass must fill in and return the
     * storage rect, where the storage rect is with the union of the src rect
     * and the looper's bounding rect.
     */
    bool canComputeFastBounds(const SkPaint& paint) const;
    void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const;

    struct BlurShadowRec {
        SkScalar        fSigma;
        SkVector        fOffset;
        SkColor         fColor;
        SkBlurStyle     fStyle;
        SkBlurQuality   fQuality;
    };
    /**
     *  If this looper can be interpreted as having two layers, such that
     *      1. The first layer (bottom most) just has a blur and translate
     *      2. The second layer has no modifications to either paint or canvas
     *      3. No other layers.
     *  then return true, and if not null, fill out the BlurShadowRec).
     *
     *  If any of the above are not met, return false and ignore the BlurShadowRec parameter.
     */
    virtual bool asABlurShadow(BlurShadowRec*) const;

    SK_TO_STRING_PUREVIRT()
    SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper)

protected:
    SkDrawLooper() {}

private:
    typedef SkFlattenable INHERITED;
};

#endif