2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkImageFilter_DEFINED
9 #define SkImageFilter_DEFINED
11 #include "SkFlattenable.h"
23 * Base class for image filters. If one is installed in the paint, then
24 * all drawing occurs as usual, but it is as if the drawing happened into an
25 * offscreen (before the xfermode is applied). This offscreen bitmap will
26 * then be handed to the imagefilter, who in turn creates a new bitmap which
27 * is what will finally be drawn to the device (using the original xfermode).
29 class SK_API SkImageFilter : public SkFlattenable {
31 SK_DECLARE_INST_COUNT(SkImageFilter)
36 kHasLeft_CropEdge = 0x01,
37 kHasTop_CropEdge = 0x02,
38 kHasRight_CropEdge = 0x04,
39 kHasBottom_CropEdge = 0x08,
40 kHasAll_CropEdge = 0x0F,
43 explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
44 uint32_t flags() const { return fFlags; }
45 const SkRect& rect() const { return fRect; }
51 class SK_API Cache : public SkRefCnt {
53 // By default, we cache only image filters with 2 or more children.
54 static Cache* Create(int minChildren = 2);
56 virtual bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) = 0;
57 virtual void set(const SkImageFilter* key,
58 const SkBitmap& result, const SkIPoint& offset) = 0;
59 virtual void remove(const SkImageFilter* key) = 0;
64 Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) :
65 fCTM(ctm), fClipBounds(clipBounds), fCache(cache) {
67 const SkMatrix& ctm() const { return fCTM; }
68 const SkIRect& clipBounds() const { return fClipBounds; }
69 Cache* cache() const { return fCache; }
80 virtual SkBaseDevice* createDevice(int width, int height) = 0;
81 // returns true if the proxy can handle this filter natively
82 virtual bool canHandleImageFilter(const SkImageFilter*) = 0;
83 // returns true if the proxy handled the filter itself. if this returns
84 // false then the filter's code will be called.
85 virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
87 SkBitmap* result, SkIPoint* offset) = 0;
91 * Request a new (result) image to be created from the src image.
92 * If the src has no pixels (isNull()) then the request just wants to
93 * receive the config and width/height of the result.
95 * The matrix is the current matrix on the canvas.
97 * Offset is the amount to translate the resulting image relative to the
98 * src when it is drawn. This is an out-param.
100 * If the result image cannot be created, return false, in which case both
101 * the result and offset parameters will be ignored by the caller.
103 bool filterImage(Proxy*, const SkBitmap& src, const Context&,
104 SkBitmap* result, SkIPoint* offset) const;
107 * Given the src bounds of an image, this returns the bounds of the result
108 * image after the filter has been applied.
110 bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const;
113 * Returns true if the filter can be processed on the GPU. This is most
114 * often used for multi-pass effects, where intermediate results must be
115 * rendered to textures. For single-pass effects, use asNewEffect().
116 * The default implementation returns asNewEffect(NULL, NULL, SkMatrix::I(),
119 virtual bool canFilterImageGPU() const;
122 * Process this image filter on the GPU. This is most often used for
123 * multi-pass effects, where intermediate results must be rendered to
124 * textures. For single-pass effects, use asNewEffect(). src is the
125 * source image for processing, as a texture-backed bitmap. result is
126 * the destination bitmap, which should contain a texture-backed pixelref
127 * on success. offset is the amount to translate the resulting image
128 * relative to the src when it is drawn. The default implementation does
129 * single-pass processing using asNewEffect().
131 virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&,
132 SkBitmap* result, SkIPoint* offset) const;
135 * Returns whether this image filter is a color filter and puts the color filter into the
136 * "filterPtr" parameter if it can. Does nothing otherwise.
137 * If this returns false, then the filterPtr is unchanged.
138 * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
139 * (i.e. it may not be set to NULL).
141 virtual bool asColorFilter(SkColorFilter** filterPtr) const;
144 * Returns the number of inputs this filter will accept (some inputs can
147 int countInputs() const { return fInputCount; }
150 * Returns the input filter at a given index, or NULL if no input is
151 * connected. The indices used are filter-specific.
153 SkImageFilter* getInput(int i) const {
154 SkASSERT(i < fInputCount);
159 * Returns whether any edges of the crop rect have been set. The crop
160 * rect is set at construction time, and determines which pixels from the
161 * input image will be processed. The size of the crop rect should be
162 * used as the size of the destination image. The origin of this rect
163 * should be used to offset access to the input images, and should also
164 * be added to the "offset" parameter in onFilterImage and
165 * filterImageGPU(). (The latter ensures that the resulting buffer is
166 * drawn in the correct location.)
168 bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
170 // Default impl returns union of all input bounds.
171 virtual void computeFastBounds(const SkRect&, SkRect*) const;
173 #ifdef SK_SUPPORT_GPU
175 * Wrap the given texture in a texture-backed SkBitmap.
177 static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result);
180 * Recursively evaluate this filter on the GPU. If the filter has no GPU
181 * implementation, it will be processed in software and uploaded to the GPU.
183 bool getInputResultGPU(SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&,
184 SkBitmap* result, SkIPoint* offset) const;
188 * Set an external cache to be used for all image filter processing. This
189 * will replace the default intra-frame cache.
191 static void SetExternalCache(Cache* cache);
194 * Returns the currently-set external cache, or NULL if none is set.
196 static Cache* GetExternalCache();
198 SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
201 SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
203 // Convenience constructor for 1-input filters.
204 explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL);
206 // Convenience constructor for 2-input filters.
207 SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL);
209 virtual ~SkImageFilter();
212 * Constructs a new SkImageFilter read from an SkReadBuffer object.
214 * @param inputCount The exact number of inputs expected for this SkImageFilter object.
215 * -1 can be used if the filter accepts any number of inputs.
216 * @param rb SkReadBuffer object from which the SkImageFilter is read.
218 explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
220 virtual void flatten(SkWriteBuffer& wb) const SK_OVERRIDE;
223 * This is the virtual which should be overridden by the derived class
224 * to perform image filtering.
226 * src is the original primitive bitmap. If the filter has a connected
227 * input, it should recurse on that input and use that in place of src.
229 * The matrix is the current matrix on the canvas.
231 * Offset is the amount to translate the resulting image relative to the
232 * src when it is drawn. This is an out-param.
234 * If the result image cannot be created, this should false, in which
235 * case both the result and offset parameters will be ignored by the
238 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
239 SkBitmap* result, SkIPoint* offset) const;
240 // Given the bounds of the destination rect to be filled in device
241 // coordinates (first parameter), and the CTM, compute (conservatively)
242 // which rect of the source image would be required (third parameter).
243 // Used for clipping and temp-buffer allocations, so the result need not
244 // be exact, but should never be smaller than the real answer. The default
245 // implementation recursively unions all input bounds, or returns false if
247 virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
249 /** Computes source bounds as the src bitmap bounds offset by srcOffset.
250 * Apply the transformed crop rect to the bounds if any of the
251 * corresponding edge flags are set. Intersects the result against the
252 * context's clipBounds, and returns the result in "bounds". If there is
253 * no intersection, returns false and leaves "bounds" unchanged.
255 bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
256 SkIRect* bounds) const;
258 /** Same as the above call, except that if the resulting crop rect is not
259 * entirely contained by the source bitmap's bounds, it creates a new
260 * bitmap in "result" and pads the edges with transparent black. In that
261 * case, the srcOffset is modified to be the same as the bounds, since no
262 * further adjustment is needed by the caller. This version should only
263 * be used by filters which are not capable of processing a smaller
264 * source bitmap into a larger destination.
266 bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset,
267 SkIRect* bounds, SkBitmap* result) const;
270 * Returns true if the filter can be expressed a single-pass
271 * GrEffect, used to process this filter on the GPU, or false if
274 * If effect is non-NULL, a new GrEffect instance is stored
275 * in it. The caller assumes ownership of the stage, and it is up to the
276 * caller to unref it.
278 * The effect can assume its vertexCoords space maps 1-to-1 with texels
279 * in the texture. "matrix" is a transformation to apply to filter
280 * parameters before they are used in the effect. Note that this function
281 * will be called with (NULL, NULL, SkMatrix::I()) to query for support,
282 * so returning "true" indicates support for all possible matrices.
284 virtual bool asNewEffect(GrEffectRef** effect,
286 const SkMatrix& matrix,
287 const SkIRect& bounds) const;
290 typedef SkFlattenable INHERITED;
292 SkImageFilter** fInputs;