ref: 3ce4cfc9371c16b2ac4ac167668122fca13cc850
parent: 613e3bb3449b423ec3d96438f8b9a93aa58c731b
author: Philip Silva <[email protected]>
date: Sun Dec 27 06:52:29 EST 2020
svg tag
--- a/browser/browser.go
+++ b/browser/browser.go
@@ -2,6 +2,7 @@
import (
"9fans.net/go/draw"
+ "bytes"
"errors"
"fmt"
"golang.org/x/net/html"
@@ -133,17 +134,39 @@
}
func newImage(n *nodes.Node) (ui duit.UI, err error) {
+ var i *draw.Image
+ var cached bool
+ src := attr(*n.DomSubtree, "src")
+
if display == nil {
// probably called from a unit test
return nil, fmt.Errorf("display nil")
}
- src := attr(*n.DomSubtree, "src")
+
+ if n.Data() == "svg" {
+ xml, err := n.Serialized()
+ if err != nil {
+ return nil, fmt.Errorf("serialize: %w", err)
+ }
+ 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 {
+ return nil, fmt.Errorf("img svg %v: %v", xml, err)
+ }
+ }
+
if src == "" {
return nil, fmt.Errorf("no src in %+v", n.Attrs)
}
- var i *draw.Image
- var cached bool
if i, cached = imageCache[src]; !cached {
r, err := img.Load(browser, src, n.Width(), n.Height())
if err != nil {
@@ -158,6 +181,7 @@
imageCache[src] = i
}
+img_elem:
return NewElement(
&Image{
Image: &duit.Image{
@@ -283,8 +307,8 @@
if v := attr(*n.DomSubtree, "value"); v != "" {
t = v
- } else if nodes.IsPureTextContent(*n) {
- t = strings.TrimSpace(nodes.ContentFrom(*n))
+ } else if c := strings.TrimSpace(nodes.ContentFrom(*n)); c != "" {
+ t = c
} else {
t = "Submit"
}
@@ -797,7 +821,7 @@
if n.Type() == html.ElementNode {
switch n.Data() {
- case "style", "script", "svg", "template":
+ case "style", "script", "template":
return nil
case "input":
numElements++
@@ -851,7 +875,7 @@
innerContent,
n,
)
- case "img":
+ case "img", "svg":
numElements++
return NewElement(
NewImage(n),
@@ -1230,7 +1254,7 @@
func (b *Browser) LoadUrl() (e duit.Event) {
addr := b.LocationField.Text
if !strings.HasPrefix(addr, "http") {
- addr = "https://" + addr
+ addr = "http://" + addr
}
log.Printf("Getting %v...", addr)
url, err := url.Parse(addr)
--- a/img/img.go
+++ b/img/img.go
@@ -62,6 +62,33 @@
return
}
+// 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) {
+ data = strings.ReplaceAll(data, "currentColor", "black")
+ r := bytes.NewReader([]byte(data))
+ icon, err := oksvg.ReadIconStream(r)
+ if err != nil {
+ return nil, fmt.Errorf("read icon stream: %w", err)
+ }
+
+ if w == 0 || h == 0 {
+ w = int(icon.ViewBox.W)
+ h = int(icon.ViewBox.H)
+ }
+
+ 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)
+ }
+
+ return buf.Bytes(), nil
+}
+
// Load and resize to w and h if != 0
func Load(f opossum.Fetcher, src string, w, h int) (r io.Reader, err error) {
var imgUrl *url.URL
@@ -82,20 +109,10 @@
}
if contentType.IsSvg() {
- r := bytes.NewReader(data)
- icon, _ := oksvg.ReadIconStream(r)
- if w == 0 || h == 0 {
- w = 20
- h = 20
+ data, err = Svg(string(data), w, h)
+ if err != nil {
+ return nil, fmt.Errorf("svg: %v", err)
}
- 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()
} else if w != 0 || h != 0 {
image, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
--- a/img/img_test.go
+++ b/img/img_test.go
@@ -26,3 +26,16 @@
}
}
+func TestSvg(t *testing.T) {
+ xml := `
+ <svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24">
+ </svg>
+ `
+
+ _, err := Svg(xml, 0, 0)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+}
+
+
--- a/nodes/nodes.go
+++ b/nodes/nodes.go
@@ -1,6 +1,7 @@
package nodes
import (
+ "bytes"
"golang.org/x/net/html"
"opossum/logger"
"opossum/style"
@@ -95,6 +96,18 @@
return nil
}
+func (n *Node) Find(tag string) (c *Node) {
+ for _, cc := range n.Children {
+ if cc.Data() == tag {
+ return cc
+ } else if f := cc.Find(tag); f != nil {
+ return f
+ }
+ }
+
+ return
+}
+
func (n *Node) Attr(k string) string {
for _, a := range n.Attrs {
if a.Key == k {
@@ -147,4 +160,13 @@
}
return strings.TrimSpace(content)
-}
\ No newline at end of file
+}
+
+func (n *Node) Serialized() (string, error) {
+ var b bytes.Buffer
+
+ err := html.Render(&b, n.DomSubtree)
+
+ return b.String(), err
+}
+
--- a/style/stylesheets.go
+++ b/style/stylesheets.go
@@ -310,6 +310,7 @@
func (cs Map) preferedFontName(preferences []string) string {
avails := availableFontNames
+
if len(avails) == 0 {
return preferences[0]
}
@@ -319,7 +320,7 @@
pref, preferences = preferences[0], preferences[1:]
for _, avail := range avails {
- if pref == avail {
+ if pref == strings.TrimSuffix(avail, "/") {
return avail
}
}