mclock.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * mclock.c - graphical clock for Plan 9 using draw(2) API
  3. *
  4. * Graphical image is based on a clock program for Tektronix vector
  5. * graphics displays written in PDP-11 BASIC by Dave Robinson at the
  6. * University of Delaware in the 1970s.
  7. *
  8. * 071218 - initial release
  9. * 071223 - fix window label, fix redraw after hide, add tongue
  10. */
  11. #include <u.h>
  12. #include <libc.h>
  13. #include <draw.h>
  14. #include <event.h>
  15. int anghr, angmin, dia, offx, offy;
  16. Image *dots, *back, *blk, *wht, *red, *org, *flesh;
  17. Tm *mtime;
  18. enum {DBIG=600,
  19. XDarkOrange=0xff8c0000,
  20. Xwheat=0xf5deb300};
  21. /* hair is head[0..41*2], face is head[27*2..56*2] */
  22. int head[] = {286,386,263,410,243,417,230,415,234,426,227,443,210,450,190,448,
  23. 172,435,168,418,175,400,190,398,201,400,188,390,180,375,178,363,
  24. 172,383,157,390,143,388,130,370,125,350,130,330,140,318,154,318,
  25. 165,325,176,341,182,320,195,305,200,317,212,322,224,319,218,334,
  26. 217,350,221,370,232,382,250,389,264,387,271,380,275,372,276,381,
  27. 279,388,286,386,300,360,297,337,294,327,284,320,300,301,297,297,
  28. 282,286,267,284,257,287,254,280,249,273,236,274,225,290,195,305};
  29. int mouth[] = {235,305,233,297,235,285,243,280,250,282,252,288,248,290,235,305};
  30. int mouth1[] = {240,310,235,305,226,306};
  31. int mouth2[] = {257,287,248,290};
  32. int tongue[] = {235,285,243,280,246,281,247,286,245,289,241,291,237,294,233,294,
  33. 235,285};
  34. int tongue1[] = {241,291,241,286};
  35. int shirt[] = {200,302,192,280,176,256,170,247,186,230,210,222,225,226,237,235,
  36. 222,291,200,302};
  37. int pants[] = {199,164,203,159,202,143,189,138,172,135,160,137,160,166,151,170,
  38. 145,180,142,200,156,230,170,247,186,230,210,222,225,226,237,235,
  39. 245,205,242,190,236,176,229,182,243,153,240,150,228,142,217,145,
  40. 212,162,199,164};
  41. int eyel[] = {294,327,296,335,293,345,285,345,280,337,281,325,284,320,294,327};
  42. int eyer[] = {275,320,278,337,275,345,268,344,260,333,260,323,264,316,275,320};
  43. int pupill[] = {284,320,294,327,293,329,291,333,289,333,286,331,284,325,284,320};
  44. int pupilr[] = {265,316,275,320,275,325,273,330,271,332,269,333,267,331,265,327,
  45. 265,316};
  46. int nose[] = {285,308,288,302,294,301,298,301,302,303,305,305,308,308,309,310,
  47. 310,312,310,316,308,320,305,323,302,324,297,324,294,322,288,317,
  48. 286,312,285,308};
  49. int nose1[] = {275,313,280,317,286,319};
  50. int buttonl[] = {201,210,194,208,190,196,191,187,199,188,208,200,201,210};
  51. int buttonr[] = {224,213,221,209,221,197,228,191,232,200,230,211,224,213};
  52. int tail[] = {40,80,50,76,66,79,90,102,106,151,128,173,145,180};
  53. int cuffl[] = {202,143,197,148,188,150,160,137};
  54. int cuffr[] = {243,153,233,154,217,145};
  55. int legl[] = {239,153,244,134,243,96,229,98,231,130,226,150,233,154,239,153};
  56. int legr[] = {188,150,187,122,182,92,168,91,172,122,173,143,188,150};
  57. int shoel[] = {230,109,223,107,223,98,228,90,231,76,252,70,278,73,288,82,
  58. 284,97,271,99,251,100,244,106,230,109};
  59. int shoel1[] = {223,98,229,98,243,96,251,100};
  60. int shoel2[] = {271,99,248,89};
  61. int shoer[] = {170,102,160,100,160,92,163,85,157,82,160,73,178,66,215,63,
  62. 231,76,228,90,213,97,195,93,186,93,187,100,184,102,170,102};
  63. int shoer1[] = {160,92,168,91,182,92,186,93};
  64. int shoer2[] = {195,93,182,83};
  65. int tick1[] = {302,432,310,446};
  66. int tick2[] = {370,365,384,371};
  67. int tick3[] = {395,270,410,270};
  68. int tick4[] = {370,180,384,173};
  69. int tick5[] = {302,113,310,100};
  70. int tick7[] = {119,113,110,100};
  71. int tick8[] = {40,173,52,180};
  72. int tick9[] = {10,270,25,270};
  73. int tick10[] = {40,371,52,365};
  74. int tick11[] = {110,446,119,432};
  75. int tick12[] = {210,455,210,470};
  76. int armh[] = {-8,0,9,30,10,70,8,100,20,101,23,80,22,30,4,-5};
  77. int armm[] = {-8,0,10,80,8,130,22,134,25,80,4,-5};
  78. int handm[] = {8,140,5,129,8,130,22,134,30,137,27,143,33,163,30,168,
  79. 21,166,18,170,12,168,10,170,5,167,4,195,-4,195,-6,170,
  80. 0,154,8,140};
  81. int handm1[] = {0,154,5,167};
  82. int handm2[] = {14,167,12,158,10,152};
  83. int handm3[] = {12,158,18,152,21,166};
  84. int handm4[] = {20,156,29,151};
  85. int handh[] = {20,130,15,135,6,129,4,155,-4,155,-6,127,-8,121,4,108,
  86. 3,100,8,100,20,101,23,102,21,108,28,126,24,132,20,130};
  87. int handh1[] = {20,130,16,118};
  88. void
  89. xlate(int* in, Point* out, int np)
  90. {
  91. int i;
  92. for (i = 0; i < np; i++) {
  93. out[i].x = offx + (dia * (in[2*i]) + 210) / 420;
  94. out[i].y = offy + (dia * (480 - in[2*i+1]) + 210) / 420;
  95. }
  96. }
  97. void
  98. myfill(int* p, int np, Image* color)
  99. {
  100. Point* out;
  101. out = (Point *)malloc(sizeof(Point) * np);
  102. xlate(p, out, np);
  103. fillpoly(screen, out, np, ~0, color, ZP);
  104. free(out);
  105. }
  106. void
  107. mypoly(int* p, int np, Image* color)
  108. {
  109. Point* out;
  110. out = (Point *)malloc(sizeof(Point) * np);
  111. xlate(p, out, np);
  112. poly(screen, out, np, Enddisc, Enddisc, dia>DBIG?1:0, color, ZP);
  113. free(out);
  114. }
  115. void
  116. arm(int* p, Point* out, int np, double angle)
  117. {
  118. int i;
  119. double cosp, sinp;
  120. for (i = 0; i < np; i++) {
  121. cosp = cos(PI * angle / 180.0);
  122. sinp = sin(PI * angle / 180.0);
  123. out[i].x = p[2*i] * cosp + p[2*i+1] * sinp + 210.5;
  124. out[i].y = p[2*i+1] * cosp - p[2*i] * sinp + 270.5;
  125. }
  126. }
  127. void
  128. polyarm(int *p, int np, Image *color, double angle)
  129. {
  130. Point *tmp, *out;
  131. tmp = (Point *)malloc(sizeof(Point) * np);
  132. out = (Point *)malloc(sizeof(Point) * np);
  133. arm(p, tmp, np, angle);
  134. xlate((int*)tmp, out, np);
  135. poly(screen, out, np, Enddisc, Enddisc, dia>DBIG?1:0, color, ZP);
  136. free(out);
  137. free(tmp);
  138. }
  139. void
  140. fillarm(int *p, int np, Image *color, double angle)
  141. {
  142. Point *tmp, *out;
  143. tmp = (Point *)malloc(sizeof(Point) * np);
  144. out = (Point *)malloc(sizeof(Point) * np);
  145. arm(p, tmp, np, angle);
  146. xlate((int*)tmp, out, np);
  147. fillpoly(screen, out, np, ~0, color, ZP);
  148. free(out);
  149. free(tmp);
  150. }
  151. void
  152. arms(void)
  153. {
  154. /* arms */
  155. fillarm(armh, 8, blk, anghr);
  156. fillarm(armm, 6, blk, angmin);
  157. /* hour hand */
  158. fillarm(handh, 16, wht, anghr);
  159. polyarm(handh, 16, blk, anghr);
  160. polyarm(handh1, 2, blk, anghr);
  161. /* minute hand */
  162. fillarm(handm, 18, wht, angmin);
  163. polyarm(handm, 18, blk, angmin);
  164. polyarm(handm1, 2, blk, angmin);
  165. polyarm(handm2, 3, blk, angmin);
  166. polyarm(handm3, 3, blk, angmin);
  167. polyarm(handm4, 2, blk, angmin);
  168. }
  169. void
  170. redraw(Image *screen)
  171. {
  172. anghr = mtime->hour*30 + mtime->min/2;
  173. angmin = mtime->min*6;
  174. dia = Dx(screen->r) < Dy(screen->r) ? Dx(screen->r) : Dy(screen->r);
  175. offx = screen->r.min.x + (Dx(screen->r) - dia) / 2;
  176. offy = screen->r.min.y + (Dy(screen->r) - dia) / 2;
  177. draw(screen, screen->r, back, nil, ZP);
  178. /* first draw the filled areas */
  179. myfill(head, 42, blk); /* hair */
  180. myfill(&head[27*2], 29, flesh); /* face */
  181. myfill(mouth, 8, blk);
  182. myfill(tongue, 9, red);
  183. myfill(shirt, 10, blk);
  184. myfill(pants, 26, red);
  185. myfill(buttonl, 7, wht);
  186. myfill(buttonr, 7, wht);
  187. myfill(eyel, 8, wht);
  188. myfill(eyer, 8, wht);
  189. myfill(pupill, 8, blk);
  190. myfill(pupilr, 9, blk);
  191. myfill(nose, 18, blk);
  192. myfill(shoel, 13, org);
  193. myfill(shoer, 16, org);
  194. myfill(legl, 8, blk);
  195. myfill(legr, 7, blk);
  196. /* outline the color-filled areas */
  197. mypoly(&head[27*2], 29, blk); /* face */
  198. mypoly(tongue, 9, blk);
  199. mypoly(pants, 26, blk);
  200. mypoly(buttonl, 7, blk);
  201. mypoly(buttonr, 7, blk);
  202. mypoly(eyel, 8, blk);
  203. mypoly(eyer, 8, blk);
  204. mypoly(shoel, 13, blk);
  205. mypoly(shoer, 16, blk);
  206. /* draw the details */
  207. mypoly(nose1, 3, blk);
  208. mypoly(mouth1, 3, blk);
  209. mypoly(mouth2, 2, blk);
  210. mypoly(tongue1, 2, blk);
  211. mypoly(tail, 7, blk);
  212. mypoly(cuffl, 4, blk);
  213. mypoly(cuffr, 3, blk);
  214. mypoly(shoel1, 4, blk);
  215. mypoly(shoel2, 2, blk);
  216. mypoly(shoer1, 4, blk);
  217. mypoly(shoer2, 2, blk);
  218. mypoly(tick1, 2, dots);
  219. mypoly(tick2, 2, dots);
  220. mypoly(tick3, 2, dots);
  221. mypoly(tick4, 2, dots);
  222. mypoly(tick5, 2, dots);
  223. mypoly(tick7, 2, dots);
  224. mypoly(tick8, 2, dots);
  225. mypoly(tick9, 2, dots);
  226. mypoly(tick10, 2, dots);
  227. mypoly(tick11, 2, dots);
  228. mypoly(tick12, 2, dots);
  229. arms();
  230. flushimage(display, 1);
  231. return;
  232. }
  233. void
  234. eresized(int new)
  235. {
  236. if(new && getwindow(display, Refnone) < 0)
  237. fprint(2,"can't reattach to window");
  238. redraw(screen);
  239. }
  240. void
  241. main(void)
  242. {
  243. Event e;
  244. Mouse m;
  245. Menu menu;
  246. char *mstr[] = {"exit", 0};
  247. int key, timer, oldmin;
  248. initdraw(0,0,"mclock");
  249. back = allocimagemix(display, DPalebluegreen, DWhite);
  250. dots = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DBlue);
  251. blk = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DBlack);
  252. wht = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DWhite);
  253. red = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DRed);
  254. org = allocimage(display, Rect(0,0,1,1), CMAP8, 1, XDarkOrange);
  255. flesh = allocimage(display, Rect(0,0,1,1), CMAP8, 1, Xwheat);
  256. mtime = localtime(time(0));
  257. redraw(screen);
  258. einit(Emouse);
  259. timer = etimer(0, 30*1000);
  260. menu.item = mstr;
  261. menu.lasthit = 0;
  262. for(;;) {
  263. key = event(&e);
  264. if(key == Emouse) {
  265. m = e.mouse;
  266. if(m.buttons & 4) {
  267. if(emenuhit(3, &m, &menu) == 0)
  268. exits(0);
  269. }
  270. } else if(key == timer) {
  271. oldmin = mtime->min;
  272. mtime = localtime(time(0));
  273. if(mtime->min != oldmin) redraw(screen);
  274. }
  275. }
  276. }