SkImageFilter.h revision 8b0e8ac5f582de80356019406e2975079bf0829d
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#include "SkRect.h" 13 14class SkBitmap; 15class SkColorFilter; 16class SkBaseDevice; 17class SkMatrix; 18struct SkIPoint; 19class SkShader; 20class GrEffectRef; 21class GrTexture; 22 23/** 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). 29 */ 30class SK_API SkImageFilter : public SkFlattenable { 31public: 32 SK_DECLARE_INST_COUNT(SkImageFilter) 33 34 class CropRect { 35 public: 36 enum CropEdge { 37 kHasLeft_CropEdge = 0x01, 38 kHasTop_CropEdge = 0x02, 39 kHasRight_CropEdge = 0x04, 40 kHasBottom_CropEdge = 0x08, 41 kHasAll_CropEdge = 0x0F, 42 }; 43 CropRect() {} 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; } 47 private: 48 SkRect fRect; 49 uint32_t fFlags; 50 }; 51 52 class Proxy { 53 public: 54 virtual ~Proxy() {}; 55 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, 62 const SkMatrix& ctm, 63 SkBitmap* result, SkIPoint* offset) = 0; 64 }; 65 66 /** 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. 70 * 71 * The matrix is the current matrix on the canvas. 72 * 73 * Offset is the amount to translate the resulting image relative to the 74 * src when it is drawn. This is an out-param. 75 * 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. 78 */ 79 bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm, 80 SkBitmap* result, SkIPoint* offset); 81 82 /** 83 * Given the src bounds of an image, this returns the bounds of the result 84 * image after the filter has been applied. 85 */ 86 bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst); 87 88 /** 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(), 93 * SkIRect()). 94 */ 95 virtual bool canFilterImageGPU() const; 96 97 /** 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(). 106 */ 107 virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const SkMatrix& ctm, 108 SkBitmap* result, SkIPoint* offset); 109 110 /** 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). 116 */ 117 virtual bool asColorFilter(SkColorFilter** filterPtr) const; 118 119 /** 120 * Returns the number of inputs this filter will accept (some inputs can 121 * be NULL). 122 */ 123 int countInputs() const { return fInputCount; } 124 125 /** 126 * Returns the input filter at a given index, or NULL if no input is 127 * connected. The indices used are filter-specific. 128 */ 129 SkImageFilter* getInput(int i) const { 130 SkASSERT(i < fInputCount); 131 return fInputs[i]; 132 } 133 134 /** 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.) 143 */ 144 bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } 145 146 // Default impl returns union of all input bounds. 147 virtual void computeFastBounds(const SkRect&, SkRect*) const; 148 149 SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter) 150 151protected: 152 SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL); 153 154 // Convenience constructor for 1-input filters. 155 explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL); 156 157 // Convenience constructor for 2-input filters. 158 SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL); 159 160 virtual ~SkImageFilter(); 161 162 /** 163 * Constructs a new SkImageFilter read from an SkReadBuffer object. 164 * 165 * @param inputCount The exact number of inputs expected for this SkImageFilter object. 166 * -1 can be used if the filter accepts any number of inputs. 167 * @param rb SkReadBuffer object from which the SkImageFilter is read. 168 */ 169 explicit SkImageFilter(int inputCount, SkReadBuffer& rb); 170 171 virtual void flatten(SkWriteBuffer& wb) const SK_OVERRIDE; 172 173 /** 174 * This is the virtual which should be overridden by the derived class 175 * to perform image filtering. 176 * 177 * src is the original primitive bitmap. If the filter has a connected 178 * input, it should recurse on that input and use that in place of src. 179 * 180 * The matrix is the current matrix on the canvas. 181 * 182 * Offset is the amount to translate the resulting image relative to the 183 * src when it is drawn. This is an out-param. 184 * 185 * If the result image cannot be created, this should false, in which 186 * case both the result and offset parameters will be ignored by the 187 * caller. 188 */ 189 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, 190 SkBitmap* result, SkIPoint* offset); 191 // Default impl copies src into dst and returns true 192 virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*); 193 194 // Applies "matrix" to the crop rect, and sets "rect" to the intersection of 195 // "rect" and the transformed crop rect. If there is no overlap, returns 196 // false and leaves "rect" unchanged. 197 bool applyCropRect(SkIRect* rect, const SkMatrix& matrix) const; 198 199 /** 200 * Returns true if the filter can be expressed a single-pass 201 * GrEffect, used to process this filter on the GPU, or false if 202 * not. 203 * 204 * If effect is non-NULL, a new GrEffect instance is stored 205 * in it. The caller assumes ownership of the stage, and it is up to the 206 * caller to unref it. 207 * 208 * The effect can assume its vertexCoords space maps 1-to-1 with texels 209 * in the texture. "matrix" is a transformation to apply to filter 210 * parameters before they are used in the effect. Note that this function 211 * will be called with (NULL, NULL, SkMatrix::I()) to query for support, 212 * so returning "true" indicates support for all possible matrices. 213 */ 214 virtual bool asNewEffect(GrEffectRef** effect, 215 GrTexture*, 216 const SkMatrix& matrix, 217 const SkIRect& bounds) const; 218 219private: 220 typedef SkFlattenable INHERITED; 221 int fInputCount; 222 SkImageFilter** fInputs; 223 CropRect fCropRect; 224}; 225 226#endif 227