SkImageFilter.h revision d686ac77c2c485c4a3302eda9c1de597a6f8c568
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkImageFilter_DEFINED
9#define SkImageFilter_DEFINED
10
11#include "SkFlattenable.h"
12
13class SkBitmap;
14class SkColorFilter;
15class SkDevice;
16class SkMatrix;
17struct SkIPoint;
18struct SkIRect;
19class GrEffectRef;
20class GrTexture;
21
22/**
23 *  Experimental.
24 *
25 *  Base class for image filters. If one is installed in the paint, then
26 *  all drawing occurs as usual, but it is as if the drawing happened into an
27 *  offscreen (before the xfermode is applied). This offscreen bitmap will
28 *  then be handed to the imagefilter, who in turn creates a new bitmap which
29 *  is what will finally be drawn to the device (using the original xfermode).
30 *
31 *  THIS SIGNATURE IS TEMPORARY
32 *
33 *  There are several weaknesses in this function signature:
34 *  1. Does not expose the destination/target device, so filters that can draw
35 *     directly to it are unable to take advantage of that optimization.
36 *  2. Does not expose a way to create a "compabitible" image (i.e. gpu -> gpu)
37 *  3. As with #1, the filter is unable to "read" the dest (which would be slow)
38 *
39 *  Therefore, we should not create any real dependencies on this API yet -- it
40 *  is being checked in as a check-point so we can explore these and other
41 *  considerations.
42 */
43class SK_API SkImageFilter : public SkFlattenable {
44public:
45    SK_DECLARE_INST_COUNT(SkImageFilter)
46
47    class Proxy {
48    public:
49        virtual ~Proxy() {};
50
51        virtual SkDevice* createDevice(int width, int height) = 0;
52        // returns true if the proxy can handle this filter natively
53        virtual bool canHandleImageFilter(SkImageFilter*) = 0;
54        // returns true if the proxy handled the filter itself. if this returns
55        // false then the filter's code will be called.
56        virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
57                                 const SkMatrix& ctm,
58                                 SkBitmap* result, SkIPoint* offset) = 0;
59    };
60
61    /**
62     *  Request a new (result) image to be created from the src image.
63     *  If the src has no pixels (isNull()) then the request just wants to
64     *  receive the config and width/height of the result.
65     *
66     *  The matrix is the current matrix on the canvas.
67     *
68     *  Offset is the amount to translate the resulting image relative to the
69     *  src when it is drawn.
70     *
71     *  If the result image cannot be created, return false, in which case both
72     *  the result and offset parameters will be ignored by the caller.
73     */
74    bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
75                     SkBitmap* result, SkIPoint* offset);
76
77    /**
78     *  Given the src bounds of an image, this returns the bounds of the result
79     *  image after the filter has been applied.
80     */
81    bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst);
82
83    /**
84     *  Returns true if the filter can be expressed a single-pass
85     *  GrEffect, used to process this filter on the GPU, or false if
86     *  not.
87     *
88     *  If effect is non-NULL, a new GrEffect instance is stored
89     *  in it.  The caller assumes ownership of the stage, and it is up to the
90     *  caller to unref it.
91     *
92     *  The effect can assume its vertexCoords space maps 1-to-1 with texels
93     *  in the texture.
94     */
95    virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const;
96
97    /**
98     *  Returns true if the filter can be processed on the GPU.  This is most
99     *  often used for multi-pass effects, where intermediate results must be
100     *  rendered to textures.  For single-pass effects, use asNewEffect().
101     *  The default implementation returns false.
102     */
103    virtual bool canFilterImageGPU() const;
104
105    /**
106     *  Process this image filter on the GPU.  src is the source image for
107     *  processing, as a texture-backed bitmap.  result is the destination
108     *  bitmap, which should contain a texture-backed pixelref on success.
109     *  The default implementation returns returns false and ignores the
110     *  result parameter.
111     */
112    virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result);
113
114    /**
115     *  Returns this image filter as a color filter if possible,
116     *  NULL otherwise.
117     */
118    virtual SkColorFilter* asColorFilter() const;
119
120    /**
121     *  Returns the number of inputs this filter will accept (some inputs can
122     *  be NULL).
123     */
124    int countInputs() const { return fInputCount; }
125
126    /**
127     *  Returns the input filter at a given index, or NULL if no input is
128     *  connected.  The indices used are filter-specific.
129     */
130    SkImageFilter* getInput(int i) const {
131        SkASSERT(i < fInputCount);
132        return fInputs[i];
133    }
134
135protected:
136    SkImageFilter(int inputCount, SkImageFilter** inputs);
137
138    // Convenience constructor for 1-input filters.
139    explicit SkImageFilter(SkImageFilter* input);
140
141    // Convenience constructor for 2-input filters.
142    SkImageFilter(SkImageFilter* input1, SkImageFilter* input2);
143
144    virtual ~SkImageFilter();
145
146    explicit SkImageFilter(SkFlattenableReadBuffer& rb);
147
148    virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
149
150    // Default impl returns false
151    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
152                               SkBitmap* result, SkIPoint* offset);
153    // Default impl copies src into dst and returns true
154    virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
155
156    // Return the result of processing the given input, or the source bitmap
157    // if we have no connected input at that index.
158    SkBitmap getInputResult(int index, Proxy*, const SkBitmap& src, const SkMatrix&,
159                            SkIPoint*);
160
161private:
162    typedef SkFlattenable INHERITED;
163    int fInputCount;
164    SkImageFilter** fInputs;
165};
166
167#endif
168