shithub: mycel

Download patch

ref: 6fea339d0e40d598f093146c0d096b64e2e10c91
parent: f00d509c3efd320c795af6964d861a73761da3e9
author: Philip Silva <philip.silva@protonmail.com>
date: Tue Aug 3 06:54:27 EDT 2021

Some code for gradients

- upgrade to more recent plan9 go library

--- a/browser/browser.go
+++ b/browser/browser.go
@@ -673,7 +673,7 @@
 	maxX := self.R.Dx()
 	maxY := self.R.Dy()
 	if 5 <= x && x <= (maxX-5) && 5 <= y && y <= (maxY-5) && el.IsLink {
-		//dui.Display.SetCursor(&draw.Cursor{
+		//dui.Display.SwitchCursor(&draw.Cursor{
 		//	Set: cursor,
 		//})
 		if m.Buttons == 0 {
@@ -681,7 +681,7 @@
 			return r
 		}
 	} else {
-		dui.Display.SetCursor(nil)
+		dui.Display.SwitchCursor(nil)
 	}
 
 	return el.UI.Mouse(dui, self, m, origM, orig)
--- a/go.mod
+++ b/go.mod
@@ -2,11 +2,11 @@
 
 go 1.16
 
-replace 9fans.net/go v0.0.0-00010101000000-000000000000 => github.com/psilva261/go v0.0.0-20210710174246-83fbc9c615a4
+replace 9fans.net/go v0.0.0-00010101000000-000000000000 => github.com/psilva261/go v0.0.0-20210802153818-99e868f39f77
 
-replace 9fans.net/go v0.0.2 => github.com/psilva261/go v0.0.0-20210710174246-83fbc9c615a4
+replace 9fans.net/go v0.0.2 => github.com/psilva261/go v0.0.0-20210802153818-99e868f39f77
 
-replace github.com/mjl-/duit v0.0.0-20200330125617-580cb0b2843f => github.com/psilva261/duit v0.0.0-20210627123547-8bc19650d4a2
+replace github.com/mjl-/duit v0.0.0-20200330125617-580cb0b2843f => github.com/psilva261/duit v0.0.0-20210802155600-7e8fedefa7ba
 
 replace github.com/knusbaum/go9p v1.17.0 => github.com/psilva261/go9p-1 v1.17.1-0.20210620075710-0428cf31f72f
 
--- a/go.sum
+++ b/go.sum
@@ -22,10 +22,10 @@
 github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/psilva261/duit v0.0.0-20210627123547-8bc19650d4a2 h1:XVUpKOs8MDCaGCyyrpr5an4rflKIpJpMq/76XhqdC5I=
-github.com/psilva261/duit v0.0.0-20210627123547-8bc19650d4a2/go.mod h1:bCuFm7lhAl9wLyLCC6E4RVLDpAv7bWfnTMeDd+C4OQ8=
-github.com/psilva261/go v0.0.0-20210710174246-83fbc9c615a4 h1:sejI8Sc8MAeHriTWRzGOxQFJanm0tC9hVbneobr/KHM=
-github.com/psilva261/go v0.0.0-20210710174246-83fbc9c615a4/go.mod h1:AWpRSZZ474OlNPxa7mOyFZ6Ceg9FRel9f+EONmhPbu0=
+github.com/psilva261/duit v0.0.0-20210802155600-7e8fedefa7ba h1:p8M5yp22QzefbIU3xGERHYnGxlfkcjWV6dh62xIO0U4=
+github.com/psilva261/duit v0.0.0-20210802155600-7e8fedefa7ba/go.mod h1:Ukumf0oazEttGwdWuN21g81jNap4NVccEgKuAUAqkf0=
+github.com/psilva261/go v0.0.0-20210802153818-99e868f39f77 h1:Oy+TCTt29ad3OMoPd3z1pb8YSrmQTAE5SyC8pdM2GDc=
+github.com/psilva261/go v0.0.0-20210802153818-99e868f39f77/go.mod h1:AWpRSZZ474OlNPxa7mOyFZ6Ceg9FRel9f+EONmhPbu0=
 github.com/psilva261/go9p-1 v1.17.1-0.20210620075710-0428cf31f72f h1:gJVK1NhzFXZye5ki4bvyu8dzo0qIckxTf68Vm+Qh4BI=
 github.com/psilva261/go9p-1 v1.17.1-0.20210620075710-0428cf31f72f/go.mod h1:HtMoJKqZUe1Oqag5uJqG5RKQ9gWPSP+wolsnLLv44r8=
 github.com/srwiley/oksvg v0.0.0-20210320200257-875f767ac39a h1:Lhe6HPtH4ndWfV56fWc4/yQhOP3vEGlwl5nfPyBxUAg=
--- a/style/experimental.go
+++ b/style/experimental.go
@@ -31,14 +31,19 @@
 func (cs Map) BoxBackground() (i *draw.Image, err error) {
 	var bgImg *draw.Image
 
-	bgImg = cs.backgroundImage()
+	if bgImg = cs.backgroundImage(); bgImg != nil {
+		return bgImg, nil
+	}
 
+	if bgImg = cs.BackgroundGradient(); bgImg != nil {
+		return bgImg, nil
+	}
+
 	if bgImg == nil {
 		bgColor, ok := cs.backgroundColor()
 		if !ok {
 			return
 		}
-		log.Printf("bgColor=%+v", bgColor)
 		i, ok = colorCache[bgColor]
 		if !ok {
 			var err error
@@ -55,17 +60,17 @@
 }
 
 func (cs Map) backgroundColor() (c draw.Color, ok bool) {
-	_, ok = cs.Declarations["background-color"]
+	d, ok := cs.Declarations["background-color"]
 	if ok {
-		c, ok = cs.colorHex("background-color")
+		c, ok = colorHex(d.Value)
 		if !ok {
 			return
 		}
 		return c, true
 	}
-	_, ok = cs.Declarations["background"]
+	d, ok = cs.Declarations["background"]
 	if ok {
-		c, ok = cs.colorHex("background")
+		c, ok = colorHex(d.Value)
 		if !ok {
 			return
 		}
@@ -74,6 +79,82 @@
 	return
 }
 
+// BackgroundGradient is a stub implemention right now (TODO)
+func (cs Map) BackgroundGradient() (img *draw.Image) {
+	var err error
+	c, ok := cs.backgroundGradient()
+	if !ok {
+		return
+	}
+	img, err = dui.Display.AllocImage(image.Rect(0, 0, 10, 10), draw.ARGB32, true, c)
+	if err != nil {
+		log.Errorf("alloc img: %v", err)
+		img = nil
+	}
+	return
+}
+
+func (cs Map) backgroundGradient() (c draw.Color, ok bool) {
+	d, ok := cs.Declarations["background"]
+	if !ok {
+		return
+	}
+	v := strings.TrimSpace(d.Value)
+	if strings.HasPrefix(v, "linear-gradient(") {
+		v = strings.TrimPrefix(v, "linear-gradient(")
+	} else {
+		return
+	}
+	v = strings.TrimSuffix(v, ")")
+
+	colors := make([]draw.Color, 0, 2)
+
+	for	i := 0; i < len(v); {
+		m := strings.Index(v[i:], ",")
+		op := strings.Index(v[i:], "(")
+		cl := strings.Index(v[i:], ")")
+		if m < 0 {
+			break
+		}
+		var arg string
+		if cl > 0 && op < m && m < cl {
+			arg = v[i:i+cl+1]
+			i += cl + 1
+		} else {
+			arg = v[i:i+m]
+			i += m + 1
+		}
+
+		arg = strings.ReplaceAll(arg, " ", "")
+		c, ok := colorHex(arg)
+		if ok {
+			colors = append(colors, c)
+		}
+	}
+	if len(colors) >= 2 {
+		from := colors[0]
+		to := colors[1]
+		c := linearGradient(from, to, 0.5, 0, 1)
+		return c, true
+	}
+	return
+}
+
+func linearGradient(from, to draw.Color, x, y, xmax float64) (c draw.Color) {
+	fr, fg, fb, fa := from.RGBA()
+	tr, tg, tb, ta := to.RGBA()
+	d := x/xmax
+	r := uint32(float64(fr) + d*float64(tr-fr))
+	g := uint32(float64(fg) + d*float64(tg-fg))
+	b := uint32(float64(fb) + d*float64(tb-fb))
+	a := uint32(float64(fa) + d*float64(ta-fa))
+	cc := (r/256) << 24
+	cc = cc | ((g/256) << 16)
+	cc = cc | ((b/256) << 8)
+	cc = cc | (a/256)
+	return draw.Color(cc)
+}
+
 func backgroundImageUrl(decl css.Declaration) (url string, ok bool) {
 	if v := decl.Value; strings.Contains(v, "url(") && strings.Contains(v, ")") {
 		v = strings.ReplaceAll(v, `"`, "")
@@ -80,7 +161,7 @@
 		v = strings.ReplaceAll(v, `'`, "")
 		from := strings.Index(v, "url(")
 		if from < 0 {
-			log.Printf("bg img: no url: %v", decl.Value)
+			log.Printf("bg img: no url: %v", v)
 			return
 		}
 		from += len("url(")
@@ -87,13 +168,13 @@
 		imgUrl := v[from:]
 		to := strings.Index(imgUrl, ")")
 		if to < 0 {
-			log.Printf("bg img: no ): %v", decl.Value)
+			log.Printf("bg img: no ): %v", v)
 			return
 		}
 		imgUrl = imgUrl[:to]
 		return imgUrl, true
 	} else {
-		log.Printf("bg img: missing ( or ) '%+v'", decl.Value)
+		log.Printf("bg img: missing ( or ) '%+v'", v)
 		return
 	}
 }
--- a/style/experimental_test.go
+++ b/style/experimental_test.go
@@ -3,9 +3,14 @@
 import (
 	"9fans.net/go/draw"
 	"github.com/chris-ramon/douceur/css"
+	"github.com/psilva261/opossum/logger"
 	"testing"
 )
 
+func init() {
+	log.Debug = true
+}
+
 func TestBackgroundImageUrl(t *testing.T) {
 	suffix := ""
 	for _, quote := range []string{"", "'", `"`} {
@@ -42,6 +47,30 @@
 			if b, ok := m.backgroundColor(); !ok || b != d {
 				t.Fatalf("%v", b)
 			}
+		}
+	}
+}
+
+func TestBackgroundGradient(t *testing.T) {
+	values := map[string]uint32{
+		"linear-gradient(to right,rgb(10,0,50,1),rgb(200,0,50,1))": 0x690032ff,
+		"linear-gradient(to right,rgb(0,60,60,1),rgba(0,180,180,1))": 0x007878ff,
+		"linear-gradient(to bottom, rgba(40,40,40,1) 0%,rgba(40,40,40,1) 100%)": 0x282828ff,
+	}
+	for v, cc := range values {
+		m := Map{
+			Declarations: make(map[string]css.Declaration),
+		}
+		m.Declarations["background"] = css.Declaration{
+			Property: "background",
+			Value:    v,
+		}
+		c, ok := m.backgroundGradient()
+		if !ok {
+			t.Fail()
+		}
+		if uint32(c) != cc {
+			t.Fail()
 		}
 	}
 }
--- a/style/fonts_plan9.go
+++ b/style/fonts_plan9.go
@@ -26,7 +26,7 @@
 		// unit tests
 		return
 	}
-	def := dui.Display.DefaultFont.Name
+	def := dui.Display.Font.Name
 	ms, err := fontsLike(def)
 	if err != nil {
 		log.Errorf("find fonts: %v", err)
--- a/style/stylesheets.go
+++ b/style/stylesheets.go
@@ -176,7 +176,7 @@
 		}
 
 		// for media queries
-		if strings.Contains(r.Prelude, "print") {
+		if strings.Contains(r.Prelude, "print") && !strings.Contains(r.Prelude, "screen") {
 			continue
 		}
 		if rMaxWidth.MatchString(r.Prelude) {
@@ -366,96 +366,98 @@
 }
 
 func (cs Map) Color() draw.Color {
-	h, ok := cs.colorHex("color")
-	if !ok {
-		return draw.Black
+	if d, ok := cs.Declarations["color"]; ok {
+		if h, ok := colorHex(d.Value); ok {
+			c := draw.Color(h)
+			return c
+		}
 	}
-	c := draw.Color(h)
-	return c
+	return draw.Black
 }
 
-func (cs Map) colorHex(cssPropName string) (c draw.Color, ok bool) {
-	propVal, ok := cs.Declarations[cssPropName]
-	if ok {
-		var r, g, b uint32
-		if strings.HasPrefix(propVal.Value, "rgb") {
-			val := propVal.Value[3:]
-			val = strings.TrimPrefix(val, "(")
-			val = strings.TrimSuffix(val, ")")
-			vals := strings.Split(val, ",")
-			rr, err := strconv.ParseInt(vals[0], 10, 32)
+func colorHex(propVal string) (c draw.Color, ok bool) {
+	var r, g, b uint32
+	var x uint32
+	if strings.HasPrefix(propVal, "rgb") {
+		val := propVal[3:]
+		val = strings.TrimPrefix(val, "a")
+		val = strings.TrimPrefix(val, "(")
+		val = strings.TrimSuffix(val, ")")
+		vals := strings.Split(val, ",")
+		if len(vals) < 3 {
+			log.Errorf("vals=%+v", vals)
+			return
+		}
+		rr, err := strconv.ParseInt(vals[0], 10, 32)
+		if err != nil {
+			goto default_value
+		}
+		gg, err := strconv.ParseInt(vals[1], 10, 32)
+		if err != nil {
+			goto default_value
+		}
+		bb, err := strconv.ParseInt(vals[2], 10, 32)
+		if err != nil {
+			goto default_value
+		}
+		r = uint32(rr) * 256
+		g = uint32(gg) * 256
+		b = uint32(bb) * 256
+	} else if strings.HasPrefix(propVal, "#") {
+		hexColor := propVal[1:]
+
+		if len(hexColor) == 3 {
+			rr, err := strconv.ParseInt(hexColor[0:1], 16, 32)
 			if err != nil {
 				goto default_value
 			}
-			gg, err := strconv.ParseInt(vals[1], 10, 32)
+			gg, err := strconv.ParseInt(hexColor[1:2], 16, 32)
 			if err != nil {
 				goto default_value
 			}
-			bb, err := strconv.ParseInt(vals[2], 10, 32)
+			bb, err := strconv.ParseInt(hexColor[2:3], 16, 32)
 			if err != nil {
 				goto default_value
 			}
-			r = uint32(rr) * 256
-			g = uint32(gg) * 256
-			b = uint32(bb) * 256
-		} else if strings.HasPrefix(propVal.Value, "#") {
-			hexColor := propVal.Value[1:]
-
-			if len(hexColor) == 3 {
-				rr, err := strconv.ParseInt(hexColor[0:1], 16, 32)
-				if err != nil {
-					goto default_value
-				}
-				gg, err := strconv.ParseInt(hexColor[1:2], 16, 32)
-				if err != nil {
-					goto default_value
-				}
-				bb, err := strconv.ParseInt(hexColor[2:3], 16, 32)
-				if err != nil {
-					goto default_value
-				}
-				r = uint32(rr) * 256 * 0x11
-				g = uint32(gg) * 256 * 0x11
-				b = uint32(bb) * 256 * 0x11
-			} else if len(hexColor) == 6 {
-				rr, err := strconv.ParseInt(hexColor[0:2], 16, 32)
-				if err != nil {
-					goto default_value
-				}
-				gg, err := strconv.ParseInt(hexColor[2:4], 16, 32)
-				if err != nil {
-					goto default_value
-				}
-				bb, err := strconv.ParseInt(hexColor[4:6], 16, 32)
-				if err != nil {
-					goto default_value
-				}
-				r = uint32(rr) * 256
-				g = uint32(gg) * 256
-				b = uint32(bb) * 256
-			} else {
+			r = uint32(rr) * 256 * 0x11
+			g = uint32(gg) * 256 * 0x11
+			b = uint32(bb) * 256 * 0x11
+		} else if len(hexColor) == 6 {
+			rr, err := strconv.ParseInt(hexColor[0:2], 16, 32)
+			if err != nil {
 				goto default_value
 			}
-		} else if propVal.Value == "inherit" {
-			// TODO: handle properly
-			goto default_value
-		} else {
-			colorRGBA, ok := colornames.Map[propVal.Value]
-			if !ok {
+			gg, err := strconv.ParseInt(hexColor[2:4], 16, 32)
+			if err != nil {
 				goto default_value
 			}
-			r, g, b, _ = colorRGBA.RGBA()
+			bb, err := strconv.ParseInt(hexColor[4:6], 16, 32)
+			if err != nil {
+				goto default_value
+			}
+			r = uint32(rr) * 256
+			g = uint32(gg) * 256
+			b = uint32(bb) * 256
+		} else {
+			goto default_value
 		}
-
-		x := (r / 256) << 24
-		x = x | ((g / 256) << 16)
-		x = x | ((b / 256) << 8)
-		x = x | 0x000000ff
-
-		return draw.Color(uint32(x)), true
+	} else if propVal == "inherit" {
+		// TODO: handle properly
+		goto default_value
 	} else {
-		return 0, false
+		colorRGBA, ok := colornames.Map[propVal]
+		if !ok {
+			goto default_value
+		}
+		r, g, b, _ = colorRGBA.RGBA()
 	}
+
+	x = (r / 256) << 24
+	x = x | ((g / 256) << 16)
+	x = x | ((b / 256) << 8)
+	x = x | 0x000000ff
+
+	return draw.Color(uint32(x)), true
 default_value:
 	log.Printf("could not interpret %v", propVal)
 	return 0, false
--- a/style/stylesheets_test.go
+++ b/style/stylesheets_test.go
@@ -13,27 +13,13 @@
 	log.Debug = true
 }
 
-func d(c string) Map {
-	m := Map{
-		Declarations: make(map[string]css.Declaration),
-	}
-	m.Declarations["color"] = css.Declaration{
-		Property: "color",
-		Value:    c,
-	}
-	return m
-}
-
 func TestColorHex(t *testing.T) {
-	tr := d("red")
-	hr := d("#ff0000")
-
-	tri, ok := tr.colorHex("color")
+	tri, ok := colorHex("red")
 	if !ok {
 		t.Fail()
 	}
 
-	hri, ok := hr.colorHex("color")
+	hri, ok := colorHex("#ff0000")
 	if !ok {
 		t.Fail()
 	}
@@ -41,12 +27,14 @@
 	if tri != hri {
 		t.Fatalf("tri=%x hri=%x", tri, hri)
 	}
+
+	if _, ok := colorHex("rgb(1,2)"); ok {
+		t.Fail()
+	}
 }
 
 func TestColorHex3(t *testing.T) {
-	m := d("#fff")
-
-	c, ok := m.colorHex("color")
+	c, ok := colorHex("#fff")
 	if !ok {
 		t.Fail()
 	}