SkImageFilter.h revision 1aa68723b8ef4ce0b6db9fe51e7d8051cdd543ff
1894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com/* 2894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Copyright 2011 Google Inc. 3894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 4894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Use of this source code is governed by a BSD-style license that can be 5894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * found in the LICENSE file. 6894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com */ 7894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 8894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#ifndef SkImageFilter_DEFINED 9894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#define SkImageFilter_DEFINED 10894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 11894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h" 12194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkRect.h" 13894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 1415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkBitmap; 158d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter; 161f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comclass SkBaseDevice; 1715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkMatrix; 18c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint; 19a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.comclass SkShader; 200ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.comclass GrEffectRef; 21d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.comclass GrTexture; 2215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com 2315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com/** 2415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * Base class for image filters. If one is installed in the paint, then 2515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * all drawing occurs as usual, but it is as if the drawing happened into an 2615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * offscreen (before the xfermode is applied). This offscreen bitmap will 2715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * then be handed to the imagefilter, who in turn creates a new bitmap which 2815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * is what will finally be drawn to the device (using the original xfermode). 2915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com */ 3054e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.orgclass SK_API SkImageFilter : public SkFlattenable { 31894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.compublic: 320456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com SK_DECLARE_INST_COUNT(SkImageFilter) 330456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com 343f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org class CropRect { 353f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org public: 36b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org enum CropEdge { 37b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org kHasLeft_CropEdge = 0x01, 38b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org kHasTop_CropEdge = 0x02, 39b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org kHasRight_CropEdge = 0x04, 40b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org kHasBottom_CropEdge = 0x08, 41b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org kHasAll_CropEdge = 0x0F, 42b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org }; 43b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org CropRect() {} 44b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {} 453f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org uint32_t flags() const { return fFlags; } 463f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org const SkRect& rect() const { return fRect; } 473f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org private: 483f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org SkRect fRect; 493f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org uint32_t fFlags; 50b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org }; 51b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org 5276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com class Proxy { 5376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com public: 548926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com virtual ~Proxy() {}; 558926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com 561f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com virtual SkBaseDevice* createDevice(int width, int height) = 0; 578926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com // returns true if the proxy can handle this filter natively 588926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com virtual bool canHandleImageFilter(SkImageFilter*) = 0; 5976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com // returns true if the proxy handled the filter itself. if this returns 6076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com // false then the filter's code will be called. 6176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com virtual bool filterImage(SkImageFilter*, const SkBitmap& src, 6276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com const SkMatrix& ctm, 6376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com SkBitmap* result, SkIPoint* offset) = 0; 6476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com }; 65894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 66894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com /** 67894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Request a new (result) image to be created from the src image. 68894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * If the src has no pixels (isNull()) then the request just wants to 69894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * receive the config and width/height of the result. 70894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 71894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * The matrix is the current matrix on the canvas. 72894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 73894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Offset is the amount to translate the resulting image relative to the 74fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * src when it is drawn. 75894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 76894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * If the result image cannot be created, return false, in which case both 77894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * the result and offset parameters will be ignored by the caller. 78894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com */ 7976dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm, 8015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com SkBitmap* result, SkIPoint* offset); 8115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com 8215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com /** 8332d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com * Given the src bounds of an image, this returns the bounds of the result 8432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com * image after the filter has been applied. 8532d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com */ 8632d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst); 8732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com 8832d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com /** 89302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org * Returns true if the filter can be processed on the GPU. This is most 90302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org * often used for multi-pass effects, where intermediate results must be 918ea78d83dc4e8243c16eedf8100a3987c54123fabsalomon@google.com * rendered to textures. For single-pass effects, use asNewEffect(). 92fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org * The default implementation returns asNewEffect(NULL, NULL, SkMatrix::I()). 9305054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org */ 94302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org virtual bool canFilterImageGPU() const; 9505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org 9605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org /** 973284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com * Process this image filter on the GPU. This is most often used for 98d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * multi-pass effects, where intermediate results must be rendered to 99d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * textures. For single-pass effects, use asNewEffect(). src is the 100d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * source image for processing, as a texture-backed bitmap. result is 101d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * the destination bitmap, which should contain a texture-backed pixelref 102de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com * on success. offset is the amount to translate the resulting image 1037b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org * relative to the src when it is drawn. The default implementation does 1047b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org * single-pass processing using asNewEffect(). 10505054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org */ 1061aa54bf6696afc7d06fc8ecc63dad2840a4d6179commit-bot@chromium.org virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const SkMatrix& ctm, 1071aa54bf6696afc7d06fc8ecc63dad2840a4d6179commit-bot@chromium.org SkBitmap* result, SkIPoint* offset); 10805054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org 1098d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org /** 110a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com * Returns whether this image filter is a color filter and puts the color filter into the 1114b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * "filterPtr" parameter if it can. Does nothing otherwise. 1124b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * If this returns false, then the filterPtr is unchanged. 1134b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler 1144b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * (i.e. it may not be set to NULL). 1158d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org */ 1164b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com virtual bool asColorFilter(SkColorFilter** filterPtr) const; 1178d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org 1188d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org /** 1198d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * Returns the number of inputs this filter will accept (some inputs can 1208d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * be NULL). 1218d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org */ 1228d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org int countInputs() const { return fInputCount; } 1238d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org 1248d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org /** 1258d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * Returns the input filter at a given index, or NULL if no input is 1268d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * connected. The indices used are filter-specific. 1278d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org */ 1288d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org SkImageFilter* getInput(int i) const { 1298d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org SkASSERT(i < fInputCount); 1308d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org return fInputs[i]; 1318d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org } 1328d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org 133194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org /** 1343f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * Returns whether any edges of the crop rect have been set. The crop 1353f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * rect is set at construction time, and determines which pixels from the 1363f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * input image will be processed. The size of the crop rect should be 1373f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * used as the size of the destination image. The origin of this rect 1383f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * should be used to offset access to the input images, and should also 1393f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * be added to the "offset" parameter in onFilterImage and 1403f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * filterImageGPU(). (The latter ensures that the resulting buffer is 1413f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * drawn in the correct location.) 142194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org */ 1433f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } 144194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org 145894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected: 146b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL); 1479f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 148c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org // Convenience constructor for 1-input filters. 149b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL); 150c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org 151c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org // Convenience constructor for 2-input filters. 152b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL); 1539f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 1549f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org virtual ~SkImageFilter(); 1559f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 1569f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org explicit SkImageFilter(SkFlattenableReadBuffer& rb); 1579f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 1589f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE; 15932d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com 16032d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com // Default impl returns false 16176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, 16215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com SkBitmap* result, SkIPoint* offset); 16332d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com // Default impl copies src into dst and returns true 16432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*); 165894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 166fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org // Applies "matrix" to the crop rect, and sets "rect" to the intersection of 167fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org // "rect" and the transformed crop rect. If there is no overlap, returns 168fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org // false and leaves "rect" unchanged. 169fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org bool applyCropRect(SkIRect* rect, const SkMatrix& matrix) const; 170194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org 1711aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org /** 1721aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * Returns true if the filter can be expressed a single-pass 1731aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * GrEffect, used to process this filter on the GPU, or false if 1741aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * not. 1751aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * 1761aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * If effect is non-NULL, a new GrEffect instance is stored 1771aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * in it. The caller assumes ownership of the stage, and it is up to the 1781aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * caller to unref it. 1791aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * 1801aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * The effect can assume its vertexCoords space maps 1-to-1 with texels 1811aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * in the texture. "matrix" is a transformation to apply to filter 1821aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * parameters before they are used in the effect. Note that this function 1831aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * will be called with (NULL, NULL, SkMatrix::I()) to query for support, 1841aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org * so returning "true" indicates support for all possible matrices. 1851aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org */ 1861aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix) const; 1871aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org 188894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate: 18954e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org typedef SkFlattenable INHERITED; 1908d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org int fInputCount; 1919f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org SkImageFilter** fInputs; 192b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org CropRect fCropRect; 193894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com}; 194894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 195894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif 196