shithub: mycel

Download patch

ref: 294b8735087508d83c93f56e7991d64a97c3edea
parent: 4d0b99d04d24818c1b1d05ff49ce11b4c1131215
author: Philip Silva <philip.silva@protonmail.com>
date: Mon Jan 10 16:50:01 EST 2022

no more superfluous png encoding in between

--- a/browser/browser.go
+++ b/browser/browser.go
@@ -2,7 +2,6 @@
 
 import (
 	"9fans.net/go/draw"
-	"bytes"
 	"errors"
 	"fmt"
 	"github.com/psilva261/opossum"
@@ -200,19 +199,11 @@
 			return nil, fmt.Errorf("serialize: %w", err)
 		}
 		log.Printf("newImage: xml: %v", xml)
-		buf, err := img.Svg(xml, n.Width(), n.Height())
-		if err == nil {
-			var err error
-			r := bytes.NewReader(buf)
-			i, err = duit.ReadImage(display, r)
-			if err != nil {
-				return nil, fmt.Errorf("read image %v: %v", xml, err)
-			}
-
-			goto img_elem
-		} else {
+		i, err = img.Svg(dui, xml, n.Width(), n.Height())
+		if err != nil {
 			return nil, fmt.Errorf("img svg %v: %v", xml, err)
 		}
+		goto img_elem
 	} else if n.Data() == "img" {
 		_, s := srcSet(n)
 		if s != "" {
@@ -228,16 +219,10 @@
 		mw, _ := n.CssPx("max-width")
 		w := n.Width()
 		h := n.Height()
-		r, err := img.Load(browser, src, mw, w, h)
+		i, err = img.Load(dui, browser, src, mw, w, h)
 		if err != nil {
-			return nil, fmt.Errorf("load draw image: %w", err)
+			return nil, fmt.Errorf("load image: %w", err)
 		}
-		log.Printf("Read %v...", src)
-		i, err = duit.ReadImage(display, r)
-		if err != nil {
-			return nil, fmt.Errorf("duit read image: %w", err)
-		}
-		log.Printf("Done reading %v", src)
 		imageCache[src] = i
 	}
 
--- a/img/img.go
+++ b/img/img.go
@@ -1,17 +1,18 @@
 package img
 
 import (
+	"9fans.net/go/draw"
 	"bytes"
 	"encoding/base64"
 	"fmt"
+	"github.com/mjl-/duit"
 	"github.com/psilva261/opossum"
 	"github.com/psilva261/opossum/logger"
 	"github.com/srwiley/oksvg"
 	"github.com/srwiley/rasterx"
-	"golang.org/x/image/draw"
+	xdraw "golang.org/x/image/draw"
 	"image"
-	"image/png"
-	"io"
+	imagedraw "image/draw"
 	"net/url"
 	"strings"
 
@@ -151,7 +152,23 @@
 
 // Svg returns the svg+xml encoded as jpg with the sizing defined in
 // viewbox unless w and h != 0
-func Svg(data string, w, h int) (bs []byte, err error) {
+func Svg(dui *duit.DUI, data string, w, h int) (ni *draw.Image, err error) {
+	rgba, err := svg(data, w, h)
+	if err != nil {
+		return nil, err
+	}
+	ni, err = dui.Display.AllocImage(rgba.Bounds(), draw.ABGR32, false, draw.White)
+	if err != nil {
+		return nil, fmt.Errorf("allocimage: %s", err)
+	}
+	_, err = ni.Load(rgba.Bounds(), rgba.Pix)
+	if err != nil {
+		return nil, fmt.Errorf("load image: %s", err)
+	}
+	return
+}
+
+func svg(data string, w, h int) (img *image.RGBA, err error) {
 	data = strings.ReplaceAll(data, "currentColor", "black")
 	data = strings.ReplaceAll(data, "inherit", "black")
 	data = quoteAttrs(data)
@@ -171,16 +188,40 @@
 	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 = png.Encode(buf, rgba); err != nil {
-		return nil, fmt.Errorf("encode: %w", err)
+	return rgba, nil
+}
+
+// Load and resize to w and h if != 0
+//
+// Stolen from duit.ReadImage
+func Load(dui *duit.DUI, f opossum.Fetcher, src string, maxW, w, h int) (ni *draw.Image, err error) {
+	drawImg, err := load(f, src, maxW, w, h)
+	if err != nil {
+		return nil, err
 	}
+	var rgba *image.RGBA
+	switch i := drawImg.(type) {
+	case *image.RGBA:
+		rgba = i
+	default:
+		b := drawImg.Bounds()
+		rgba = image.NewRGBA(image.Rectangle{image.ZP, b.Size()})
+		imagedraw.Draw(rgba, rgba.Bounds(), drawImg, b.Min, imagedraw.Src)
+	}
 
-	return buf.Bytes(), nil
+	// todo: package image claims data is in r,g,b,a.  who is reversing the bytes? devdraw? will this work on big endian?
+	ni, err = dui.Display.AllocImage(rgba.Bounds(), draw.ABGR32, false, draw.White)
+	if err != nil {
+		return nil, fmt.Errorf("allocimage: %s", err)
+	}
+	_, err = ni.Load(rgba.Bounds(), rgba.Pix)
+	if err != nil {
+		return nil, fmt.Errorf("load image: %s", err)
+	}
+	return
 }
 
-// Load and resize to w and h if != 0
-func Load(f opossum.Fetcher, src string, maxW, w, h int) (r io.Reader, err error) {
+func load(f opossum.Fetcher, src string, maxW, w, h int) (img image.Image, err error) {
 	var imgUrl *url.URL
 	var data []byte
 	var contentType opossum.ContentType
@@ -199,41 +240,38 @@
 	}
 
 	if contentType.IsSvg() {
-		data, err = Svg(string(data), w, h)
+		img, err := svg(string(data), w, h)
 		if err != nil {
 			return nil, fmt.Errorf("svg: %v", err)
 		}
-	} else if maxW != 0 || w != 0 || h != 0 {
-		img, _, err := image.Decode(bytes.NewReader(data))
+		return img, nil
+	} else {
+		img, _, err = image.Decode(bytes.NewReader(data))
 		if err != nil {
 			return nil, fmt.Errorf("decode %v: %w", imgUrl, err)
 		}
+		if maxW != 0 || w != 0 || h != 0 {
+			dx := img.Bounds().Max.X
+			dy := img.Bounds().Max.Y
+			log.Printf("dx,dy=%v,%v", dx, dy)
+			if w == 0 && h == 0 && 0 < maxW && maxW < dx {
+				w = maxW
+			}
 
-		dx := img.Bounds().Max.X
-		dy := img.Bounds().Max.Y
-		log.Printf("dx,dy=%v,%v", dx, dy)
-		if w == 0 && h == 0 && 0 < maxW && maxW < dx {
-			w = maxW
-		}
+			newX, newY, skip := newSizes(dx, dy, w, h)
 
-		newX, newY, skip := newSizes(dx, dy, w, h)
-
-		if !skip {
-			log.Printf("resize image to %v x %v", newX, newY)
-			dst := image.NewRGBA(image.Rect(0, 0, newX, newY))
-			draw.NearestNeighbor.Scale(dst, dst.Rect, img, img.Bounds(), draw.Over, nil)
-			buf := bytes.NewBufferString("")
-
-			if err = png.Encode(buf, dst); err != nil {
-				return nil, fmt.Errorf("encode: %w", err)
+			if !skip {
+				log.Printf("resize image to %v x %v", newX, newY)
+				dst := image.NewRGBA(image.Rect(0, 0, newX, newY))
+				xdraw.NearestNeighbor.Scale(dst, dst.Rect, img, img.Bounds(), xdraw.Over, nil)
+				img = dst
+			} else {
+				log.Printf("skip resizing")
 			}
-			data = buf.Bytes()
-		} else {
-			log.Printf("skip resizing")
 		}
 	}
 
-	return bytes.NewReader(data), nil
+	return img, nil
 }
 
 func newSizes(oldX, oldY, wantedX, wantedY int) (newX, newY int, skip bool) {
--- a/img/img_test.go
+++ b/img/img_test.go
@@ -46,7 +46,7 @@
                </svg>
        `
 
-	_, err := Svg(xml, 0, 0)
+	_, err := svg(xml, 0, 0)
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
@@ -61,7 +61,7 @@
        `
 	xml = `<svg xmlns=http://www.w3.org/2000/svg viewBox=0 0 37 37 fill=#000000><path class=border fill=blue stroke=green/></svg>`
 
-	_, err := Svg(xml, 0, 0)
+	_, err := svg(xml, 0, 0)
 	if err != nil {
 		t.Fatalf(err.Error())
 	}
@@ -110,13 +110,9 @@
 			t.Fail()
 		}
 		b := &MockBrowser{buf.Bytes()}
-		r, err := Load(b, "", mw, w, h)
+		img, err := load(b, "", mw, w, h)
 		if err != nil {
 			t.Errorf("load: %v", err)
-		}
-		img, _, err := image.Decode(r)
-		if err != nil {
-			t.Errorf("decode")
 		}
 		dx := img.Bounds().Max.X
 		dy := img.Bounds().Max.Y
--- a/style/experimental.go
+++ b/style/experimental.go
@@ -3,7 +3,6 @@
 import (
 	"9fans.net/go/draw"
 	"fmt"
-	"github.com/mjl-/duit"
 	"github.com/psilva261/opossum"
 	"github.com/psilva261/opossum/img"
 	"github.com/psilva261/opossum/logger"
@@ -194,18 +193,12 @@
 		w := cs.Width()
 		h := cs.Height()
 
-		r, err := img.Load(fetcher, imgUrl, 0, w, h)
+		var err error
+		i, err = img.Load(dui, fetcher, imgUrl, 0, w, h)
 		if err != nil {
 			log.Errorf("bg img load %v: %v", imgUrl, err)
-			return nil
-		}
-
-		i, err = duit.ReadImage(dui.Display, r)
-		if err != nil {
-			log.Errorf("bg read image %v: %v", imgUrl, err)
 			return
 		}
-		return i
 	}
 	return
 }