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 #include "config.h"
     27 #include "core/platform/graphics/filters/FilterOperations.h"
     28 
     29 #include "core/css/LengthFunctions.h"
     30 #include "core/platform/graphics/IntSize.h"
     31 #include "core/platform/graphics/filters/FEGaussianBlur.h"
     32 
     33 namespace WebCore {
     34 
     35 static inline IntSize outsetSizeForBlur(float stdDeviation)
     36 {
     37     unsigned kernelSizeX = 0;
     38     unsigned kernelSizeY = 0;
     39     FEGaussianBlur::calculateUnscaledKernelSize(kernelSizeX, kernelSizeY, stdDeviation, stdDeviation);
     40 
     41     IntSize outset;
     42     // We take the half kernel size and multiply it with three, because we run box blur three times.
     43     outset.setWidth(3 * kernelSizeX * 0.5f);
     44     outset.setHeight(3 * kernelSizeY * 0.5f);
     45 
     46     return outset;
     47 }
     48 
     49 FilterOperations::FilterOperations()
     50 {
     51 }
     52 
     53 FilterOperations& FilterOperations::operator=(const FilterOperations& other)
     54 {
     55     m_operations = other.m_operations;
     56     return *this;
     57 }
     58 
     59 bool FilterOperations::operator==(const FilterOperations& o) const
     60 {
     61     if (m_operations.size() != o.m_operations.size())
     62         return false;
     63 
     64     unsigned s = m_operations.size();
     65     for (unsigned i = 0; i < s; i++) {
     66         if (*m_operations[i] != *o.m_operations[i])
     67             return false;
     68     }
     69 
     70     return true;
     71 }
     72 
     73 bool FilterOperations::operationsMatch(const FilterOperations& other) const
     74 {
     75     size_t numOperations = operations().size();
     76     // If the sizes of the function lists don't match, the lists don't match
     77     if (numOperations != other.operations().size())
     78         return false;
     79 
     80     // If the types of each function are not the same, the lists don't match
     81     for (size_t i = 0; i < numOperations; ++i) {
     82         if (!operations()[i]->isSameType(*other.operations()[i]))
     83             return false;
     84     }
     85     return true;
     86 }
     87 
     88 bool FilterOperations::hasCustomFilter() const
     89 {
     90     for (size_t i = 0; i < m_operations.size(); ++i) {
     91         FilterOperation::OperationType type = m_operations.at(i)->getOperationType();
     92         if (type == FilterOperation::CUSTOM || type == FilterOperation::VALIDATED_CUSTOM)
     93             return true;
     94     }
     95     return false;
     96 }
     97 
     98 bool FilterOperations::hasReferenceFilter() const
     99 {
    100     for (size_t i = 0; i < m_operations.size(); ++i) {
    101         if (m_operations.at(i)->getOperationType() == FilterOperation::REFERENCE)
    102             return true;
    103     }
    104     return false;
    105 }
    106 
    107 bool FilterOperations::hasOutsets() const
    108 {
    109     for (size_t i = 0; i < m_operations.size(); ++i) {
    110         FilterOperation::OperationType operationType = m_operations.at(i).get()->getOperationType();
    111         if (operationType == FilterOperation::BLUR || operationType == FilterOperation::DROP_SHADOW || operationType == FilterOperation::REFERENCE)
    112             return true;
    113     }
    114     return false;
    115 }
    116 
    117 FilterOutsets FilterOperations::outsets() const
    118 {
    119     FilterOutsets totalOutsets;
    120     for (size_t i = 0; i < m_operations.size(); ++i) {
    121         FilterOperation* filterOperation = m_operations.at(i).get();
    122         switch (filterOperation->getOperationType()) {
    123         case FilterOperation::BLUR: {
    124             BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
    125             float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
    126             IntSize outsetSize = outsetSizeForBlur(stdDeviation);
    127             FilterOutsets outsets(outsetSize.height(), outsetSize.width(), outsetSize.height(), outsetSize.width());
    128             totalOutsets += outsets;
    129             break;
    130         }
    131         case FilterOperation::DROP_SHADOW: {
    132             DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
    133             IntSize outsetSize = outsetSizeForBlur(dropShadowOperation->stdDeviation());
    134             FilterOutsets outsets(
    135                 std::max(0, outsetSize.height() - dropShadowOperation->y()),
    136                 std::max(0, outsetSize.width() + dropShadowOperation->x()),
    137                 std::max(0, outsetSize.height() + dropShadowOperation->y()),
    138                 std::max(0, outsetSize.width() - dropShadowOperation->x())
    139             );
    140             totalOutsets += outsets;
    141             break;
    142         }
    143         case FilterOperation::REFERENCE: {
    144             ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation);
    145             if (referenceOperation->filter() && referenceOperation->filter()->lastEffect()) {
    146                 FloatRect outsetRect(0, 0, 1, 1);
    147                 outsetRect = referenceOperation->filter()->lastEffect()->mapRectRecursive(outsetRect);
    148                 FilterOutsets outsets(
    149                     std::max(0.0f, -outsetRect.y()),
    150                     std::max(0.0f, outsetRect.x() + outsetRect.width() - 1),
    151                     std::max(0.0f, outsetRect.y() + outsetRect.height() - 1),
    152                     std::max(0.0f, -outsetRect.x())
    153                 );
    154                 totalOutsets += outsets;
    155             }
    156             break;
    157         }
    158         case FilterOperation::CUSTOM:
    159         case FilterOperation::VALIDATED_CUSTOM: {
    160             // FIXME: Need to include the filter margins here.
    161             // https://bugs.webkit.org/show_bug.cgi?id=71400
    162             break;
    163         }
    164         default:
    165             break;
    166         }
    167     }
    168     return totalOutsets;
    169 }
    170 
    171 bool FilterOperations::hasFilterThatAffectsOpacity() const
    172 {
    173     for (size_t i = 0; i < m_operations.size(); ++i)
    174         if (m_operations[i]->affectsOpacity())
    175             return true;
    176     return false;
    177 }
    178 
    179 bool FilterOperations::hasFilterThatMovesPixels() const
    180 {
    181     for (size_t i = 0; i < m_operations.size(); ++i)
    182         if (m_operations[i]->movesPixels())
    183             return true;
    184     return false;
    185 }
    186 
    187 } // namespace WebCore
    188 
    189