func roundhand(cx, cy, px, py, stroke openvg.VGfloat, color string) { openvg.StrokeWidth(stroke) openvg.StrokeColor(color) openvg.Line(cx, cy, px, py) openvg.StrokeWidth(0) openvg.FillColor(color) openvg.Ellipse(px, py, stroke, stroke) }
func secondhand(cx, cy, sx, sy, textsize openvg.VGfloat) { openvg.FillColor(secolor, 0.4) openvg.Ellipse(sx, sy, textsize, textsize) if secline { openvg.StrokeWidth(textsize / 6) openvg.StrokeColor(secolor) openvg.Line(cx, cy, sx, sy) openvg.StrokeWidth(0) } }
func face(x, y, r openvg.VGfloat, ts int) { var fx, fy, va openvg.VGfloat va = openvg.VGfloat(ts) / 2.0 secsize := openvg.VGfloat(ts) / 3 radius := float64(r) ir := radius * 1.2 // hour display openvg.FillColor(digitcolor) openvg.StrokeColor(digitcolor) openvg.StrokeWidth(5) for h := 12; h > 0; h-- { t := hourangles[h%12] * deg2rad fx = x + openvg.VGfloat(radius*math.Cos(t)) fy = y + openvg.VGfloat(radius*math.Sin(t)) ix := x + openvg.VGfloat(ir*math.Cos(t)) iy := y + openvg.VGfloat(ir*math.Sin(t)) if showdigits { openvg.TextMid(fx, fy-va, hourdigits[h%12], "sans", ts) } else { openvg.Line(fx, fy, ix, iy) } } // second display openvg.FillColor(dotcolor) openvg.StrokeColor(dotcolor) openvg.StrokeWidth(2) re := radius * edge for a := 0.0; a < 360; a += 6.0 { t := a * deg2rad sx := x + openvg.VGfloat(re*math.Cos(t)) sy := y + openvg.VGfloat(re*math.Sin(t)) if showdots { openvg.Ellipse(sx, sy, secsize, secsize) } else { ix := x + openvg.VGfloat(ir*math.Cos(t)) iy := y + openvg.VGfloat(ir*math.Sin(t)) openvg.Line(sx, sy, ix, iy) } } openvg.StrokeWidth(0) }
//planets is an exploration of scale func planets(width, height int, message string) { w := openvg.VGfloat(width) h := openvg.VGfloat(height) y := h / 2 margin := openvg.VGfloat(100.0) minsize := openvg.VGfloat(7.0) labeloc := openvg.VGfloat(100.0) bgcolor := "black" labelcolor := "white" maxsize := (h / 2) * 0.05 origin := sun.distance mostDistant := neptune.distance firstSize := mercury.radius lastSize := neptune.radius openvg.Start(width, height) openvg.BackgroundColor(bgcolor) for _, p := range solarSystem { x := vmap(p.distance, origin, mostDistant, margin, w-margin) r := vmap(p.radius, firstSize, lastSize, minsize, maxsize) if p.name == "Sun" { openvg.FillRGB(p.color.Red, p.color.Green, p.color.Blue, 1) openvg.Circle(margin-(r/2), y, r) } else { light(x, y, r, p.color) openvg.Circle(x, y, r) if p.name == "Saturn" { ringwidth := r * 2.35 // Saturn's rings are over 2x the planet radius openvg.StrokeWidth(3) openvg.StrokeRGB(p.color.Red, p.color.Green, p.color.Blue, 1) openvg.Line((x - ringwidth/2), y, (x + ringwidth/2), y) openvg.StrokeWidth(0) } } if p.name == "Earth" && len(message) > 1 { openvg.StrokeColor(labelcolor) openvg.StrokeWidth(1) openvg.Line(x, y+(r/2), x, y+labeloc) openvg.StrokeWidth(0) openvg.FillColor(labelcolor) openvg.TextMid(x, y+labeloc+10, message, "sans", 12) } } openvg.End() }
func combohand(cx, cy, px, py, r, stroke openvg.VGfloat, t float64, value int, color string) { thinr := float64(r * 0.25) t = minadjust(t, value) * deg2rad tx := cx + openvg.VGfloat(thinr*math.Cos(t)) ty := cy + openvg.VGfloat(thinr*math.Sin(t)) openvg.FillColor(color) openvg.Ellipse(px, py, stroke*2, stroke*2) openvg.Ellipse(tx, ty, stroke*2, stroke*2) openvg.StrokeWidth(stroke) openvg.StrokeColor(color) openvg.Line(cx, cy, tx, ty) openvg.StrokeWidth(stroke * 2) openvg.Line(tx, ty, px, py) openvg.StrokeWidth(0) }
func main() { width, height := openvg.Init() w := openvg.VGfloat(width) h := openvg.VGfloat(height) y := h / 2 var ( margin openvg.VGfloat = 100.0 minsize openvg.VGfloat = 7.0 labeloc openvg.VGfloat = 100.0 ) bgcolor := "black" labelcolor := "white" maxsize := (h / 2) * 0.05 origin := sun.distance mostDistant := neptune.distance firstSize := mercury.radius lastSize := neptune.radius openvg.Start(width, height) openvg.BackgroundColor(bgcolor) for _, p := range solarSystem { x := vmap(p.distance, origin, mostDistant, margin, w-margin) r := vmap(p.radius, firstSize, lastSize, minsize, maxsize) if p.name == "Sun" { openvg.FillRGB(p.color.Red, p.color.Green, p.color.Blue, 1) openvg.Circle(margin-(r/2), y, r) } else { light(x, y, r, p.color) openvg.Circle(x, y, r) } if p.name == "Earth" && len(os.Args) > 1 { openvg.StrokeColor(labelcolor) openvg.StrokeWidth(1) openvg.Line(x, y+(r/2), x, y+labeloc) openvg.StrokeWidth(0) openvg.FillColor(labelcolor) openvg.TextMid(x, y+labeloc+10, os.Args[1], "sans", 12) } } openvg.End() bufio.NewReader(os.Stdin).ReadByte() openvg.Finish() }
// showgrid xrays a slide func showgrid(d deck.Deck, n int, p float64) { w := openvg.VGfloat(d.Canvas.Width) h := openvg.VGfloat(d.Canvas.Height) percent := openvg.VGfloat(p) fs := (w / 100) // labels are 1% of the width xpct := (percent / 100.0) * w ypct := (percent / 100.0) * h openvg.StrokeColor("lightgray", 0.5) openvg.StrokeWidth(3) // horizontal gridlines xl := percent for x := xpct; x <= w; x += xpct { openvg.Line(x, 0, x, h) openvg.Text(x, percent, fmt.Sprintf("%.0f%%", xl), "sans", int(fs)) xl += percent } // vertical gridlines yl := percent for y := ypct; y <= h; y += ypct { openvg.Line(0, y, w, y) openvg.Text(percent, y, fmt.Sprintf("%.0f%%", yl), "sans", int(fs)) yl += percent } // show boundary and location of images if n < 0 || n > len(d.Slide) { return } for _, im := range d.Slide[n].Image { x := pct(im.Xp, w) y := pct(im.Yp, h) iw := openvg.VGfloat(im.Width) ih := openvg.VGfloat(im.Height) if im.Scale > 0 { iw *= openvg.VGfloat(im.Scale / 100) ih *= openvg.VGfloat(im.Scale / 100) } openvg.FillRGB(127, 0, 0, 0.3) openvg.Circle(x, y, fs) openvg.FillRGB(255, 0, 0, 0.1) openvg.Rect(x-iw/2, y-ih/2, iw, ih) } openvg.End() }
func main() { var ( filename = flag.String("f", "svgcolors.txt", "input file") fontname = flag.String("font", "sans", "fontname") neg = flag.Bool("neg", false, "negative") showrgb = flag.Bool("rgb", false, "show RGB") showcode = flag.Bool("showcode", true, "show colors and codes") circsw = flag.Bool("circle", true, "circle swatch") outline = flag.Bool("outline", false, "outline swatch") fontsize = flag.Int("fs", 12, "fontsize") rowsize = flag.Int("r", 32, "rowsize") colw = flag.Float64("c", 340, "column size") swatch = flag.Float64("s", 16, "swatch size") gutter = flag.Float64("g", 12, "gutter") err error tcolor, line string ) flag.Parse() f, oerr := os.Open(*filename) if oerr != nil { fmt.Fprintf(os.Stderr, "%v\n", oerr) return } width, height := openvg.Init() openvg.Start(width, height) fw := openvg.VGfloat(width) fh := openvg.VGfloat(height) if *neg { openvg.FillColor("black") openvg.Rect(0, 0, fw, fh) tcolor = "white" } else { openvg.FillColor("white") openvg.Rect(0, 0, fw, fh) tcolor = "black" } top := fh - 32.0 left := openvg.VGfloat(32.0) cw := openvg.VGfloat(*colw) sw := openvg.VGfloat(*swatch) g := openvg.VGfloat(*gutter) in := bufio.NewReader(f) for x, y, nr := left, top, 0; err == nil; nr++ { line, err = in.ReadString('\n') fields := strings.Split(strings.TrimSpace(line), "\t") if nr%*rowsize == 0 && nr > 0 { x += cw y = top } if len(fields) == 3 { var red, green, blue uint8 fmt.Sscanf(fields[2], "%d,%d,%d", &red, &green, &blue) openvg.FillRGB(red, green, blue, 1) if *outline { openvg.StrokeColor("black") openvg.StrokeWidth(1) } if *circsw { openvg.Circle(x+sw/2, y+sw/2, sw) } else { openvg.Rect(x, y, sw, sw) } openvg.StrokeWidth(0) openvg.FillColor(tcolor) openvg.Text(x+sw+openvg.VGfloat(*fontsize/2), y, fields[0], *fontname, *fontsize) var label string if *showcode { if *showrgb { label = fields[1] } else { label = fields[2] } openvg.FillColor("gray") openvg.TextEnd(x+cw-(sw+g), y, label, *fontname, *fontsize) } } y -= (sw + g) } openvg.End() bufio.NewReader(os.Stdin).ReadBytes('\n') openvg.Finish() }
// plot places a plot at the specified location with the specified dimemsions // using the specified settings, using the specified data func plot(x, y, w, h openvg.VGfloat, settings plotset, d []rawdata) { nd := len(d) if nd < 2 { fmt.Fprintf(os.Stderr, "%d is not enough points to plot\n", len(d)) return } // Compute the minima and maxima of the data maxx, minx := d[0].x, d[0].x maxy, miny := d[0].y, d[0].y for _, v := range d { if v.x > maxx { maxx = v.x } if v.y > maxy { maxy = v.y } if v.x < minx { minx = v.x } if v.y < miny { miny = v.y } } // Prepare for a area or line chart by allocating // polygon coordinates; for the horizon plot, you need two extra coordinates // for the extrema. needpoly := settings.opt["area"] || settings.opt["connect"] var xpoly, ypoly []openvg.VGfloat if needpoly { xpoly = make([]openvg.VGfloat, nd+2) ypoly = make([]openvg.VGfloat, nd+2) // preload the extrema of the polygon, // the bottom left and bottom right of the plot's rectangle xpoly[0] = x ypoly[0] = y xpoly[nd+1] = x + w ypoly[nd+1] = y } // Draw the plot's bounding rectangle if settings.opt["showbg"] && !settings.opt["sameplot"] { openvg.FillColor(settings.attr["bgcolor"]) openvg.Rect(x, y, w, h) } // Loop through the data, drawing items as specified spacer := openvg.VGfloat(10.0) for i, v := range d { xp := fmap(v.x, minx, maxx, x, x+w) yp := fmap(v.y, miny, maxy, y, y+h) if needpoly { xpoly[i+1] = xp ypoly[i+1] = yp } if settings.opt["showbar"] { openvg.StrokeColor(settings.attr["barcolor"]) openvg.StrokeWidth(settings.size["barsize"]) openvg.Line(xp, yp, xp, y) } if settings.opt["showdot"] { openvg.FillColor(settings.attr["dotcolor"]) openvg.StrokeWidth(0) openvg.Circle(xp, yp, settings.size["dotsize"]) } if settings.opt["showx"] { if i%int(settings.size["xinterval"]) == 0 { openvg.FillColor("black") openvg.TextMid(xp, y-(spacer*2), fmt.Sprintf("%d", int(v.x)), settings.attr["font"], int(settings.size["fontsize"])) openvg.StrokeColor("silver") openvg.StrokeWidth(1) openvg.Line(xp, y, xp, y-spacer) } openvg.StrokeWidth(0) } } // Done constructing the points for the area or line plots, display them in one shot if settings.opt["area"] { openvg.FillColor(settings.attr["areacolor"]) openvg.Polygon(xpoly, ypoly) } if settings.opt["connect"] { openvg.StrokeColor(settings.attr["linecolor"]) openvg.StrokeWidth(settings.size["linesize"]) openvg.Polyline(xpoly[1:nd+1], ypoly[1:nd+1]) } // Put on the y axis labels, if specified if settings.opt["showy"] { bot := openvg.VGfloat(math.Floor(float64(miny))) top := openvg.VGfloat(math.Ceil(float64(maxy))) yrange := top - bot interval := yrange / openvg.VGfloat(settings.size["yinterval"]) for yax := bot; yax <= top; yax += interval { yaxp := fmap(yax, bot, top, openvg.VGfloat(y), openvg.VGfloat(y+h)) openvg.FillColor("black") openvg.TextEnd(x-spacer, yaxp, fmt.Sprintf("%.1f", yax), settings.attr["font"], int(settings.size["fontsize"])) openvg.StrokeColor("silver") openvg.StrokeWidth(1) openvg.Line(x-spacer, yaxp, x, yaxp) } openvg.StrokeWidth(0) } // Finally, tack on the label, if specified if len(settings.attr["label"]) > 0 { openvg.FillColor(settings.attr["labelcolor"], 0.3) openvg.TextMid(x+(w/2), y+(h/2), settings.attr["label"], settings.attr["font"], int(w/8)) // int(settings.size["fontsize"])) } openvg.StrokeWidth(0) }
// showlide displays slides func showslide(d deck.Deck, imap map[string]image.Image, n int) { var video videoType if n < 0 || n > len(d.Slide)-1 { return } slide := d.Slide[n] if slide.Bg == "" { slide.Bg = "white" } if slide.Fg == "" { slide.Fg = "black" } openvg.Start(d.Canvas.Width, d.Canvas.Height) cw := openvg.VGfloat(d.Canvas.Width) ch := openvg.VGfloat(d.Canvas.Height) if slide.Gradcolor1 != "" && slide.Gradcolor2 != "" { oc := []openvg.Offcolor{ {0, openvg.Colorlookup(slide.Gradcolor1), 1}, {1, openvg.Colorlookup(slide.Gradcolor2), 1}, } openvg.FillLinearGradient(0, ch, 0, 0, oc) } else { openvg.FillColor(slide.Bg) } openvg.Rect(0, 0, cw, ch) var x, y, fs openvg.VGfloat // every image in the slide for _, im := range slide.Image { x = pct(im.Xp, cw) y = pct(im.Yp, ch) imw := openvg.VGfloat(im.Width) imh := openvg.VGfloat(im.Height) if im.Scale > 0 { imw *= openvg.VGfloat(im.Scale / 100) imh *= openvg.VGfloat(im.Scale / 100) } midx := openvg.VGfloat(imw / 2) midy := openvg.VGfloat(imh / 2) if im.Type == "video" { // Only one video per slide supported video.name = im.Name video.x = x - midx video.y = y - midy video.w = imw video.h = imh video.altimg = im.Link } else { img, ok := imap[im.Name] if ok { openvg.Img(x-midx, y-midy, img) } if len(im.Caption) > 0 { capfs := pctwidth(im.Sp, cw, cw/100) if im.Font == "" { im.Font = "sans" } if im.Color == "" { openvg.FillColor(slide.Fg) } else { openvg.FillColor(im.Color) } if im.Align == "" { im.Align = "center" } switch im.Align { case "left", "start": x -= midx case "right", "end": x += midx } showtext(x, y-((midy)+(capfs*2.0)), im.Caption, im.Align, im.Font, capfs) } } } // every graphic on the slide const defaultColor = "rgb(127,127,127)" const defaultSw = 1.5 var strokeopacity float64 // line for _, line := range slide.Line { if line.Color == "" { line.Color = slide.Fg // defaultColor } if line.Opacity == 0 { strokeopacity = 1 } else { strokeopacity = line.Opacity / 100.0 } x1, y1, sw := dimen(d, line.Xp1, line.Yp1, line.Sp) x2, y2, _ := dimen(d, line.Xp2, line.Yp2, 0) openvg.StrokeColor(line.Color, openvg.VGfloat(strokeopacity)) if sw == 0 { sw = defaultSw } openvg.StrokeWidth(openvg.VGfloat(sw)) openvg.StrokeColor(line.Color) openvg.Line(x1, y1, x2, y2) openvg.StrokeWidth(0) } // ellipse for _, ellipse := range slide.Ellipse { x, y, _ = dimen(d, ellipse.Xp, ellipse.Yp, 0) var w, h openvg.VGfloat w = pct(ellipse.Wp, cw) if ellipse.Hr == 0 { // if relative height not specified, base height on overall height h = pct(ellipse.Hp, ch) } else { h = pct(ellipse.Hr, w) } if ellipse.Color == "" { ellipse.Color = defaultColor } if ellipse.Opacity == 0 { ellipse.Opacity = 1 } else { ellipse.Opacity /= 100 } openvg.FillColor(ellipse.Color, openvg.VGfloat(ellipse.Opacity)) openvg.Ellipse(x, y, w, h) } // rect for _, rect := range slide.Rect { x, y, _ = dimen(d, rect.Xp, rect.Yp, 0) var w, h openvg.VGfloat w = pct(rect.Wp, cw) if rect.Hr == 0 { // if relative height not specified, base height on overall height h = pct(rect.Hp, ch) } else { h = pct(rect.Hr, w) } if rect.Color == "" { rect.Color = defaultColor } if rect.Opacity == 0 { rect.Opacity = 1 } else { rect.Opacity /= 100 } openvg.FillColor(rect.Color, openvg.VGfloat(rect.Opacity)) openvg.Rect(x-(w/2), y-(h/2), w, h) } // curve for _, curve := range slide.Curve { if curve.Color == "" { curve.Color = defaultColor } if curve.Opacity == 0 { strokeopacity = 1 } else { strokeopacity = curve.Opacity / 100.0 } x1, y1, sw := dimen(d, curve.Xp1, curve.Yp1, curve.Sp) x2, y2, _ := dimen(d, curve.Xp2, curve.Yp2, 0) x3, y3, _ := dimen(d, curve.Xp3, curve.Yp3, 0) openvg.StrokeColor(curve.Color, openvg.VGfloat(strokeopacity)) openvg.FillColor(slide.Bg, openvg.VGfloat(curve.Opacity)) if sw == 0 { sw = defaultSw } openvg.StrokeWidth(sw) openvg.Qbezier(x1, y1, x2, y2, x3, y3) openvg.StrokeWidth(0) } // arc for _, arc := range slide.Arc { if arc.Color == "" { arc.Color = defaultColor } if arc.Opacity == 0 { strokeopacity = 1 } else { strokeopacity = arc.Opacity / 100.0 } ax, ay, sw := dimen(d, arc.Xp, arc.Yp, arc.Sp) w := pct(arc.Wp, cw) h := pct(arc.Hp, cw) openvg.StrokeColor(arc.Color, openvg.VGfloat(strokeopacity)) openvg.FillColor(slide.Bg, openvg.VGfloat(arc.Opacity)) if sw == 0 { sw = defaultSw } openvg.StrokeWidth(sw) openvg.Arc(ax, ay, w, h, openvg.VGfloat(arc.A1), openvg.VGfloat(arc.A2)) openvg.StrokeWidth(0) } // polygon for _, poly := range slide.Polygon { if poly.Color == "" { poly.Color = defaultColor } if poly.Opacity == 0 { poly.Opacity = 1 } else { poly.Opacity /= 100 } xs := strings.Split(poly.XC, " ") ys := strings.Split(poly.YC, " ") if len(xs) != len(ys) { continue } if len(xs) < 3 || len(ys) < 3 { continue } px := make([]openvg.VGfloat, len(xs)) py := make([]openvg.VGfloat, len(ys)) for i := 0; i < len(xs); i++ { x, err := strconv.ParseFloat(xs[i], 32) if err != nil { px[i] = 0 } else { px[i] = pct(x, cw) } y, err := strconv.ParseFloat(ys[i], 32) if err != nil { py[i] = 0 } else { py[i] = pct(y, ch) } } openvg.FillColor(poly.Color, openvg.VGfloat(poly.Opacity)) openvg.Polygon(px, py) } openvg.FillColor(slide.Fg) // every list in the slide var offset, textopacity openvg.VGfloat const blinespacing = 2.4 for _, l := range slide.List { if l.Font == "" { l.Font = "sans" } x, y, fs = dimen(d, l.Xp, l.Yp, l.Sp) if l.Type == "bullet" { offset = 1.2 * fs } else { offset = 0 } if l.Lp == 0 { l.Lp = blinespacing } if l.Opacity == 0 { textopacity = 1 } else { textopacity = openvg.VGfloat(l.Opacity / 100) } // every list item var li, lifont string for ln, tl := range l.Li { if len(l.Color) > 0 { openvg.FillColor(l.Color, textopacity) } else { openvg.FillColor(slide.Fg) } if l.Type == "bullet" { boffset := fs / 2 openvg.Ellipse(x, y+boffset, boffset, boffset) //openvg.Rect(x, y+boffset/2, boffset, boffset) } if l.Type == "number" { li = fmt.Sprintf("%d. ", ln+1) + tl.ListText } else { li = tl.ListText } if len(tl.Color) > 0 { openvg.FillColor(tl.Color, textopacity) } if len(tl.Font) > 0 { lifont = tl.Font } else { lifont = l.Font } showtext(x+offset, y, li, l.Align, lifont, fs) y -= fs * openvg.VGfloat(l.Lp) } } openvg.FillColor(slide.Fg) // every text in the slide const linespacing = 1.8 var tdata string for _, t := range slide.Text { if t.File != "" { tdata = includefile(t.File) } else { tdata = t.Tdata } if t.Font == "" { t.Font = "sans" } if t.Opacity == 0 { textopacity = 1 } else { textopacity = openvg.VGfloat(t.Opacity / 100) } if t.Lp == 0 { t.Lp = linespacing } x, y, fs = dimen(d, t.Xp, t.Yp, t.Sp) td := strings.Split(tdata, "\n") if t.Type == "code" { ls := fs * openvg.VGfloat(t.Lp) t.Font = "mono" tdepth := (ls * openvg.VGfloat(len(td))) + fs openvg.FillColor("rgb(240,240,240)") openvg.Rect(x-20, y-tdepth+(ls), pctwidth(t.Wp, cw, cw-x-20), tdepth) } if t.Color == "" { openvg.FillColor(slide.Fg, textopacity) } else { openvg.FillColor(t.Color, textopacity) } if t.Type == "block" { textwrap(x, y, pctwidth(t.Wp, cw, cw/2), tdata, t.Font, fs, fs*openvg.VGfloat(t.Lp), 0.3) } else { // every text line ls := fs * openvg.VGfloat(t.Lp) for _, txt := range td { showtext(x, y, txt, t.Align, t.Font, fs) y -= ls } } } openvg.FillColor(slide.Fg) openvg.End() if video.altimg != "" { img, ok := imap[video.altimg] if ok { openvg.Img(video.x, video.y, img) } } if video.name != "" { openvg.Video(video.x, video.y, video.w, video.h, video.name) } }