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" {