ref: 35e034e341b0794b327eabb3f25392e3b27dd99b
dir: /style/experimental.go/
package style import ( "9fans.net/go/draw" "github.com/chris-ramon/douceur/css" "fmt" "github.com/mjl-/duit" "image" "github.com/psilva261/opossum" "github.com/psilva261/opossum/img" "github.com/psilva261/opossum/logger" "strings" ) var colorCache = make(map[draw.Color]*draw.Image) var fetcher opossum.Fetcher func SetFetcher(f opossum.Fetcher) { fetcher = f } var TextNode = Map{ Declarations: map[string]css.Declaration{ "display": css.Declaration{ Property: "display", Value: "inline", }, }, } func (cs Map) BoxBackground() (i *draw.Image, err error) { var bgImg *draw.Image 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 } i, ok = colorCache[bgColor] if !ok { var err error i, err = dui.Display.AllocImage(image.Rect(0, 0, 10, 10), draw.ARGB32, true, bgColor) if err != nil { return nil, fmt.Errorf("alloc img: %w", err) } colorCache[bgColor] = i } } else { i = bgImg } return } func (cs Map) backgroundColor() (c draw.Color, ok bool) { d, ok := cs.Declarations["background-color"] if ok { c, ok = colorHex(d.Value) if !ok { return } return c, true } d, ok = cs.Declarations["background"] if ok { c, ok = colorHex(d.Value) if !ok { return } return c, true } 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, `"`, "") v = strings.ReplaceAll(v, `'`, "") from := strings.Index(v, "url(") if from < 0 { log.Printf("bg img: no url: %v", v) return } from += len("url(") imgUrl := v[from:] to := strings.Index(imgUrl, ")") if to < 0 { log.Printf("bg img: no ): %v", v) return } imgUrl = imgUrl[:to] return imgUrl, true } else { log.Printf("bg img: missing ( or ) '%+v'", v) return } } func (cs Map) backgroundImage() (i *draw.Image) { decl, ok := cs.Declarations["background-image"] if !ok { decl, ok = cs.Declarations["background"] } if ok { imgUrl, ok := backgroundImageUrl(decl) if !ok { log.Printf("bg img not ok") return } w := cs.Width() h := cs.Height() r, err := img.Load(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 }