shithub: opossum

Download patch

ref: 5598fa5fc7e9fda9610e85fd663b03554fb8915f
parent: 0a38e51ad3bb7965942bdceb5614d332d76b27bf
author: Philip Silva <philip.silva@protonmail.com>
date: Sun Dec 13 16:14:03 EST 2020

Add svg support

--- a/go.mod
+++ b/go.mod
@@ -19,6 +19,8 @@
 	github.com/mjl-/duit v0.0.0-20200330125617-580cb0b2843f
 	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
 	github.com/psilva261/css v0.1.0
+	github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564
+	github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9
 	golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
 	golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
 	golang.org/x/text v0.3.4
--- a/go.sum
+++ b/go.sum
@@ -33,6 +33,10 @@
 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
 github.com/psilva261/css v0.1.0 h1:lzQtXIUKSdH7s6Vi4SeOt1YnTWFY2O/H//rujTGcu10=
 github.com/psilva261/css v0.1.0/go.mod h1:3jVsGoeXcAQqOOyDYqJe4p3bFgR1IXdAilbe2V4WMbE=
+github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM=
+github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
+github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM=
+github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
 github.com/stvp/assert v0.0.0-20170616060220-4bc16443988b h1:GlTM/aMVIwU3luIuSN2SIVRuTqGPt1P97YxAi514ulw=
 github.com/stvp/assert v0.0.0-20170616060220-4bc16443988b/go.mod h1:CC7OXV9IjEZRA+znA6/Kz5vbSwh69QioernOHeDCatU=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
--- a/img/img.go
+++ b/img/img.go
@@ -7,6 +7,8 @@
 	"encoding/base64"
 	"fmt"
 	//"github.com/mjl-/duit"
+	"github.com/srwiley/oksvg"
+	"github.com/srwiley/rasterx"
 	"image"
 	"image/jpeg"
 	"io"
@@ -26,17 +28,24 @@
 	log = l
 }
 
-func parseDataUri(addr string) (data []byte, err error) {
+func parseDataUri(addr string) (data []byte, ct opossum.ContentType, err error) {
+	addr = strings.TrimPrefix(addr, "data:")
 	if strings.Contains(addr, "charset=UTF-8") {
-		return nil, fmt.Errorf("cannot handle charset")
+		return nil, ct, fmt.Errorf("cannot handle charset")
 	}
 	parts := strings.Split(addr, ",")
+	
+	header := strings.Split(parts[0], ";")
+	if ct, err = opossum.NewContentType(header[1]); err != nil {
+		return nil, ct, err
+	}
+	
 	e := base64.RawStdEncoding
 	if strings.HasSuffix(addr, "=") {
 		e = base64.StdEncoding
 	}
 	if data, err = e.DecodeString(parts[1]); err != nil {
-		return nil, fmt.Errorf("decode %v src: %w", addr, err)
+		return nil, ct, fmt.Errorf("decode %v src: %w", addr, err)
 	}
 	return
 }
@@ -45,8 +54,10 @@
 func Load(f opossum.Fetcher, src string, w, h int) (r io.Reader, err error) {
 	var imgUrl *url.URL
 	var data []byte
+	var contentType opossum.ContentType
+
 	if strings.HasPrefix(src, "data:") {
-		if data, err = parseDataUri(src); err != nil {
+		if data, contentType, err = parseDataUri(src); err != nil {
 			return nil, fmt.Errorf("parse data uri %v: %w", src, err)
 		}
 	} else {
@@ -53,9 +64,24 @@
 		if imgUrl, err = f.LinkedUrl(src); err != nil {
 			return nil, err
 		}
-		if data, _, err = f.Get(imgUrl); err != nil {
+		if data, contentType, err = f.Get(imgUrl); err != nil {
 			return nil, fmt.Errorf("get %v: %w", imgUrl, err)
 		}
+	}
+
+	if contentType.IsSvg() {
+		r := bytes.NewReader(data)
+		icon, _ := oksvg.ReadIconStream(r)
+		w := 100
+		h := 100
+		icon.SetTarget(0, 0, float64(w), float64(h))
+		rgba := image.NewRGBA(image.Rect(0, 0, w, h))
+		icon.Draw(rasterx.NewDasher(w, h, rasterx.NewScannerGV(w, h, rgba, rgba.Bounds())), 1)
+		buf := bytes.NewBufferString("")
+		if err = jpeg.Encode(buf, rgba, nil); err != nil {
+			return nil, fmt.Errorf("encode: %w", err)
+		}
+		data = buf.Bytes()
 	}
 
 	if w != 0 || h != 0 {
--- a/img/img_test.go
+++ b/img/img_test.go
@@ -12,10 +12,12 @@
 func TestParseDataUri(t *testing.T) {
 	srcs := []string{"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP//yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
 		"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=",
+		// svg example from github.com/tigt/mini-svg-data-uri (MIT License, (c) 2018 Taylor Hunt)
+		"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MCA1MCI+PHBhdGggZD0iTTIyIDM4VjUxTDMyIDMybDE5LTE5djEyQzQ0IDI2IDQzIDEwIDM4IDAgNTIgMTUgNDkgMzkgMjIgMzh6Ii8+PC9zdmc+",
 	}
 
 	for _, src := range srcs {
-		data, err := parseDataUri(src)
+		data, _, err := parseDataUri(src)
 		if err != nil {
 			t.Fatalf(err.Error())
 		}
--- a/opossum.go
+++ b/opossum.go
@@ -59,6 +59,10 @@
 		c.MediaType == "application/zip"
 }
 
+func (c ContentType) IsSvg() bool {
+	return c.MediaType == "image/svg+xml"	
+}
+
 func (c ContentType) Utf8(buf []byte) []byte {
 	charset, ok := c.Params["charset"]
 	if !ok || charset == "utf8" || charset == "utf-8" {