coval.c 4.1 KB

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