SkImageFilter.h revision 6b13473dd4d5915309cc2caddbab2e22f2f21d5f
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 11bf521ff9415b3bdb1acde7b8d18139df176236e5bungeman#include "../private/SkTArray.h" 12f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "../private/SkTemplates.h" 1323526963135bd15737505bd560d41b0d5a41439exidachen#include "../private/SkMutex.h" 148c874eee943bdea0fab5b4d2707083c863e37c55senorblanco#include "SkFilterQuality.h" 15894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#include "SkFlattenable.h" 164cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org#include "SkMatrix.h" 17194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org#include "SkRect.h" 182c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed#include "SkSurfaceProps.h" 19894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 20af9b8c804643952d5ff3deed62f1355319b72f72robertphillipsclass GrContext; 212c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrFragmentProcessor; 222c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass GrTexture; 232c55d7b7f3c2c834085d019bf6b1519b315c8aa1reedclass SkBaseDevice; 2415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comclass SkBitmap; 258d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.orgclass SkColorFilter; 26c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.comstruct SkIPoint; 27df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillipsclass SkSpecialImage; 2815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com 2915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com/** 3015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * Base class for image filters. If one is installed in the paint, then 3115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * all drawing occurs as usual, but it is as if the drawing happened into an 3215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * offscreen (before the xfermode is applied). This offscreen bitmap will 3315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * then be handed to the imagefilter, who in turn creates a new bitmap which 3415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com * is what will finally be drawn to the device (using the original xfermode). 3515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com */ 3654e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.orgclass SK_API SkImageFilter : public SkFlattenable { 37894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.compublic: 3855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco // This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to 3955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco // (result, offset). 40be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco class Cache : public SkRefCnt { 4155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco public: 4255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco struct Key; 43be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco virtual ~Cache() {} 44be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco static Cache* Create(size_t maxBytes); 45be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco static Cache* Get(); 4655b6d8be997a447ef9ce0f029697677a940bfc24senorblanco virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0; 47df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillips virtual SkSpecialImage* get(const Key& key, SkIPoint* offset) const = 0; 4855b6d8be997a447ef9ce0f029697677a940bfc24senorblanco virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0; 49df7bb471e5455dece2784a970d9ae50d3ab0ca75robertphillips virtual void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset) = 0; 50242397a1c95e34e3e2e5e85c85c81090317115cbmtklein virtual void purge() {} 5123526963135bd15737505bd560d41b0d5a41439exidachen virtual void purgeByKeys(const Key[], int) {} 5255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco }; 5355b6d8be997a447ef9ce0f029697677a940bfc24senorblanco 544cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org class Context { 554cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org public: 564e23cdaa6b892afeaa150c6d74099dc6c2065b7ereed Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache) 57c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed : fCTM(ctm) 58c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed , fClipBounds(clipBounds) 59c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed , fCache(cache) 60c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed {} 61c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed 624cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org const SkMatrix& ctm() const { return fCTM; } 634cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org const SkIRect& clipBounds() const { return fClipBounds; } 64be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco Cache* cache() const { return fCache; } 65c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed 664cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org private: 67c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed SkMatrix fCTM; 68c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed SkIRect fClipBounds; 69c9b5f8b1522e72449d704d30ed6aee4fc6211ee8reed Cache* fCache; 704cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org }; 714cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org 72189186337eb91b0b21c15db42377bbf3ae4acf23reed class CropRect { 73189186337eb91b0b21c15db42377bbf3ae4acf23reed public: 74189186337eb91b0b21c15db42377bbf3ae4acf23reed enum CropEdge { 75189186337eb91b0b21c15db42377bbf3ae4acf23reed kHasLeft_CropEdge = 0x01, 76189186337eb91b0b21c15db42377bbf3ae4acf23reed kHasTop_CropEdge = 0x02, 77ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco kHasWidth_CropEdge = 0x04, 78ed7cf273226ca5818a9d58b0f9183d665bb1ff58senorblanco kHasHeight_CropEdge = 0x08, 79189186337eb91b0b21c15db42377bbf3ae4acf23reed kHasAll_CropEdge = 0x0F, 80189186337eb91b0b21c15db42377bbf3ae4acf23reed }; 81189186337eb91b0b21c15db42377bbf3ae4acf23reed CropRect() {} 82189186337eb91b0b21c15db42377bbf3ae4acf23reed explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) 83189186337eb91b0b21c15db42377bbf3ae4acf23reed : fRect(rect), fFlags(flags) {} 84189186337eb91b0b21c15db42377bbf3ae4acf23reed uint32_t flags() const { return fFlags; } 85189186337eb91b0b21c15db42377bbf3ae4acf23reed const SkRect& rect() const { return fRect; } 86189186337eb91b0b21c15db42377bbf3ae4acf23reed#ifndef SK_IGNORE_TO_STRING 87189186337eb91b0b21c15db42377bbf3ae4acf23reed void toString(SkString* str) const; 88189186337eb91b0b21c15db42377bbf3ae4acf23reed#endif 89189186337eb91b0b21c15db42377bbf3ae4acf23reed 90189186337eb91b0b21c15db42377bbf3ae4acf23reed /** 91189186337eb91b0b21c15db42377bbf3ae4acf23reed * Apply this cropRect to the imageBounds. If a given edge of the cropRect is not 926db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco * set, then the corresponding edge from imageBounds will be used. If "embiggen" 936db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco * is true, the crop rect is allowed to enlarge the size of the rect, otherwise 946db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco * it may only reduce the rect. Filters that can affect transparent black should 956db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco * pass "true", while all other filters should pass "false". 96189186337eb91b0b21c15db42377bbf3ae4acf23reed * 97189186337eb91b0b21c15db42377bbf3ae4acf23reed * Note: imageBounds is in "device" space, as the output cropped rectangle will be, 98d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * so the matrix is ignored for those. It is only applied the croprect's bounds. 99189186337eb91b0b21c15db42377bbf3ae4acf23reed */ 1006db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco void applyTo(const SkIRect& imageBounds, const SkMatrix&, bool embiggen, 1016db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco SkIRect* cropped) const; 102189186337eb91b0b21c15db42377bbf3ae4acf23reed 103189186337eb91b0b21c15db42377bbf3ae4acf23reed private: 104189186337eb91b0b21c15db42377bbf3ae4acf23reed SkRect fRect; 105189186337eb91b0b21c15db42377bbf3ae4acf23reed uint32_t fFlags; 106189186337eb91b0b21c15db42377bbf3ae4acf23reed }; 107189186337eb91b0b21c15db42377bbf3ae4acf23reed 108a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco enum TileUsage { 109a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco kPossible_TileUsage, //!< the created device may be drawn tiled 110a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco kNever_TileUsage, //!< the created device will never be drawn tiled 111a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco }; 112a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco 11376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com class Proxy { 11476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com public: 11588d064d0e481949184305c7b1d6b282dddffac39reed virtual ~Proxy() {} 1162766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein 117a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco virtual SkBaseDevice* createDevice(int width, int height, 118a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco TileUsage usage = kNever_TileUsage) = 0; 11988d064d0e481949184305c7b1d6b282dddffac39reed 12088d064d0e481949184305c7b1d6b282dddffac39reed // Returns true if the proxy handled the filter itself. If this returns 12188d064d0e481949184305c7b1d6b282dddffac39reed // false then the filter's code will be called. 12288d064d0e481949184305c7b1d6b282dddffac39reed virtual bool filterImage(const SkImageFilter*, const SkBitmap& src, 12388d064d0e481949184305c7b1d6b282dddffac39reed const SkImageFilter::Context&, 12488d064d0e481949184305c7b1d6b282dddffac39reed SkBitmap* result, SkIPoint* offset) = 0; 12588d064d0e481949184305c7b1d6b282dddffac39reed }; 12688d064d0e481949184305c7b1d6b282dddffac39reed 12788d064d0e481949184305c7b1d6b282dddffac39reed class DeviceProxy : public Proxy { 12888d064d0e481949184305c7b1d6b282dddffac39reed public: 12988d064d0e481949184305c7b1d6b282dddffac39reed DeviceProxy(SkBaseDevice* device) : fDevice(device) {} 13088d064d0e481949184305c7b1d6b282dddffac39reed 131a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco SkBaseDevice* createDevice(int width, int height, 132a9fbd1676cf8bd0078c5be1f1c4abd4c76ea60adsenorblanco TileUsage usage = kNever_TileUsage) override; 133efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips 134efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips // Returns true if the proxy handled the filter itself. If this returns 13576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com // false then the filter's code will be called. 1362c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed bool filterImage(const SkImageFilter*, const SkBitmap& src, const SkImageFilter::Context&, 137d82bc7b90ab0a88d6fb401994f3763d3057ab6e7reed SkBitmap* result, SkIPoint* offset) override; 138efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips 1392c55d7b7f3c2c834085d019bf6b1519b315c8aa1reed private: 140efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips SkBaseDevice* fDevice; 14176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com }; 1422766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein 143894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com /** 144894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Request a new (result) image to be created from the src image. 145894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 1464418dbac3386f26c8da62ab242be9c178961eb18robertphillips * The context contains the environment in which the filter is occurring. 1474418dbac3386f26c8da62ab242be9c178961eb18robertphillips * It includes the clip bounds, CTM and cache. 148894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 149894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * Offset is the amount to translate the resulting image relative to the 1506776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * src when it is drawn. This is an out-param. 151894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com * 1524418dbac3386f26c8da62ab242be9c178961eb18robertphillips * If the result image cannot be created, return null, in which case 1534418dbac3386f26c8da62ab242be9c178961eb18robertphillips * the offset parameters will be ignored by the caller. 1544418dbac3386f26c8da62ab242be9c178961eb18robertphillips * 1554418dbac3386f26c8da62ab242be9c178961eb18robertphillips * TODO: Right now the imagefilters sometimes return empty result bitmaps/ 1564418dbac3386f26c8da62ab242be9c178961eb18robertphillips * specialimages. That doesn't seem quite right. 157894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com */ 1582302de920e5434809bd0e85b871a6e002856dfdbrobertphillips sk_sp<SkSpecialImage> filterImage(SkSpecialImage* src, const Context&, SkIPoint* offset) const; 159eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips 160d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco enum MapDirection { 161d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco kForward_MapDirection, 162d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco kReverse_MapDirection 163d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco }; 16415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com /** 165d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * Map a device-space rect recursively forward or backward through the 166d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * filter DAG. kForward_MapDirection is used to determine which pixels of 167d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * the destination canvas a source image rect would touch after filtering. 168127fe3e24b488b7cf67308e791847ee229012862jbroman * kReverse_MapDirection is used to determine which rect of the source 169d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * image would be required to fill the given rect (typically, clip bounds). 170d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * Used for clipping and temp-buffer allocations, so the result need not 171d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * be exact, but should never be smaller than the real answer. The default 172e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco * implementation recursively unions all input bounds, or returns the 173e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco * source rect if no inputs. 17432d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com */ 175e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm, 176e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco MapDirection = kReverse_MapDirection) const; 177e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco 17832d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com /** 179302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org * Returns true if the filter can be processed on the GPU. This is most 180302cffba86a188373c99833d83392f33e6014542senorblanco@chromium.org * often used for multi-pass effects, where intermediate results must be 181b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * rendered to textures. For single-pass effects, use asFragmentProcessor(). 182b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(), 1837938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org * SkIRect()). 18405054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org */ 185938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips virtual bool canFilterImageGPU() const { return false; } 18605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org 18705054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org /** 1883284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com * Process this image filter on the GPU. This is most often used for 189d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * multi-pass effects, where intermediate results must be rendered to 190b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * textures. For single-pass effects, use asFragmentProcessor(). src is the 191d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * source image for processing, as a texture-backed bitmap. result is 192d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org * the destination bitmap, which should contain a texture-backed pixelref 193de2e4e8a6422c7d8b5847f038f5c6360b187f7a2skia.committer@gmail.com * on success. offset is the amount to translate the resulting image 1947b320703d47ff2b242ae74faba5e4b0af3560d71commit-bot@chromium.org * relative to the src when it is drawn. The default implementation does 195b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * single-pass processing using asFragmentProcessor(). 19605054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org */ 197938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips virtual bool filterImageGPUDeprecated(Proxy*, const SkBitmap&, const Context&, 198938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips SkBitmap*, SkIPoint*) const { 199938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips SkASSERT(false); 200938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips return false; 201938115c9f8a3453ad6f511c0a23dabb46ec5a71frobertphillips } 20205054f1a78a697b507580d0025db6c90423e033fsenorblanco@chromium.org 203af9b8c804643952d5ff3deed62f1355319b72f72robertphillips#if SK_SUPPORT_GPU 204af9b8c804643952d5ff3deed62f1355319b72f72robertphillips static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context, 205af9b8c804643952d5ff3deed62f1355319b72f72robertphillips sk_sp<GrFragmentProcessor> fp, 206af9b8c804643952d5ff3deed62f1355319b72f72robertphillips const SkIRect& bounds, 207af9b8c804643952d5ff3deed62f1355319b72f72robertphillips SkImageFilter::Proxy* proxy); 208af9b8c804643952d5ff3deed62f1355319b72f72robertphillips#endif 209af9b8c804643952d5ff3deed62f1355319b72f72robertphillips 2108d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org /** 211a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com * Returns whether this image filter is a color filter and puts the color filter into the 2124b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * "filterPtr" parameter if it can. Does nothing otherwise. 2134b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * If this returns false, then the filterPtr is unchanged. 2144b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler 2154b6d432f1e4ea0a6556dfff1b4d19b69ca005c27sugoi@google.com * (i.e. it may not be set to NULL). 2168d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org */ 217cedc36f18b2254c5ee21f6348124886b6db4f4c2reed bool isColorFilterNode(SkColorFilter** filterPtr) const { 218cedc36f18b2254c5ee21f6348124886b6db4f4c2reed return this->onIsColorFilterNode(filterPtr); 219cedc36f18b2254c5ee21f6348124886b6db4f4c2reed } 220cedc36f18b2254c5ee21f6348124886b6db4f4c2reed 221cedc36f18b2254c5ee21f6348124886b6db4f4c2reed // DEPRECATED : use isColorFilterNode() instead 222cedc36f18b2254c5ee21f6348124886b6db4f4c2reed bool asColorFilter(SkColorFilter** filterPtr) const { 223cedc36f18b2254c5ee21f6348124886b6db4f4c2reed return this->isColorFilterNode(filterPtr); 224cedc36f18b2254c5ee21f6348124886b6db4f4c2reed } 225cedc36f18b2254c5ee21f6348124886b6db4f4c2reed 226cedc36f18b2254c5ee21f6348124886b6db4f4c2reed /** 227cedc36f18b2254c5ee21f6348124886b6db4f4c2reed * Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely 228cedc36f18b2254c5ee21f6348124886b6db4f4c2reed * replaced by the returned colorfilter. i.e. the two effects will affect drawing in the 229cedc36f18b2254c5ee21f6348124886b6db4f4c2reed * same way. 230cedc36f18b2254c5ee21f6348124886b6db4f4c2reed */ 231a544eda5ddea215037b1ada6ba5cfc98f6c8ee15senorblanco bool asAColorFilter(SkColorFilter** filterPtr) const; 2328d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org 2338d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org /** 2348d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * Returns the number of inputs this filter will accept (some inputs can 2358d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * be NULL). 2368d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org */ 2376b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips int countInputs() const { return fInputs.count(); } 2388d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org 2398d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org /** 2408d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * Returns the input filter at a given index, or NULL if no input is 2418d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org * connected. The indices used are filter-specific. 2428d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org */ 2438d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org SkImageFilter* getInput(int i) const { 2446b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips SkASSERT(i < fInputs.count()); 2456b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips return fInputs[i].get(); 2468d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org } 2478d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org 248194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org /** 2493f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * Returns whether any edges of the crop rect have been set. The crop 2503f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * rect is set at construction time, and determines which pixels from the 251189186337eb91b0b21c15db42377bbf3ae4acf23reed * input image will be processed, and which pixels in the output image will be allowed. 252189186337eb91b0b21c15db42377bbf3ae4acf23reed * The size of the crop rect should be 2533f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * used as the size of the destination image. The origin of this rect 2543f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * should be used to offset access to the input images, and should also 2553f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * be added to the "offset" parameter in onFilterImage and 2563f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * filterImageGPU(). (The latter ensures that the resulting buffer is 2573f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org * drawn in the correct location.) 258194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org */ 2593f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } 260194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org 261b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed CropRect getCropRect() const { return fCropRect; } 262b3fe1b87e0ceefa27c183420c02d93d8fdf495dcreed 263336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org // Default impl returns union of all input bounds. 264e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco virtual SkRect computeFastBounds(const SkRect&) const; 265336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org 2660abdf766d395ed3b7059511425f431589eca05f6senorblanco // Can this filter DAG compute the resulting bounds of an object-space rectangle? 2676db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco bool canComputeFastBounds() const; 2680abdf766d395ed3b7059511425f431589eca05f6senorblanco 2698c874eee943bdea0fab5b4d2707083c863e37c55senorblanco /** 27094dd7a52d3fe0632cd830f2e9cd14103c2726aacreed * If this filter can be represented by another filter + a localMatrix, return that filter, 27194dd7a52d3fe0632cd830f2e9cd14103c2726aacreed * else return null. 27294dd7a52d3fe0632cd830f2e9cd14103c2726aacreed */ 273372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix&) const; 274372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips 275372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR 276372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips SkImageFilter* newWithLocalMatrix(const SkMatrix& matrix) const { 277372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips return this->makeWithLocalMatrix(matrix).release(); 278372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips } 279372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips#endif 28094dd7a52d3fe0632cd830f2e9cd14103c2726aacreed 28194dd7a52d3fe0632cd830f2e9cd14103c2726aacreed /** 2828c874eee943bdea0fab5b4d2707083c863e37c55senorblanco * Create an SkMatrixImageFilter, which transforms its input by the given matrix. 2838c874eee943bdea0fab5b4d2707083c863e37c55senorblanco */ 284ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix, 285ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips SkFilterQuality, 286ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips sk_sp<SkImageFilter> input); 287ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR 2888c874eee943bdea0fab5b4d2707083c863e37c55senorblanco static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix, 289ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips SkFilterQuality filterQuality, 290ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips SkImageFilter* input = nullptr) { 291ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips return MakeMatrixFilter(matrix, filterQuality, sk_ref_sp<SkImageFilter>(input)).release(); 292ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips } 293ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips#endif 294ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips 2958c874eee943bdea0fab5b4d2707083c863e37c55senorblanco 2962302de920e5434809bd0e85b871a6e002856dfdbrobertphillips sk_sp<SkSpecialImage> filterInput(int index, 2972302de920e5434809bd0e85b871a6e002856dfdbrobertphillips SkSpecialImage* src, 2982302de920e5434809bd0e85b871a6e002856dfdbrobertphillips const Context&, 2992302de920e5434809bd0e85b871a6e002856dfdbrobertphillips SkIPoint* offset) const; 300eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips 3014509517e03fd245298d4059f4568435d640a1758kkinnunen#if SK_SUPPORT_GPU 3029a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco // Helper function which invokes GPU filter processing on the 3039a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco // input at the specified "index". If the input is null, it leaves 3049a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco // "result" and "offset" untouched, and returns true. If the input 3059a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco // has a GPU implementation, it will be invoked directly. 3069a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco // Otherwise, the filter will be processed in software and 3079a70b6ef59c38f3cbe6646aed624f22155326d05senorblanco // uploaded to the GPU. 30848e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips bool filterInputGPUDeprecated(int index, SkImageFilter::Proxy* proxy, 30948e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips const SkBitmap& src, const Context&, 31048e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips SkBitmap* result, SkIPoint* offset) const; 3116aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif 3126aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org 313f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips SK_TO_STRING_PUREVIRT() 3143b37545bc594a96de45eba62dea0ce478750f2a9mtklein SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter) 315c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org 316894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprotected: 317b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed class Common { 318b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed public: 3199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed /** 3209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * Attempt to unflatten the cropRect and the expected number of input filters. 3219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * If any number of input filters is valid, pass -1. 3229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * If this fails (i.e. corrupt buffer or contents) then return false and common will 3239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * be left uninitialized. 3249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * If this returns true, then inputCount() is the number of found input filters, each 3259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * of which may be NULL or a valid imagefilter. 3269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */ 3279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed bool unflatten(SkReadBuffer&, int expectedInputs); 3289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed const CropRect& cropRect() const { return fCropRect; } 330b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed int inputCount() const { return fInputs.count(); } 3312238c9dbca4b791edc512957728a18ce14d55912robertphillips sk_sp<SkImageFilter>* inputs() const { return fInputs.get(); } 332b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed 3332238c9dbca4b791edc512957728a18ce14d55912robertphillips sk_sp<SkImageFilter> getInput(int index) const { return fInputs[index]; } 3349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 335b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed private: 336b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed CropRect fCropRect; 337b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed // most filters accept at most 2 input-filters 3382238c9dbca4b791edc512957728a18ce14d55912robertphillips SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs; 339b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed 340b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed void allocInputs(int count); 341b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed }; 342b959ec7815ae0f65f2aabdeaf280a2a2ee6db955reed 343372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips SkImageFilter(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect); 3449f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 3459f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org virtual ~SkImageFilter(); 3469f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 347c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org /** 3488b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * Constructs a new SkImageFilter read from an SkReadBuffer object. 349c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org * 350c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org * @param inputCount The exact number of inputs expected for this SkImageFilter object. 351c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org * -1 can be used if the filter accepts any number of inputs. 3528b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org * @param rb SkReadBuffer object from which the SkImageFilter is read. 353c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org */ 3548b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org explicit SkImageFilter(int inputCount, SkReadBuffer& rb); 3559f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org 35636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void flatten(SkWriteBuffer&) const override; 35732d25b6f5f4355d4c5281694034ba3a5aa2cf571reed@google.com 3586776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org /** 3596776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * This is the virtual which should be overridden by the derived class 3606776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * to perform image filtering. 3616776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * 3626776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * src is the original primitive bitmap. If the filter has a connected 3636776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * input, it should recurse on that input and use that in place of src. 3646776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * 3656776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * The matrix is the current matrix on the canvas. 3666776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * 3676776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * Offset is the amount to translate the resulting image relative to the 3686776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * src when it is drawn. This is an out-param. 3696776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * 3706776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * If the result image cannot be created, this should false, in which 3716776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * case both the result and offset parameters will be ignored by the 3726776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org * caller. 3736776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org */ 37448e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips virtual bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, 37548e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips SkBitmap* result, SkIPoint* offset) const; 376d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco 3772302de920e5434809bd0e85b871a6e002856dfdbrobertphillips virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* src, const Context&, 3782302de920e5434809bd0e85b871a6e002856dfdbrobertphillips SkIPoint* offset) const; 379eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips 380d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco /** 381e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco * This function recurses into its inputs with the given rect (first 382d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * argument), calls filterBounds() with the given map direction on each, 383e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco * and returns the union of those results. If a derived class has special 384e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco * recursion requirements (e.g., it has an input which does not participate 385e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco * in bounds computation), it can be overridden here. 386d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * 387d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * Note that this function is *not* responsible for mapping the rect for 388d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * this node's filter bounds requirements (i.e., calling 389d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco * onFilterNodeBounds()); that is handled by filterBounds(). 390d8ff5b336e586ad971ebcafa5fb2eb1e7ac95589senorblanco */ 391e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix&, MapDirection) const; 392db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco 393db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco /** 394db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * Performs a forwards or reverse mapping of the given rect to accommodate 395db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * this filter's margin requirements. kForward_MapDirection is used to 396db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * determine the destination pixels which would be touched by filtering 397db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * the given given source rect (e.g., given source bitmap bounds, 398db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * determine the optimal bounds of the filtered offscreen bitmap). 399db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * kReverse_MapDirection is used to determine which pixels of the 400db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * input(s) would be required to fill the given destination rect 401db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * (e.g., clip bounds). NOTE: these operations may not be the 402db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * inverse of the other. For example, blurring expands the given rect 403db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * in both forward and reverse directions. Unlike 404db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * onFilterBounds(), this function is non-recursive. 405db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco */ 406e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const; 407894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 408b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco // Helper function which invokes filter processing on the input at the 409b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco // specified "index". If the input is null, it leaves "result" and 410b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco // "offset" untouched, and returns true. If the input is non-null, it 411b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco // calls filterImage() on that input, and returns true on success. 412b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco // i.e., return !getInput(index) || getInput(index)->filterImage(...); 41348e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips bool filterInputDeprecated(int index, Proxy*, const SkBitmap& src, const Context&, 41448e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips SkBitmap* result, SkIPoint* offset) const; 415b9519f86bbce946e505980a4fa950fdc4bcf74absenorblanco 416cedc36f18b2254c5ee21f6348124886b6db4f4c2reed /** 417cedc36f18b2254c5ee21f6348124886b6db4f4c2reed * Return true (and return a ref'd colorfilter) if this node in the DAG is just a 418cedc36f18b2254c5ee21f6348124886b6db4f4c2reed * colorfilter w/o CropRect constraints. 419cedc36f18b2254c5ee21f6348124886b6db4f4c2reed */ 420cedc36f18b2254c5ee21f6348124886b6db4f4c2reed virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const { 421cedc36f18b2254c5ee21f6348124886b6db4f4c2reed return false; 422cedc36f18b2254c5ee21f6348124886b6db4f4c2reed } 423cedc36f18b2254c5ee21f6348124886b6db4f4c2reed 424af9b8c804643952d5ff3deed62f1355319b72f72robertphillips /** Given a "srcBounds" rect, computes destination bounds for this filter. 425af9b8c804643952d5ff3deed62f1355319b72f72robertphillips * "dstBounds" are computed by transforming the crop rect by the context's 426af9b8c804643952d5ff3deed62f1355319b72f72robertphillips * CTM, applying it to the initial bounds, and intersecting the result with 427af9b8c804643952d5ff3deed62f1355319b72f72robertphillips * the context's clip bounds. "srcBounds" (if non-null) are computed by 428af9b8c804643952d5ff3deed62f1355319b72f72robertphillips * intersecting the initial bounds with "dstBounds", to ensure that we never 429af9b8c804643952d5ff3deed62f1355319b72f72robertphillips * sample outside of the crop rect (this restriction may be relaxed in the 430afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * future). 431118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org */ 432afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const; 433afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco 434afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco /** A variant of the above call which takes the original source bitmap and 435afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * source offset. If the resulting crop rect is not entirely contained by 436afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * the source bitmap's bounds, it creates a new bitmap in "result" and 437afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * pads the edges with transparent black. In that case, the srcOffset is 438afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * modified to be the same as the bounds, since no further adjustment is 439afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * needed by the caller. This version should only be used by filters 440afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * which are not capable of processing a smaller source bitmap into a 441afec27f13b28d900232cb1825c63cab2d6e4e103senorblanco * larger destination. 442118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org */ 44348e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips bool applyCropRectDeprecated(const Context&, Proxy* proxy, const SkBitmap& src, 44448e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* result) const; 445194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org 4462302de920e5434809bd0e85b871a6e002856dfdbrobertphillips sk_sp<SkSpecialImage> applyCropRect(const Context&, SkSpecialImage* src, SkIPoint* srcOffset, 4472302de920e5434809bd0e85b871a6e002856dfdbrobertphillips SkIRect* bounds) const; 448eaf086e3ce1b8351a8cd01762ca5144254bddbc4robertphillips 4491aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org /** 450db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * Creates a modified Context for use when recursing up the image filter DAG. 451db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * The clip bounds are adjusted to accommodate any margins that this 452db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * filter requires by calling this node's 453db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco * onFilterNodeBounds(..., kReverse_MapDirection). 454db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco */ 455db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco Context mapContext(const Context& ctx) const; 456db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco 457894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.comprivate: 458242397a1c95e34e3e2e5e85c85c81090317115cbmtklein friend class SkGraphics; 459242397a1c95e34e3e2e5e85c85c81090317115cbmtklein static void PurgeCache(); 460242397a1c95e34e3e2e5e85c85c81090317115cbmtklein 4616b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips void init(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect); 4624418dbac3386f26c8da62ab242be9c178961eb18robertphillips bool filterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, 4634418dbac3386f26c8da62ab242be9c178961eb18robertphillips SkBitmap* result, SkIPoint* offset) const; 4644418dbac3386f26c8da62ab242be9c178961eb18robertphillips 46555b6d8be997a447ef9ce0f029697677a940bfc24senorblanco bool usesSrcInput() const { return fUsesSrcInput; } 4666db0a7bdceb6be85721bfb0db8dea7fd27db5970senorblanco virtual bool affectsTransparentBlack() const { return false; } 46755b6d8be997a447ef9ce0f029697677a940bfc24senorblanco 4686b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs; 4696b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips 47055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco bool fUsesSrcInput; 471b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org CropRect fCropRect; 47255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco uint32_t fUniqueID; // Globally unique 47323526963135bd15737505bd560d41b0d5a41439exidachen mutable SkTArray<Cache::Key> fCacheKeys; 47423526963135bd15737505bd560d41b0d5a41439exidachen mutable SkMutex fMutex; 4756b13473dd4d5915309cc2caddbab2e22f2f21d5frobertphillips typedef SkFlattenable INHERITED; 476894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com}; 477894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com 4789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed/** 4799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed * Helper to unflatten the common data, and return NULL if we fail. 4809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */ 4819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount) \ 4829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed Common localVar; \ 4839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed do { \ 4849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!localVar.unflatten(buffer, expectedCount)) { \ 4859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; \ 4869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } \ 4879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } while (0) 4889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 489894aa9a7af0e5598600df694d184d3c7d2e454b0reed@google.com#endif 490