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