1 /* 2 * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> 3 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 4 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 5 * Copyright (C) 2013 Google Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23 #ifndef FilterEffect_h 24 #define FilterEffect_h 25 26 #include "platform/PlatformExport.h" 27 #include "platform/geometry/FloatRect.h" 28 #include "platform/geometry/IntRect.h" 29 #include "platform/graphics/Color.h" 30 #include "platform/graphics/ColorSpace.h" 31 32 #include "third_party/skia/include/core/SkImageFilter.h" 33 34 #include "wtf/PassOwnPtr.h" 35 #include "wtf/RefCounted.h" 36 #include "wtf/RefPtr.h" 37 #include "wtf/Uint8ClampedArray.h" 38 #include "wtf/Vector.h" 39 40 namespace blink { 41 42 class Filter; 43 class FilterEffect; 44 class ImageBuffer; 45 class TextStream; 46 47 class SkiaImageFilterBuilder; 48 49 typedef Vector<RefPtr<FilterEffect> > FilterEffectVector; 50 51 enum FilterEffectType { 52 FilterEffectTypeUnknown, 53 FilterEffectTypeImage, 54 FilterEffectTypeTile, 55 FilterEffectTypeSourceInput 56 }; 57 58 enum DetermineSubregionFlag { 59 DetermineSubregionNone = 0, 60 MapRectForward = 1, 61 ClipToFilterRegion = 1 << 1 62 }; 63 64 typedef int DetermineSubregionFlags; 65 66 class PLATFORM_EXPORT FilterEffect : public RefCounted<FilterEffect> { 67 public: 68 virtual ~FilterEffect(); 69 70 static bool isFilterSizeValid(const FloatRect&); 71 static float maxFilterArea(); 72 73 void clearResult(); 74 void clearResultsRecursive(); 75 76 ImageBuffer* asImageBuffer(); 77 PassRefPtr<Uint8ClampedArray> asUnmultipliedImage(const IntRect&); 78 PassRefPtr<Uint8ClampedArray> asPremultipliedImage(const IntRect&); 79 void copyUnmultipliedImage(Uint8ClampedArray* destination, const IntRect&); 80 void copyPremultipliedImage(Uint8ClampedArray* destination, const IntRect&); 81 inputEffects()82 FilterEffectVector& inputEffects() { return m_inputEffects; } 83 FilterEffect* inputEffect(unsigned) const; numberOfEffectInputs()84 unsigned numberOfEffectInputs() const { return m_inputEffects.size(); } 85 hasResult()86 inline bool hasResult() const 87 { 88 // This function needs platform specific checks, if the memory managment is not done by FilterEffect. 89 return m_imageBufferResult 90 || m_unmultipliedImageResult 91 || m_premultipliedImageResult; 92 } hasImageFilter()93 inline bool hasImageFilter() const 94 { 95 return m_imageFilters[0] || m_imageFilters[1] || m_imageFilters[2] || m_imageFilters[3]; 96 } 97 98 IntRect drawingRegionOfInputImage(const IntRect&) const; 99 IntRect requestedRegionOfInputImageData(const IntRect&) const; 100 101 // Solid black image with different alpha values. isAlphaImage()102 bool isAlphaImage() const { return m_alphaImage; } setIsAlphaImage(bool alphaImage)103 void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; } 104 absolutePaintRect()105 IntRect absolutePaintRect() const { return m_absolutePaintRect; } 106 maxEffectRect()107 FloatRect maxEffectRect() const { return m_maxEffectRect; } setMaxEffectRect(const FloatRect & maxEffectRect)108 void setMaxEffectRect(const FloatRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; } 109 110 void apply(); 111 112 // Correct any invalid pixels, if necessary, in the result of a filter operation. 113 // This method is used to ensure valid pixel values on filter inputs and the final result. 114 // Only the arithmetic composite filter ever needs to perform correction. correctFilterResultIfNeeded()115 virtual void correctFilterResultIfNeeded() { } 116 117 virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*); 118 virtual PassRefPtr<SkImageFilter> createImageFilterWithoutValidation(SkiaImageFilterBuilder*); 119 120 // Mapping a rect forwards determines which which destination pixels a 121 // given source rect would affect. Mapping a rect backwards determines 122 // which pixels from the source rect would be required to fill a given 123 // destination rect. Note that these are not necessarily the inverse of 124 // each other. For example, for FEGaussianBlur, they are the same 125 // transformation. 126 virtual FloatRect mapRect(const FloatRect& rect, bool forward = true) { return rect; } 127 // A version of the above that is used for calculating paint rects. We can't 128 // use mapRect above for that, because that is also used for calculating effect 129 // regions for CSS filters and has undesirable effects for tile and 130 // displacement map. mapPaintRect(const FloatRect & rect,bool forward)131 virtual FloatRect mapPaintRect(const FloatRect& rect, bool forward) 132 { 133 return mapRect(rect, forward); 134 } 135 FloatRect mapRectRecursive(const FloatRect&); 136 137 // This is a recursive version of a backwards mapRect(), which also takes 138 // into account the filter primitive subregion of each effect. 139 // Note: This works in absolute coordinates! 140 FloatRect getSourceRect(const FloatRect& destRect, const FloatRect& clipRect); 141 filterEffectType()142 virtual FilterEffectType filterEffectType() const { return FilterEffectTypeUnknown; } 143 144 virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const; 145 146 // The following functions are SVG specific and will move to RenderSVGResourceFilterPrimitive. 147 // See bug https://bugs.webkit.org/show_bug.cgi?id=45614. hasX()148 bool hasX() const { return m_hasX; } setHasX(bool value)149 void setHasX(bool value) { m_hasX = value; } 150 hasY()151 bool hasY() const { return m_hasY; } setHasY(bool value)152 void setHasY(bool value) { m_hasY = value; } 153 hasWidth()154 bool hasWidth() const { return m_hasWidth; } setHasWidth(bool value)155 void setHasWidth(bool value) { m_hasWidth = value; } 156 hasHeight()157 bool hasHeight() const { return m_hasHeight; } setHasHeight(bool value)158 void setHasHeight(bool value) { m_hasHeight = value; } 159 filterPrimitiveSubregion()160 FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; } setFilterPrimitiveSubregion(const FloatRect & filterPrimitiveSubregion)161 void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; } 162 effectBoundaries()163 FloatRect effectBoundaries() const { return m_effectBoundaries; } setEffectBoundaries(const FloatRect & effectBoundaries)164 void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; } 165 filter()166 Filter* filter() { return m_filter; } filter()167 const Filter* filter() const { return m_filter; } 168 clipsToBounds()169 bool clipsToBounds() const { return m_clipsToBounds; } setClipsToBounds(bool value)170 void setClipsToBounds(bool value) { m_clipsToBounds = value; } 171 operatingColorSpace()172 ColorSpace operatingColorSpace() const { return m_operatingColorSpace; } setOperatingColorSpace(ColorSpace colorSpace)173 virtual void setOperatingColorSpace(ColorSpace colorSpace) { m_operatingColorSpace = colorSpace; } resultColorSpace()174 ColorSpace resultColorSpace() const { return m_resultColorSpace; } setResultColorSpace(ColorSpace colorSpace)175 virtual void setResultColorSpace(ColorSpace colorSpace) { m_resultColorSpace = colorSpace; } 176 transformResultColorSpace(FilterEffect * in,const int)177 virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); } 178 void transformResultColorSpace(ColorSpace); 179 180 FloatRect determineFilterPrimitiveSubregion(DetermineSubregionFlags = DetermineSubregionNone); 181 void determineAllAbsolutePaintRects(); 182 183 virtual FloatRect determineAbsolutePaintRect(const FloatRect& requestedAbsoluteRect); affectsTransparentPixels()184 virtual bool affectsTransparentPixels() { return false; } 185 186 // Return false if the filter will only operate correctly on valid RGBA values, with 187 // alpha in [0,255] and each color component in [0, alpha]. mayProduceInvalidPreMultipliedPixels()188 virtual bool mayProduceInvalidPreMultipliedPixels() { return false; } 189 190 SkImageFilter* getImageFilter(ColorSpace, bool requiresPMColorValidation) const; 191 void setImageFilter(ColorSpace, bool requiresPMColorValidation, PassRefPtr<SkImageFilter>); 192 193 protected: 194 FilterEffect(Filter*); 195 ImageBuffer* createImageBufferResult(); 196 Uint8ClampedArray* createUnmultipliedImageResult(); 197 Uint8ClampedArray* createPremultipliedImageResult(); 198 199 Color adaptColorToOperatingColorSpace(const Color& deviceColor); 200 201 // If a pre-multiplied image, check every pixel for validity and correct if necessary. 202 void forceValidPreMultipliedPixels(); 203 SkImageFilter::CropRect getCropRect(const FloatSize& cropOffset) const; 204 205 void addAbsolutePaintRect(const FloatRect& absolutePaintRect); 206 207 private: 208 void applyRecursive(); 209 virtual void applySoftware() = 0; 210 211 inline void copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect&); 212 213 OwnPtr<ImageBuffer> m_imageBufferResult; 214 RefPtr<Uint8ClampedArray> m_unmultipliedImageResult; 215 RefPtr<Uint8ClampedArray> m_premultipliedImageResult; 216 FilterEffectVector m_inputEffects; 217 218 bool m_alphaImage; 219 220 IntRect m_absolutePaintRect; 221 222 // The maximum size of a filter primitive. In SVG this is the primitive subregion in absolute coordinate space. 223 // The absolute paint rect should never be bigger than m_maxEffectRect. 224 FloatRect m_maxEffectRect; 225 Filter* m_filter; 226 227 // The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive. 228 // See bug https://bugs.webkit.org/show_bug.cgi?id=45614. 229 230 // The subregion of a filter primitive according to the SVG Filter specification in local coordinates. 231 // This is SVG specific and needs to move to RenderSVGResourceFilterPrimitive. 232 FloatRect m_filterPrimitiveSubregion; 233 234 // x, y, width and height of the actual SVGFE*Element. Is needed to determine the subregion of the 235 // filter primitive on a later step. 236 FloatRect m_effectBoundaries; 237 bool m_hasX; 238 bool m_hasY; 239 bool m_hasWidth; 240 bool m_hasHeight; 241 242 // Should the effect clip to its primitive region, or expand to use the combined region of its inputs. 243 bool m_clipsToBounds; 244 245 ColorSpace m_operatingColorSpace; 246 ColorSpace m_resultColorSpace; 247 248 RefPtr<SkImageFilter> m_imageFilters[4]; 249 }; 250 251 } // namespace blink 252 253 #endif // FilterEffect_h 254