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 "SkFilterQuality.h" 12 #include "SkFlattenable.h" 13 #include "SkMatrix.h" 14 #include "SkRect.h" 15 #include "SkTemplates.h" 16 17 class SkBitmap; 18 class SkColorFilter; 19 class SkBaseDevice; 20 class SkSurfaceProps; 21 struct SkIPoint; 22 class GrFragmentProcessor; 23 class GrTexture; 24 25 /** 26 * Base class for image filters. If one is installed in the paint, then 27 * all drawing occurs as usual, but it is as if the drawing happened into an 28 * offscreen (before the xfermode is applied). This offscreen bitmap will 29 * then be handed to the imagefilter, who in turn creates a new bitmap which 30 * is what will finally be drawn to the device (using the original xfermode). 31 */ 32 class SK_API SkImageFilter : public SkFlattenable { 33 public: 34 SK_DECLARE_INST_COUNT(SkImageFilter) 35 36 class CropRect { 37 public: 38 enum CropEdge { 39 kHasLeft_CropEdge = 0x01, 40 kHasTop_CropEdge = 0x02, 41 kHasRight_CropEdge = 0x04, 42 kHasBottom_CropEdge = 0x08, 43 kHasAll_CropEdge = 0x0F, 44 }; 45 CropRect() {} 46 explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {} 47 uint32_t flags() const { return fFlags; } 48 const SkRect& rect() const { return fRect; } 49 private: 50 SkRect fRect; 51 uint32_t fFlags; 52 }; 53 54 // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to 55 // (result, offset). 56 class Cache : public SkRefCnt { 57 public: 58 struct Key; 59 virtual ~Cache() {} 60 static Cache* Create(size_t maxBytes); 61 static Cache* Get(); 62 virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0; 63 virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0; 64 }; 65 66 class Context { 67 public: 68 Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) : 69 fCTM(ctm), fClipBounds(clipBounds), fCache(cache) { 70 } 71 const SkMatrix& ctm() const { return fCTM; } 72 const SkIRect& clipBounds() const { return fClipBounds; } 73 Cache* cache() const { return fCache; } 74 private: 75 SkMatrix fCTM; 76 SkIRect fClipBounds; 77 Cache* fCache; 78 }; 79 80 class Proxy { 81 public: 82 virtual ~Proxy() {}; 83 84 virtual SkBaseDevice* createDevice(int width, int height) = 0; 85 // returns true if the proxy can handle this filter natively 86 virtual bool canHandleImageFilter(const SkImageFilter*) = 0; 87 // returns true if the proxy handled the filter itself. if this returns 88 // false then the filter's code will be called. 89 virtual bool filterImage(const SkImageFilter*, const SkBitmap& src, 90 const Context&, 91 SkBitmap* result, SkIPoint* offset) = 0; 92 virtual const SkSurfaceProps* surfaceProps() const = 0; 93 }; 94 95 /** 96 * Request a new (result) image to be created from the src image. 97 * If the src has no pixels (isNull()) then the request just wants to 98 * receive the config and width/height of the result. 99 * 100 * The matrix is the current matrix on the canvas. 101 * 102 * Offset is the amount to translate the resulting image relative to the 103 * src when it is drawn. This is an out-param. 104 * 105 * If the result image cannot be created, return false, in which case both 106 * the result and offset parameters will be ignored by the caller. 107 */ 108 bool filterImage(Proxy*, const SkBitmap& src, const Context&, 109 SkBitmap* result, SkIPoint* offset) const; 110 111 /** 112 * Given the src bounds of an image, this returns the bounds of the result 113 * image after the filter has been applied. 114 */ 115 bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const; 116 117 /** 118 * Returns true if the filter can be processed on the GPU. This is most 119 * often used for multi-pass effects, where intermediate results must be 120 * rendered to textures. For single-pass effects, use asFragmentProcessor(). 121 * The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(), 122 * SkIRect()). 123 */ 124 virtual bool canFilterImageGPU() const; 125 126 /** 127 * Process this image filter on the GPU. This is most often used for 128 * multi-pass effects, where intermediate results must be rendered to 129 * textures. For single-pass effects, use asFragmentProcessor(). src is the 130 * source image for processing, as a texture-backed bitmap. result is 131 * the destination bitmap, which should contain a texture-backed pixelref 132 * on success. offset is the amount to translate the resulting image 133 * relative to the src when it is drawn. The default implementation does 134 * single-pass processing using asFragmentProcessor(). 135 */ 136 virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&, 137 SkBitmap* result, SkIPoint* offset) const; 138 139 /** 140 * Returns whether this image filter is a color filter and puts the color filter into the 141 * "filterPtr" parameter if it can. Does nothing otherwise. 142 * If this returns false, then the filterPtr is unchanged. 143 * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler 144 * (i.e. it may not be set to NULL). 145 */ 146 bool isColorFilterNode(SkColorFilter** filterPtr) const { 147 return this->onIsColorFilterNode(filterPtr); 148 } 149 150 // DEPRECATED : use isColorFilterNode() instead 151 bool asColorFilter(SkColorFilter** filterPtr) const { 152 return this->isColorFilterNode(filterPtr); 153 } 154 155 /** 156 * Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely 157 * replaced by the returned colorfilter. i.e. the two effects will affect drawing in the 158 * same way. 159 */ 160 bool asAColorFilter(SkColorFilter** filterPtr) const { 161 return this->countInputs() > 0 && 162 NULL == this->getInput(0) && 163 this->isColorFilterNode(filterPtr); 164 } 165 166 /** 167 * Returns the number of inputs this filter will accept (some inputs can 168 * be NULL). 169 */ 170 int countInputs() const { return fInputCount; } 171 172 /** 173 * Returns the input filter at a given index, or NULL if no input is 174 * connected. The indices used are filter-specific. 175 */ 176 SkImageFilter* getInput(int i) const { 177 SkASSERT(i < fInputCount); 178 return fInputs[i]; 179 } 180 181 /** 182 * Returns whether any edges of the crop rect have been set. The crop 183 * rect is set at construction time, and determines which pixels from the 184 * input image will be processed. The size of the crop rect should be 185 * used as the size of the destination image. The origin of this rect 186 * should be used to offset access to the input images, and should also 187 * be added to the "offset" parameter in onFilterImage and 188 * filterImageGPU(). (The latter ensures that the resulting buffer is 189 * drawn in the correct location.) 190 */ 191 bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } 192 193 // Default impl returns union of all input bounds. 194 virtual void computeFastBounds(const SkRect&, SkRect*) const; 195 196 /** 197 * Create an SkMatrixImageFilter, which transforms its input by the given matrix. 198 */ 199 static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix, 200 SkFilterQuality, 201 SkImageFilter* input = NULL); 202 203 #if SK_SUPPORT_GPU 204 /** 205 * Wrap the given texture in a texture-backed SkBitmap. 206 */ 207 static void WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result); 208 209 /** 210 * Recursively evaluate this filter on the GPU. If the filter has no GPU 211 * implementation, it will be processed in software and uploaded to the GPU. 212 */ 213 bool getInputResultGPU(SkImageFilter::Proxy* proxy, const SkBitmap& src, const Context&, 214 SkBitmap* result, SkIPoint* offset) const; 215 #endif 216 217 SK_TO_STRING_PUREVIRT() 218 SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter) 219 220 protected: 221 class Common { 222 public: 223 Common() {} 224 ~Common(); 225 226 /** 227 * Attempt to unflatten the cropRect and the expected number of input filters. 228 * If any number of input filters is valid, pass -1. 229 * If this fails (i.e. corrupt buffer or contents) then return false and common will 230 * be left uninitialized. 231 * If this returns true, then inputCount() is the number of found input filters, each 232 * of which may be NULL or a valid imagefilter. 233 */ 234 bool unflatten(SkReadBuffer&, int expectedInputs); 235 236 const CropRect& cropRect() const { return fCropRect; } 237 int inputCount() const { return fInputs.count(); } 238 SkImageFilter** inputs() const { return fInputs.get(); } 239 240 SkImageFilter* getInput(int index) const { return fInputs[index]; } 241 242 // If the caller wants a copy of the inputs, call this and it will transfer ownership 243 // of the unflattened input filters to the caller. This is just a short-cut for copying 244 // the inputs, calling ref() on each, and then waiting for Common's destructor to call 245 // unref() on each. 246 void detachInputs(SkImageFilter** inputs); 247 248 private: 249 CropRect fCropRect; 250 // most filters accept at most 2 input-filters 251 SkAutoSTArray<2, SkImageFilter*> fInputs; 252 253 void allocInputs(int count); 254 }; 255 256 SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL); 257 258 virtual ~SkImageFilter(); 259 260 /** 261 * Constructs a new SkImageFilter read from an SkReadBuffer object. 262 * 263 * @param inputCount The exact number of inputs expected for this SkImageFilter object. 264 * -1 can be used if the filter accepts any number of inputs. 265 * @param rb SkReadBuffer object from which the SkImageFilter is read. 266 */ 267 explicit SkImageFilter(int inputCount, SkReadBuffer& rb); 268 269 void flatten(SkWriteBuffer&) const override; 270 271 /** 272 * This is the virtual which should be overridden by the derived class 273 * to perform image filtering. 274 * 275 * src is the original primitive bitmap. If the filter has a connected 276 * input, it should recurse on that input and use that in place of src. 277 * 278 * The matrix is the current matrix on the canvas. 279 * 280 * Offset is the amount to translate the resulting image relative to the 281 * src when it is drawn. This is an out-param. 282 * 283 * If the result image cannot be created, this should false, in which 284 * case both the result and offset parameters will be ignored by the 285 * caller. 286 */ 287 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, 288 SkBitmap* result, SkIPoint* offset) const; 289 // Given the bounds of the destination rect to be filled in device 290 // coordinates (first parameter), and the CTM, compute (conservatively) 291 // which rect of the source image would be required (third parameter). 292 // Used for clipping and temp-buffer allocations, so the result need not 293 // be exact, but should never be smaller than the real answer. The default 294 // implementation recursively unions all input bounds, or returns false if 295 // no inputs. 296 virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const; 297 298 /** 299 * Return true (and return a ref'd colorfilter) if this node in the DAG is just a 300 * colorfilter w/o CropRect constraints. 301 */ 302 virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const { 303 return false; 304 } 305 306 /** Computes source bounds as the src bitmap bounds offset by srcOffset. 307 * Apply the transformed crop rect to the bounds if any of the 308 * corresponding edge flags are set. Intersects the result against the 309 * context's clipBounds, and returns the result in "bounds". If there is 310 * no intersection, returns false and leaves "bounds" unchanged. 311 */ 312 bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset, 313 SkIRect* bounds) const; 314 315 /** Same as the above call, except that if the resulting crop rect is not 316 * entirely contained by the source bitmap's bounds, it creates a new 317 * bitmap in "result" and pads the edges with transparent black. In that 318 * case, the srcOffset is modified to be the same as the bounds, since no 319 * further adjustment is needed by the caller. This version should only 320 * be used by filters which are not capable of processing a smaller 321 * source bitmap into a larger destination. 322 */ 323 bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset, 324 SkIRect* bounds, SkBitmap* result) const; 325 326 /** 327 * Returns true if the filter can be expressed a single-pass 328 * GrProcessor, used to process this filter on the GPU, or false if 329 * not. 330 * 331 * If effect is non-NULL, a new GrProcessor instance is stored 332 * in it. The caller assumes ownership of the stage, and it is up to the 333 * caller to unref it. 334 * 335 * The effect can assume its vertexCoords space maps 1-to-1 with texels 336 * in the texture. "matrix" is a transformation to apply to filter 337 * parameters before they are used in the effect. Note that this function 338 * will be called with (NULL, NULL, SkMatrix::I()) to query for support, 339 * so returning "true" indicates support for all possible matrices. 340 */ 341 virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, 342 const SkIRect& bounds) const; 343 344 private: 345 bool usesSrcInput() const { return fUsesSrcInput; } 346 347 typedef SkFlattenable INHERITED; 348 int fInputCount; 349 SkImageFilter** fInputs; 350 bool fUsesSrcInput; 351 CropRect fCropRect; 352 uint32_t fUniqueID; // Globally unique 353 }; 354 355 /** 356 * Helper to unflatten the common data, and return NULL if we fail. 357 */ 358 #define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount) \ 359 Common localVar; \ 360 do { \ 361 if (!localVar.unflatten(buffer, expectedCount)) { \ 362 return NULL; \ 363 } \ 364 } while (0) 365 366 #endif 367