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 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 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 "FilterOperations.h" 28 29#include "FEGaussianBlur.h" 30#include "IntSize.h" 31#include "LengthFunctions.h" 32 33#if ENABLE(CSS_FILTERS) 34 35namespace WebCore { 36 37static inline IntSize outsetSizeForBlur(float stdDeviation) 38{ 39 IntSize kernelSize = FEGaussianBlur::calculateUnscaledKernelSize(FloatPoint(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 * kernelSize.width() * 0.5f); 44 outset.setHeight(3 * kernelSize.height() * 0.5f); 45 46 return outset; 47} 48 49FilterOperations::FilterOperations() 50{ 51} 52 53FilterOperations& FilterOperations::operator=(const FilterOperations& other) 54{ 55 m_operations = other.m_operations; 56 return *this; 57} 58 59bool 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 73bool 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 88bool FilterOperations::hasReferenceFilter() const 89{ 90 for (size_t i = 0; i < m_operations.size(); ++i) { 91 if (m_operations.at(i)->type() == FilterOperation::REFERENCE) 92 return true; 93 } 94 return false; 95} 96 97bool FilterOperations::hasOutsets() const 98{ 99 for (size_t i = 0; i < m_operations.size(); ++i) { 100 FilterOperation::OperationType operationType = m_operations.at(i).get()->type(); 101 if (operationType == FilterOperation::BLUR || operationType == FilterOperation::DROP_SHADOW) 102 return true; 103 } 104 return false; 105} 106 107FilterOutsets FilterOperations::outsets() const 108{ 109 FilterOutsets totalOutsets; 110 for (size_t i = 0; i < m_operations.size(); ++i) { 111 const FilterOperation* filterOperation = m_operations.at(i).get(); 112 switch (filterOperation->type()) { 113 case FilterOperation::BLUR: { 114 const BlurFilterOperation* blurOperation = toBlurFilterOperation(filterOperation); 115 float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0); 116 IntSize outsetSize = outsetSizeForBlur(stdDeviation); 117 FilterOutsets outsets(outsetSize.height(), outsetSize.width(), outsetSize.height(), outsetSize.width()); 118 totalOutsets += outsets; 119 break; 120 } 121 case FilterOperation::DROP_SHADOW: { 122 const DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterOperation(filterOperation); 123 IntSize outsetSize = outsetSizeForBlur(dropShadowOperation->stdDeviation()); 124 FilterOutsets outsets( 125 std::max(0, outsetSize.height() - dropShadowOperation->y()), 126 std::max(0, outsetSize.width() + dropShadowOperation->x()), 127 std::max(0, outsetSize.height() + dropShadowOperation->y()), 128 std::max(0, outsetSize.width() - dropShadowOperation->x()) 129 ); 130 totalOutsets += outsets; 131 break; 132 } 133 default: 134 break; 135 } 136 } 137 return totalOutsets; 138} 139 140bool FilterOperations::hasFilterThatAffectsOpacity() const 141{ 142 for (size_t i = 0; i < m_operations.size(); ++i) 143 if (m_operations[i]->affectsOpacity()) 144 return true; 145 return false; 146} 147 148bool FilterOperations::hasFilterThatMovesPixels() const 149{ 150 for (size_t i = 0; i < m_operations.size(); ++i) 151 if (m_operations[i]->movesPixels()) 152 return true; 153 return false; 154} 155 156} // namespace WebCore 157 158#endif // ENABLE(CSS_FILTERS) 159