diff --git a/CHANGELOG.md b/CHANGELOG.md
index 54fd9e34..394cc067 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,9 @@
- (pro) Fix BlurHash generation when the `IMGPROXY_USE_LINEAR_COLORSPACE` config is set to `true`.
- (pro) Fix detection of PDF files with a header offset.
+### Removed
+- Remove the `IMGPROXY_SVG_FIX_UNSUPPORTED` config. The problem it was solving is now fixed in librsvg.
+
## [3.28.0] - 2025-03-31
### Added
- Add [IMGPROXY_BASE64_URL_INCLUDES_FILENAME](https://docs.imgproxy.net/latest/configuration/options#IMGPROXY_BASE64_URL_INCLUDES_FILENAME) config.
diff --git a/config/config.go b/config/config.go
index d3fa55e1..e1528388 100644
--- a/config/config.go
+++ b/config/config.go
@@ -65,7 +65,6 @@ var (
AutoRotate bool
EnforceThumbnail bool
ReturnAttachment bool
- SvgFixUnsupported bool
AutoWebp bool
EnforceWebp bool
@@ -276,7 +275,6 @@ func Reset() {
AutoRotate = true
EnforceThumbnail = false
ReturnAttachment = false
- SvgFixUnsupported = false
AutoWebp = false
EnforceWebp = false
@@ -508,7 +506,6 @@ func Configure() error {
configurators.Bool(&AutoRotate, "IMGPROXY_AUTO_ROTATE")
configurators.Bool(&EnforceThumbnail, "IMGPROXY_ENFORCE_THUMBNAIL")
configurators.Bool(&ReturnAttachment, "IMGPROXY_RETURN_ATTACHMENT")
- configurators.Bool(&SvgFixUnsupported, "IMGPROXY_SVG_FIX_UNSUPPORTED")
if _, ok := os.LookupEnv("IMGPROXY_ENABLE_WEBP_DETECTION"); ok {
log.Warning("IMGPROXY_ENABLE_WEBP_DETECTION is deprecated, use IMGPROXY_AUTO_WEBP instead")
diff --git a/processing_handler.go b/processing_handler.go
index 0522951b..94fc805d 100644
--- a/processing_handler.go
+++ b/processing_handler.go
@@ -446,21 +446,6 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) {
))
}
- // We're going to rasterize SVG. Since librsvg lacks the support of some SVG
- // features, we're going to replace them to minimize rendering error
- if originData.Type == imagetype.SVG && config.SvgFixUnsupported {
- fixed, changed, svgErr := svg.FixUnsupported(originData)
- checkErr(ctx, "svg_processing", svgErr)
-
- if changed {
- // Since we'll replace origin data, it's better to close it to return
- // it's buffer to the pool
- originData.Close()
-
- originData = fixed
- }
- }
-
resultData, err := func() (*imagedata.ImageData, error) {
defer metrics.StartProcessingSegment(ctx, metrics.Meta{
metrics.MetaProcessingOptions: metricsMeta[metrics.MetaProcessingOptions],
diff --git a/svg/svg.go b/svg/svg.go
index cfc70261..103c5089 100644
--- a/svg/svg.go
+++ b/svg/svg.go
@@ -2,31 +2,15 @@ package svg
import (
"bytes"
- "fmt"
"io"
"strings"
- nanoid "github.com/matoous/go-nanoid/v2"
"github.com/tdewolff/parse/v2"
"github.com/tdewolff/parse/v2/xml"
"github.com/imgproxy/imgproxy/v3/imagedata"
)
-var feDropShadowName = []byte("feDropShadow")
-
-var feDropShadowTemplate = strings.TrimSpace(`
-
-
-
-
-
-
-
-
-
-`)
-
func cloneHeaders(src map[string]string) map[string]string {
if src == nil {
return nil
@@ -111,120 +95,3 @@ func Sanitize(data *imagedata.ImageData) (*imagedata.ImageData, error) {
}
}
}
-
-func replaceDropShadowNode(l *xml.Lexer, buf *bytes.Buffer) error {
- var (
- inAttrs strings.Builder
- blurAttrs strings.Builder
- offsetAttrs strings.Builder
- floodAttrs strings.Builder
- finalAttrs strings.Builder
- )
-
- inID, _ := nanoid.New(8)
- offsetID, _ := nanoid.New(8)
-
- hasStdDeviation := false
- hasDx := false
- hasDy := false
-
-TOKEN_LOOP:
- for {
- tt, tdata := l.Next()
-
- switch tt {
- case xml.ErrorToken:
- if l.Err() != io.EOF {
- return l.Err()
- }
- break TOKEN_LOOP
- case xml.EndTagToken, xml.StartTagCloseVoidToken:
- break TOKEN_LOOP
- case xml.AttributeToken:
- switch strings.ToLower(string(l.Text())) {
- case "in":
- inAttrs.Write(tdata)
- case "stddeviation":
- blurAttrs.Write(tdata)
- hasStdDeviation = true
- case "dx":
- offsetAttrs.Write(tdata)
- hasDx = true
- case "dy":
- offsetAttrs.Write(tdata)
- hasDy = true
- case "flood-color", "flood-opacity":
- floodAttrs.Write(tdata)
- default:
- finalAttrs.Write(tdata)
- }
- }
- }
-
- if !hasStdDeviation {
- blurAttrs.WriteString(` stdDeviation="2"`)
- }
-
- if !hasDx {
- offsetAttrs.WriteString(` dx="2"`)
- }
-
- if !hasDy {
- offsetAttrs.WriteString(` dy="2"`)
- }
-
- fmt.Fprintf(
- buf, feDropShadowTemplate,
- inID, offsetID,
- inAttrs.String(),
- blurAttrs.String(),
- offsetAttrs.String(),
- floodAttrs.String(),
- finalAttrs.String(),
- )
-
- return nil
-}
-
-func FixUnsupported(data *imagedata.ImageData) (*imagedata.ImageData, bool, error) {
- if !bytes.Contains(data.Data, feDropShadowName) {
- return data, false, nil
- }
-
- r := bytes.NewReader(data.Data)
- l := xml.NewLexer(parse.NewInput(r))
-
- buf, cancel := imagedata.BorrowBuffer()
-
- for {
- tt, tdata := l.Next()
-
- switch tt {
- case xml.ErrorToken:
- if l.Err() != io.EOF {
- cancel()
- return nil, false, l.Err()
- }
-
- newData := imagedata.ImageData{
- Data: buf.Bytes(),
- Type: data.Type,
- Headers: cloneHeaders(data.Headers),
- }
- newData.SetCancel(cancel)
-
- return &newData, true, nil
- case xml.StartTagToken:
- if bytes.Equal(l.Text(), feDropShadowName) {
- if err := replaceDropShadowNode(l, buf); err != nil {
- cancel()
- return nil, false, err
- }
- continue
- }
- buf.Write(tdata)
- default:
- buf.Write(tdata)
- }
- }
-}
diff --git a/svg/svg_test.go b/svg/svg_test.go
index 432da392..c141ef3f 100644
--- a/svg/svg_test.go
+++ b/svg/svg_test.go
@@ -3,7 +3,6 @@ package svg
import (
"os"
"path/filepath"
- "regexp"
"testing"
"github.com/stretchr/testify/suite"
@@ -52,32 +51,6 @@ func (s *SvgTestSuite) TestSanitize() {
s.Require().Equal(origin.Headers, actual.Headers)
}
-func (s *SvgTestSuite) TestFixUnsupportedDropShadow() {
- origin := s.readTestFile("test1.drop-shadow.svg")
- expected := s.readTestFile("test1.drop-shadow.fixed.svg")
-
- actual, changed, err := FixUnsupported(origin)
-
- // `FixUnsupported` generates random IDs, we need to replace them for the test
- re := regexp.MustCompile(`"ds(in|of)-.+?"`)
- actualData := re.ReplaceAllString(string(actual.Data), `"ds$1-test"`)
-
- s.Require().NoError(err)
- s.Require().True(changed)
- s.Require().Equal(string(expected.Data), actualData)
- s.Require().Equal(origin.Headers, actual.Headers)
-}
-
-func (s *SvgTestSuite) TestFixUnsupportedNothingChanged() {
- origin := s.readTestFile("test1.svg")
-
- actual, changed, err := FixUnsupported(origin)
-
- s.Require().NoError(err)
- s.Require().False(changed)
- s.Require().Equal(origin, actual)
-}
-
func TestSvg(t *testing.T) {
suite.Run(t, new(SvgTestSuite))
}