graph.c 4.1 KB

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