diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /layout/svg/nsCSSFilterInstance.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'layout/svg/nsCSSFilterInstance.cpp')
-rw-r--r-- | layout/svg/nsCSSFilterInstance.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/layout/svg/nsCSSFilterInstance.cpp b/layout/svg/nsCSSFilterInstance.cpp new file mode 100644 index 000000000..79bf83b94 --- /dev/null +++ b/layout/svg/nsCSSFilterInstance.cpp @@ -0,0 +1,421 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Main header first: +#include "nsCSSFilterInstance.h" + +// Keep others in (case-insensitive) order: +#include "gfx2DGlue.h" +#include "gfxUtils.h" +#include "nsIFrame.h" +#include "nsStyleStruct.h" +#include "nsTArray.h" + +using namespace mozilla; +using namespace mozilla::gfx; + +static float ClampFactor(float aFactor) +{ + if (aFactor > 1) { + return 1; + } else if (aFactor < 0) { + NS_NOTREACHED("A negative value should not have been parsed."); + return 0; + } + + return aFactor; +} + +nsCSSFilterInstance::nsCSSFilterInstance(const nsStyleFilter& aFilter, + nscolor aShadowFallbackColor, + const nsIntRect& aTargetBoundsInFilterSpace, + const gfxMatrix& aFrameSpaceInCSSPxToFilterSpaceTransform) + : mFilter(aFilter) + , mShadowFallbackColor(aShadowFallbackColor) + , mTargetBoundsInFilterSpace(aTargetBoundsInFilterSpace) + , mFrameSpaceInCSSPxToFilterSpaceTransform(aFrameSpaceInCSSPxToFilterSpaceTransform) +{ +} + +nsresult +nsCSSFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, + bool aInputIsTainted) +{ + FilterPrimitiveDescription descr; + nsresult result; + + switch(mFilter.GetType()) { + case NS_STYLE_FILTER_BLUR: + descr = CreatePrimitiveDescription(PrimitiveType::GaussianBlur, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForBlur(descr); + break; + case NS_STYLE_FILTER_BRIGHTNESS: + descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForBrightness(descr); + break; + case NS_STYLE_FILTER_CONTRAST: + descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForContrast(descr); + break; + case NS_STYLE_FILTER_DROP_SHADOW: + descr = CreatePrimitiveDescription(PrimitiveType::DropShadow, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForDropShadow(descr); + break; + case NS_STYLE_FILTER_GRAYSCALE: + descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForGrayscale(descr); + break; + case NS_STYLE_FILTER_HUE_ROTATE: + descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForHueRotate(descr); + break; + case NS_STYLE_FILTER_INVERT: + descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForInvert(descr); + break; + case NS_STYLE_FILTER_OPACITY: + descr = CreatePrimitiveDescription(PrimitiveType::ComponentTransfer, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForOpacity(descr); + break; + case NS_STYLE_FILTER_SATURATE: + descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForSaturate(descr); + break; + case NS_STYLE_FILTER_SEPIA: + descr = CreatePrimitiveDescription(PrimitiveType::ColorMatrix, + aPrimitiveDescrs, + aInputIsTainted); + result = SetAttributesForSepia(descr); + break; + default: + NS_NOTREACHED("not a valid CSS filter type"); + return NS_ERROR_FAILURE; + } + + if (NS_FAILED(result)) { + return result; + } + + // Compute the primitive's bounds now that we've determined its attributes. + // Some attributes like blur radius can influence the bounds. + SetBounds(descr, aPrimitiveDescrs); + + // Add this primitive to the filter chain. + aPrimitiveDescrs.AppendElement(descr); + return NS_OK; +} + +FilterPrimitiveDescription +nsCSSFilterInstance::CreatePrimitiveDescription(PrimitiveType aType, + const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, + bool aInputIsTainted) { + FilterPrimitiveDescription descr(aType); + int32_t inputIndex = GetLastResultIndex(aPrimitiveDescrs); + descr.SetInputPrimitive(0, inputIndex); + descr.SetIsTainted(inputIndex < 0 ? aInputIsTainted : aPrimitiveDescrs[inputIndex].IsTainted()); + descr.SetInputColorSpace(0, ColorSpace::SRGB); + descr.SetOutputColorSpace(ColorSpace::SRGB); + return descr; +} + +nsresult +nsCSSFilterInstance::SetAttributesForBlur(FilterPrimitiveDescription& aDescr) +{ + const nsStyleCoord& radiusInFrameSpace = mFilter.GetFilterParameter(); + if (radiusInFrameSpace.GetUnit() != eStyleUnit_Coord) { + NS_NOTREACHED("unexpected unit"); + return NS_ERROR_FAILURE; + } + + Size radiusInFilterSpace = BlurRadiusToFilterSpace(radiusInFrameSpace.GetCoordValue()); + aDescr.Attributes().Set(eGaussianBlurStdDeviation, radiusInFilterSpace); + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForBrightness(FilterPrimitiveDescription& aDescr) +{ + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = styleValue.GetFactorOrPercentValue(); + + // Set transfer functions for RGB. + AttributeMap brightnessAttrs; + brightnessAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_LINEAR); + brightnessAttrs.Set(eComponentTransferFunctionSlope, value); + brightnessAttrs.Set(eComponentTransferFunctionIntercept, 0.0f); + aDescr.Attributes().Set(eComponentTransferFunctionR, brightnessAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionG, brightnessAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionB, brightnessAttrs); + + // Set identity transfer function for A. + AttributeMap identityAttrs; + identityAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY); + aDescr.Attributes().Set(eComponentTransferFunctionA, identityAttrs); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForContrast(FilterPrimitiveDescription& aDescr) +{ + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = styleValue.GetFactorOrPercentValue(); + float intercept = -(0.5 * value) + 0.5; + + // Set transfer functions for RGB. + AttributeMap contrastAttrs; + contrastAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_LINEAR); + contrastAttrs.Set(eComponentTransferFunctionSlope, value); + contrastAttrs.Set(eComponentTransferFunctionIntercept, intercept); + aDescr.Attributes().Set(eComponentTransferFunctionR, contrastAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionG, contrastAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionB, contrastAttrs); + + // Set identity transfer function for A. + AttributeMap identityAttrs; + identityAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY); + aDescr.Attributes().Set(eComponentTransferFunctionA, identityAttrs); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForDropShadow(FilterPrimitiveDescription& aDescr) +{ + nsCSSShadowArray* shadows = mFilter.GetDropShadow(); + if (!shadows || shadows->Length() != 1) { + NS_NOTREACHED("Exactly one drop shadow should have been parsed."); + return NS_ERROR_FAILURE; + } + + nsCSSShadowItem* shadow = shadows->ShadowAt(0); + + // Set drop shadow blur radius. + Size radiusInFilterSpace = BlurRadiusToFilterSpace(shadow->mRadius); + aDescr.Attributes().Set(eDropShadowStdDeviation, radiusInFilterSpace); + + // Set offset. + IntPoint offsetInFilterSpace = OffsetToFilterSpace(shadow->mXOffset, shadow->mYOffset); + aDescr.Attributes().Set(eDropShadowOffset, offsetInFilterSpace); + + // Set color. If unspecified, use the CSS color property. + nscolor shadowColor = shadow->mHasColor ? shadow->mColor : mShadowFallbackColor; + aDescr.Attributes().Set(eDropShadowColor, ToAttributeColor(shadowColor)); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForGrayscale(FilterPrimitiveDescription& aDescr) +{ + // Set color matrix type. + aDescr.Attributes().Set(eColorMatrixType, (uint32_t)SVG_FECOLORMATRIX_TYPE_SATURATE); + + // Set color matrix values. + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = 1 - ClampFactor(styleValue.GetFactorOrPercentValue()); + aDescr.Attributes().Set(eColorMatrixValues, &value, 1); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForHueRotate(FilterPrimitiveDescription& aDescr) +{ + // Set color matrix type. + aDescr.Attributes().Set(eColorMatrixType, (uint32_t)SVG_FECOLORMATRIX_TYPE_HUE_ROTATE); + + // Set color matrix values. + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = styleValue.GetAngleValueInDegrees(); + aDescr.Attributes().Set(eColorMatrixValues, &value, 1); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForInvert(FilterPrimitiveDescription& aDescr) +{ + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = ClampFactor(styleValue.GetFactorOrPercentValue()); + + // Set transfer functions for RGB. + AttributeMap invertAttrs; + float invertTableValues[2]; + invertTableValues[0] = value; + invertTableValues[1] = 1 - value; + invertAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_TABLE); + invertAttrs.Set(eComponentTransferFunctionTableValues, invertTableValues, 2); + aDescr.Attributes().Set(eComponentTransferFunctionR, invertAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionG, invertAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionB, invertAttrs); + + // Set identity transfer function for A. + AttributeMap identityAttrs; + identityAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY); + aDescr.Attributes().Set(eComponentTransferFunctionA, identityAttrs); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForOpacity(FilterPrimitiveDescription& aDescr) +{ + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = ClampFactor(styleValue.GetFactorOrPercentValue()); + + // Set identity transfer functions for RGB. + AttributeMap identityAttrs; + identityAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY); + aDescr.Attributes().Set(eComponentTransferFunctionR, identityAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionG, identityAttrs); + aDescr.Attributes().Set(eComponentTransferFunctionB, identityAttrs); + + // Set transfer function for A. + AttributeMap opacityAttrs; + float opacityTableValues[2]; + opacityTableValues[0] = 0; + opacityTableValues[1] = value; + opacityAttrs.Set(eComponentTransferFunctionType, + (uint32_t)SVG_FECOMPONENTTRANSFER_TYPE_TABLE); + opacityAttrs.Set(eComponentTransferFunctionTableValues, opacityTableValues, 2); + aDescr.Attributes().Set(eComponentTransferFunctionA, opacityAttrs); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForSaturate(FilterPrimitiveDescription& aDescr) +{ + // Set color matrix type. + aDescr.Attributes().Set(eColorMatrixType, (uint32_t)SVG_FECOLORMATRIX_TYPE_SATURATE); + + // Set color matrix values. + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = styleValue.GetFactorOrPercentValue(); + aDescr.Attributes().Set(eColorMatrixValues, &value, 1); + + return NS_OK; +} + +nsresult +nsCSSFilterInstance::SetAttributesForSepia(FilterPrimitiveDescription& aDescr) +{ + // Set color matrix type. + aDescr.Attributes().Set(eColorMatrixType, (uint32_t)SVG_FECOLORMATRIX_TYPE_SEPIA); + + // Set color matrix values. + const nsStyleCoord& styleValue = mFilter.GetFilterParameter(); + float value = ClampFactor(styleValue.GetFactorOrPercentValue()); + aDescr.Attributes().Set(eColorMatrixValues, &value, 1); + + return NS_OK; +} + +Size +nsCSSFilterInstance::BlurRadiusToFilterSpace(nscoord aRadiusInFrameSpace) +{ + float radiusInFrameSpaceInCSSPx = + nsPresContext::AppUnitsToFloatCSSPixels(aRadiusInFrameSpace); + + // Convert the radius to filter space. + Size radiusInFilterSpace(radiusInFrameSpaceInCSSPx, + radiusInFrameSpaceInCSSPx); + gfxSize frameSpaceInCSSPxToFilterSpaceScale = + mFrameSpaceInCSSPxToFilterSpaceTransform.ScaleFactors(true); + radiusInFilterSpace.Scale(frameSpaceInCSSPxToFilterSpaceScale.width, + frameSpaceInCSSPxToFilterSpaceScale.height); + + // Check the radius limits. + if (radiusInFilterSpace.width < 0 || radiusInFilterSpace.height < 0) { + NS_NOTREACHED("we shouldn't have parsed a negative radius in the style"); + return Size(); + } + Float maxStdDeviation = (Float)kMaxStdDeviation; + radiusInFilterSpace.width = std::min(radiusInFilterSpace.width, maxStdDeviation); + radiusInFilterSpace.height = std::min(radiusInFilterSpace.height, maxStdDeviation); + + return radiusInFilterSpace; +} + +IntPoint +nsCSSFilterInstance::OffsetToFilterSpace(nscoord aXOffsetInFrameSpace, + nscoord aYOffsetInFrameSpace) +{ + gfxPoint offsetInFilterSpace(nsPresContext::AppUnitsToFloatCSSPixels(aXOffsetInFrameSpace), + nsPresContext::AppUnitsToFloatCSSPixels(aYOffsetInFrameSpace)); + + // Convert the radius to filter space. + gfxSize frameSpaceInCSSPxToFilterSpaceScale = + mFrameSpaceInCSSPxToFilterSpaceTransform.ScaleFactors(true); + offsetInFilterSpace.x *= frameSpaceInCSSPxToFilterSpaceScale.width; + offsetInFilterSpace.y *= frameSpaceInCSSPxToFilterSpaceScale.height; + + return IntPoint(int32_t(offsetInFilterSpace.x), int32_t(offsetInFilterSpace.y)); +} + +Color +nsCSSFilterInstance::ToAttributeColor(nscolor aColor) +{ + return Color( + NS_GET_R(aColor) / 255.0, + NS_GET_G(aColor) / 255.0, + NS_GET_B(aColor) / 255.0, + NS_GET_A(aColor) / 255.0 + ); +} + +int32_t +nsCSSFilterInstance::GetLastResultIndex(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs) +{ + uint32_t numPrimitiveDescrs = aPrimitiveDescrs.Length(); + return !numPrimitiveDescrs ? + FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic : + numPrimitiveDescrs - 1; +} + +void +nsCSSFilterInstance::SetBounds(FilterPrimitiveDescription& aDescr, + const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs) +{ + int32_t inputIndex = GetLastResultIndex(aPrimitiveDescrs); + nsIntRect inputBounds = (inputIndex < 0) ? + mTargetBoundsInFilterSpace : aPrimitiveDescrs[inputIndex].PrimitiveSubregion(); + + nsTArray<nsIntRegion> inputExtents; + inputExtents.AppendElement(inputBounds); + + nsIntRegion outputExtents = + FilterSupport::PostFilterExtentsForPrimitive(aDescr, inputExtents); + IntRect outputBounds = outputExtents.GetBounds(); + + aDescr.SetPrimitiveSubregion(outputBounds); + aDescr.SetFilterSpaceBounds(outputBounds); +} |