Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2008 Alex Mathews <possessedpenguinbob (at) gmail.com>
      3  * Copyright (C) 2009 Dirk Schulze <krit (at) 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 WebCore {
     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 
     82     FilterEffectVector& inputEffects() { return m_inputEffects; }
     83     FilterEffect* inputEffect(unsigned) const;
     84     unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
     85 
     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     }
     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.
    102     bool isAlphaImage() const { return m_alphaImage; }
    103     void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
    104 
    105     IntRect absolutePaintRect() const { return m_absolutePaintRect; }
    106 
    107     FloatRect maxEffectRect() const { return m_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.
    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.
    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 
    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.
    148     bool hasX() const { return m_hasX; }
    149     void setHasX(bool value) { m_hasX = value; }
    150 
    151     bool hasY() const { return m_hasY; }
    152     void setHasY(bool value) { m_hasY = value; }
    153 
    154     bool hasWidth() const { return m_hasWidth; }
    155     void setHasWidth(bool value) { m_hasWidth = value; }
    156 
    157     bool hasHeight() const { return m_hasHeight; }
    158     void setHasHeight(bool value) { m_hasHeight = value; }
    159 
    160     FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; }
    161     void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; }
    162 
    163     FloatRect effectBoundaries() const { return m_effectBoundaries; }
    164     void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
    165 
    166     Filter* filter() { return m_filter; }
    167     const Filter* filter() const { return m_filter; }
    168 
    169     bool clipsToBounds() const { return m_clipsToBounds; }
    170     void setClipsToBounds(bool value) { m_clipsToBounds = value; }
    171 
    172     ColorSpace operatingColorSpace() const { return m_operatingColorSpace; }
    173     virtual void setOperatingColorSpace(ColorSpace colorSpace) { m_operatingColorSpace = colorSpace; }
    174     ColorSpace resultColorSpace() const { return m_resultColorSpace; }
    175     virtual void setResultColorSpace(ColorSpace colorSpace) { m_resultColorSpace = colorSpace; }
    176 
    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);
    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].
    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 WebCore
    252 
    253 #endif // FilterEffect_h
    254