Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
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 };
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;
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 };
35 Memimage*
36 allocrepl(ulong color)
37 {
38 Memimage *m;
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 }
47 static void
48 ginit(void)
49 {
50 static int first = 1;
51 int i;
53 if(!first)
54 return;
56 first = 0;
57 memimageinit();
58 smallfont = openmemsubfont(unsharp("#9/font/lucidasans/lstr.10"));
59 black = memblack;
60 blue = allocrepl(DBlue);
61 red = allocrepl(DRed);
62 grid = allocrepl(0x77777777);
63 for(i=0; i<nelem(fill)/2 && i<nelem(lofill) && i<nelem(hifill); i++){
64 lofill[i] = allocrepl(fill[2*i]);
65 hifill[i] = allocrepl(fill[2*i+1]);
66 }
67 }
69 static void
70 mklabel(char *str, int v)
71 {
72 if(v < 0){
73 v = -v;
74 *str++ = '-';
75 }
76 if(v < 10000)
77 sprint(str, "%d", v);
78 else if(v < 10000000)
79 sprint(str, "%dk", v/1000);
80 else
81 sprint(str, "%dM", v/1000000);
82 }
84 static void
85 drawlabel(Memimage *m, Point p, int n)
86 {
87 char buf[30];
88 Point w;
90 mklabel(buf, n);
91 w = memsubfontwidth(smallfont, buf);
92 memimagestring(m, Pt(p.x-5-w.x, p.y), memblack, ZP, smallfont, buf);
93 }
95 static int
96 scalept(int val, int valmin, int valmax, int ptmin, int ptmax)
97 {
98 if(val <= valmin)
99 val = valmin;
100 if(val >= valmax)
101 val = valmax;
102 if(valmax == valmin)
103 valmax++;
104 return ptmin + (vlong)(val-valmin)*(ptmax-ptmin)/(valmax-valmin);
107 Memimage*
108 statgraph(Graph *g)
110 int i, lastlo, nbin, x, lo, hi, min, max, first;
111 Memimage *m;
112 Rectangle r;
113 Statbin *b, bin[2000]; /* 32 kB, but whack is worse */
115 needstack(8192); /* double check that bin didn't kill us */
117 if(g->wid <= MinWidth)
118 g->wid = DefaultWidth;
119 if(g->ht <= MinHeight)
120 g->ht = DefaultHeight;
121 if(g->wid > nelem(bin))
122 g->wid = nelem(bin);
123 if(g->fill < 0)
124 g->fill = ((uint)g->arg>>8)%nelem(lofill);
125 if(g->fill > nelem(lofill))
126 g->fill %= nelem(lofill);
128 nbin = g->wid - (Left+Right);
129 binstats(g->fn, g->arg, g->t0, g->t1, bin, nbin);
131 /*
132 * compute bounds
133 */
134 min = g->min;
135 max = g->max;
136 if(min < 0 || max <= min){
137 min = max = 0;
138 first = 1;
139 for(i=0; i<nbin; i++){
140 b = &bin[i];
141 if(b->nsamp == 0)
142 continue;
143 if(first || b->min < min)
144 min = b->min;
145 if(first || b->max > max)
146 max = b->max;
147 first = 0;
151 qlock(&memdrawlock);
152 ginit();
153 if(smallfont==nil || black==nil || blue==nil || red==nil || hifill==nil || lofill==nil){
154 werrstr("graphics initialization failed");
155 qunlock(&memdrawlock);
156 return nil;
159 /* fresh image */
160 m = allocmemimage(Rect(0,0,g->wid,g->ht), ABGR32);
161 if(m == nil){
162 qunlock(&memdrawlock);
163 return nil;
165 r = Rect(Left, Top, g->wid-Right, g->ht-Bottom);
166 memfillcolor(m, DTransparent);
168 /* x axis */
169 memimagedraw(m, Rect(r.min.x, r.max.y, r.max.x, r.max.y+1), black, ZP, memopaque, ZP, S);
171 /* y labels */
172 drawlabel(m, r.min, max);
173 if(min != 0)
174 drawlabel(m, Pt(r.min.x, r.max.y-smallfont->height), min);
176 /* actual data */
177 lastlo = -1;
178 for(i=0; i<nbin; i++){
179 b = &bin[i];
180 if(b->nsamp == 0)
181 continue;
182 lo = scalept(b->min, min, max, r.max.y, r.min.y);
183 hi = scalept(b->max, min, max, r.max.y, r.min.y);
184 x = r.min.x+i;
185 hi-=2;
186 if(0)
187 if(lastlo != -1){
188 if(lastlo < lo)
189 memimagedraw(m, Rect(x-1, lastlo, x, lo), hifill[g->fill], ZP, memopaque, ZP, S);
190 else if(lastlo > lo)
191 memimagedraw(m, Rect(x-1, lo, x, lastlo), hifill[g->fill], ZP, memopaque, ZP, S);
193 memimagedraw(m, Rect(x, hi, x+1,lo), hifill[g->fill], ZP, memopaque, ZP, S);
194 memimagedraw(m, Rect(x, lo, x+1, r.max.y), lofill[g->fill], ZP, memopaque, ZP, S);
195 lastlo = lo;
198 if(bin[nbin-1].nsamp)
199 drawlabel(m, Pt(r.max.x, r.min.y+(Dy(r)-smallfont->height)/2), bin[nbin-1].avg);
200 qunlock(&memdrawlock);
201 return m;