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 "SkMatrix.h" 13#include "SkRect.h" 14 15class SkBitmap; 16class SkColorFilter; 17class SkBaseDevice; 18struct SkIPoint; 19class GrEffectRef; 20class GrTexture; 21 22/** 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). 28 */ 29class SK_API SkImageFilter : public SkFlattenable { 30public: 31 SK_DECLARE_INST_COUNT(SkImageFilter) 32 33 class CropRect { 34 public: 35 enum CropEdge { 36 kHasLeft_CropEdge = 0x01, 37 kHasTop_CropEdge = 0x02, 38 kHasRight_CropEdge = 0x04, 39 kHasBottom_CropEdge = 0x08, 40 kHasAll_CropEdge = 0x0F, 41 }; 42 CropRect() {} 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; } 46 private: 47 SkRect fRect; 48 uint32_t fFlags; 49 }; 50 51 class SK_API Cache : public SkRefCnt { 52 public: 53 // By default, we cache only image filters with 2 or more children. 54 static Cache* Create(int minChildren = 2); 55 virtual ~Cache() {} 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; 60 }; 61 62 class Context { 63 public: 64 Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) : 65 fCTM(ctm), fClipBounds(clipBounds), fCache(cache) { 66 } 67 const SkMatrix& ctm() const { return fCTM; } 68 const SkIRect& clipBounds() const { return fClipBounds; } 69 Cache* cache() const { return fCache; } 70 private: 71 SkMatrix fCTM; 72 SkIRect fClipBounds; 73 Cache* fCache; 74 }; 75 76 class Proxy { 77 public: 78 virtual ~Proxy() {}; 79 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, 86 const Context&, 87 SkBitmap* result, SkIPoint* offset) = 0; 88 }; 89 90 /** 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. 94 * 95 * The matrix is the current matrix on the canvas. 96 * 97 * Offset is the amount to translate the resulting image relative to the 98 * src when it is drawn. This is an out-param. 99 * 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. 102 */ 103 bool filterImage(Proxy*, const SkBitmap& src, const Context&, 104 SkBitmap* result, SkIPoint* offset) const; 105 106 /** 107 * Given the src bounds of an image, this returns the bounds of the result 108 * image after the filter has been applied. 109 */ 110 bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const; 111 112 /** 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(), 117 * SkIRect()). 118 */ 119 virtual bool canFilterImageGPU() const; 120 121 /** 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(). 130 */ 131 virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&, 132 SkBitmap* result, SkIPoint* offset) const; 133 134 /** 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). 140 */ 141 virtual bool asColorFilter(SkColorFilter** filterPtr) const; 142 143 /** 144 * Returns the number of inputs this filter will accept (some inputs can 145 * be NULL). 146 */ 147 int countInputs() const { return fInputCount; } 148 149 /** 150 * Returns the input filter at a given index, or NULL if no input is 151 * connected. The indices used are filter-specific. 152 */ 153 SkImageFilter* getInput(int i) const { 154 SkASSERT(i < fInputCount); 155 return fInputs[i]; 156 } 157 158 /** 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.) 167 */ 168 bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } 169 170 // Default impl returns union of all input bounds. 171 virtual void computeFastBounds(const SkRect&, SkRect*) const; 172 173#ifdef SK_SUPPORT_GPU 174 /** 175 * Wrap the given texture in a texture-backed SkBitmap. 176 */ 177 static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result); 178 179 /** 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. 182 */ 183 bool getInputResultGPU(SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&, 184 SkBitmap* result, SkIPoint* offset) const; 185#endif 186 187 /** 188 * Set an external cache to be used for all image filter processing. This 189 * will replace the default intra-frame cache. 190 */ 191 static void SetExternalCache(Cache* cache); 192 193 /** 194 * Returns the currently-set external cache, or NULL if none is set. 195 */ 196 static Cache* GetExternalCache(); 197 198 SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter) 199 200protected: 201 SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL); 202 203 // Convenience constructor for 1-input filters. 204 explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL); 205 206 // Convenience constructor for 2-input filters. 207 SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL); 208 209 virtual ~SkImageFilter(); 210 211 /** 212 * Constructs a new SkImageFilter read from an SkReadBuffer object. 213 * 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. 217 */ 218 explicit SkImageFilter(int inputCount, SkReadBuffer& rb); 219 220 virtual void flatten(SkWriteBuffer& wb) const SK_OVERRIDE; 221 222 /** 223 * This is the virtual which should be overridden by the derived class 224 * to perform image filtering. 225 * 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. 228 * 229 * The matrix is the current matrix on the canvas. 230 * 231 * Offset is the amount to translate the resulting image relative to the 232 * src when it is drawn. This is an out-param. 233 * 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 236 * caller. 237 */ 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 246 // no inputs. 247 virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const; 248 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. 254 */ 255 bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset, 256 SkIRect* bounds) const; 257 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. 265 */ 266 bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset, 267 SkIRect* bounds, SkBitmap* result) const; 268 269 /** 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 272 * not. 273 * 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. 277 * 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. 283 */ 284 virtual bool asNewEffect(GrEffectRef** effect, 285 GrTexture*, 286 const SkMatrix& matrix, 287 const SkIRect& bounds) const; 288 289private: 290 typedef SkFlattenable INHERITED; 291 int fInputCount; 292 SkImageFilter** fInputs; 293 CropRect fCropRect; 294}; 295 296#endif 297