plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

graph.c (4187B)


      1 #include "stdinc.h"
      2 #include "dat.h"
      3 #include "fns.h"
      4 
      5 enum
      6 {
      7 	Top = 1,
      8 	Bottom = 1,
      9 	Left = 40,
     10 	Right = 0,
     11 	MinWidth = Left+Right+2,
     12 	MinHeight = Top+Bottom+2,
     13 	DefaultWidth = Left+Right+500,
     14 	DefaultHeight = Top+Bottom+40
     15 };
     16 
     17 QLock memdrawlock;
     18 static Memsubfont *smallfont;
     19 static Memimage *black;
     20 static Memimage *blue;
     21 static Memimage *red;
     22 static Memimage *lofill[6];
     23 static Memimage *hifill[6];
     24 static Memimage *grid;
     25 
     26 static ulong fill[] = {
     27 	0xFFAAAAFF,	0xBB5D5DFF,	/* peach */
     28 	DPalegreygreen, DPurpleblue,	/* aqua */
     29 	DDarkyellow, DYellowgreen,	/* yellow */
     30 	DMedgreen, DDarkgreen,		/* green */
     31 	0x00AAFFFF, 0x0088CCFF,	/* blue */
     32 	0xCCCCCCFF, 0x888888FF,	/* grey */
     33 };
     34 
     35 Memimage*
     36 allocrepl(ulong color)
     37 {
     38 	Memimage *m;
     39 
     40 	m = allocmemimage(Rect(0,0,1,1), RGB24);
     41 	memfillcolor(m, color);
     42 	m->flags |= Frepl;
     43 	m->clipr = Rect(-1000000, -1000000, 1000000, 1000000);
     44 	return m;
     45 }
     46 
     47 static void
     48 ginit(void)
     49 {
     50 	static int first = 1;
     51 	int i;
     52 
     53 	if(!first)
     54 		return;
     55 
     56 	first = 0;
     57 	memimageinit();
     58 #ifdef PLAN9PORT
     59 	smallfont = openmemsubfont(unsharp("#9/font/lucsans/lstr.10"));
     60 #else
     61 	smallfont = openmemsubfont("/lib/font/bit/lucidasans/lstr.10");
     62 #endif
     63 	black = memblack;
     64 	blue = allocrepl(DBlue);
     65 	red = allocrepl(DRed);
     66 	grid = allocrepl(0x77777777);
     67 	for(i=0; i<nelem(fill)/2 && i<nelem(lofill) && i<nelem(hifill); i++){
     68 		lofill[i] = allocrepl(fill[2*i]);
     69 		hifill[i] = allocrepl(fill[2*i+1]);
     70 	}
     71 }
     72 
     73 static void
     74 mklabel(char *str, int v)
     75 {
     76 	if(v < 0){
     77 		v = -v;
     78 		*str++ = '-';
     79 	}
     80 	if(v < 10000)
     81 		sprint(str, "%d", v);
     82 	else if(v < 10000000)
     83 		sprint(str, "%dk", v/1000);
     84 	else
     85 		sprint(str, "%dM", v/1000000);
     86 }
     87 
     88 static void
     89 drawlabel(Memimage *m, Point p, int n)
     90 {
     91 	char buf[30];
     92 	Point w;
     93 
     94 	mklabel(buf, n);
     95 	w = memsubfontwidth(smallfont, buf);
     96 	memimagestring(m, Pt(p.x-5-w.x, p.y), memblack, ZP, smallfont, buf);
     97 }
     98 
     99 static int
    100 scalept(int val, int valmin, int valmax, int ptmin, int ptmax)
    101 {
    102 	if(val <= valmin)
    103 		val = valmin;
    104 	if(val >= valmax)
    105 		val = valmax;
    106 	if(valmax == valmin)
    107 		valmax++;
    108 	return ptmin + (vlong)(val-valmin)*(ptmax-ptmin)/(valmax-valmin);
    109 }
    110 
    111 Memimage*
    112 statgraph(Graph *g)
    113 {
    114 	int i, nbin, x, lo, hi, min, max, first;
    115 	Memimage *m;
    116 	Rectangle r;
    117 	Statbin *b, bin[2000];	/* 32 kB, but whack is worse */
    118 
    119 	needstack(8192);	/* double check that bin didn't kill us */
    120 
    121 	if(g->wid <= MinWidth)
    122 		g->wid = DefaultWidth;
    123 	if(g->ht <= MinHeight)
    124 		g->ht = DefaultHeight;
    125 	if(g->wid > nelem(bin))
    126 		g->wid = nelem(bin);
    127 	if(g->fill < 0)
    128 		g->fill = ((uint)(uintptr)g->arg>>8)%nelem(lofill);
    129 	if(g->fill > nelem(lofill))
    130 		g->fill %= nelem(lofill);
    131 
    132 	nbin = g->wid - (Left+Right);
    133 	binstats(g->fn, g->arg, g->t0, g->t1, bin, nbin);
    134 
    135 	/*
    136 	 * compute bounds
    137 	 */
    138 	min = g->min;
    139 	max = g->max;
    140 	if(min < 0 || max <= min){
    141 		min = max = 0;
    142 		first = 1;
    143 		for(i=0; i<nbin; i++){
    144 			b = &bin[i];
    145 			if(b->nsamp == 0)
    146 				continue;
    147 			if(first || b->min < min)
    148 				min = b->min;
    149 			if(first || b->max > max)
    150 				max = b->max;
    151 			first = 0;
    152 		}
    153 	}
    154 
    155 	qlock(&memdrawlock);
    156 	ginit();
    157 	if(smallfont==nil || black==nil || blue==nil || red==nil || hifill[0]==nil || lofill[0]==nil){
    158 		werrstr("graphics initialization failed: %r");
    159 		qunlock(&memdrawlock);
    160 		return nil;
    161 	}
    162 
    163 	/* fresh image */
    164 	m = allocmemimage(Rect(0,0,g->wid,g->ht), ABGR32);
    165 	if(m == nil){
    166 		qunlock(&memdrawlock);
    167 		return nil;
    168 	}
    169 	r = Rect(Left, Top, g->wid-Right, g->ht-Bottom);
    170 	memfillcolor(m, DTransparent);
    171 
    172 	/* x axis */
    173 	memimagedraw(m, Rect(r.min.x, r.max.y, r.max.x, r.max.y+1), black, ZP, memopaque, ZP, S);
    174 
    175 	/* y labels */
    176 	drawlabel(m, r.min, max);
    177 	if(min != 0)
    178 		drawlabel(m, Pt(r.min.x, r.max.y-smallfont->height), min);
    179 
    180 	/* actual data */
    181 	for(i=0; i<nbin; i++){
    182 		b = &bin[i];
    183 		if(b->nsamp == 0)
    184 			continue;
    185 		lo = scalept(b->min, min, max, r.max.y, r.min.y);
    186 		hi = scalept(b->max, min, max, r.max.y, r.min.y);
    187 		x = r.min.x+i;
    188 		hi-=2;
    189 		memimagedraw(m, Rect(x, hi, x+1,lo), hifill[g->fill%nelem(hifill)], ZP, memopaque, ZP, S);
    190 		memimagedraw(m, Rect(x, lo, x+1, r.max.y), lofill[g->fill%nelem(lofill)], ZP, memopaque, ZP, S);
    191 	}
    192 
    193 	if(bin[nbin-1].nsamp)
    194 		drawlabel(m, Pt(r.max.x, r.min.y+(Dy(r)-smallfont->height)/2), bin[nbin-1].avg);
    195 	qunlock(&memdrawlock);
    196 	return m;
    197 }