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/ColorSpace.h"
30
31#include "third_party/skia/include/core/SkImageFilter.h"
32
33#include "wtf/PassOwnPtr.h"
34#include "wtf/RefCounted.h"
35#include "wtf/RefPtr.h"
36#include "wtf/Uint8ClampedArray.h"
37#include "wtf/Vector.h"
38
39static const float kMaxFilterSize = 5000.0f;
40
41namespace WebCore {
42
43class Filter;
44class FilterEffect;
45class ImageBuffer;
46class TextStream;
47
48class SkiaImageFilterBuilder;
49
50typedef Vector<RefPtr<FilterEffect> > FilterEffectVector;
51
52enum FilterEffectType {
53    FilterEffectTypeUnknown,
54    FilterEffectTypeImage,
55    FilterEffectTypeTile,
56    FilterEffectTypeSourceInput
57};
58
59enum DetermineSubregionFlag {
60    DetermineSubregionNone = 0,
61    MapRectForward = 1,
62    ClipToFilterRegion = 1 << 1
63};
64
65typedef int DetermineSubregionFlags;
66
67class PLATFORM_EXPORT FilterEffect : public RefCounted<FilterEffect> {
68public:
69    virtual ~FilterEffect();
70
71    void clearResult();
72    void clearResultsRecursive();
73
74    ImageBuffer* asImageBuffer();
75    PassRefPtr<Uint8ClampedArray> asUnmultipliedImage(const IntRect&);
76    PassRefPtr<Uint8ClampedArray> asPremultipliedImage(const IntRect&);
77    void copyUnmultipliedImage(Uint8ClampedArray* destination, const IntRect&);
78    void copyPremultipliedImage(Uint8ClampedArray* destination, const IntRect&);
79
80    FilterEffectVector& inputEffects() { return m_inputEffects; }
81    FilterEffect* inputEffect(unsigned) const;
82    unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
83
84    inline bool hasResult() const
85    {
86        // This function needs platform specific checks, if the memory managment is not done by FilterEffect.
87        return m_imageBufferResult
88            || m_unmultipliedImageResult
89            || m_premultipliedImageResult;
90    }
91
92    IntRect drawingRegionOfInputImage(const IntRect&) const;
93    IntRect requestedRegionOfInputImageData(const IntRect&) const;
94
95    // Solid black image with different alpha values.
96    bool isAlphaImage() const { return m_alphaImage; }
97    void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
98
99    IntRect absolutePaintRect() const { return m_absolutePaintRect; }
100    void setAbsolutePaintRect(const IntRect& absolutePaintRect) { m_absolutePaintRect = absolutePaintRect; }
101
102    FloatRect maxEffectRect() const { return m_maxEffectRect; }
103    void setMaxEffectRect(const FloatRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; }
104
105    void apply();
106
107    // Correct any invalid pixels, if necessary, in the result of a filter operation.
108    // This method is used to ensure valid pixel values on filter inputs and the final result.
109    // Only the arithmetic composite filter ever needs to perform correction.
110    virtual void correctFilterResultIfNeeded() { }
111
112    virtual PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*);
113
114    virtual void determineAbsolutePaintRect();
115
116    // Mapping a rect forwards determines which which destination pixels a
117    // given source rect would affect. Mapping a rect backwards determines
118    // which pixels from the source rect would be required to fill a given
119    // destination rect. Note that these are not necessarily the inverse of
120    // each other. For example, for FEGaussianBlur, they are the same
121    // transformation.
122    virtual FloatRect mapRect(const FloatRect& rect, bool forward = true) { return rect; }
123    FloatRect mapRectRecursive(const FloatRect&);
124
125    // This is a recursive version of a backwards mapRect(), which also takes
126    // into account the filter primitive subregion of each effect.
127    FloatRect getSourceRect(const FloatRect& destRect, const FloatRect& clipRect);
128
129    virtual FilterEffectType filterEffectType() const { return FilterEffectTypeUnknown; }
130
131    virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const;
132
133    // The following functions are SVG specific and will move to RenderSVGResourceFilterPrimitive.
134    // See bug https://bugs.webkit.org/show_bug.cgi?id=45614.
135    bool hasX() const { return m_hasX; }
136    void setHasX(bool value) { m_hasX = value; }
137
138    bool hasY() const { return m_hasY; }
139    void setHasY(bool value) { m_hasY = value; }
140
141    bool hasWidth() const { return m_hasWidth; }
142    void setHasWidth(bool value) { m_hasWidth = value; }
143
144    bool hasHeight() const { return m_hasHeight; }
145    void setHasHeight(bool value) { m_hasHeight = value; }
146
147    FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; }
148    void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; }
149
150    FloatRect effectBoundaries() const { return m_effectBoundaries; }
151    void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
152
153    Filter* filter() { return m_filter; }
154    const Filter* filter() const { return m_filter; }
155
156    bool clipsToBounds() const { return m_clipsToBounds; }
157    void setClipsToBounds(bool value) { m_clipsToBounds = value; }
158
159    ColorSpace operatingColorSpace() const { return m_operatingColorSpace; }
160    virtual void setOperatingColorSpace(ColorSpace colorSpace) { m_operatingColorSpace = colorSpace; }
161    ColorSpace resultColorSpace() const { return m_resultColorSpace; }
162    virtual void setResultColorSpace(ColorSpace colorSpace) { m_resultColorSpace = colorSpace; }
163
164    virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
165    void transformResultColorSpace(ColorSpace);
166
167    FloatRect determineFilterPrimitiveSubregion(DetermineSubregionFlags = DetermineSubregionNone);
168
169protected:
170    FilterEffect(Filter*);
171
172    ImageBuffer* createImageBufferResult();
173    Uint8ClampedArray* createUnmultipliedImageResult();
174    Uint8ClampedArray* createPremultipliedImageResult();
175
176    // Return true if the filter will only operate correctly on valid RGBA values, with
177    // alpha in [0,255] and each color component in [0, alpha].
178    virtual bool requiresValidPreMultipliedPixels() { return true; }
179
180    // If a pre-multiplied image, check every pixel for validity and correct if necessary.
181    void forceValidPreMultipliedPixels();
182    SkImageFilter::CropRect getCropRect(const FloatSize& cropOffset) const;
183
184private:
185    virtual void applySoftware() = 0;
186    virtual bool applySkia() { return false; }
187
188    inline void copyImageBytes(Uint8ClampedArray* source, Uint8ClampedArray* destination, const IntRect&);
189
190    OwnPtr<ImageBuffer> m_imageBufferResult;
191    RefPtr<Uint8ClampedArray> m_unmultipliedImageResult;
192    RefPtr<Uint8ClampedArray> m_premultipliedImageResult;
193    FilterEffectVector m_inputEffects;
194
195    bool m_alphaImage;
196
197    IntRect m_absolutePaintRect;
198
199    // The maximum size of a filter primitive. In SVG this is the primitive subregion in absolute coordinate space.
200    // The absolute paint rect should never be bigger than m_maxEffectRect.
201    FloatRect m_maxEffectRect;
202    Filter* m_filter;
203
204    // The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive.
205    // See bug https://bugs.webkit.org/show_bug.cgi?id=45614.
206
207    // The subregion of a filter primitive according to the SVG Filter specification in local coordinates.
208    // This is SVG specific and needs to move to RenderSVGResourceFilterPrimitive.
209    FloatRect m_filterPrimitiveSubregion;
210
211    // x, y, width and height of the actual SVGFE*Element. Is needed to determine the subregion of the
212    // filter primitive on a later step.
213    FloatRect m_effectBoundaries;
214    bool m_hasX;
215    bool m_hasY;
216    bool m_hasWidth;
217    bool m_hasHeight;
218
219    // Should the effect clip to its primitive region, or expand to use the combined region of its inputs.
220    bool m_clipsToBounds;
221
222    ColorSpace m_operatingColorSpace;
223    ColorSpace m_resultColorSpace;
224};
225
226} // namespace WebCore
227
228#endif // FilterEffect_h
229