crect.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include <lib9.h>
  2. #include <kernel.h>
  3. #include "draw.h"
  4. #include "tk.h"
  5. #include "canvs.h"
  6. #define O(t, e) ((long)(&((t*)0)->e))
  7. /* Rectangle Options (+ means implemented)
  8. +fill
  9. +outline
  10. +stipple
  11. +tags
  12. +width
  13. */
  14. typedef struct TkCrect TkCrect;
  15. struct TkCrect
  16. {
  17. int width;
  18. Image* stipple;
  19. };
  20. static
  21. TkOption rectopts[] =
  22. {
  23. "width", OPTnnfrac, O(TkCrect, width), nil,
  24. "stipple", OPTbmap, O(TkCrect, stipple), nil,
  25. nil
  26. };
  27. static
  28. TkOption itemopts[] =
  29. {
  30. "tags", OPTctag, O(TkCitem, tags), nil,
  31. "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill),
  32. "outline", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd),
  33. nil
  34. };
  35. void
  36. tkcvsrectsize(TkCitem *i)
  37. {
  38. TkCrect *r;
  39. int w;
  40. r = TKobj(TkCrect, i);
  41. w = TKF2I(r->width)*2;
  42. i->p.bb = bbnil;
  43. tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
  44. i->p.bb = insetrect(i->p.bb, -w);
  45. }
  46. static void
  47. tkmkstipple(Image *stipple)
  48. {
  49. int locked;
  50. if (stipple != nil && !stipple->repl) {
  51. locked = lockdisplay(stipple->display);
  52. replclipr(stipple, 1, huger);
  53. if (locked)
  54. unlockdisplay(stipple->display);
  55. }
  56. }
  57. char*
  58. tkcvsrectcreat(Tk* tk, char *arg, char **val)
  59. {
  60. char *e;
  61. TkCrect *r;
  62. TkCitem *i;
  63. TkCanvas *c;
  64. TkOptab tko[3];
  65. c = TKobj(TkCanvas, tk);
  66. i = tkcnewitem(tk, TkCVrect, sizeof(TkCitem)+sizeof(TkCrect));
  67. if(i == nil)
  68. return TkNomem;
  69. r = TKobj(TkCrect, i);
  70. r->width = TKI2F(1);
  71. e = tkparsepts(tk->env->top, &i->p, &arg, 0);
  72. if(e != nil) {
  73. tkcvsfreeitem(i);
  74. return e;
  75. }
  76. if(i->p.npoint != 2) {
  77. tkcvsfreeitem(i);
  78. return TkFewpt;
  79. }
  80. tko[0].ptr = r;
  81. tko[0].optab = rectopts;
  82. tko[1].ptr = i;
  83. tko[1].optab = itemopts;
  84. tko[2].ptr = nil;
  85. e = tkparse(tk->env->top, arg, tko, nil);
  86. if(e != nil) {
  87. tkcvsfreeitem(i);
  88. return e;
  89. }
  90. tkmkstipple(r->stipple);
  91. e = tkcaddtag(tk, i, 1);
  92. if(e != nil) {
  93. tkcvsfreeitem(i);
  94. return e;
  95. }
  96. tkcvsrectsize(i);
  97. e = tkvalue(val, "%d", i->id);
  98. if(e != nil) {
  99. tkcvsfreeitem(i);
  100. return e;
  101. }
  102. tkcvsappend(c, i);
  103. tkbbmax(&c->update, &i->p.bb);
  104. tkcvssetdirty(tk);
  105. return nil;
  106. }
  107. char*
  108. tkcvsrectcget(TkCitem *i, char *arg, char **val)
  109. {
  110. TkOptab tko[3];
  111. TkCrect *r = TKobj(TkCrect, i);
  112. tko[0].ptr = r;
  113. tko[0].optab = rectopts;
  114. tko[1].ptr = i;
  115. tko[1].optab = itemopts;
  116. tko[2].ptr = nil;
  117. return tkgencget(tko, arg, val, i->env->top);
  118. }
  119. char*
  120. tkcvsrectconf(Tk *tk, TkCitem *i, char *arg)
  121. {
  122. char *e;
  123. TkOptab tko[3];
  124. TkCrect *r = TKobj(TkCrect, i);
  125. tko[0].ptr = r;
  126. tko[0].optab = rectopts;
  127. tko[1].ptr = i;
  128. tko[1].optab = itemopts;
  129. tko[2].ptr = nil;
  130. e = tkparse(tk->env->top, arg, tko, nil);
  131. tkcvsrectsize(i);
  132. tkmkstipple(r->stipple);
  133. return e;
  134. }
  135. void
  136. tkcvsrectfree(TkCitem *i)
  137. {
  138. TkCrect *r;
  139. r = TKobj(TkCrect, i);
  140. if(r->stipple)
  141. freeimage(r->stipple);
  142. }
  143. void
  144. tkcvsrectdraw(Image *img, TkCitem *i, TkEnv *pe)
  145. {
  146. int lw, rw;
  147. TkEnv *e;
  148. TkCrect *r;
  149. Rectangle d, rr;
  150. Point tr, bl;
  151. Image *pen;
  152. USED(pe);
  153. d.min = i->p.drawpt[0];
  154. d.max = i->p.drawpt[1];
  155. e = i->env;
  156. r = TKobj(TkCrect, i);
  157. pen = nil;
  158. if((e->set & (1<<TkCfill)))
  159. pen = tkgc(e, TkCfill);
  160. if(pen != nil)
  161. draw(img, d, pen, r->stipple, d.min);
  162. tr.x = d.max.x;
  163. tr.y = d.min.y;
  164. bl.x = d.min.x;
  165. bl.y = d.max.y;
  166. rw = (TKF2I(r->width) + 1)/2;
  167. if(rw <= 0)
  168. return;
  169. lw = (TKF2I(r->width))/2;
  170. pen = tkgc(e, TkCforegnd);
  171. if(pen != nil) {
  172. /* horizontal lines first */
  173. rr.min.x = d.min.x - lw;
  174. rr.max.x = d.max.x + rw;
  175. rr.min.y = d.min.y - lw;
  176. rr.max.y = d.min.y + rw;
  177. draw(img, rr, pen, nil, rr.min);
  178. rr.min.y += Dy(d);
  179. rr.max.y += Dy(d);
  180. draw(img, rr, pen, nil, rr.min);
  181. /* now the vertical */
  182. /* horizontal lines first */
  183. rr.min.x = d.min.x - lw;
  184. rr.max.x = d.min.x + rw;
  185. rr.min.y = d.min.y + rw;
  186. rr.max.y = d.max.y - lw;
  187. draw(img, rr, pen, nil, rr.min);
  188. rr.min.x += Dx(d);
  189. rr.max.x += Dx(d);
  190. draw(img, rr, pen, nil, rr.min);
  191. }
  192. }
  193. char*
  194. tkcvsrectcoord(TkCitem *i, char *arg, int x, int y)
  195. {
  196. char *e;
  197. TkCpoints p;
  198. if(arg == nil) {
  199. tkxlatepts(i->p.parampt, i->p.npoint, x, y);
  200. tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
  201. i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
  202. }
  203. else {
  204. e = tkparsepts(i->env->top, &p, &arg, 0);
  205. if(e != nil)
  206. return e;
  207. if(p.npoint != 2) {
  208. tkfreepoint(&p);
  209. return TkFewpt;
  210. }
  211. tkfreepoint(&i->p);
  212. i->p = p;
  213. tkcvsrectsize(i);
  214. }
  215. return nil;
  216. }