SkImageFilter.h revision 6b13473dd4d5915309cc2caddbab2e22f2f21d5f
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
11bf521ff9415b3bdb1acde7b8d18139df176236e5bungeman#include "../private/SkTArray.h"
12f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "../private/SkTemplates.h"
1323526963135bd15737505bd560d41b0d5a41439exidachen#include "../private/SkMutex.h"
148c874eee943bdea0fab5b4d2707083c863e37c55senorblanco#include "SkFilterQuality.h"
15894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h"
164cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org#include "SkMatrix.h"
17194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkRect.h"
182c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed#include "SkSurfaceProps.h"
19894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
20af9b8c804643952d5ff3deed62f1355319b72f72robertphillipsclass GrContext;
212c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrFragmentProcessor;
222c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrTexture;
232c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass SkBaseDevice;
2415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkBitmap;
258d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter;
26c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint;
27df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillipsclass SkSpecialImage;
2815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
2915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com/**
3015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  Base class for image filters. If one is installed in the paint, then
3115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  all drawing occurs as usual, but it is as if the drawing happened into an
3215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  offscreen (before the xfermode is applied). This offscreen bitmap will
3315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  then be handed to the imagefilter, who in turn creates a new bitmap which
3415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com *  is what will finally be drawn to the device (using the original xfermode).
3515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com */
3654e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.orgclass SK_API SkImageFilter : public SkFlattenable {
37894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.compublic:
3855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
3955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    // (result, offset).
40be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco    class Cache : public SkRefCnt {
4155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    public:
4255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        struct Key;
43be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        virtual ~Cache() {}
44be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        static Cache* Create(size_t maxBytes);
45be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        static Cache* Get();
4655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
47df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillips        virtual SkSpecialImage* get(const Key& key, SkIPoint* offset) const = 0;
4855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco        virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
49df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillips        virtual void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset) = 0;
50242397a1c95e34e3e2e5e85c85c81090317115cbmtklein        virtual void purge() {}
5123526963135bd15737505bd560d41b0d5a41439exidachen        virtual void purgeByKeys(const Key[], int) {}
5255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    };
5355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
544cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    class Context {
554cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    public:
564e23cdaa6b892afeaa150c6d74099dc6c2065b7ereed        Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
57c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            : fCTM(ctm)
58c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            , fClipBounds(clipBounds)
59c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            , fCache(cache)
60c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        {}
61c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed
624cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkMatrix& ctm() const { return fCTM; }
634cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkIRect& clipBounds() const { return fClipBounds; }
64be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco        Cache* cache() const { return fCache; }
65c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed
664cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    private:
67c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        SkMatrix        fCTM;
68c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        SkIRect         fClipBounds;
69c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        Cache*          fCache;
704cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    };
714cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org
72189186337eb91b0b21c15db42377bbf3ae4acf23reed    class CropRect {
73189186337eb91b0b21c15db42377bbf3ae4acf23reed    public:
74189186337eb91b0b21c15db42377bbf3ae4acf23reed        enum CropEdge {
75189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasLeft_CropEdge   = 0x01,
76189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasTop_CropEdge    = 0x02,
77ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco            kHasWidth_CropEdge  = 0x04,
78ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco            kHasHeight_CropEdge = 0x08,
79189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasAll_CropEdge    = 0x0F,
80189186337eb91b0b21c15db42377bbf3ae4acf23reed        };
81189186337eb91b0b21c15db42377bbf3ae4acf23reed        CropRect() {}
82189186337eb91b0b21c15db42377bbf3ae4acf23reed        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
83189186337eb91b0b21c15db42377bbf3ae4acf23reed            : fRect(rect), fFlags(flags) {}
84189186337eb91b0b21c15db42377bbf3ae4acf23reed        uint32_t flags() const { return fFlags; }
85189186337eb91b0b21c15db42377bbf3ae4acf23reed        const SkRect& rect() const { return fRect; }
86189186337eb91b0b21c15db42377bbf3ae4acf23reed#ifndef SK_IGNORE_TO_STRING
87189186337eb91b0b21c15db42377bbf3ae4acf23reed        void toString(SkString* str) const;
88189186337eb91b0b21c15db42377bbf3ae4acf23reed#endif
89189186337eb91b0b21c15db42377bbf3ae4acf23reed
90189186337eb91b0b21c15db42377bbf3ae4acf23reed        /**
91189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
926db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  set, then the corresponding edge from imageBounds will be used. If "embiggen"
936db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  is true, the crop rect is allowed to enlarge the size of the rect, otherwise
946db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  it may only reduce the rect. Filters that can affect transparent black should
956db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  pass "true", while all other filters should pass "false".
96189186337eb91b0b21c15db42377bbf3ae4acf23reed         *
97189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  Note: imageBounds is in "device" space, as the output cropped rectangle will be,
98d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco         *  so the matrix is ignored for those. It is only applied the croprect's bounds.
99189186337eb91b0b21c15db42377bbf3ae4acf23reed         */
1006db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco        void applyTo(const SkIRect& imageBounds, const SkMatrix&, bool embiggen,
1016db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco                     SkIRect* cropped) const;
102189186337eb91b0b21c15db42377bbf3ae4acf23reed
103189186337eb91b0b21c15db42377bbf3ae4acf23reed    private:
104189186337eb91b0b21c15db42377bbf3ae4acf23reed        SkRect fRect;
105189186337eb91b0b21c15db42377bbf3ae4acf23reed        uint32_t fFlags;
106189186337eb91b0b21c15db42377bbf3ae4acf23reed    };
107189186337eb91b0b21c15db42377bbf3ae4acf23reed
108a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco    enum TileUsage {
109a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        kPossible_TileUsage,    //!< the created device may be drawn tiled
110a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        kNever_TileUsage,       //!< the created device will never be drawn tiled
111a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco    };
112a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco
11376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    class Proxy {
11476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    public:
11588d064d0e481949184305c7b1d6b282dddffac39reed        virtual ~Proxy() {}
1162766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein
117a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        virtual SkBaseDevice* createDevice(int width, int height,
118a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco                                           TileUsage usage = kNever_TileUsage) = 0;
11988d064d0e481949184305c7b1d6b282dddffac39reed
12088d064d0e481949184305c7b1d6b282dddffac39reed        // Returns true if the proxy handled the filter itself. If this returns
12188d064d0e481949184305c7b1d6b282dddffac39reed        // false then the filter's code will be called.
12288d064d0e481949184305c7b1d6b282dddffac39reed        virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
12388d064d0e481949184305c7b1d6b282dddffac39reed                                 const SkImageFilter::Context&,
12488d064d0e481949184305c7b1d6b282dddffac39reed                                 SkBitmap* result, SkIPoint* offset) = 0;
12588d064d0e481949184305c7b1d6b282dddffac39reed    };
12688d064d0e481949184305c7b1d6b282dddffac39reed
12788d064d0e481949184305c7b1d6b282dddffac39reed    class DeviceProxy : public Proxy {
12888d064d0e481949184305c7b1d6b282dddffac39reed    public:
12988d064d0e481949184305c7b1d6b282dddffac39reed        DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
13088d064d0e481949184305c7b1d6b282dddffac39reed
131a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        SkBaseDevice* createDevice(int width, int height,
132a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco                                   TileUsage usage = kNever_TileUsage) override;
133efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips
134efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // Returns true if the proxy handled the filter itself. If this returns
13576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        // false then the filter's code will be called.
1362c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed        bool filterImage(const SkImageFilter*, const SkBitmap& src, const SkImageFilter::Context&,
137d82bc7b90ab0a88d6fb401994f3763d3057ab6e7reed                         SkBitmap* result, SkIPoint* offset) override;
138efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips
1392c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed    private:
140efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkBaseDevice* fDevice;
14176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com    };
1422766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein
143894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com    /**
144894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Request a new (result) image to be created from the src image.
145894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
1464418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  The context contains the environment in which the filter is occurring.
1474418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  It includes the clip bounds, CTM and cache.
148894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
149894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Offset is the amount to translate the resulting image relative to the
1506776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
151894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
1524418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  If the result image cannot be created, return null, in which case
1534418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  the offset parameters will be ignored by the caller.
1544418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *
1554418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  TODO: Right now the imagefilters sometimes return empty result bitmaps/
1564418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *        specialimages. That doesn't seem quite right.
157894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     */
1582302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> filterImage(SkSpecialImage* src, const Context&, SkIPoint* offset) const;
159eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
160d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco    enum MapDirection {
161d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco        kForward_MapDirection,
162d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco        kReverse_MapDirection
163d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco    };
16415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    /**
165d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * Map a device-space rect recursively forward or backward through the
166d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * filter DAG. kForward_MapDirection is used to determine which pixels of
167d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * the destination canvas a source image rect would touch after filtering.
168127fe3e24b488b7cf67308e791847ee229012862jbroman     * kReverse_MapDirection is used to determine which rect of the source
169d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * image would be required to fill the given rect (typically, clip bounds).
170d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * Used for clipping and temp-buffer allocations, so the result need not
171d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * be exact, but should never be smaller than the real answer. The default
172e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * implementation recursively unions all input bounds, or returns the
173e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * source rect if no inputs.
17432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     */
175e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
176e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco                         MapDirection = kReverse_MapDirection) const;
177e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco
17832d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com    /**
179302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  Returns true if the filter can be processed on the GPU.  This is most
180302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org     *  often used for multi-pass effects, where intermediate results must be
181b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  rendered to textures.  For single-pass effects, use asFragmentProcessor().
182b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
1837938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org     *  SkIRect()).
18405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
185938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips    virtual bool canFilterImageGPU() const { return false; }
18605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
18705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org    /**
1883284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com     *  Process this image filter on the GPU.  This is most often used for
189d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  multi-pass effects, where intermediate results must be rendered to
190b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  textures.  For single-pass effects, use asFragmentProcessor().  src is the
191d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  source image for processing, as a texture-backed bitmap.  result is
192d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org     *  the destination bitmap, which should contain a texture-backed pixelref
193de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com     *  on success.  offset is the amount to translate the resulting image
1947b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org     *  relative to the src when it is drawn. The default implementation does
195b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     *  single-pass processing using asFragmentProcessor().
19605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org     */
197938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips    virtual bool filterImageGPUDeprecated(Proxy*, const SkBitmap&, const Context&,
198938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips                                          SkBitmap*, SkIPoint*) const {
199938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips        SkASSERT(false);
200938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips        return false;
201938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips    }
20205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org
203af9b8c804643952d5ff3deed62f1355319b72f72robertphillips#if SK_SUPPORT_GPU
204af9b8c804643952d5ff3deed62f1355319b72f72robertphillips    static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context,
205af9b8c804643952d5ff3deed62f1355319b72f72robertphillips                                            sk_sp<GrFragmentProcessor> fp,
206af9b8c804643952d5ff3deed62f1355319b72f72robertphillips                                            const SkIRect& bounds,
207af9b8c804643952d5ff3deed62f1355319b72f72robertphillips                                            SkImageFilter::Proxy* proxy);
208af9b8c804643952d5ff3deed62f1355319b72f72robertphillips#endif
209af9b8c804643952d5ff3deed62f1355319b72f72robertphillips
2108d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
211a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com     *  Returns whether this image filter is a color filter and puts the color filter into the
2124b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  "filterPtr" parameter if it can. Does nothing otherwise.
2134b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns false, then the filterPtr is unchanged.
2144b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
2154b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  (i.e. it may not be set to NULL).
2168d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
217cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool isColorFilterNode(SkColorFilter** filterPtr) const {
218cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->onIsColorFilterNode(filterPtr);
219cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
220cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
221cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    // DEPRECATED : use isColorFilterNode() instead
222cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool asColorFilter(SkColorFilter** filterPtr) const {
223cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->isColorFilterNode(filterPtr);
224cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
225cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
226cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
227cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
228cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
229cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  same way.
230cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
231a544eda5ddea215037b1ada6ba5cfc98f6c8ee15senorblanco    bool asAColorFilter(SkColorFilter** filterPtr) const;
2328d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
2338d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
2348d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the number of inputs this filter will accept (some inputs can
2358d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  be NULL).
2368d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
2376b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    int countInputs() const { return fInputs.count(); }
2388d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
2398d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
2408d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the input filter at a given index, or NULL if no input is
2418d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  connected.  The indices used are filter-specific.
2428d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
2438d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    SkImageFilter* getInput(int i) const {
2446b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips        SkASSERT(i < fInputs.count());
2456b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips        return fInputs[i].get();
2468d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    }
2478d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
248194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    /**
2493f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  Returns whether any edges of the crop rect have been set. The crop
2503f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  rect is set at construction time, and determines which pixels from the
251189186337eb91b0b21c15db42377bbf3ae4acf23reed     *  input image will be processed, and which pixels in the output image will be allowed.
252189186337eb91b0b21c15db42377bbf3ae4acf23reed     *  The size of the crop rect should be
2533f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  used as the size of the destination image. The origin of this rect
2543f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  should be used to offset access to the input images, and should also
2553f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  be added to the "offset" parameter in onFilterImage and
2563f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  filterImageGPU(). (The latter ensures that the resulting buffer is
2573f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  drawn in the correct location.)
258194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org     */
2593f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
260194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
261b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed    CropRect getCropRect() const { return fCropRect; }
262b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed
263336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    // Default impl returns union of all input bounds.
264e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    virtual SkRect computeFastBounds(const SkRect&) const;
265336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2660abdf766d395ed3b7059511425f431589eca05f6senorblanco    // Can this filter DAG compute the resulting bounds of an object-space rectangle?
2676db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco    bool canComputeFastBounds() const;
2680abdf766d395ed3b7059511425f431589eca05f6senorblanco
2698c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    /**
27094dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     *  If this filter can be represented by another filter + a localMatrix, return that filter,
27194dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     *  else return null.
27294dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     */
273372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix&) const;
274372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips
275372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
276372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    SkImageFilter* newWithLocalMatrix(const SkMatrix& matrix) const {
277372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips        return this->makeWithLocalMatrix(matrix).release();
278372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    }
279372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips#endif
28094dd7a52d3fe0632cd830f2e9cd14103c2726aacreed
28194dd7a52d3fe0632cd830f2e9cd14103c2726aacreed    /**
2828c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     * Create an SkMatrixImageFilter, which transforms its input by the given matrix.
2838c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     */
284ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips    static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix,
285ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                                 SkFilterQuality,
286ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                                 sk_sp<SkImageFilter> input);
287ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
2888c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
289ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                             SkFilterQuality filterQuality,
290ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                             SkImageFilter* input = nullptr) {
291ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips        return MakeMatrixFilter(matrix, filterQuality, sk_ref_sp<SkImageFilter>(input)).release();
292ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips    }
293ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips#endif
294ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips
2958c874eee943bdea0fab5b4d2707083c863e37c55senorblanco
2962302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> filterInput(int index,
2972302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                      SkSpecialImage* src,
2982302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                      const Context&,
2992302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                      SkIPoint* offset) const;
300eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
3014509517e03fd245298d4059f4568435d640a1758kkinnunen#if SK_SUPPORT_GPU
3029a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // Helper function which invokes GPU filter processing on the
3039a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // input at the specified "index". If the input is null, it leaves
3049a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // "result" and "offset" untouched, and returns true. If the input
3059a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // has a GPU implementation, it will be invoked directly.
3069a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // Otherwise, the filter will be processed in software and
3079a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco    // uploaded to the GPU.
30848e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips    bool filterInputGPUDeprecated(int index, SkImageFilter::Proxy* proxy,
30948e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips                                  const SkBitmap& src, const Context&,
31048e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips                                  SkBitmap* result, SkIPoint* offset) const;
3116aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
3126aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
313f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    SK_TO_STRING_PUREVIRT()
3143b37545bc594a96de45eba62dea0ce478750f2a9mtklein    SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
315c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
316894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected:
317b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    class Common {
318b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    public:
3199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        /**
3209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  Attempt to unflatten the cropRect and the expected number of input filters.
3219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If any number of input filters is valid, pass -1.
3229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
3239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  be left uninitialized.
3249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this returns true, then inputCount() is the number of found input filters, each
3259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  of which may be NULL or a valid imagefilter.
3269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         */
3279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        bool unflatten(SkReadBuffer&, int expectedInputs);
3289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
3299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        const CropRect& cropRect() const { return fCropRect; }
330b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        int             inputCount() const { return fInputs.count(); }
3312238c9dbca4b791edc512957728a18ce14d55912robertphillips        sk_sp<SkImageFilter>* inputs() const { return fInputs.get(); }
332b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
3332238c9dbca4b791edc512957728a18ce14d55912robertphillips        sk_sp<SkImageFilter>  getInput(int index) const { return fInputs[index]; }
3349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
335b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    private:
336b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        CropRect fCropRect;
337b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // most filters accept at most 2 input-filters
3382238c9dbca4b791edc512957728a18ce14d55912robertphillips        SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
339b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
340b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        void allocInputs(int count);
341b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    };
342b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
343372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    SkImageFilter(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect);
3449f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
3459f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    virtual ~SkImageFilter();
3469f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
347c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org    /**
3488b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  Constructs a new SkImageFilter read from an SkReadBuffer object.
349c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *
350c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
351c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *                       -1 can be used if the filter accepts any number of inputs.
3528b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
353c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     */
3548b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
3559f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
35636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer&) const override;
35732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
3586776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    /**
3596776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  This is the virtual which should be overridden by the derived class
3606776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  to perform image filtering.
3616776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3626776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src is the original primitive bitmap. If the filter has a connected
3636776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  input, it should recurse on that input and use that in place of src.
3646776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3656776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  The matrix is the current matrix on the canvas.
3666776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3676776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  Offset is the amount to translate the resulting image relative to the
3686776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
3696776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3706776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  If the result image cannot be created, this should false, in which
3716776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  case both the result and offset parameters will be ignored by the
3726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  caller.
3736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     */
37448e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips    virtual bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
37548e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips                                         SkBitmap* result, SkIPoint* offset) const;
376d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco
3772302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* src, const Context&,
3782302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                                SkIPoint* offset) const;
379eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
380d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco    /**
381e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * This function recurses into its inputs with the given rect (first
382d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * argument), calls filterBounds() with the given map direction on each,
383e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * and returns the union of those results. If a derived class has special
384e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * recursion requirements (e.g., it has an input which does not participate
385e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * in bounds computation), it can be overridden here.
386d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     *
387d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * Note that this function is *not* responsible for mapping the rect for
388d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * this node's filter bounds requirements (i.e., calling
389d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * onFilterNodeBounds()); that is handled by filterBounds().
390d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     */
391e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix&, MapDirection) const;
392db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco
393db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    /**
394db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * Performs a forwards or reverse mapping of the given rect to accommodate
395db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * this filter's margin requirements. kForward_MapDirection is used to
396db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * determine the destination pixels which would be touched by filtering
397db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * the given given source rect (e.g., given source bitmap bounds,
398db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * determine the optimal bounds of the filtered offscreen bitmap).
399db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * kReverse_MapDirection is used to determine which pixels of the
400db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * input(s) would be required to fill the given destination rect
401db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * (e.g., clip bounds). NOTE: these operations may not be the
402db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * inverse of the other. For example, blurring expands the given rect
403db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * in both forward and reverse directions. Unlike
404db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * onFilterBounds(), this function is non-recursive.
405db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     */
406e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const;
407894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
408b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // Helper function which invokes filter processing on the input at the
409b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // specified "index". If the input is null, it leaves "result" and
410b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // "offset" untouched, and returns true. If the input is non-null, it
411b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // calls filterImage() on that input, and returns true on success.
412b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // i.e., return !getInput(index) || getInput(index)->filterImage(...);
41348e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips    bool filterInputDeprecated(int index, Proxy*, const SkBitmap& src, const Context&,
41448e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips                               SkBitmap* result, SkIPoint* offset) const;
415b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco
416cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
417cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
418cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  colorfilter w/o CropRect constraints.
419cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
420cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
421cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return false;
422cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
423cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
424af9b8c804643952d5ff3deed62f1355319b72f72robertphillips    /** Given a "srcBounds" rect, computes destination bounds for this filter.
425af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  "dstBounds" are computed by transforming the crop rect by the context's
426af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  CTM, applying it to the initial bounds, and intersecting the result with
427af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  the context's clip bounds.  "srcBounds" (if non-null) are computed by
428af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  intersecting the initial bounds with "dstBounds", to ensure that we never
429af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  sample outside of the crop rect (this restriction may be relaxed in the
430afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  future).
431118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
432afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco    bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
433afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco
434afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco    /** A variant of the above call which takes the original source bitmap and
435afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  source offset. If the resulting crop rect is not entirely contained by
436afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  the source bitmap's bounds, it creates a new bitmap in "result" and
437afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  pads the edges with transparent black. In that case, the srcOffset is
438afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  modified to be the same as the bounds, since no further adjustment is
439afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  needed by the caller. This version should only be used by filters
440afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  which are not capable of processing a smaller source bitmap into a
441afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  larger destination.
442118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
44348e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips    bool applyCropRectDeprecated(const Context&, Proxy* proxy, const SkBitmap& src,
44448e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips                                 SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* result) const;
445194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
4462302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> applyCropRect(const Context&, SkSpecialImage* src, SkIPoint* srcOffset,
4472302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                        SkIRect* bounds) const;
448eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
4491aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org    /**
450db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  Creates a modified Context for use when recursing up the image filter DAG.
451db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  The clip bounds are adjusted to accommodate any margins that this
452db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  filter requires by calling this node's
453db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  onFilterNodeBounds(..., kReverse_MapDirection).
454db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     */
455db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    Context mapContext(const Context& ctx) const;
456db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco
457894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate:
458242397a1c95e34e3e2e5e85c85c81090317115cbmtklein    friend class SkGraphics;
459242397a1c95e34e3e2e5e85c85c81090317115cbmtklein    static void PurgeCache();
460242397a1c95e34e3e2e5e85c85c81090317115cbmtklein
4616b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    void init(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect);
4624418dbac3386f26c8da62ab242be9c178961eb18robertphillips    bool filterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
4634418dbac3386f26c8da62ab242be9c178961eb18robertphillips                               SkBitmap* result, SkIPoint* offset) const;
4644418dbac3386f26c8da62ab242be9c178961eb18robertphillips
46555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool usesSrcInput() const { return fUsesSrcInput; }
4666db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco    virtual bool affectsTransparentBlack() const { return false; }
46755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
4686b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
4696b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips
47055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool fUsesSrcInput;
471b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    CropRect fCropRect;
47255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fUniqueID; // Globally unique
47323526963135bd15737505bd560d41b0d5a41439exidachen    mutable SkTArray<Cache::Key> fCacheKeys;
47423526963135bd15737505bd560d41b0d5a41439exidachen    mutable SkMutex fMutex;
4756b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    typedef SkFlattenable INHERITED;
476894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com};
477894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
4789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed/**
4799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  Helper to unflatten the common data, and return NULL if we fail.
4809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */
4819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
4829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    Common localVar;                                                \
4839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    do {                                                            \
4849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        if (!localVar.unflatten(buffer, expectedCount)) {           \
4859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return NULL;                                            \
4869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }                                                           \
4879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    } while (0)
4889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
489894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif
490