FilterOutsets FilterOperations::outsets() const { FilterOutsets totalOutsets; for (size_t i = 0; i < m_operations.size(); ++i) { FilterOperation* filterOperation = m_operations.at(i).get(); switch (filterOperation->type()) { case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = toBlurFilterOperation(filterOperation); float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0); IntSize outsetSize = outsetSizeForBlur(stdDeviation); FilterOutsets outsets(outsetSize.height(), outsetSize.width(), outsetSize.height(), outsetSize.width()); totalOutsets += outsets; break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterOperation(filterOperation); IntSize outsetSize = outsetSizeForBlur(dropShadowOperation->stdDeviation()); FilterOutsets outsets( std::max(0, outsetSize.height() - dropShadowOperation->y()), std::max(0, outsetSize.width() + dropShadowOperation->x()), std::max(0, outsetSize.height() + dropShadowOperation->y()), std::max(0, outsetSize.width() - dropShadowOperation->x()) ); totalOutsets += outsets; break; } case FilterOperation::REFERENCE: { ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation); if (referenceOperation->filter() && referenceOperation->filter()->lastEffect()) { FloatRect outsetRect(0, 0, 1, 1); outsetRect = referenceOperation->filter()->lastEffect()->mapRectRecursive(outsetRect); FilterOutsets outsets( std::max(0.0f, -outsetRect.y()), std::max(0.0f, outsetRect.x() + outsetRect.width() - 1), std::max(0.0f, outsetRect.y() + outsetRect.height() - 1), std::max(0.0f, -outsetRect.x()) ); totalOutsets += outsets; } break; } default: break; } } return totalOutsets; }
void FilterOperations::getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const { top = 0; right = 0; bottom = 0; left = 0; for (size_t i = 0; i < m_operations.size(); ++i) { FilterOperation* filterOperation = m_operations.at(i).get(); switch (filterOperation->getOperationType()) { case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation); float stdDeviation = blurOperation->stdDeviation().calcFloatValue(0); IntSize outset = outsetSizeForBlur(stdDeviation); top += outset.height(); right += outset.width(); bottom += outset.height(); left += outset.width(); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation); IntSize outset = outsetSizeForBlur(dropShadowOperation->stdDeviation()); top += outset.height() - dropShadowOperation->y(); right += outset.width() + dropShadowOperation->x(); bottom += outset.height() + dropShadowOperation->y(); left += outset.width() - dropShadowOperation->x(); break; } #if ENABLE(CSS_SHADERS) case FilterOperation::CUSTOM: { // Need to include the filter margins here. break; } #endif default: break; } } }
void FilterEffectRenderer::build(Document* document, const FilterOperations& operations) { #if !ENABLE(CSS_SHADERS) || !ENABLE(WEBGL) UNUSED_PARAM(document); #else CustomFilterProgramList cachedCustomFilterPrograms; #endif m_effects.clear(); RefPtr<FilterEffect> previousEffect; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->getOperationType()) { case FilterOperation::REFERENCE: { // FIXME: Not yet implemented. // https://bugs.webkit.org/show_bug.cgi?id=72443 break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = 1; transferFunction.intercept = narrowPrecisionToFloat(componentTransferOperation->amount()); ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation); float stdDeviation = blurOperation->stdDeviation().calcFloatValue(0); effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation); effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(), dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1); break; } #if ENABLE(CSS_SHADERS) case FilterOperation::CUSTOM: { #if ENABLE(WEBGL) if (!isCSSCustomFilterEnabled(document)) continue; CustomFilterOperation* customFilterOperation = static_cast<CustomFilterOperation*>(filterOperation); RefPtr<CustomFilterProgram> program = customFilterOperation->program(); cachedCustomFilterPrograms.append(program); program->addClient(this); if (program->isLoaded()) { effect = FECustomFilter::create(this, document, program, customFilterOperation->parameters(), customFilterOperation->meshRows(), customFilterOperation->meshColumns(), customFilterOperation->meshBoxType(), customFilterOperation->meshType()); } #endif break; } #endif default: break; } if (effect) { // Unlike SVG, filters applied here should not clip to their primitive subregions. effect->setClipsToBounds(false); if (previousEffect) effect->inputEffects().append(previousEffect); m_effects.append(effect); previousEffect = effect.release(); } } // If we didn't make a real filter, create a null-op (FEMerge with one input). if (!previousEffect) m_effects.append(FEMerge::create(this)); m_effects.first()->inputEffects().append(m_sourceGraphic); setMaxEffectRects(m_sourceDrawingRegion); #if ENABLE(CSS_SHADERS) && ENABLE(WEBGL) removeCustomFilterClients(); m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms); #endif }
bool FilterEffectRenderer::build(Document* document, const FilterOperations& operations) { #if !ENABLE(CSS_SHADERS) || !USE(3D_GRAPHICS) UNUSED_PARAM(document); #endif #if ENABLE(CSS_SHADERS) m_hasCustomShaderFilter = false; #endif m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels(); if (m_hasFilterThatMovesPixels) operations.getOutsets(m_topOutset, m_rightOutset, m_bottomOutset, m_leftOutset); // Keep the old effects on the stack until we've created the new effects. // New FECustomFilters can reuse cached resources from old FECustomFilters. FilterEffectList oldEffects; m_effects.swap(oldEffects); RefPtr<FilterEffect> previousEffect = m_sourceGraphic; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->getOperationType()) { case FilterOperation::REFERENCE: { ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation); effect = buildReferenceFilter(document, previousEffect, referenceOperation); referenceOperation->setFilterEffect(effect); break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = 1; transferFunction.intercept = narrowPrecisionToFloat(componentTransferOperation->amount()); ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation); float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0); effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation); effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(), dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1); break; } #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) case FilterOperation::CUSTOM: // CUSTOM operations are always converted to VALIDATED_CUSTOM before getting here. // The conversion happens in RenderLayer::computeFilterOperations. ASSERT_NOT_REACHED(); break; case FilterOperation::VALIDATED_CUSTOM: { ValidatedCustomFilterOperation* customFilterOperation = static_cast<ValidatedCustomFilterOperation*>(filterOperation); effect = createCustomFilterEffect(this, document, customFilterOperation); if (effect) m_hasCustomShaderFilter = true; break; } #endif default: break; } if (effect) { // Unlike SVG, filters applied here should not clip to their primitive subregions. effect->setClipsToBounds(false); effect->setColorSpace(ColorSpaceDeviceRGB); if (filterOperation->getOperationType() != FilterOperation::REFERENCE) { effect->inputEffects().append(previousEffect); m_effects.append(effect); } previousEffect = effect.release(); } } // If we didn't make any effects, tell our caller we are not valid if (!m_effects.size()) return false; setMaxEffectRects(m_sourceDrawingRegion); return true; }
bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& operations) { m_hasCustomShaderFilter = false; m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels(); // Inverse zoom the pre-zoomed CSS shorthand filters, so that they are in the same zoom as the unzoomed reference filters. const RenderStyle* style = renderer->style(); // FIXME: The effects now contain high dpi information, but the software path doesn't (yet) scale its backing. // When the proper dpi dependant backing size is allocated, we should remove deviceScaleFactor(...) here. float invZoom = 1.0f / ((style ? style->effectiveZoom() : 1.0f) * deviceScaleFactor(renderer->frame())); RefPtr<FilterEffect> previousEffect = m_sourceGraphic; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->getOperationType()) { case FilterOperation::REFERENCE: { ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation); effect = ReferenceFilterBuilder::build(this, renderer, previousEffect.get(), referenceOperation); break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.intercept = 0; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation); float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0) * invZoom; effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation); float stdDeviation = dropShadowOperation->stdDeviation() * invZoom; float x = dropShadowOperation->x() * invZoom; float y = dropShadowOperation->y() * invZoom; effect = FEDropShadow::create(this, stdDeviation, stdDeviation, x, y, dropShadowOperation->color(), 1); break; } case FilterOperation::CUSTOM: // CUSTOM operations are always converted to VALIDATED_CUSTOM before getting here. // The conversion happens in RenderLayer::computeFilterOperations. ASSERT_NOT_REACHED(); break; case FilterOperation::VALIDATED_CUSTOM: { ValidatedCustomFilterOperation* customFilterOperation = static_cast<ValidatedCustomFilterOperation*>(filterOperation); Document* document = renderer ? &renderer->document() : 0; effect = createCustomFilterEffect(this, document, customFilterOperation); if (effect) m_hasCustomShaderFilter = true; break; } default: break; } if (effect) { if (filterOperation->getOperationType() != FilterOperation::REFERENCE) { // Unlike SVG, filters applied here should not clip to their primitive subregions. effect->setClipsToBounds(false); effect->setOperatingColorSpace(ColorSpaceDeviceRGB); effect->inputEffects().append(previousEffect); } previousEffect = effect.release(); } } // We need to keep the old effects alive until this point, so that filters like FECustomFilter // can share cached resources across frames. m_lastEffect = previousEffect; // If we didn't make any effects, tell our caller we are not valid if (!m_lastEffect.get()) return false; return true; }
bool FilterEffectRenderer::build(RenderElement* renderer, const FilterOperations& operations, FilterConsumer consumer) { m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels(); if (m_hasFilterThatMovesPixels) m_outsets = operations.outsets(); m_effects.clear(); RefPtr<FilterEffect> previousEffect = m_sourceGraphic; for (size_t i = 0; i < operations.operations().size(); ++i) { RefPtr<FilterEffect> effect; FilterOperation* filterOperation = operations.operations().at(i).get(); switch (filterOperation->type()) { case FilterOperation::REFERENCE: { ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation); effect = buildReferenceFilter(renderer, previousEffect, referenceOperation); referenceOperation->setFilterEffect(effect); break; } case FilterOperation::GRAYSCALE: { BasicColorMatrixFilterOperation* colorMatrixOperation = toBasicColorMatrixFilterOperation(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SEPIA: { BasicColorMatrixFilterOperation* colorMatrixOperation = toBasicColorMatrixFilterOperation(filterOperation); Vector<float> inputParameters; double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0); // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent // for information on parameters. inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount)); endMatrixRow(inputParameters); inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount)); inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount)); endMatrixRow(inputParameters); lastMatrixRow(inputParameters); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); break; } case FilterOperation::SATURATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = toBasicColorMatrixFilterOperation(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); break; } case FilterOperation::HUE_ROTATE: { BasicColorMatrixFilterOperation* colorMatrixOperation = toBasicColorMatrixFilterOperation(filterOperation); Vector<float> inputParameters; inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount())); effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* componentTransferOperation = toBasicComponentTransferFilterOperation(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::OPACITY: { BasicComponentTransferFilterOperation* componentTransferOperation = toBasicComponentTransferFilterOperation(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transferParameters; transferParameters.append(0); transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount())); transferFunction.tableValues = transferParameters; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); break; } case FilterOperation::BRIGHTNESS: { BasicComponentTransferFilterOperation* componentTransferOperation = toBasicComponentTransferFilterOperation(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.intercept = 0; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::CONTRAST: { BasicComponentTransferFilterOperation* componentTransferOperation = toBasicComponentTransferFilterOperation(filterOperation); ComponentTransferFunction transferFunction; transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = narrowPrecisionToFloat(componentTransferOperation->amount()); transferFunction.slope = amount; transferFunction.intercept = -0.5 * amount + 0.5; ComponentTransferFunction nullFunction; effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); break; } case FilterOperation::BLUR: { BlurFilterOperation* blurOperation = toBlurFilterOperation(filterOperation); float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0); effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation, consumer == FilterProperty ? EDGEMODE_NONE : EDGEMODE_DUPLICATE); break; } case FilterOperation::DROP_SHADOW: { DropShadowFilterOperation* dropShadowOperation = toDropShadowFilterOperation(filterOperation); effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(), dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1); break; } default: break; } if (effect) { // Unlike SVG Filters and CSSFilterImages, filter functions on the filter // property applied here should not clip to their primitive subregions. effect->setClipsToBounds(consumer == FilterFunction); effect->setOperatingColorSpace(ColorSpaceDeviceRGB); if (filterOperation->type() != FilterOperation::REFERENCE) { effect->inputEffects().append(previousEffect); m_effects.append(effect); } previousEffect = effect.release(); } } // If we didn't make any effects, tell our caller we are not valid if (!m_effects.size()) return false; setMaxEffectRects(m_sourceDrawingRegion); return true; }