diff --git a/src/Svg.Model/SvgFilterContext.cs b/src/Svg.Model/SvgFilterContext.cs index 6635358f4c..f1c18e6268 100644 --- a/src/Svg.Model/SvgFilterContext.cs +++ b/src/Svg.Model/SvgFilterContext.cs @@ -1276,12 +1276,6 @@ private void Apply(byte[] values, SvgComponentTransferFunction transferFunction) { TransformsService.GetOptionalNumbers(svgConvolveMatrix.Order, 3f, 3f, out var orderX, out var orderY); - if (_primitiveUnits == SvgCoordinateUnits.ObjectBoundingBox) - { - orderX *= _skBounds.Width; - orderY *= _skBounds.Height; - } - if (orderX <= 0f || orderY <= 0f) { return default; @@ -1323,7 +1317,19 @@ private void Apply(byte[] values, SvgComponentTransferFunction transferFunction) var gain = 1f / divisor; var bias = svgConvolveMatrix.Bias * 255f; - var kernelOffset = new SKPointI(svgConvolveMatrix.TargetX, svgConvolveMatrix.TargetY); + var targetX = svgConvolveMatrix.TargetX; + var targetY = svgConvolveMatrix.TargetY; + if (!svgConvolveMatrix.ContainsAttribute("targetX")) + { + targetX = (int)Math.Floor(orderX / 2f); + } + if (!svgConvolveMatrix.ContainsAttribute("targetY")) + { + targetY = (int)Math.Floor(orderY / 2f); + } + targetX = Math.Max(0, Math.Min(targetX, (int)orderX - 1)); + targetY = Math.Max(0, Math.Min(targetY, (int)orderY - 1)); + var kernelOffset = new SKPointI(targetX, targetY); var tileMode = svgConvolveMatrix.EdgeMode switch { SvgEdgeMode.Duplicate => SKShaderTileMode.Clamp, diff --git a/tests/Svg.Skia.UnitTests/resvgTests.cs b/tests/Svg.Skia.UnitTests/resvgTests.cs index fa672cd62f..a64ad5b12f 100644 --- a/tests/Svg.Skia.UnitTests/resvgTests.cs +++ b/tests/Svg.Skia.UnitTests/resvgTests.cs @@ -867,13 +867,13 @@ private void TestImpl(string name, double errorThreshold, float scaleX = 1.5f, f public void e_feComposite(string name, double errorThreshold) => TestImpl(name, errorThreshold); [Theory] - [InlineData("e-feConvolveMatrix-001", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-002", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-003", 0.022, Skip = "TODO")] + [InlineData("e-feConvolveMatrix-001", 0.022)] + [InlineData("e-feConvolveMatrix-002", 0.022)] + [InlineData("e-feConvolveMatrix-003", 0.022)] [InlineData("e-feConvolveMatrix-004", 0.022)] [InlineData("e-feConvolveMatrix-005", 0.022)] [InlineData("e-feConvolveMatrix-006", 0.022)] - [InlineData("e-feConvolveMatrix-007", 0.022, Skip = "TODO")] + [InlineData("e-feConvolveMatrix-007", 0.022)] [InlineData("e-feConvolveMatrix-008", 0.022)] [InlineData("e-feConvolveMatrix-009", 0.022)] [InlineData("e-feConvolveMatrix-010", 0.022)] @@ -884,14 +884,14 @@ private void TestImpl(string name, double errorThreshold, float scaleX = 1.5f, f [InlineData("e-feConvolveMatrix-015", 0.022, Skip = "TODO")] [InlineData("e-feConvolveMatrix-016", 0.022, Skip = "TODO")] [InlineData("e-feConvolveMatrix-017", 0.022)] - [InlineData("e-feConvolveMatrix-018", 0.022)] - [InlineData("e-feConvolveMatrix-019", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-020", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-021", 0.022)] - [InlineData("e-feConvolveMatrix-022", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-023", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-024", 0.022, Skip = "TODO")] - [InlineData("e-feConvolveMatrix-025", 0.022, Skip = "TODO")] + [InlineData("e-feConvolveMatrix-018", 0.022, Skip = "TODO")] + [InlineData("e-feConvolveMatrix-019", 0.022)] + [InlineData("e-feConvolveMatrix-020", 0.022)] + [InlineData("e-feConvolveMatrix-021", 0.022, Skip = "TODO")] + [InlineData("e-feConvolveMatrix-022", 0.022)] + [InlineData("e-feConvolveMatrix-023", 0.022)] + [InlineData("e-feConvolveMatrix-024", 0.022)] + [InlineData("e-feConvolveMatrix-025", 0.022)] public void e_feConvolveMatrix(string name, double errorThreshold) => TestImpl(name, errorThreshold); [Theory]