diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/histogram.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/histogram.c')
-rwxr-xr-x | sys/src/cmd/histogram.c | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/sys/src/cmd/histogram.c b/sys/src/cmd/histogram.c new file mode 100755 index 000000000..3de1950fb --- /dev/null +++ b/sys/src/cmd/histogram.c @@ -0,0 +1,314 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <bio.h> +#include <thread.h> +#include <mouse.h> +#include <keyboard.h> + +enum { + STACK = 8*1024, + + Dot = 2, /* height of dot */ + Lx = 4, /* x offset */ + Ly = 4, /* y offset */ + Bw = 2, /* border width */ +}; + +Image *neutral; +Image *light; +Image *dark; +Image *txtcolor; + +char *title = "histogram"; +Rectangle hrect; +Point maxvloc; +double *data; +double vmax = 100, scale = 1.0; +uint nval; +int dontdie = 0, col = 1; + +int colors[][3] = { + { 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF }, /* Peach */ + { DPalebluegreen, DPalegreygreen, DPurpleblue }, /* Aqua */ + { DPaleyellow, DDarkyellow, DYellowgreen }, /* Yellow */ + { DPalegreen, DMedgreen, DDarkgreen }, /* Green */ + { 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF }, /* Blue */ + { 0xEEEEEEFF, 0xCCCCCCFF, 0x888888F }, /* Grey */ +}; + +void +initcolor(int i) +{ + neutral = allocimagemix(display, colors[i][0], DWhite); + light = allocimage(display, Rect(0,0,1,1), CMAP8, 1, colors[i][1]); + dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, colors[i][2]); + txtcolor = display->black; +} + +void* +erealloc(void *v, ulong sz) +{ + v = realloc(v, sz); + if(v == nil){ + sysfatal("realloc: %r"); + threadexitsall("memory"); + } + return v; +} + +Point +datapoint(int x, double v) +{ + Point p; + double y; + + p.x = x; + y = (v*scale) / vmax; + p.y = hrect.max.y - Dy(hrect)*y - Dot; + if(p.y < hrect.min.y) + p.y = hrect.min.y; + if(p.y > hrect.max.y - Dot) + p.y = hrect.max.y - Dot; + return p; +} + +void +drawdatum(int x, double prev, double v) +{ + Point p, q; + + p = datapoint(x, v); + q = datapoint(x, prev); + if(p.y < q.y){ + draw(screen, Rect(p.x, hrect.min.y, p.x+1, p.y), neutral, + nil, ZP); + draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), dark, nil, ZP); + draw(screen, Rect(p.x, q.y+Dot, p.x+1, hrect.max.y), light, + nil, ZP); + }else{ + draw(screen, Rect(p.x, hrect.min.y, p.x+1, q.y), neutral, + nil, ZP); + draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), dark, nil, ZP); + draw(screen, Rect(p.x, p.y+Dot, p.x+1, hrect.max.y), light, + nil, ZP); + } + +} + +void +updatehistogram(double v) +{ + char buf[32]; + + draw(screen, hrect, screen, nil, Pt(hrect.min.x+1, hrect.min.y)); + if(v * scale > vmax) + v = vmax / scale; + drawdatum(hrect.max.x-1, data[0], v); + memmove(&data[1], &data[0], (nval-1) * sizeof data[0]); + data[0] = v; + snprint(buf, sizeof buf, "%0.9f", v); + stringbg(screen, maxvloc, txtcolor, ZP, display->defaultfont, buf, + neutral, ZP); + flushimage(display, 1); +} + +void +redrawhistogram(int new) +{ + Point p, q; + Rectangle r; + uint onval = nval; + int i; + char buf[32]; + + if(new && getwindow(display, Refnone) < 0) + sysfatal("getwindow: %r"); + + r = screen->r; + draw(screen, r, neutral, nil, ZP); + p = string(screen, addpt(r.min, Pt(Lx, Ly)), txtcolor, ZP, + display->defaultfont, title); + + p.x = r.min.x + Lx; + p.y += display->defaultfont->height + Ly; + + q = subpt(r.max, Pt(Lx, Ly)); + hrect = Rpt(p, q); + + maxvloc = Pt(r.max.x - Lx - stringwidth(display->defaultfont, + "999999999"), r.min.y + Ly); + + nval = abs(Dx(hrect)); + if(nval != onval){ + data = erealloc(data, nval * sizeof data[0]); + if(nval > onval) + memset(data+onval, 0, (nval - onval) * sizeof data[0]); + } + + border(screen, hrect, -Bw, dark, ZP); + snprint(buf, sizeof buf, "%0.9f", data[0]); + stringbg(screen, maxvloc, txtcolor, ZP, display->defaultfont, buf, + neutral, ZP); + draw(screen, hrect, neutral, nil, ZP); + for(i = 1; i < nval - 1; i++) + drawdatum(hrect.max.x - i, data[i-1], data[i]); + drawdatum(hrect.min.x, data[i], data[i]); + flushimage(display, 1); +} + +void +reader(void *arg) +{ + int fd; + double v; + char *p, *f[2]; + uchar buf[512]; + Biobufhdr b; + Channel *c = arg; + + threadsetname("reader"); + fd = dup(0, -1); + Binits(&b, fd, OREAD, buf, sizeof buf); + + while((p = Brdline(&b, '\n')) != nil) { + p[Blinelen(&b) - 1] = '\0'; + if(tokenize(p, f, 1) != 1) + continue; + v = strtod(f[0], 0); + send(c, &v); + } + if(!dontdie) + threadexitsall(nil); +} + + +void +histogram(char *rect) +{ + int rm; + double dm; + Channel *dc; + Keyboardctl *kc; + Mouse mm; + Mousectl *mc; + Rune km; + Alt a[] = { + /* c v op */ + {nil, &dm, CHANRCV}, /* data from stdin */ + {nil, &mm, CHANRCV}, /* mouse message */ + {nil, &km, CHANRCV}, /* keyboard runes */ + {nil, &rm, CHANRCV}, /* resize event */ + {nil, nil, CHANEND}, + }; + static char *mitems[] = { + "exit", + nil + }; + static Menu menu = { + mitems, + nil, + -1 + }; + + memset(&mm, 0, sizeof mm); + memset(&km, 0, sizeof km); + dm = rm = 0; + + if(newwindow(rect) < 0) + sysfatal("newwindow: %r"); + if(initdraw(nil, nil, "histogram") < 0) + sysfatal("initdraw: %r"); + + initcolor(col); + + mc = initmouse(nil, screen); + if(!mc) + sysfatal("initmouse: %r"); + kc = initkeyboard(nil); + if(!kc) + sysfatal("initkeyboard: %r"); + + dc = chancreate(sizeof dm, 10); + if(!dc) + sysfatal("chancreate: %r"); + + a[0].c = dc; + a[1].c = mc->c; + a[2].c = kc->c; + a[3].c = mc->resizec; + + proccreate(reader, a[0].c, STACK + sizeof(Biobuf)); + + redrawhistogram(0); + for(;;) + switch(alt(a)){ + case 0: + updatehistogram(dm); + break; + case 1: + if(mm.buttons & 4 && menuhit(3, mc, &menu, nil) == 0) + goto done; + break; + case 2: + if(km == 0x7F) + goto done; + break; + case 3: + redrawhistogram(1); + break; + default: + sysfatal("shouldn't happen"); + } +done: + closekeyboard(kc); + closemouse(mc); + chanfree(a[0].c); + threadexitsall(nil); +} + +void +usage(void) +{ + fprint(2, "usage: histogram [-h] [-c index] [-r minx,miny,maxx,maxy] " + "[-s scale] [-t title] [-v maxv]\n"); + exits("usage"); +} + +void +threadmain(int argc, char **argv) +{ + char *p, *q; + + p = "-r 0,0,400,150"; + + ARGBEGIN{ + case 'v': + vmax = strtod(EARGF(usage()), 0); + break; + case 'r': + p = smprint("-r %s", EARGF(usage())); + break; + case 's': + scale = strtod(EARGF(usage()), 0); + if(scale <= 0) + usage(); + break; + case 'h': + dontdie = 1; + break; + case 't': + title = EARGF(usage()); + break; + case 'c': + col = atoi(EARGF(usage())) % nelem(colors); + break; + default: + usage(); + }ARGEND; + + while((q = strchr(p, ',')) != nil) + *q = ' '; + + histogram(p); +} |