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