Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef FilterOperation_h
     27 #define FilterOperation_h
     28 
     29 #include "platform/Length.h"
     30 #include "platform/PlatformExport.h"
     31 #include "platform/graphics/Color.h"
     32 #include "platform/graphics/filters/Filter.h"
     33 #include "platform/graphics/filters/ReferenceFilter.h"
     34 #include "wtf/OwnPtr.h"
     35 #include "wtf/PassOwnPtr.h"
     36 #include "wtf/RefCounted.h"
     37 #include "wtf/text/WTFString.h"
     38 
     39 namespace WebCore {
     40 
     41 // CSS Filters
     42 
     43 class PLATFORM_EXPORT FilterOperation : public RefCounted<FilterOperation> {
     44 public:
     45     enum OperationType {
     46         REFERENCE, // url(#somefilter)
     47         GRAYSCALE,
     48         SEPIA,
     49         SATURATE,
     50         HUE_ROTATE,
     51         INVERT,
     52         OPACITY,
     53         BRIGHTNESS,
     54         CONTRAST,
     55         BLUR,
     56         DROP_SHADOW,
     57         CUSTOM,
     58         VALIDATED_CUSTOM,
     59         NONE
     60     };
     61 
     62     static bool canInterpolate(FilterOperation::OperationType type)
     63     {
     64         switch (type) {
     65         case GRAYSCALE:
     66         case SEPIA:
     67         case SATURATE:
     68         case HUE_ROTATE:
     69         case INVERT:
     70         case OPACITY:
     71         case BRIGHTNESS:
     72         case CONTRAST:
     73         case BLUR:
     74         case DROP_SHADOW:
     75         case CUSTOM:
     76         case VALIDATED_CUSTOM:
     77             return true;
     78         case REFERENCE:
     79             return false;
     80         case NONE:
     81             break;
     82         }
     83         ASSERT_NOT_REACHED();
     84         return false;
     85     }
     86 
     87     virtual ~FilterOperation() { }
     88 
     89     static PassRefPtr<FilterOperation> blend(const FilterOperation* from, const FilterOperation* to, double progress);
     90     virtual bool operator==(const FilterOperation&) const = 0;
     91     bool operator!=(const FilterOperation& o) const { return !(*this == o); }
     92 
     93     OperationType type() const { return m_type; }
     94     virtual bool isSameType(const FilterOperation& o) const { return o.type() == m_type; }
     95 
     96     // True if the alpha channel of any pixel can change under this operation.
     97     virtual bool affectsOpacity() const { return false; }
     98     // True if the the value of one pixel can affect the value of another pixel under this operation, such as blur.
     99     virtual bool movesPixels() const { return false; }
    100 
    101 protected:
    102     FilterOperation(OperationType type)
    103         : m_type(type)
    104     {
    105     }
    106 
    107     OperationType m_type;
    108 
    109 private:
    110     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const = 0;
    111 };
    112 
    113 #define DEFINE_FILTER_OPERATION_TYPE_CASTS(thisType, operationType) \
    114     DEFINE_TYPE_CASTS(thisType, FilterOperation, op, op->type() == FilterOperation::operationType, op.type() == FilterOperation::operationType);
    115 
    116 class PLATFORM_EXPORT ReferenceFilterOperation : public FilterOperation {
    117 public:
    118     static PassRefPtr<ReferenceFilterOperation> create(const String& url, const String& fragment)
    119     {
    120         return adoptRef(new ReferenceFilterOperation(url, fragment));
    121     }
    122 
    123     virtual bool affectsOpacity() const { return true; }
    124     virtual bool movesPixels() const { return true; }
    125 
    126     const String& url() const { return m_url; }
    127     const String& fragment() const { return m_fragment; }
    128 
    129     ReferenceFilter* filter() const { return m_filter.get(); }
    130     void setFilter(PassRefPtr<ReferenceFilter> filter) { m_filter = filter; }
    131 
    132 private:
    133     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE
    134     {
    135         ASSERT_NOT_REACHED();
    136         return 0;
    137     }
    138 
    139     virtual bool operator==(const FilterOperation& o) const
    140     {
    141         if (!isSameType(o))
    142             return false;
    143         const ReferenceFilterOperation* other = static_cast<const ReferenceFilterOperation*>(&o);
    144         return m_url == other->m_url;
    145     }
    146 
    147     ReferenceFilterOperation(const String& url, const String& fragment)
    148         : FilterOperation(REFERENCE)
    149         , m_url(url)
    150         , m_fragment(fragment)
    151     {
    152     }
    153 
    154     String m_url;
    155     String m_fragment;
    156     RefPtr<ReferenceFilter> m_filter;
    157 };
    158 
    159 DEFINE_FILTER_OPERATION_TYPE_CASTS(ReferenceFilterOperation, REFERENCE);
    160 
    161 // GRAYSCALE, SEPIA, SATURATE and HUE_ROTATE are variations on a basic color matrix effect.
    162 // For HUE_ROTATE, the angle of rotation is stored in m_amount.
    163 class PLATFORM_EXPORT BasicColorMatrixFilterOperation : public FilterOperation {
    164 public:
    165     static PassRefPtr<BasicColorMatrixFilterOperation> create(double amount, OperationType type)
    166     {
    167         return adoptRef(new BasicColorMatrixFilterOperation(amount, type));
    168     }
    169 
    170     double amount() const { return m_amount; }
    171 
    172 
    173 private:
    174     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
    175     virtual bool operator==(const FilterOperation& o) const
    176     {
    177         if (!isSameType(o))
    178             return false;
    179         const BasicColorMatrixFilterOperation* other = static_cast<const BasicColorMatrixFilterOperation*>(&o);
    180         return m_amount == other->m_amount;
    181     }
    182 
    183     BasicColorMatrixFilterOperation(double amount, OperationType type)
    184         : FilterOperation(type)
    185         , m_amount(amount)
    186     {
    187     }
    188 
    189     double m_amount;
    190 };
    191 
    192 inline bool isBasicColorMatrixFilterOperation(const FilterOperation& operation)
    193 {
    194     FilterOperation::OperationType type = operation.type();
    195     return type == FilterOperation::GRAYSCALE || type == FilterOperation::SEPIA || type == FilterOperation::SATURATE || type == FilterOperation::HUE_ROTATE;
    196 }
    197 
    198 DEFINE_TYPE_CASTS(BasicColorMatrixFilterOperation, FilterOperation, op, isBasicColorMatrixFilterOperation(*op), isBasicColorMatrixFilterOperation(op));
    199 
    200 // INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component transfer effect.
    201 class PLATFORM_EXPORT BasicComponentTransferFilterOperation : public FilterOperation {
    202 public:
    203     static PassRefPtr<BasicComponentTransferFilterOperation> create(double amount, OperationType type)
    204     {
    205         return adoptRef(new BasicComponentTransferFilterOperation(amount, type));
    206     }
    207 
    208     double amount() const { return m_amount; }
    209 
    210     virtual bool affectsOpacity() const { return m_type == OPACITY; }
    211 
    212 
    213 private:
    214     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
    215     virtual bool operator==(const FilterOperation& o) const
    216     {
    217         if (!isSameType(o))
    218             return false;
    219         const BasicComponentTransferFilterOperation* other = static_cast<const BasicComponentTransferFilterOperation*>(&o);
    220         return m_amount == other->m_amount;
    221     }
    222 
    223     BasicComponentTransferFilterOperation(double amount, OperationType type)
    224         : FilterOperation(type)
    225         , m_amount(amount)
    226     {
    227     }
    228 
    229     double m_amount;
    230 };
    231 
    232 inline bool isBasicComponentTransferFilterOperation(const FilterOperation& operation)
    233 {
    234     FilterOperation::OperationType type = operation.type();
    235     return type == FilterOperation::INVERT || type == FilterOperation::OPACITY || type == FilterOperation::BRIGHTNESS || type == FilterOperation::CONTRAST;
    236 }
    237 
    238 DEFINE_TYPE_CASTS(BasicComponentTransferFilterOperation, FilterOperation, op, isBasicComponentTransferFilterOperation(*op), isBasicComponentTransferFilterOperation(op));
    239 
    240 class PLATFORM_EXPORT BlurFilterOperation : public FilterOperation {
    241 public:
    242     static PassRefPtr<BlurFilterOperation> create(Length stdDeviation)
    243     {
    244         return adoptRef(new BlurFilterOperation(stdDeviation));
    245     }
    246 
    247     Length stdDeviation() const { return m_stdDeviation; }
    248 
    249     virtual bool affectsOpacity() const { return true; }
    250     virtual bool movesPixels() const { return true; }
    251 
    252 
    253 private:
    254     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
    255     virtual bool operator==(const FilterOperation& o) const
    256     {
    257         if (!isSameType(o))
    258             return false;
    259         const BlurFilterOperation* other = static_cast<const BlurFilterOperation*>(&o);
    260         return m_stdDeviation == other->m_stdDeviation;
    261     }
    262 
    263     BlurFilterOperation(Length stdDeviation)
    264         : FilterOperation(BLUR)
    265         , m_stdDeviation(stdDeviation)
    266     {
    267     }
    268 
    269     Length m_stdDeviation;
    270 };
    271 
    272 DEFINE_FILTER_OPERATION_TYPE_CASTS(BlurFilterOperation, BLUR);
    273 
    274 class PLATFORM_EXPORT DropShadowFilterOperation : public FilterOperation {
    275 public:
    276     static PassRefPtr<DropShadowFilterOperation> create(const IntPoint& location, int stdDeviation, Color color)
    277     {
    278         return adoptRef(new DropShadowFilterOperation(location, stdDeviation, color));
    279     }
    280 
    281     int x() const { return m_location.x(); }
    282     int y() const { return m_location.y(); }
    283     IntPoint location() const { return m_location; }
    284     int stdDeviation() const { return m_stdDeviation; }
    285     Color color() const { return m_color; }
    286 
    287     virtual bool affectsOpacity() const { return true; }
    288     virtual bool movesPixels() const { return true; }
    289 
    290 
    291 private:
    292     virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress) const OVERRIDE;
    293     virtual bool operator==(const FilterOperation& o) const
    294     {
    295         if (!isSameType(o))
    296             return false;
    297         const DropShadowFilterOperation* other = static_cast<const DropShadowFilterOperation*>(&o);
    298         return m_location == other->m_location && m_stdDeviation == other->m_stdDeviation && m_color == other->m_color;
    299     }
    300 
    301     DropShadowFilterOperation(const IntPoint& location, int stdDeviation, Color color)
    302         : FilterOperation(DROP_SHADOW)
    303         , m_location(location)
    304         , m_stdDeviation(stdDeviation)
    305         , m_color(color)
    306     {
    307     }
    308 
    309     IntPoint m_location; // FIXME: should location be in Lengths?
    310     int m_stdDeviation;
    311     Color m_color;
    312 };
    313 
    314 DEFINE_FILTER_OPERATION_TYPE_CASTS(DropShadowFilterOperation, DROP_SHADOW);
    315 
    316 } // namespace WebCore
    317 
    318 
    319 #endif // FilterOperation_h
    320