| /* |
| * Copyright (C) 2011 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include "Color.h" |
| #include "LayoutSize.h" |
| #include "Length.h" |
| #include <wtf/ThreadSafeRefCounted.h> |
| #include <wtf/TypeCasts.h> |
| #include <wtf/text/WTFString.h> |
| |
| // Annoyingly, wingdi.h #defines this. |
| #ifdef PASSTHROUGH |
| #undef PASSTHROUGH |
| #endif |
| |
| namespace WebCore { |
| |
| // CSS Filters |
| |
| class CachedResourceLoader; |
| class CachedSVGDocumentReference; |
| class FilterEffect; |
| struct FloatComponents; |
| struct ResourceLoaderOptions; |
| |
| class FilterOperation : public ThreadSafeRefCounted<FilterOperation> { |
| public: |
| enum OperationType { |
| REFERENCE, // url(#somefilter) |
| GRAYSCALE, |
| SEPIA, |
| SATURATE, |
| HUE_ROTATE, |
| INVERT, |
| APPLE_INVERT_LIGHTNESS, |
| OPACITY, |
| BRIGHTNESS, |
| CONTRAST, |
| BLUR, |
| DROP_SHADOW, |
| PASSTHROUGH, |
| DEFAULT, |
| NONE |
| }; |
| |
| virtual ~FilterOperation() = default; |
| |
| virtual Ref<FilterOperation> clone() const = 0; |
| |
| virtual bool operator==(const FilterOperation&) const = 0; |
| bool operator!=(const FilterOperation& o) const { return !(*this == o); } |
| |
| virtual RefPtr<FilterOperation> blend(const FilterOperation* /*from*/, double /*progress*/, bool /*blendToPassthrough*/ = false) |
| { |
| return nullptr; |
| } |
| |
| virtual bool transformColor(FloatComponents&) const { return false; } |
| virtual bool inverseTransformColor(FloatComponents&) const { return false; } |
| |
| OperationType type() const { return m_type; } |
| |
| bool isBasicColorMatrixFilterOperation() const |
| { |
| return m_type == GRAYSCALE || m_type == SEPIA || m_type == SATURATE || m_type == HUE_ROTATE; |
| } |
| |
| bool isBasicComponentTransferFilterOperation() const |
| { |
| return m_type == INVERT || m_type == BRIGHTNESS || m_type == CONTRAST || m_type == OPACITY; |
| } |
| |
| bool isSameType(const FilterOperation& o) const { return o.type() == m_type; } |
| |
| // True if the alpha channel of any pixel can change under this operation. |
| virtual bool affectsOpacity() const { return false; } |
| // True if the value of one pixel can affect the value of another pixel under this operation, such as blur. |
| virtual bool movesPixels() const { return false; } |
| // True if the filter should not be allowed to work on content that is not available from this security origin. |
| virtual bool shouldBeRestrictedBySecurityOrigin() const { return false; } |
| |
| protected: |
| FilterOperation(OperationType type) |
| : m_type(type) |
| { |
| } |
| |
| OperationType m_type; |
| }; |
| |
| class WEBCORE_EXPORT DefaultFilterOperation : public FilterOperation { |
| public: |
| static Ref<DefaultFilterOperation> create(OperationType representedType) |
| { |
| return adoptRef(*new DefaultFilterOperation(representedType)); |
| } |
| |
| Ref<FilterOperation> clone() const override |
| { |
| return adoptRef(*new DefaultFilterOperation(representedType())); |
| } |
| |
| OperationType representedType() const { return m_representedType; } |
| |
| private: |
| bool operator==(const FilterOperation&) const override; |
| |
| DefaultFilterOperation(OperationType representedType) |
| : FilterOperation(DEFAULT) |
| , m_representedType(representedType) |
| { |
| } |
| |
| OperationType m_representedType; |
| }; |
| |
| class PassthroughFilterOperation : public FilterOperation { |
| public: |
| static Ref<PassthroughFilterOperation> create() |
| { |
| return adoptRef(*new PassthroughFilterOperation()); |
| } |
| |
| Ref<FilterOperation> clone() const override |
| { |
| return adoptRef(*new PassthroughFilterOperation()); |
| } |
| |
| private: |
| bool operator==(const FilterOperation& o) const override |
| { |
| return isSameType(o); |
| } |
| |
| PassthroughFilterOperation() |
| : FilterOperation(PASSTHROUGH) |
| { |
| } |
| }; |
| |
| class ReferenceFilterOperation : public FilterOperation { |
| public: |
| static Ref<ReferenceFilterOperation> create(const String& url, const String& fragment) |
| { |
| return adoptRef(*new ReferenceFilterOperation(url, fragment)); |
| } |
| virtual ~ReferenceFilterOperation(); |
| |
| Ref<FilterOperation> clone() const final |
| { |
| // Reference filters cannot be cloned. |
| RELEASE_ASSERT_NOT_REACHED(); |
| } |
| |
| bool affectsOpacity() const override { return true; } |
| bool movesPixels() const override { return true; } |
| // FIXME: This only needs to return true for graphs that include ConvolveMatrix, DisplacementMap, Morphology and possibly Lighting. |
| // https://bugs.webkit.org/show_bug.cgi?id=171753 |
| bool shouldBeRestrictedBySecurityOrigin() const override { return true; } |
| |
| const String& url() const { return m_url; } |
| const String& fragment() const { return m_fragment; } |
| |
| void loadExternalDocumentIfNeeded(CachedResourceLoader&, const ResourceLoaderOptions&); |
| |
| CachedSVGDocumentReference* cachedSVGDocumentReference() const { return m_cachedSVGDocumentReference.get(); } |
| |
| private: |
| ReferenceFilterOperation(const String& url, const String& fragment); |
| |
| bool operator==(const FilterOperation&) const override; |
| |
| String m_url; |
| String m_fragment; |
| std::unique_ptr<CachedSVGDocumentReference> m_cachedSVGDocumentReference; |
| }; |
| |
| // GRAYSCALE, SEPIA, SATURATE and HUE_ROTATE are variations on a basic color matrix effect. |
| // For HUE_ROTATE, the angle of rotation is stored in m_amount. |
| class WEBCORE_EXPORT BasicColorMatrixFilterOperation : public FilterOperation { |
| public: |
| static Ref<BasicColorMatrixFilterOperation> create(double amount, OperationType type) |
| { |
| return adoptRef(*new BasicColorMatrixFilterOperation(amount, type)); |
| } |
| |
| Ref<FilterOperation> clone() const override |
| { |
| return adoptRef(*new BasicColorMatrixFilterOperation(amount(), type())); |
| } |
| |
| double amount() const { return m_amount; } |
| |
| RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override; |
| |
| private: |
| bool operator==(const FilterOperation&) const override; |
| |
| double passthroughAmount() const; |
| |
| BasicColorMatrixFilterOperation(double amount, OperationType type) |
| : FilterOperation(type) |
| , m_amount(amount) |
| { |
| } |
| |
| bool transformColor(FloatComponents&) const override; |
| |
| double m_amount; |
| }; |
| |
| // INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component transfer effect. |
| class WEBCORE_EXPORT BasicComponentTransferFilterOperation : public FilterOperation { |
| public: |
| static Ref<BasicComponentTransferFilterOperation> create(double amount, OperationType type) |
| { |
| return adoptRef(*new BasicComponentTransferFilterOperation(amount, type)); |
| } |
| |
| Ref<FilterOperation> clone() const override |
| { |
| return adoptRef(*new BasicComponentTransferFilterOperation(amount(), type())); |
| } |
| |
| double amount() const { return m_amount; } |
| |
| bool affectsOpacity() const override { return m_type == OPACITY; } |
| |
| RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override; |
| |
| private: |
| bool operator==(const FilterOperation&) const override; |
| |
| double passthroughAmount() const; |
| |
| BasicComponentTransferFilterOperation(double amount, OperationType type) |
| : FilterOperation(type) |
| , m_amount(amount) |
| { |
| } |
| |
| bool transformColor(FloatComponents&) const override; |
| |
| double m_amount; |
| }; |
| |
| class WEBCORE_EXPORT InvertLightnessFilterOperation : public FilterOperation { |
| public: |
| static Ref<InvertLightnessFilterOperation> create() |
| { |
| return adoptRef(*new InvertLightnessFilterOperation()); |
| } |
| |
| Ref<FilterOperation> clone() const final |
| { |
| return adoptRef(*new InvertLightnessFilterOperation()); |
| } |
| |
| RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override; |
| |
| private: |
| bool operator==(const FilterOperation&) const final; |
| |
| InvertLightnessFilterOperation() |
| : FilterOperation(APPLE_INVERT_LIGHTNESS) |
| { |
| } |
| |
| bool transformColor(FloatComponents&) const final; |
| bool inverseTransformColor(FloatComponents&) const final; |
| }; |
| |
| class WEBCORE_EXPORT BlurFilterOperation : public FilterOperation { |
| public: |
| static Ref<BlurFilterOperation> create(Length stdDeviation) |
| { |
| return adoptRef(*new BlurFilterOperation(WTFMove(stdDeviation))); |
| } |
| |
| Ref<FilterOperation> clone() const override |
| { |
| return adoptRef(*new BlurFilterOperation(stdDeviation())); |
| } |
| |
| const Length& stdDeviation() const { return m_stdDeviation; } |
| |
| bool affectsOpacity() const override { return true; } |
| bool movesPixels() const override { return true; } |
| |
| RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override; |
| |
| private: |
| bool operator==(const FilterOperation&) const override; |
| |
| BlurFilterOperation(Length stdDeviation) |
| : FilterOperation(BLUR) |
| , m_stdDeviation(WTFMove(stdDeviation)) |
| { |
| } |
| |
| Length m_stdDeviation; |
| }; |
| |
| class WEBCORE_EXPORT DropShadowFilterOperation : public FilterOperation { |
| public: |
| static Ref<DropShadowFilterOperation> create(const IntPoint& location, int stdDeviation, const Color& color) |
| { |
| return adoptRef(*new DropShadowFilterOperation(location, stdDeviation, color)); |
| } |
| |
| Ref<FilterOperation> clone() const override |
| { |
| return adoptRef(*new DropShadowFilterOperation(location(), stdDeviation(), color())); |
| } |
| |
| int x() const { return m_location.x(); } |
| int y() const { return m_location.y(); } |
| IntPoint location() const { return m_location; } |
| int stdDeviation() const { return m_stdDeviation; } |
| const Color& color() const { return m_color; } |
| |
| bool affectsOpacity() const override { return true; } |
| bool movesPixels() const override { return true; } |
| |
| RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override; |
| |
| private: |
| bool operator==(const FilterOperation&) const override; |
| |
| DropShadowFilterOperation(const IntPoint& location, int stdDeviation, const Color& color) |
| : FilterOperation(DROP_SHADOW) |
| , m_location(location) |
| , m_stdDeviation(stdDeviation) |
| , m_color(color) |
| { |
| } |
| |
| IntPoint m_location; // FIXME: should location be in Lengths? |
| int m_stdDeviation; |
| Color m_color; |
| }; |
| |
| WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const FilterOperation&); |
| |
| } // namespace WebCore |
| |
| #define SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(ToValueTypeName, predicate) \ |
| SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \ |
| static bool isType(const WebCore::FilterOperation& operation) { return operation.predicate; } \ |
| SPECIALIZE_TYPE_TRAITS_END() |
| |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(DefaultFilterOperation, type() == WebCore::FilterOperation::DEFAULT) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(PassthroughFilterOperation, type() == WebCore::FilterOperation::PASSTHROUGH) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(ReferenceFilterOperation, type() == WebCore::FilterOperation::REFERENCE) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BasicColorMatrixFilterOperation, isBasicColorMatrixFilterOperation()) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BasicComponentTransferFilterOperation, isBasicComponentTransferFilterOperation()) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(InvertLightnessFilterOperation, type() == WebCore::FilterOperation::APPLE_INVERT_LIGHTNESS) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BlurFilterOperation, type() == WebCore::FilterOperation::BLUR) |
| SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(DropShadowFilterOperation, type() == WebCore::FilterOperation::DROP_SHADOW) |
| |