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"
24 * Base class for image filters. If one is installed in the paint, then
25 * all drawing occurs as usual, but it is as if the drawing happened into an
26 * offscreen (before the xfermode is applied). This offscreen bitmap will
27 * then be handed to the imagefilter, who in turn creates a new bitmap which
28 * is what will finally be drawn to the device (using the original xfermode).
30 class SK_API SkImageFilter : public SkFlattenable {
32 SK_DECLARE_INST_COUNT(SkImageFilter)
37 kHasLeft_CropEdge = 0x01,
38 kHasTop_CropEdge = 0x02,
39 kHasRight_CropEdge = 0x04,
40 kHasBottom_CropEdge = 0x08,
41 kHasAll_CropEdge = 0x0F,
44 explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
45 uint32_t flags() const { return fFlags; }
46 const SkRect& rect() const { return fRect; }
56 virtual SkBaseDevice* createDevice(int width, int height) = 0;
57 // returns true if the proxy can handle this filter natively
58 virtual bool canHandleImageFilter(SkImageFilter*) = 0;
59 // returns true if the proxy handled the filter itself. if this returns
60 // false then the filter's code will be called.
61 virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
63 SkBitmap* result, SkIPoint* offset) = 0;
67 * Request a new (result) image to be created from the src image.
68 * If the src has no pixels (isNull()) then the request just wants to
69 * receive the config and width/height of the result.
71 * The matrix is the current matrix on the canvas.
73 * Offset is the amount to translate the resulting image relative to the
74 * src when it is drawn. This is an out-param.
76 * If the result image cannot be created, return false, in which case both
77 * the result and offset parameters will be ignored by the caller.
79 bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
80 SkBitmap* result, SkIPoint* offset);
83 * Given the src bounds of an image, this returns the bounds of the result
84 * image after the filter has been applied.
86 bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst);
89 * Returns true if the filter can be processed on the GPU. This is most
90 * often used for multi-pass effects, where intermediate results must be
91 * rendered to textures. For single-pass effects, use asNewEffect().
92 * The default implementation returns asNewEffect(NULL, NULL, SkMatrix::I(),
95 virtual bool canFilterImageGPU() const;
98 * Process this image filter on the GPU. This is most often used for
99 * multi-pass effects, where intermediate results must be rendered to
100 * textures. For single-pass effects, use asNewEffect(). src is the
101 * source image for processing, as a texture-backed bitmap. result is
102 * the destination bitmap, which should contain a texture-backed pixelref
103 * on success. offset is the amount to translate the resulting image
104 * relative to the src when it is drawn. The default implementation does
105 * single-pass processing using asNewEffect().
107 virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
108 SkBitmap* result, SkIPoint* offset);
111 * Returns whether this image filter is a color filter and puts the color filter into the
112 * "filterPtr" parameter if it can. Does nothing otherwise.
113 * If this returns false, then the filterPtr is unchanged.
114 * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
115 * (i.e. it may not be set to NULL).
117 virtual bool asColorFilter(SkColorFilter** filterPtr) const;
120 * Returns the number of inputs this filter will accept (some inputs can
123 int countInputs() const { return fInputCount; }
126 * Returns the input filter at a given index, or NULL if no input is
127 * connected. The indices used are filter-specific.
129 SkImageFilter* getInput(int i) const {
130 SkASSERT(i < fInputCount);
135 * Returns whether any edges of the crop rect have been set. The crop
136 * rect is set at construction time, and determines which pixels from the
137 * input image will be processed. The size of the crop rect should be
138 * used as the size of the destination image. The origin of this rect
139 * should be used to offset access to the input images, and should also
140 * be added to the "offset" parameter in onFilterImage and
141 * filterImageGPU(). (The latter ensures that the resulting buffer is
142 * drawn in the correct location.)
144 bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
146 SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
149 SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
151 // Convenience constructor for 1-input filters.
152 explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL);
154 // Convenience constructor for 2-input filters.
155 SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL);
157 virtual ~SkImageFilter();
160 * Constructs a new SkImageFilter read from an SkFlattenableReadBuffer object.
162 * @param inputCount The exact number of inputs expected for this SkImageFilter object.
163 * -1 can be used if the filter accepts any number of inputs.
164 * @param rb SkFlattenableReadBuffer object from which the SkImageFilter is read.
166 explicit SkImageFilter(int inputCount, SkFlattenableReadBuffer& rb);
168 virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
171 * This is the virtual which should be overridden by the derived class
172 * to perform image filtering.
174 * src is the original primitive bitmap. If the filter has a connected
175 * input, it should recurse on that input and use that in place of src.
177 * The matrix is the current matrix on the canvas.
179 * Offset is the amount to translate the resulting image relative to the
180 * src when it is drawn. This is an out-param.
182 * If the result image cannot be created, this should false, in which
183 * case both the result and offset parameters will be ignored by the
186 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
187 SkBitmap* result, SkIPoint* offset);
188 // Default impl copies src into dst and returns true
189 virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
191 // Applies "matrix" to the crop rect, and sets "rect" to the intersection of
192 // "rect" and the transformed crop rect. If there is no overlap, returns
193 // false and leaves "rect" unchanged.
194 bool applyCropRect(SkIRect* rect, const SkMatrix& matrix) const;
197 * Returns true if the filter can be expressed a single-pass
198 * GrEffect, used to process this filter on the GPU, or false if
201 * If effect is non-NULL, a new GrEffect instance is stored
202 * in it. The caller assumes ownership of the stage, and it is up to the
203 * caller to unref it.
205 * The effect can assume its vertexCoords space maps 1-to-1 with texels
206 * in the texture. "matrix" is a transformation to apply to filter
207 * parameters before they are used in the effect. Note that this function
208 * will be called with (NULL, NULL, SkMatrix::I()) to query for support,
209 * so returning "true" indicates support for all possible matrices.
211 virtual bool asNewEffect(GrEffectRef** effect,
213 const SkMatrix& matrix,
214 const SkIRect& bounds) const;
217 typedef SkFlattenable INHERITED;
219 SkImageFilter** fInputs;