15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FilterOperations.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "platform/LengthFunctions.h"
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/IntSize.h"
31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FEGaussianBlur.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline IntSize outsetSizeForBlur(float stdDeviation)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    IntSize kernelSize = FEGaussianBlur::calculateUnscaledKernelSize(FloatPoint(stdDeviation, stdDeviation));
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize outset;
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We take the half kernel size and multiply it with three, because we run box blur three times.
4107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    outset.setWidth(3 * kernelSize.width() * 0.5f);
4207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    outset.setHeight(3 * kernelSize.height() * 0.5f);
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return outset;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FilterOperations::FilterOperations()
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FilterOperations& FilterOperations::operator=(const FilterOperations& other)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_operations = other.m_operations;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return *this;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FilterOperations::operator==(const FilterOperations& o) const
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_operations.size() != o.m_operations.size())
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
6102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned s = m_operations.size();
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < s; i++) {
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (*m_operations[i] != *o.m_operations[i])
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
71f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)bool FilterOperations::canInterpolateWith(const FilterOperations& other) const
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
73f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    for (size_t i = 0; i < operations().size(); ++i) {
7451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!FilterOperation::canInterpolate(operations()[i]->type()))
75f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            return false;
76f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    }
77f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
78f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    for (size_t i = 0; i < other.operations().size(); ++i) {
7951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!FilterOperation::canInterpolate(other.operations()[i]->type()))
80f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            return false;
81f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    }
8202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
83f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    size_t commonSize = std::min(operations().size(), other.operations().size());
84f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    for (size_t i = 0; i < commonSize; ++i) {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!operations()[i]->isSameType(*other.operations()[i]))
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FilterOperations::hasReferenceFilter() const
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_operations.size(); ++i) {
9451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (m_operations.at(i)->type() == FilterOperation::REFERENCE)
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FilterOperations::hasOutsets() const
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_operations.size(); ++i) {
10351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        FilterOperation::OperationType operationType = m_operations.at(i)->type();
104e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        if (operationType == FilterOperation::BLUR || operationType == FilterOperation::DROP_SHADOW || operationType == FilterOperation::REFERENCE)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)FilterOutsets FilterOperations::outsets() const
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FilterOutsets totalOutsets;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_operations.size(); ++i) {
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FilterOperation* filterOperation = m_operations.at(i).get();
11551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        switch (filterOperation->type()) {
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FilterOperation::BLUR: {
11751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            BlurFilterOperation* blurOperation = toBlurFilterOperation(filterOperation);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            IntSize outsetSize = outsetSizeForBlur(stdDeviation);
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            FilterOutsets outsets(outsetSize.height(), outsetSize.width(), outsetSize.height(), outsetSize.width());
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            totalOutsets += outsets;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case FilterOperation::DROP_SHADOW: {
12551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterOperation(filterOperation);
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            IntSize outsetSize = outsetSizeForBlur(dropShadowOperation->stdDeviation());
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            FilterOutsets outsets(
128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                std::max(0, outsetSize.height() - dropShadowOperation->y()),
129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                std::max(0, outsetSize.width() + dropShadowOperation->x()),
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                std::max(0, outsetSize.height() + dropShadowOperation->y()),
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                std::max(0, outsetSize.width() - dropShadowOperation->x())
132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            );
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            totalOutsets += outsets;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
136e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        case FilterOperation::REFERENCE: {
13751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation);
138e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (referenceOperation->filter() && referenceOperation->filter()->lastEffect()) {
139e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                FloatRect outsetRect(0, 0, 1, 1);
140e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                outsetRect = referenceOperation->filter()->lastEffect()->mapRectRecursive(outsetRect);
141e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                FilterOutsets outsets(
142e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                    std::max(0.0f, -outsetRect.y()),
143e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                    std::max(0.0f, outsetRect.x() + outsetRect.width() - 1),
144e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                    std::max(0.0f, outsetRect.y() + outsetRect.height() - 1),
145e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                    std::max(0.0f, -outsetRect.x())
146e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                );
147e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                totalOutsets += outsets;
148e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            }
149e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            break;
150e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        }
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return totalOutsets;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FilterOperations::hasFilterThatAffectsOpacity() const
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_operations.size(); ++i)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_operations[i]->affectsOpacity())
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FilterOperations::hasFilterThatMovesPixels() const
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_operations.size(); ++i)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_operations[i]->movesPixels())
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return true;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
174c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
176