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 }