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"
14afbf71dd924c7bb46ccdac49e7408b4b088563ffbrianosman#include "SkColorSpace.h"
158c874eee943bdea0fab5b4d2707083c863e37c55senorblanco#include "SkFilterQuality.h"
16894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h"
174cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org#include "SkMatrix.h"
18194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkRect.h"
19894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
20af9b8c804643952d5ff3deed62f1355319b72f72robertphillipsclass GrContext;
212c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrFragmentProcessor;
228d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter;
2331abf1fc945c27755173b78037e62576cf2dd62eMatt Sarettclass SkColorSpaceXformer;
24c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint;
25df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillipsclass SkSpecialImage;
26900c36779610dc65c42a5004ee3693fd70961ba4senorblancoclass SkImageFilterCache;
27900c36779610dc65c42a5004ee3693fd70961ba4senorblancostruct SkImageFilterCacheKey;
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:
382a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    // Extra information about the output of a filter DAG. For now, this is just the color space
392a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    // (of the original requesting device). This is used when constructing intermediate rendering
402a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    // surfaces, so that we ensure we land in a surface that's similar/compatible to the final
412a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    // consumer of the DAG's output.
422a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    class OutputProperties {
432a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    public:
442a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        explicit OutputProperties(SkColorSpace* colorSpace) : fColorSpace(colorSpace) {}
452a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman
462a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        SkColorSpace* colorSpace() const { return fColorSpace; }
472a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman
482a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    private:
492a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        // This will be a pointer to the device's color space, and our lifetime is bounded by
502a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        // the device, so we can store a bare pointer.
512a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        SkColorSpace* fColorSpace;
522a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    };
532a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman
544cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    class Context {
554cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    public:
562a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        Context(const SkMatrix& ctm, const SkIRect& clipBounds, SkImageFilterCache* cache,
572a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                const OutputProperties& outputProperties)
58c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            : fCTM(ctm)
59c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            , fClipBounds(clipBounds)
60c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed            , fCache(cache)
612a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman            , fOutputProperties(outputProperties)
62c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed        {}
63c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed
644cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkMatrix& ctm() const { return fCTM; }
654cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        const SkIRect& clipBounds() const { return fClipBounds; }
66900c36779610dc65c42a5004ee3693fd70961ba4senorblanco        SkImageFilterCache* cache() const { return fCache; }
672a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        const OutputProperties& outputProperties() const { return fOutputProperties; }
68c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed
694cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    private:
70900c36779610dc65c42a5004ee3693fd70961ba4senorblanco        SkMatrix               fCTM;
71900c36779610dc65c42a5004ee3693fd70961ba4senorblanco        SkIRect                fClipBounds;
72900c36779610dc65c42a5004ee3693fd70961ba4senorblanco        SkImageFilterCache*    fCache;
732a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        OutputProperties       fOutputProperties;
744cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    };
754cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org
76189186337eb91b0b21c15db42377bbf3ae4acf23reed    class CropRect {
77189186337eb91b0b21c15db42377bbf3ae4acf23reed    public:
78189186337eb91b0b21c15db42377bbf3ae4acf23reed        enum CropEdge {
79189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasLeft_CropEdge   = 0x01,
80189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasTop_CropEdge    = 0x02,
81ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco            kHasWidth_CropEdge  = 0x04,
82ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco            kHasHeight_CropEdge = 0x08,
83189186337eb91b0b21c15db42377bbf3ae4acf23reed            kHasAll_CropEdge    = 0x0F,
84189186337eb91b0b21c15db42377bbf3ae4acf23reed        };
85189186337eb91b0b21c15db42377bbf3ae4acf23reed        CropRect() {}
86189186337eb91b0b21c15db42377bbf3ae4acf23reed        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
87189186337eb91b0b21c15db42377bbf3ae4acf23reed            : fRect(rect), fFlags(flags) {}
88189186337eb91b0b21c15db42377bbf3ae4acf23reed        uint32_t flags() const { return fFlags; }
89189186337eb91b0b21c15db42377bbf3ae4acf23reed        const SkRect& rect() const { return fRect; }
90189186337eb91b0b21c15db42377bbf3ae4acf23reed#ifndef SK_IGNORE_TO_STRING
91189186337eb91b0b21c15db42377bbf3ae4acf23reed        void toString(SkString* str) const;
92189186337eb91b0b21c15db42377bbf3ae4acf23reed#endif
93189186337eb91b0b21c15db42377bbf3ae4acf23reed
94189186337eb91b0b21c15db42377bbf3ae4acf23reed        /**
95189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
966db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  set, then the corresponding edge from imageBounds will be used. If "embiggen"
976db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  is true, the crop rect is allowed to enlarge the size of the rect, otherwise
986db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  it may only reduce the rect. Filters that can affect transparent black should
996db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco         *  pass "true", while all other filters should pass "false".
100189186337eb91b0b21c15db42377bbf3ae4acf23reed         *
101189186337eb91b0b21c15db42377bbf3ae4acf23reed         *  Note: imageBounds is in "device" space, as the output cropped rectangle will be,
102d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco         *  so the matrix is ignored for those. It is only applied the croprect's bounds.
103189186337eb91b0b21c15db42377bbf3ae4acf23reed         */
1046db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco        void applyTo(const SkIRect& imageBounds, const SkMatrix&, bool embiggen,
1056db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco                     SkIRect* cropped) const;
106189186337eb91b0b21c15db42377bbf3ae4acf23reed
107189186337eb91b0b21c15db42377bbf3ae4acf23reed    private:
108189186337eb91b0b21c15db42377bbf3ae4acf23reed        SkRect fRect;
109189186337eb91b0b21c15db42377bbf3ae4acf23reed        uint32_t fFlags;
110189186337eb91b0b21c15db42377bbf3ae4acf23reed    };
111189186337eb91b0b21c15db42377bbf3ae4acf23reed
112a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco    enum TileUsage {
113a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        kPossible_TileUsage,    //!< the created device may be drawn tiled
114a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco        kNever_TileUsage,       //!< the created device will never be drawn tiled
115a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco    };
116a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco
117894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com    /**
1185878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco     *  Request a new filtered image to be created from the src image.
119894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
1204418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  The context contains the environment in which the filter is occurring.
1214418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  It includes the clip bounds, CTM and cache.
122894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
123894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *  Offset is the amount to translate the resulting image relative to the
1246776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
125894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     *
1265878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco     *  If the result image cannot be created, or the result would be
1275878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco     *  transparent black, return null, in which case the offset parameter
1285878dbdf1b5d86201d299c6e07d53e35048713c7senorblanco     *  should be ignored by the caller.
1294418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *
1304418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *  TODO: Right now the imagefilters sometimes return empty result bitmaps/
1314418dbac3386f26c8da62ab242be9c178961eb18robertphillips     *        specialimages. That doesn't seem quite right.
132894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com     */
1332302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> filterImage(SkSpecialImage* src, const Context&, SkIPoint* offset) const;
134eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
135d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco    enum MapDirection {
136d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco        kForward_MapDirection,
137d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco        kReverse_MapDirection
138d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco    };
13915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    /**
140d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * Map a device-space rect recursively forward or backward through the
141d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * filter DAG. kForward_MapDirection is used to determine which pixels of
142d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * the destination canvas a source image rect would touch after filtering.
143127fe3e24b488b7cf67308e791847ee229012862jbroman     * kReverse_MapDirection is used to determine which rect of the source
144d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * image would be required to fill the given rect (typically, clip bounds).
145d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * Used for clipping and temp-buffer allocations, so the result need not
146d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * be exact, but should never be smaller than the real answer. The default
147e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * implementation recursively unions all input bounds, or returns the
148e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * source rect if no inputs.
14932d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com     */
150e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
151e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco                         MapDirection = kReverse_MapDirection) const;
152e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco
153af9b8c804643952d5ff3deed62f1355319b72f72robertphillips#if SK_SUPPORT_GPU
1542a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman    static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context,
155af9b8c804643952d5ff3deed62f1355319b72f72robertphillips                                            sk_sp<GrFragmentProcessor> fp,
156afbf71dd924c7bb46ccdac49e7408b4b088563ffbrianosman                                            const SkIRect& bounds,
1572a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                            const OutputProperties& outputProperties);
158af9b8c804643952d5ff3deed62f1355319b72f72robertphillips#endif
159af9b8c804643952d5ff3deed62f1355319b72f72robertphillips
1608d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
161a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com     *  Returns whether this image filter is a color filter and puts the color filter into the
1624b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  "filterPtr" parameter if it can. Does nothing otherwise.
1634b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns false, then the filterPtr is unchanged.
1644b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
1654b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com     *  (i.e. it may not be set to NULL).
1668d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
167cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool isColorFilterNode(SkColorFilter** filterPtr) const {
168cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->onIsColorFilterNode(filterPtr);
169cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
170cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
171cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    // DEPRECATED : use isColorFilterNode() instead
172cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    bool asColorFilter(SkColorFilter** filterPtr) const {
173cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return this->isColorFilterNode(filterPtr);
174cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
175cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
176185a3798db64c64d47ef89a5fd3d4c5c70f1e621xidachen    void removeKey(const SkImageFilterCacheKey& key) const;
177185a3798db64c64d47ef89a5fd3d4c5c70f1e621xidachen
178cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
179cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
180cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
181cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  same way.
182cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
183a544eda5ddea215037b1ada6ba5cfc98f6c8ee15senorblanco    bool asAColorFilter(SkColorFilter** filterPtr) const;
1848d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
1858d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1868d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the number of inputs this filter will accept (some inputs can
1878d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  be NULL).
1888d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1896b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    int countInputs() const { return fInputs.count(); }
1908d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
1918d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    /**
1928d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  Returns the input filter at a given index, or NULL if no input is
1938d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     *  connected.  The indices used are filter-specific.
1948d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org     */
1958d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    SkImageFilter* getInput(int i) const {
1966b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips        SkASSERT(i < fInputs.count());
1976b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips        return fInputs[i].get();
1988d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    }
1998d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
200194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    /**
2013f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  Returns whether any edges of the crop rect have been set. The crop
2023f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  rect is set at construction time, and determines which pixels from the
203189186337eb91b0b21c15db42377bbf3ae4acf23reed     *  input image will be processed, and which pixels in the output image will be allowed.
204189186337eb91b0b21c15db42377bbf3ae4acf23reed     *  The size of the crop rect should be
2053f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  used as the size of the destination image. The origin of this rect
2063f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org     *  should be used to offset access to the input images, and should also
2073e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  be added to the "offset" parameter in onFilterImage.
208194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org     */
2093f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
210194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
211b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed    CropRect getCropRect() const { return fCropRect; }
212b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed
213336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    // Default impl returns union of all input bounds.
214e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    virtual SkRect computeFastBounds(const SkRect&) const;
215336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2160abdf766d395ed3b7059511425f431589eca05f6senorblanco    // Can this filter DAG compute the resulting bounds of an object-space rectangle?
2176db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco    bool canComputeFastBounds() const;
2180abdf766d395ed3b7059511425f431589eca05f6senorblanco
2198c874eee943bdea0fab5b4d2707083c863e37c55senorblanco    /**
22094dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     *  If this filter can be represented by another filter + a localMatrix, return that filter,
22194dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     *  else return null.
22294dd7a52d3fe0632cd830f2e9cd14103c2726aacreed     */
223372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips    sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix&) const;
224372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips
22594dd7a52d3fe0632cd830f2e9cd14103c2726aacreed    /**
226bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed     *  ImageFilters can natively handle scaling and translate components in the CTM. Only some of
227bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed     *  them can handle affine (or more complex) matrices. This call returns true iff the filter
228bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed     *  and all of its (non-null) inputs can handle these more complex matrices.
229bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed     */
23096a04f329926099f0002f97883242793ff04f61creed    bool canHandleComplexCTM() const;
231bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed
232bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed    /**
2338c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     * Return an imagefilter which transforms its input by the given matrix.
2348c874eee943bdea0fab5b4d2707083c863e37c55senorblanco     */
235ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips    static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix,
2368c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                 SkFilterQuality quality,
237ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips                                                 sk_sp<SkImageFilter> input);
2388c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
239f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    SK_TO_STRING_PUREVIRT()
2403b37545bc594a96de45eba62dea0ce478750f2a9mtklein    SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
241e1e5c74086ceb7143bf2f7968a324e8c06d33914vjiaoblack    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
242c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
243894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected:
244b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    class Common {
245b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    public:
2469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        /**
2479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  Attempt to unflatten the cropRect and the expected number of input filters.
2489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If any number of input filters is valid, pass -1.
2499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
2509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  be left uninitialized.
2519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  If this returns true, then inputCount() is the number of found input filters, each
2529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         *  of which may be NULL or a valid imagefilter.
2539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed         */
2549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        bool unflatten(SkReadBuffer&, int expectedInputs);
2559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
2569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        const CropRect& cropRect() const { return fCropRect; }
257b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        int             inputCount() const { return fInputs.count(); }
2582238c9dbca4b791edc512957728a18ce14d55912robertphillips        sk_sp<SkImageFilter>* inputs() const { return fInputs.get(); }
259b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
2602238c9dbca4b791edc512957728a18ce14d55912robertphillips        sk_sp<SkImageFilter>  getInput(int index) const { return fInputs[index]; }
2619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
262b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    private:
263b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        CropRect fCropRect;
264b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        // most filters accept at most 2 input-filters
2652238c9dbca4b791edc512957728a18ce14d55912robertphillips        SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
266b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
267b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed        void allocInputs(int count);
268b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed    };
269b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed
270ce6b4b004b2842e61cd9f86ebb75d1872044b382Mike Reed    SkImageFilter(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);
2719f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
272d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~SkImageFilter() override;
2739f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
274c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org    /**
2758b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  Constructs a new SkImageFilter read from an SkReadBuffer object.
276c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *
277c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
278c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     *                       -1 can be used if the filter accepts any number of inputs.
2798b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
280c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org     */
2818b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
2829f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
28336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer&) const override;
28432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com
28531abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett    const CropRect* getCropRectIfSet() const {
28631abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett        return this->cropRectIsSet() ? &fCropRect : nullptr;
28731abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett    }
28831abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett
2896776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    /**
2906776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  This is the virtual which should be overridden by the derived class
2916776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  to perform image filtering.
2926776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2936776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src is the original primitive bitmap. If the filter has a connected
2946776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  input, it should recurse on that input and use that in place of src.
2956776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2966776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  The matrix is the current matrix on the canvas.
2976776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
2986776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  Offset is the amount to translate the resulting image relative to the
2996776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *  src when it is drawn. This is an out-param.
3006776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     *
3013e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  If the result image cannot be created (either because of error or if, say, the result
3023e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  is entirely clipped out), this should return nullptr.
3033e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  Callers that affect transparent black should explicitly handle nullptr
3043e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  results and press on. In the error case this behavior will produce a better result
3053e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  than nothing and is necessary for the clipped out case.
3063e302275b324172c845627cbd00cee8a06571bafrobertphillips     *  If the return value is nullptr then offset should be ignored.
3076776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org     */
3082302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* src, const Context&,
3093e302275b324172c845627cbd00cee8a06571bafrobertphillips                                                SkIPoint* offset) const = 0;
310eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
311d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco    /**
312e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * This function recurses into its inputs with the given rect (first
313d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * argument), calls filterBounds() with the given map direction on each,
314e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * and returns the union of those results. If a derived class has special
315e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * recursion requirements (e.g., it has an input which does not participate
316e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco     * in bounds computation), it can be overridden here.
317d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     *
318d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * Note that this function is *not* responsible for mapping the rect for
319d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * this node's filter bounds requirements (i.e., calling
320d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     * onFilterNodeBounds()); that is handled by filterBounds().
321d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco     */
322e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix&, MapDirection) const;
323db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco
324db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    /**
325db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * Performs a forwards or reverse mapping of the given rect to accommodate
326db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * this filter's margin requirements. kForward_MapDirection is used to
327db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * determine the destination pixels which would be touched by filtering
328db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * the given given source rect (e.g., given source bitmap bounds,
329db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * determine the optimal bounds of the filtered offscreen bitmap).
330db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * kReverse_MapDirection is used to determine which pixels of the
331db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * input(s) would be required to fill the given destination rect
332db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * (e.g., clip bounds). NOTE: these operations may not be the
333db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * inverse of the other. For example, blurring expands the given rect
334db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * in both forward and reverse directions. Unlike
335db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     * onFilterBounds(), this function is non-recursive.
336db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     */
337e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco    virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const;
338894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
339b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco    // Helper function which invokes filter processing on the input at the
3403e302275b324172c845627cbd00cee8a06571bafrobertphillips    // specified "index". If the input is null, it returns "src" and leaves
3413e302275b324172c845627cbd00cee8a06571bafrobertphillips    // "offset" untouched. If the input is non-null, it
3423e302275b324172c845627cbd00cee8a06571bafrobertphillips    // calls filterImage() on that input, and returns the result.
3433e302275b324172c845627cbd00cee8a06571bafrobertphillips    sk_sp<SkSpecialImage> filterInput(int index,
3443e302275b324172c845627cbd00cee8a06571bafrobertphillips                                      SkSpecialImage* src,
3453e302275b324172c845627cbd00cee8a06571bafrobertphillips                                      const Context&,
3463e302275b324172c845627cbd00cee8a06571bafrobertphillips                                      SkIPoint* offset) const;
347b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco
348cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    /**
349cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
350cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     *  colorfilter w/o CropRect constraints.
351cedc36f18b2254c5ee21f6348124886b6db4f4c2reed     */
352cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
353cedc36f18b2254c5ee21f6348124886b6db4f4c2reed        return false;
354cedc36f18b2254c5ee21f6348124886b6db4f4c2reed    }
355cedc36f18b2254c5ee21f6348124886b6db4f4c2reed
35696a04f329926099f0002f97883242793ff04f61creed    /**
35796a04f329926099f0002f97883242793ff04f61creed     *  Override this to describe the behavior of your subclass - as a leaf node. The caller will
35896a04f329926099f0002f97883242793ff04f61creed     *  take care of calling your inputs (and return false if any of them could not handle it).
35996a04f329926099f0002f97883242793ff04f61creed     */
36096a04f329926099f0002f97883242793ff04f61creed    virtual bool onCanHandleComplexCTM() const { return false; }
361bb34a8ac59850f128d9602e629a7475e3ad1a9d2reed
362af9b8c804643952d5ff3deed62f1355319b72f72robertphillips    /** Given a "srcBounds" rect, computes destination bounds for this filter.
363af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  "dstBounds" are computed by transforming the crop rect by the context's
364af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  CTM, applying it to the initial bounds, and intersecting the result with
365af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  the context's clip bounds.  "srcBounds" (if non-null) are computed by
366af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  intersecting the initial bounds with "dstBounds", to ensure that we never
367af9b8c804643952d5ff3deed62f1355319b72f72robertphillips     *  sample outside of the crop rect (this restriction may be relaxed in the
368afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  future).
369118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
370afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco    bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
371afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco
372afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco    /** A variant of the above call which takes the original source bitmap and
373afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  source offset. If the resulting crop rect is not entirely contained by
374afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  the source bitmap's bounds, it creates a new bitmap in "result" and
375afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  pads the edges with transparent black. In that case, the srcOffset is
376afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  modified to be the same as the bounds, since no further adjustment is
377afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  needed by the caller. This version should only be used by filters
378afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  which are not capable of processing a smaller source bitmap into a
379afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco     *  larger destination.
380118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org     */
3812302de920e5434809bd0e85b871a6e002856dfdbrobertphillips    sk_sp<SkSpecialImage> applyCropRect(const Context&, SkSpecialImage* src, SkIPoint* srcOffset,
3822302de920e5434809bd0e85b871a6e002856dfdbrobertphillips                                        SkIRect* bounds) const;
383eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips
3841aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org    /**
385db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  Creates a modified Context for use when recursing up the image filter DAG.
386db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  The clip bounds are adjusted to accommodate any margins that this
387db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  filter requires by calling this node's
388db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     *  onFilterNodeBounds(..., kReverse_MapDirection).
389db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco     */
390db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco    Context mapContext(const Context& ctx) const;
391db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco
392615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman#if SK_SUPPORT_GPU
393615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman    /**
394615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman     *  Returns a version of the passed-in image (possibly the original), that is in a colorspace
395615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman     *  with the same gamut as the one from the OutputProperties. This allows filters that do many
396615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman     *  texture samples to guarantee that any color space conversion has happened before running.
397615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman     */
398615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman    static sk_sp<SkSpecialImage> ImageToColorSpace(SkSpecialImage* src, const OutputProperties&);
399615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman#endif
400615d66d1aed8f0b6510d58658e639b69c4d73b35Brian Osman
40131abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett    /**
40231abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett     *  Returns an image filter transformed into a new color space via the |xformer|.
40331abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett     */
40431abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett    sk_sp<SkImageFilter> makeColorSpace(SkColorSpaceXformer* xformer) const {
40531abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett        return this->onMakeColorSpace(xformer);
40631abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett    }
40762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    virtual sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const = 0;
40831abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett
4096d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    sk_sp<SkImageFilter> refMe() const {
4106d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed        return sk_ref_sp(const_cast<SkImageFilter*>(this));
4116d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    }
4126d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed
413894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate:
4146d72ed918d8763e65899183c2d12b06958c791f4Matt Sarett    // For makeColorSpace().
41531abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett    friend class SkColorSpaceXformer;
4166d72ed918d8763e65899183c2d12b06958c791f4Matt Sarett
417242397a1c95e34e3e2e5e85c85c81090317115cbmtklein    friend class SkGraphics;
41831abf1fc945c27755173b78037e62576cf2dd62eMatt Sarett
419242397a1c95e34e3e2e5e85c85c81090317115cbmtklein    static void PurgeCache();
420242397a1c95e34e3e2e5e85c85c81090317115cbmtklein
421ce6b4b004b2842e61cd9f86ebb75d1872044b382Mike Reed    void init(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);
4224418dbac3386f26c8da62ab242be9c178961eb18robertphillips
42355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool usesSrcInput() const { return fUsesSrcInput; }
4246db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco    virtual bool affectsTransparentBlack() const { return false; }
42555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco
4266b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
4276b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips
42855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    bool fUsesSrcInput;
429b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    CropRect fCropRect;
43055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco    uint32_t fUniqueID; // Globally unique
431900c36779610dc65c42a5004ee3693fd70961ba4senorblanco    mutable SkTArray<SkImageFilterCacheKey> fCacheKeys;
43223526963135bd15737505bd560d41b0d5a41439exidachen    mutable SkMutex fMutex;
4336b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips    typedef SkFlattenable INHERITED;
434894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com};
435894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com
4369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed/**
4379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  Helper to unflatten the common data, and return NULL if we fail.
4389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */
4399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)    \
4409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    Common localVar;                                                \
4419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    do {                                                            \
4429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        if (!localVar.unflatten(buffer, expectedCount)) {           \
4439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return NULL;                                            \
4449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }                                                           \
4459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    } while (0)
4469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
447894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif
448