| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2011 Apple Inc. All rights reserved. | |
| 3 * Copyright (C) 2013 Google Inc. All rights reserved. | |
| 4 * | |
| 5 * Redistribution and use in source and binary forms, with or without | |
| 6 * modification, are permitted provided that the following conditions | |
| 7 * are met: | |
| 8 * 1. Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | |
| 11 * notice, this list of conditions and the following disclaimer in the | |
| 12 * documentation and/or other materials provided with the distribution. | |
| 13 * | |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
| 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 25 */ | |
| 26 | |
| 27 #include "config.h" | |
| 28 | |
| 29 #include "core/layout/FilterEffectRenderer.h" | |
| 30 | |
| 31 #include "core/fetch/DocumentResource.h" | |
| 32 #include "core/fetch/DocumentResourceReference.h" | |
| 33 #include "core/frame/Settings.h" | |
| 34 #include "core/layout/LayoutObject.h" | |
| 35 #include "core/layout/svg/ReferenceFilterBuilder.h" | |
| 36 #include "core/page/Page.h" | |
| 37 #include "core/svg/SVGElement.h" | |
| 38 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h" | |
| 39 #include "platform/FloatConversion.h" | |
| 40 #include "platform/LengthFunctions.h" | |
| 41 #include "platform/graphics/ColorSpace.h" | |
| 42 #include "platform/graphics/UnacceleratedImageBufferSurface.h" | |
| 43 #include "platform/graphics/filters/FEColorMatrix.h" | |
| 44 #include "platform/graphics/filters/FEComponentTransfer.h" | |
| 45 #include "platform/graphics/filters/FEDropShadow.h" | |
| 46 #include "platform/graphics/filters/FEGaussianBlur.h" | |
| 47 #include "platform/graphics/filters/SourceGraphic.h" | |
| 48 #include "wtf/MathExtras.h" | |
| 49 #include <algorithm> | |
| 50 | |
| 51 namespace blink { | |
| 52 | |
| 53 static inline void endMatrixRow(Vector<float>& parameters) | |
| 54 { | |
| 55 parameters.append(0); | |
| 56 parameters.append(0); | |
| 57 } | |
| 58 | |
| 59 static inline void lastMatrixRow(Vector<float>& parameters) | |
| 60 { | |
| 61 parameters.append(0); | |
| 62 parameters.append(0); | |
| 63 parameters.append(0); | |
| 64 parameters.append(1); | |
| 65 parameters.append(0); | |
| 66 } | |
| 67 | |
| 68 FilterEffectRenderer::FilterEffectRenderer() | |
| 69 { | |
| 70 } | |
| 71 | |
| 72 FilterEffectRenderer::~FilterEffectRenderer() | |
| 73 { | |
| 74 } | |
| 75 | |
| 76 DEFINE_TRACE(FilterEffectRenderer) | |
| 77 { | |
| 78 visitor->trace(m_lastEffect); | |
| 79 visitor->trace(m_referenceFilters); | |
| 80 } | |
| 81 | |
| 82 bool FilterEffectRenderer::build(LayoutObject* renderer, const FilterOperations&
operations) | |
| 83 { | |
| 84 const ComputedStyle* style = renderer->style(); | |
| 85 float zoom = style ? style->effectiveZoom() : 1.0f; | |
| 86 | |
| 87 // Create a parent filter for shorthand filters. These have already been sca
led by the CSS code for page zoom, so scale is 1.0 here. | |
| 88 RefPtrWillBeRawPtr<ReferenceFilter> parentFilter = ReferenceFilter::create(1
.0f); | |
| 89 RefPtrWillBeRawPtr<FilterEffect> previousEffect = SourceGraphic::create(pare
ntFilter.get()); | |
| 90 for (size_t i = 0; i < operations.operations().size(); ++i) { | |
| 91 RefPtrWillBeRawPtr<FilterEffect> effect = nullptr; | |
| 92 FilterOperation* filterOperation = operations.operations().at(i).get(); | |
| 93 switch (filterOperation->type()) { | |
| 94 case FilterOperation::REFERENCE: { | |
| 95 RefPtrWillBeRawPtr<ReferenceFilter> referenceFilter = ReferenceFilte
r::create(zoom); | |
| 96 effect = ReferenceFilterBuilder::build(referenceFilter.get(), render
er, previousEffect.get(), toReferenceFilterOperation(filterOperation)); | |
| 97 referenceFilter->setLastEffect(effect); | |
| 98 m_referenceFilters.append(referenceFilter); | |
| 99 break; | |
| 100 } | |
| 101 case FilterOperation::GRAYSCALE: { | |
| 102 Vector<float> inputParameters; | |
| 103 double oneMinusAmount = clampTo(1 - toBasicColorMatrixFilterOperatio
n(filterOperation)->amount(), 0.0, 1.0); | |
| 104 | |
| 105 // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#g
rayscaleEquivalent | |
| 106 // for information on parameters. | |
| 107 | |
| 108 inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneM
inusAmount)); | |
| 109 inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneM
inusAmount)); | |
| 110 inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneM
inusAmount)); | |
| 111 endMatrixRow(inputParameters); | |
| 112 | |
| 113 inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneM
inusAmount)); | |
| 114 inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneM
inusAmount)); | |
| 115 inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneM
inusAmount)); | |
| 116 endMatrixRow(inputParameters); | |
| 117 | |
| 118 inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneM
inusAmount)); | |
| 119 inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneM
inusAmount)); | |
| 120 inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneM
inusAmount)); | |
| 121 endMatrixRow(inputParameters); | |
| 122 | |
| 123 lastMatrixRow(inputParameters); | |
| 124 | |
| 125 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_MATRIX, inputParameters); | |
| 126 break; | |
| 127 } | |
| 128 case FilterOperation::SEPIA: { | |
| 129 Vector<float> inputParameters; | |
| 130 double oneMinusAmount = clampTo(1 - toBasicColorMatrixFilterOperatio
n(filterOperation)->amount(), 0.0, 1.0); | |
| 131 | |
| 132 // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#s
epiaEquivalent | |
| 133 // for information on parameters. | |
| 134 | |
| 135 inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMin
usAmount)); | |
| 136 inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMin
usAmount)); | |
| 137 inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMin
usAmount)); | |
| 138 endMatrixRow(inputParameters); | |
| 139 | |
| 140 inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMin
usAmount)); | |
| 141 inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMin
usAmount)); | |
| 142 inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMin
usAmount)); | |
| 143 endMatrixRow(inputParameters); | |
| 144 | |
| 145 inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMin
usAmount)); | |
| 146 inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMin
usAmount)); | |
| 147 inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMin
usAmount)); | |
| 148 endMatrixRow(inputParameters); | |
| 149 | |
| 150 lastMatrixRow(inputParameters); | |
| 151 | |
| 152 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_MATRIX, inputParameters); | |
| 153 break; | |
| 154 } | |
| 155 case FilterOperation::SATURATE: { | |
| 156 Vector<float> inputParameters; | |
| 157 inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilt
erOperation(filterOperation)->amount())); | |
| 158 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_SATURATE, inputParameters); | |
| 159 break; | |
| 160 } | |
| 161 case FilterOperation::HUE_ROTATE: { | |
| 162 Vector<float> inputParameters; | |
| 163 inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilt
erOperation(filterOperation)->amount())); | |
| 164 effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYP
E_HUEROTATE, inputParameters); | |
| 165 break; | |
| 166 } | |
| 167 case FilterOperation::INVERT: { | |
| 168 BasicComponentTransferFilterOperation* componentTransferOperation =
toBasicComponentTransferFilterOperation(filterOperation); | |
| 169 ComponentTransferFunction transferFunction; | |
| 170 transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; | |
| 171 Vector<float> transferParameters; | |
| 172 transferParameters.append(narrowPrecisionToFloat(componentTransferOp
eration->amount())); | |
| 173 transferParameters.append(narrowPrecisionToFloat(1 - componentTransf
erOperation->amount())); | |
| 174 transferFunction.tableValues = transferParameters; | |
| 175 | |
| 176 ComponentTransferFunction nullFunction; | |
| 177 effect = FEComponentTransfer::create(parentFilter.get(), transferFun
ction, transferFunction, transferFunction, nullFunction); | |
| 178 break; | |
| 179 } | |
| 180 case FilterOperation::OPACITY: { | |
| 181 ComponentTransferFunction transferFunction; | |
| 182 transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; | |
| 183 Vector<float> transferParameters; | |
| 184 transferParameters.append(0); | |
| 185 transferParameters.append(narrowPrecisionToFloat(toBasicComponentTra
nsferFilterOperation(filterOperation)->amount())); | |
| 186 transferFunction.tableValues = transferParameters; | |
| 187 | |
| 188 ComponentTransferFunction nullFunction; | |
| 189 effect = FEComponentTransfer::create(parentFilter.get(), nullFunctio
n, nullFunction, nullFunction, transferFunction); | |
| 190 break; | |
| 191 } | |
| 192 case FilterOperation::BRIGHTNESS: { | |
| 193 ComponentTransferFunction transferFunction; | |
| 194 transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; | |
| 195 transferFunction.slope = narrowPrecisionToFloat(toBasicComponentTran
sferFilterOperation(filterOperation)->amount()); | |
| 196 transferFunction.intercept = 0; | |
| 197 | |
| 198 ComponentTransferFunction nullFunction; | |
| 199 effect = FEComponentTransfer::create(parentFilter.get(), transferFun
ction, transferFunction, transferFunction, nullFunction); | |
| 200 break; | |
| 201 } | |
| 202 case FilterOperation::CONTRAST: { | |
| 203 ComponentTransferFunction transferFunction; | |
| 204 transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; | |
| 205 float amount = narrowPrecisionToFloat(toBasicComponentTransferFilter
Operation(filterOperation)->amount()); | |
| 206 transferFunction.slope = amount; | |
| 207 transferFunction.intercept = -0.5 * amount + 0.5; | |
| 208 | |
| 209 ComponentTransferFunction nullFunction; | |
| 210 effect = FEComponentTransfer::create(parentFilter.get(), transferFun
ction, transferFunction, transferFunction, nullFunction); | |
| 211 break; | |
| 212 } | |
| 213 case FilterOperation::BLUR: { | |
| 214 float stdDeviation = floatValueForLength(toBlurFilterOperation(filte
rOperation)->stdDeviation(), 0); | |
| 215 effect = FEGaussianBlur::create(parentFilter.get(), stdDeviation, st
dDeviation); | |
| 216 break; | |
| 217 } | |
| 218 case FilterOperation::DROP_SHADOW: { | |
| 219 DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterO
peration(filterOperation); | |
| 220 float stdDeviation = dropShadowOperation->stdDeviation(); | |
| 221 float x = dropShadowOperation->x(); | |
| 222 float y = dropShadowOperation->y(); | |
| 223 effect = FEDropShadow::create(parentFilter.get(), stdDeviation, stdD
eviation, x, y, dropShadowOperation->color(), 1); | |
| 224 break; | |
| 225 } | |
| 226 default: | |
| 227 break; | |
| 228 } | |
| 229 | |
| 230 if (effect) { | |
| 231 if (filterOperation->type() != FilterOperation::REFERENCE) { | |
| 232 // Unlike SVG, filters applied here should not clip to their pri
mitive subregions. | |
| 233 effect->setClipsToBounds(false); | |
| 234 effect->setOperatingColorSpace(ColorSpaceDeviceRGB); | |
| 235 effect->inputEffects().append(previousEffect); | |
| 236 } | |
| 237 previousEffect = effect.release(); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 m_referenceFilters.append(parentFilter); | |
| 242 | |
| 243 // We need to keep the old effects alive until this point, so that SVG refer
ence filters | |
| 244 // can share cached resources across frames. | |
| 245 m_lastEffect = previousEffect; | |
| 246 | |
| 247 // If we didn't make any effects, tell our caller we are not valid | |
| 248 if (!m_lastEffect.get()) | |
| 249 return false; | |
| 250 | |
| 251 return true; | |
| 252 } | |
| 253 | |
| 254 void FilterEffectRenderer::clearIntermediateResults() | |
| 255 { | |
| 256 if (m_lastEffect.get()) | |
| 257 m_lastEffect->clearResultsRecursive(); | |
| 258 } | |
| 259 | |
| 260 | |
| 261 } // namespace blink | |
| 262 | |
| OLD | NEW |