SkImageFilter.h revision a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60ad
1894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com/*
2894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Copyright 2011 Google Inc.
3894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com *
4894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Use of this source code is governed by a BSD-style license that can be
5894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * found in the LICENSE file.
6894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com */
7894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
8894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#ifndef SkImageFilter_DEFINED
9894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#define SkImageFilter_DEFINED
10894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
11f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "../private/SkTemplates.h"
128c874eee943bdea0fab5b4d2707083c863e37c55senorblanco#include "SkFilterQuality.h"
13894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h"
144cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org#include "SkMatrix.h"
15194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkRect.h"
162c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed#include "SkSurfaceProps.h"
17894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
182c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrFragmentProcessor;
192c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrTexture;
202c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass SkBaseDevice;
2115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkBitmap;
228d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter;
23c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint;
2415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
2515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com/**
2615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  Base class for image filters. If one is installed in the paint, then
2715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  all drawing occurs as usual, but it is as if the drawing happened into an
2815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  offscreen (before the xfermode is applied). This offscreen bitmap will
2915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  then be handed to the imagefilter, who in turn creates a new bitmap which
3015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  is what will finally be drawn to the device (using the original xfermode).
3115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com */
3254e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.orgclass SK_API SkImageFilter : public SkFlattenable {
33894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.compublic:
3455b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
3555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // (result, offset).
36be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    class Cache : public SkRefCnt {
3755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    public:
3855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        struct Key;
39be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        virtual ~Cache() {}
40be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        static Cache* Create(size_t maxBytes);
41be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        static Cache* Get();
4255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
4355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
44242397a1c95e34e3e2e5e85c85c81090317115cbmtklein        virtual void purge() {}
45627769144d233b3abce5ee86cf315df61fa8dcd7xidachen        virtual void purgeByImageFilterId(uint32_t) {}
4655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    };
4755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
484cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    class Context {
494cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    public:
504e23cdaa6b892afeaa150c6d74099dc6c2065b7ereed        Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
51c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            : fCTM(ctm)
52c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            , fClipBounds(clipBounds)
53c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            , fCache(cache)
54c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        {}
55c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed
564cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkMatrix& ctm() const { return fCTM; }
574cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkIRect& clipBounds() const { return fClipBounds; }
58be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        Cache* cache() const { return fCache; }
59c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed
604cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    private:
61c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        SkMatrix        fCTM;
62c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        SkIRect         fClipBounds;
63c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        Cache*          fCache;
644cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    };
654cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org
66189186337eb91b0b21c15db42377bbf3ae4acf23reed    class CropRect {
67189186337eb91b0b21c15db42377bbf3ae4acf23reed    public:
68189186337eb91b0b21c15db42377bbf3ae4acf23reed        enum CropEdge {
69189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasLeft_CropEdge   = 0x01,
70189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasTop_CropEdge    = 0x02,
71ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco            kHasWidth_CropEdge  = 0x04,
72ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco            kHasHeight_CropEdge = 0x08,
73189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasAll_CropEdge    = 0x0F,
74189186337eb91b0b21c15db42377bbf3ae4acf23reed        };
75189186337eb91b0b21c15db42377bbf3ae4acf23reed        CropRect() {}
76189186337eb91b0b21c15db42377bbf3ae4acf23reed        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
77189186337eb91b0b21c15db42377bbf3ae4acf23reed            : fRect(rect), fFlags(flags) {}
78189186337eb91b0b21c15db42377bbf3ae4acf23reed        uint32_t flags() const { return fFlags; }
79189186337eb91b0b21c15db42377bbf3ae4acf23reed        const SkRect& rect() const { return fRect; }
80189186337eb91b0b21c15db42377bbf3ae4acf23reed#ifndef SK_IGNORE_TO_STRING
81189186337eb91b0b21c15db42377bbf3ae4acf23reed        void toString(SkString* str) const;
82189186337eb91b0b21c15db42377bbf3ae4acf23reed#endif
83189186337eb91b0b21c15db42377bbf3ae4acf23reed
84189186337eb91b0b21c15db42377bbf3ae4acf23reed        /**
85189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
86189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  set, then the corresponding edge from imageBounds will be used.
87189186337eb91b0b21c15db42377bbf3ae4acf23reed         *
88189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  Note: imageBounds is in "device" space, as the output cropped rectangle will be,
89189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  so the context's CTM is ignore for those. It is only applied the croprect's bounds.
90189186337eb91b0b21c15db42377bbf3ae4acf23reed         *
91189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  The resulting rect will be intersected with the context's clip. If that intersection is
92189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  empty, then this returns false and cropped is unmodified.
93189186337eb91b0b21c15db42377bbf3ae4acf23reed         */
94189186337eb91b0b21c15db42377bbf3ae4acf23reed        bool applyTo(const SkIRect& imageBounds, const Context&, SkIRect* cropped) const;
95189186337eb91b0b21c15db42377bbf3ae4acf23reed
96189186337eb91b0b21c15db42377bbf3ae4acf23reed    private:
97189186337eb91b0b21c15db42377bbf3ae4acf23reed        SkRect fRect;
98189186337eb91b0b21c15db42377bbf3ae4acf23reed        uint32_t fFlags;
99189186337eb91b0b21c15db42377bbf3ae4acf23reed    };
100189186337eb91b0b21c15db42377bbf3ae4acf23reed
101a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco    enum TileUsage {
102a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        kPossible_TileUsage,    //!< the created device may be drawn tiled
103a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        kNever_TileUsage,       //!< the created device will never be drawn tiled
104a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco    };
105a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco
10676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    class Proxy {
10776dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    public:
10888d064d0e481949184305c7b1d6b282dddffac39reed        virtual ~Proxy() {}
1092766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein
110a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        virtual SkBaseDevice* createDevice(int width, int height,
111a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco                                           TileUsage usage = kNever_TileUsage) = 0;
11288d064d0e481949184305c7b1d6b282dddffac39reed
11388d064d0e481949184305c7b1d6b282dddffac39reed        // Returns true if the proxy handled the filter itself. If this returns
11488d064d0e481949184305c7b1d6b282dddffac39reed        // false then the filter's code will be called.
11588d064d0e481949184305c7b1d6b282dddffac39reed        virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
11688d064d0e481949184305c7b1d6b282dddffac39reed                                 const SkImageFilter::Context&,
11788d064d0e481949184305c7b1d6b282dddffac39reed                                 SkBitmap* result, SkIPoint* offset) = 0;
11888d064d0e481949184305c7b1d6b282dddffac39reed    };
11988d064d0e481949184305c7b1d6b282dddffac39reed
12088d064d0e481949184305c7b1d6b282dddffac39reed    class DeviceProxy : public Proxy {
12188d064d0e481949184305c7b1d6b282dddffac39reed    public:
12288d064d0e481949184305c7b1d6b282dddffac39reed        DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
12388d064d0e481949184305c7b1d6b282dddffac39reed
124a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        SkBaseDevice* createDevice(int width, int height,
125a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco                                   TileUsage usage = kNever_TileUsage) override;
126efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips
127efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // Returns true if the proxy handled the filter itself. If this returns
12876dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        // false then the filter's code will be called.
1292c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed        bool filterImage(const SkImageFilter*, const SkBitmap& src, const SkImageFilter::Context&,
130d82bc7b90ab0a88d6fb401994f3763d3057ab6e7reed                         SkBitmap* result, SkIPoint* offset) override;
131efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips
1322c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed    private:
133efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkBaseDevice* fDevice;
13476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    };
1352766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein
136894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com    /**
137894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Request a new (result) image to be created from the src image.
138894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  If the src has no pixels (isNull()) then the request just wants to
139894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  receive the config and width/height of the result.
140894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
141894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  The matrix is the current matrix on the canvas.
142894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
143894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Offset is the amount to translate the resulting image relative to the
1446776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
145894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
146894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  If the result image cannot be created, return false, in which case both
147894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  the result and offset parameters will be ignored by the caller.
148894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     */
1494cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    bool filterImage(Proxy*, const SkBitmap& src, const Context&,
150ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                     SkBitmap* result, SkIPoint* offset) const;
15115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
15215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    /**
15332d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     *  Given the src bounds of an image, this returns the bounds of the result
15432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     *  image after the filter has been applied.
15532d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     */
156c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const;
15732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
15832d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    /**
159302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  Returns true if the filter can be processed on the GPU.  This is most
160302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  often used for multi-pass effects, where intermediate results must be
161b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  rendered to textures.  For single-pass effects, use asFragmentProcessor().
162b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
1637938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org     *  SkIRect()).
16405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
165302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org    virtual bool canFilterImageGPU() const;
16605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
16705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    /**
1683284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com     *  Process this image filter on the GPU.  This is most often used for
169d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  multi-pass effects, where intermediate results must be rendered to
170b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  textures.  For single-pass effects, use asFragmentProcessor().  src is the
171d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  source image for processing, as a texture-backed bitmap.  result is
172d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  the destination bitmap, which should contain a texture-backed pixelref
173de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com     *  on success.  offset is the amount to translate the resulting image
1747b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org     *  relative to the src when it is drawn. The default implementation does
175b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  single-pass processing using asFragmentProcessor().
17605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
1774cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
178ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                SkBitmap* result, SkIPoint* offset) const;
17905054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
1808d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
181a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com     *  Returns whether this image filter is a color filter and puts the color filter into the
1824b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  "filterPtr" parameter if it can. Does nothing otherwise.
1834b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns false, then the filterPtr is unchanged.
1844b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
1854b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  (i.e. it may not be set to NULL).
1868d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
187cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool isColorFilterNode(SkColorFilter** filterPtr) const {
188cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->onIsColorFilterNode(filterPtr);
189cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
190cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
191cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    // DEPRECATED : use isColorFilterNode() instead
192cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool asColorFilter(SkColorFilter** filterPtr) const {
193cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->isColorFilterNode(filterPtr);
194cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
195cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
196cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
197cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
198cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
199cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  same way.
200cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
201a544eda5ddea215037b1ada6ba5cfc98f6c8ee15senorblanco    bool asAColorFilter(SkColorFilter** filterPtr) const;
2028d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
2038d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
2048d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the number of inputs this filter will accept (some inputs can
2058d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  be NULL).
2068d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
2078d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    int countInputs() const { return fInputCount; }
2088d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
2098d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
2108d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the input filter at a given index, or NULL if no input is
2118d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  connected.  The indices used are filter-specific.
2128d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
2138d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    SkImageFilter* getInput(int i) const {
2148d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org        SkASSERT(i < fInputCount);
2158d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org        return fInputs[i];
2168d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    }
2178d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
218194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    /**
2193f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  Returns whether any edges of the crop rect have been set. The crop
2203f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  rect is set at construction time, and determines which pixels from the
221189186337eb91b0b21c15db42377bbf3ae4acf23reed     *  input image will be processed, and which pixels in the output image will be allowed.
222189186337eb91b0b21c15db42377bbf3ae4acf23reed     *  The size of the crop rect should be
2233f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  used as the size of the destination image. The origin of this rect
2243f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  should be used to offset access to the input images, and should also
2253f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  be added to the "offset" parameter in onFilterImage and
2263f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  filterImageGPU(). (The latter ensures that the resulting buffer is
2273f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  drawn in the correct location.)
228194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org     */
2293f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
230194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
231b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed    CropRect getCropRect() const { return fCropRect; }
232b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed
233336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    // Default impl returns union of all input bounds.
234336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    virtual void computeFastBounds(const SkRect&, SkRect*) const;
235336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2360abdf766d395ed3b7059511425f431589eca05f6senorblanco    // Can this filter DAG compute the resulting bounds of an object-space rectangle?
237a544eda5ddea215037b1ada6ba5cfc98f6c8ee15senorblanco    virtual bool canComputeFastBounds() const;
2380abdf766d395ed3b7059511425f431589eca05f6senorblanco
2398c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    /**
24094dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     *  If this filter can be represented by another filter + a localMatrix, return that filter,
24194dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     *  else return null.
24294dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     */
24394dd7a52d3fe0632cd830f2e9cd14103c2726aacreed    SkImageFilter* newWithLocalMatrix(const SkMatrix& matrix) const;
24494dd7a52d3fe0632cd830f2e9cd14103c2726aacreed
24594dd7a52d3fe0632cd830f2e9cd14103c2726aacreed    /**
2468c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     * Create an SkMatrixImageFilter, which transforms its input by the given matrix.
2478c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     */
2488c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
2498c874eee943bdea0fab5b4d2707083c863e37c55senorblanco                                             SkFilterQuality,
2508c874eee943bdea0fab5b4d2707083c863e37c55senorblanco                                             SkImageFilter* input = NULL);
2518c874eee943bdea0fab5b4d2707083c863e37c55senorblanco
2524509517e03fd245298d4059f4568435d640a1758kkinnunen#if SK_SUPPORT_GPU
2536aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    /**
2546aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     * Wrap the given texture in a texture-backed SkBitmap.
2556aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org     */
2566aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
2576aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
2589a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // Helper function which invokes GPU filter processing on the
2599a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // input at the specified "index". If the input is null, it leaves
2609a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // "result" and "offset" untouched, and returns true. If the input
2619a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // has a GPU implementation, it will be invoked directly.
2629a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // Otherwise, the filter will be processed in software and
2639a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // uploaded to the GPU.
2649a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    bool filterInputGPU(int index, SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
2652c3176c18fcb0ef1594ca9dfbcabcb5e86086301robertphillips                        SkBitmap* result, SkIPoint* offset) const;
2666aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
2676aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
268f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    SK_TO_STRING_PUREVIRT()
269c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
270c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
271894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected:
272b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    class Common {
273b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    public:
274b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        Common() {}
275b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        ~Common();
276b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
2779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        /**
2789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  Attempt to unflatten the cropRect and the expected number of input filters.
2799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If any number of input filters is valid, pass -1.
2809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
2819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  be left uninitialized.
2829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this returns true, then inputCount() is the number of found input filters, each
2839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  of which may be NULL or a valid imagefilter.
2849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         */
2859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        bool unflatten(SkReadBuffer&, int expectedInputs);
2869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
2879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        const CropRect& cropRect() const { return fCropRect; }
288b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        int             inputCount() const { return fInputs.count(); }
289b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        SkImageFilter** inputs() const { return fInputs.get(); }
290b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
2919fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        SkImageFilter*  getInput(int index) const { return fInputs[index]; }
2929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
293b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // If the caller wants a copy of the inputs, call this and it will transfer ownership
294b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // of the unflattened input filters to the caller. This is just a short-cut for copying
295b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // the inputs, calling ref() on each, and then waiting for Common's destructor to call
296b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // unref() on each.
297b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        void detachInputs(SkImageFilter** inputs);
298b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
299b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    private:
300b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        CropRect fCropRect;
301b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // most filters accept at most 2 input-filters
302b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        SkAutoSTArray<2, SkImageFilter*> fInputs;
303b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
304b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        void allocInputs(int count);
305b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    };
306b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
30724e06d5244ae96e440410e1d76e039983b2efac9senorblanco    SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
3089f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
3099f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    virtual ~SkImageFilter();
3109f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
311c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org    /**
3128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  Constructs a new SkImageFilter read from an SkReadBuffer object.
313c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *
314c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
315c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *                       -1 can be used if the filter accepts any number of inputs.
3168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
317c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     */
3188b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
3199f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
32036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer&) const override;
32132d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
3226776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    /**
3236776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  This is the virtual which should be overridden by the derived class
3246776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  to perform image filtering.
3256776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3266776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src is the original primitive bitmap. If the filter has a connected
3276776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  input, it should recurse on that input and use that in place of src.
3286776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3296776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  The matrix is the current matrix on the canvas.
3306776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3316776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  Offset is the amount to translate the resulting image relative to the
3326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
3336776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3346776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  If the result image cannot be created, this should false, in which
3356776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  case both the result and offset parameters will be ignored by the
3366776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  caller.
3376776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     */
3384cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
339ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                               SkBitmap* result, SkIPoint* offset) const;
340c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // Given the bounds of the destination rect to be filled in device
341c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // coordinates (first parameter), and the CTM, compute (conservatively)
342c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // which rect of the source image would be required (third parameter).
343c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // Used for clipping and temp-buffer allocations, so the result need not
344c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // be exact, but should never be smaller than the real answer. The default
345c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // implementation recursively unions all input bounds, or returns false if
346c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // no inputs.
347c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
348db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    enum MapDirection {
349db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        kForward_MapDirection,
350db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        kReverse_MapDirection
351db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    };
352db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco
353db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    /**
354db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * Performs a forwards or reverse mapping of the given rect to accommodate
355db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * this filter's margin requirements. kForward_MapDirection is used to
356db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * determine the destination pixels which would be touched by filtering
357db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * the given given source rect (e.g., given source bitmap bounds,
358db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * determine the optimal bounds of the filtered offscreen bitmap).
359db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * kReverse_MapDirection is used to determine which pixels of the
360db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * input(s) would be required to fill the given destination rect
361db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * (e.g., clip bounds). NOTE: these operations may not be the
362db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * inverse of the other. For example, blurring expands the given rect
363db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * in both forward and reverse directions. Unlike
364db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * onFilterBounds(), this function is non-recursive.
365db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     */
366db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    virtual void onFilterNodeBounds(const SkIRect&, const SkMatrix&, SkIRect*, MapDirection) const;
367894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
368b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // Helper function which invokes filter processing on the input at the
369b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // specified "index". If the input is null, it leaves "result" and
370b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // "offset" untouched, and returns true. If the input is non-null, it
371b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // calls filterImage() on that input, and returns true on success.
372b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // i.e., return !getInput(index) || getInput(index)->filterImage(...);
373b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    bool filterInput(int index, Proxy*, const SkBitmap& src, const Context&,
3744e23cdaa6b892afeaa150c6d74099dc6c2065b7ereed                     SkBitmap* result, SkIPoint* offset) const;
375b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco
376cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
377cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
378cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  colorfilter w/o CropRect constraints.
379cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
380cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
381cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return false;
382cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
383cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
3844449398b324a7d6226a71e766561ace0028b5153senorblanco    /** Given a "src" bitmap and its "srcOffset", computes source and
3854449398b324a7d6226a71e766561ace0028b5153senorblanco     *  destination bounds for this filter. Initial bounds are the
3864449398b324a7d6226a71e766561ace0028b5153senorblanco     *  "src" bitmap bounds offset by "srcOffset". "dstBounds" are
3874449398b324a7d6226a71e766561ace0028b5153senorblanco     *  computed by transforming the crop rect by the context's CTM,
3884449398b324a7d6226a71e766561ace0028b5153senorblanco     *  applying it to the initial bounds, and intersecting the result
3894449398b324a7d6226a71e766561ace0028b5153senorblanco     *  with the context's clip bounds.  "srcBounds" (if non-null) are
3904449398b324a7d6226a71e766561ace0028b5153senorblanco     *  computed by intersecting the initial bounds with "dstBounds", to
3914449398b324a7d6226a71e766561ace0028b5153senorblanco     *  ensure that we never sample outside of the crop rect (this restriction
3924449398b324a7d6226a71e766561ace0028b5153senorblanco     *  may be relaxed in the future).
393118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
394118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
3954449398b324a7d6226a71e766561ace0028b5153senorblanco                       SkIRect* dstBounds, SkIRect* srcBounds = nullptr) const;
396118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
397118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    /** Same as the above call, except that if the resulting crop rect is not
398118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  entirely contained by the source bitmap's bounds, it creates a new
399118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  bitmap in "result" and pads the edges with transparent black. In that
400118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  case, the srcOffset is modified to be the same as the bounds, since no
401118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  further adjustment is needed by the caller. This version should only
402118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  be used by filters which are not capable of processing a smaller
403118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     *  source bitmap into a larger destination.
404118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
405118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset,
406118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                       SkIRect* bounds, SkBitmap* result) const;
407194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
4081aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org    /**
4091aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  Returns true if the filter can be expressed a single-pass
410b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  GrProcessor, used to process this filter on the GPU, or false if
4111aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  not.
4121aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *
413b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  If effect is non-NULL, a new GrProcessor instance is stored
4141aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  in it.  The caller assumes ownership of the stage, and it is up to the
4151aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  caller to unref it.
4161aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *
4171aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  The effect can assume its vertexCoords space maps 1-to-1 with texels
4181aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  in the texture.  "matrix" is a transformation to apply to filter
4191aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  parameters before they are used in the effect. Note that this function
4201aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  will be called with (NULL, NULL, SkMatrix::I()) to query for support,
4211aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     *  so returning "true" indicates support for all possible matrices.
4221aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org     */
4234a339529612a43871d021877e58698e067d6c4cdbsalomon    virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
4244a339529612a43871d021877e58698e067d6c4cdbsalomon                                     const SkIRect& bounds) const;
4251aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org
426db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    /**
427db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  Creates a modified Context for use when recursing up the image filter DAG.
428db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  The clip bounds are adjusted to accommodate any margins that this
429db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  filter requires by calling this node's
430db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  onFilterNodeBounds(..., kReverse_MapDirection).
431db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     */
432db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    Context mapContext(const Context& ctx) const;
433db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco
434894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate:
435242397a1c95e34e3e2e5e85c85c81090317115cbmtklein    friend class SkGraphics;
436242397a1c95e34e3e2e5e85c85c81090317115cbmtklein    static void PurgeCache();
437242397a1c95e34e3e2e5e85c85c81090317115cbmtklein
43855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool usesSrcInput() const { return fUsesSrcInput; }
43955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
44054e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org    typedef SkFlattenable INHERITED;
4418d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    int fInputCount;
4429f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    SkImageFilter** fInputs;
44355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool fUsesSrcInput;
444b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    CropRect fCropRect;
44555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fUniqueID; // Globally unique
446894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com};
447894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
4489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed/**
4499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  Helper to unflatten the common data, and return NULL if we fail.
4509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */
4519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
4529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    Common localVar;                                                \
4539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    do {                                                            \
4549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        if (!localVar.unflatten(buffer, expectedCount)) {           \
4559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return NULL;                                            \
4569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }                                                           \
4579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    } while (0)
4589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
459894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif
460