carcs.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. /* Arc Options (+ means implemented)
  8. +extent
  9. +fill
  10. +outline
  11. outlinestipple
  12. +start
  13. +stipple
  14. +style (+pieslice chord +arc)
  15. +tags
  16. +width
  17. */
  18. typedef struct TkCarc TkCarc;
  19. struct TkCarc
  20. {
  21. int width;
  22. int start;
  23. int extent;
  24. int style;
  25. Image* stipple;
  26. Image* pen;
  27. };
  28. enum Style
  29. {
  30. Pieslice,
  31. Chord,
  32. Arc
  33. };
  34. static
  35. TkStab tkstyle[] =
  36. {
  37. "pieslice", Pieslice,
  38. "arc", Arc,
  39. "chord", Arc, /* Can't do chords */
  40. nil
  41. };
  42. static
  43. TkOption arcopts[] =
  44. {
  45. "start", OPTfrac, O(TkCarc, start), nil,
  46. "extent", OPTfrac, O(TkCarc, extent), nil,
  47. "style", OPTstab, O(TkCarc, style), tkstyle,
  48. "width", OPTnnfrac, O(TkCarc, width), nil,
  49. "stipple", OPTbmap, O(TkCarc, stipple), nil,
  50. nil
  51. };
  52. static
  53. TkOption itemopts[] =
  54. {
  55. "tags", OPTctag, O(TkCitem, tags), nil,
  56. "fill", OPTcolr, O(TkCitem, env), IAUX(TkCfill),
  57. "outline", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd),
  58. nil
  59. };
  60. void
  61. tkcvsarcsize(TkCitem *i)
  62. {
  63. int w;
  64. TkCarc *a;
  65. a = TKobj(TkCarc, i);
  66. w = TKF2I(a->width)*2;
  67. i->p.bb = bbnil;
  68. tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
  69. i->p.bb = insetrect(i->p.bb, -w);
  70. }
  71. char*
  72. tkcvsarccreat(Tk* tk, char *arg, char **val)
  73. {
  74. char *e;
  75. TkCarc *a;
  76. TkCitem *i;
  77. TkCanvas *c;
  78. TkOptab tko[3];
  79. c = TKobj(TkCanvas, tk);
  80. i = tkcnewitem(tk, TkCVarc, sizeof(TkCitem)+sizeof(TkCarc));
  81. if(i == nil)
  82. return TkNomem;
  83. a = TKobj(TkCarc, i);
  84. a->width = TKI2F(1);
  85. e = tkparsepts(tk->env->top, &i->p, &arg, 0);
  86. if(e != nil) {
  87. tkcvsfreeitem(i);
  88. return e;
  89. }
  90. if(i->p.npoint != 2) {
  91. tkcvsfreeitem(i);
  92. return TkFewpt;
  93. }
  94. tko[0].ptr = a;
  95. tko[0].optab = arcopts;
  96. tko[1].ptr = i;
  97. tko[1].optab = itemopts;
  98. tko[2].ptr = nil;
  99. e = tkparse(tk->env->top, arg, tko, nil);
  100. if(e != nil) {
  101. tkcvsfreeitem(i);
  102. return e;
  103. }
  104. e = tkcaddtag(tk, i, 1);
  105. if(e != nil) {
  106. tkcvsfreeitem(i);
  107. return e;
  108. }
  109. tkcvsarcsize(i);
  110. tkmkpen(&a->pen, i->env, a->stipple);
  111. tkcvsappend(c, i);
  112. tkbbmax(&c->update, &i->p.bb);
  113. tkcvssetdirty(tk);
  114. return tkvalue(val, "%d", i->id);
  115. }
  116. char*
  117. tkcvsarccget(TkCitem *i, char *arg, char **val)
  118. {
  119. TkOptab tko[3];
  120. TkCarc *a = TKobj(TkCarc, i);
  121. tko[0].ptr = a;
  122. tko[0].optab = arcopts;
  123. tko[1].ptr = i;
  124. tko[1].optab = itemopts;
  125. tko[2].ptr = nil;
  126. return tkgencget(tko, arg, val, i->env->top);
  127. }
  128. char*
  129. tkcvsarcconf(Tk *tk, TkCitem *i, char *arg)
  130. {
  131. char *e;
  132. TkOptab tko[3];
  133. TkCarc *a = TKobj(TkCarc, i);
  134. tko[0].ptr = a;
  135. tko[0].optab = arcopts;
  136. tko[1].ptr = i;
  137. tko[1].optab = itemopts;
  138. tko[2].ptr = nil;
  139. e = tkparse(tk->env->top, arg, tko, nil);
  140. tkcvsarcsize(i);
  141. tkmkpen(&a->pen, i->env, a->stipple);
  142. return e;
  143. }
  144. void
  145. tkcvsarcfree(TkCitem *i)
  146. {
  147. TkCarc *a;
  148. a = TKobj(TkCarc, i);
  149. if(a->stipple)
  150. freeimage(a->stipple);
  151. if(a->pen)
  152. freeimage(a->pen);
  153. }
  154. void
  155. tkcvsarcdraw(Image *img, TkCitem *i, TkEnv *pe)
  156. {
  157. TkEnv *e;
  158. TkCarc *a;
  159. Rectangle d;
  160. int w, dx, dy;
  161. int s, ext, s0, s1, e0, e1, l;
  162. Image *pen, *col, *tmp;
  163. Point p0, p1, c;
  164. extern void drawarc(Point,int,int,int,int,int,Image *,Image *,Image *);
  165. USED(pe);
  166. d.min = i->p.drawpt[0];
  167. d.max = i->p.drawpt[1];
  168. e = i->env;
  169. a = TKobj(TkCarc, i);
  170. pen = a->pen;
  171. if(pen == nil && (e->set & (1<<TkCfill)))
  172. pen = tkgc(e, TkCfill);
  173. w = TKF2I(a->width)/2;
  174. if(w < 0)
  175. return;
  176. d = canonrect(d);
  177. dx = Dx(d)/2;
  178. dy = Dy(d)/2;
  179. c.x = (d.min.x+d.max.x)/2;
  180. c.y = (d.min.y+d.max.y)/2;
  181. s = TKF2I(a->start);
  182. ext = TKF2I(a->extent);
  183. /*
  184. if(ext == 0)
  185. ext = 90;
  186. */
  187. if(a->style != Arc && pen != nil)
  188. fillarc(img, c, dx, dy, pen, Pt(0,0), s, ext);
  189. col = tkgc(e, TkCforegnd);
  190. arc(img, c, dx, dy, w, col, Pt(0,0), s, ext);
  191. if(a->style == Pieslice){
  192. /*
  193. * It is difficult to compute the intersection of the lines
  194. * and the ellipse using integers, so let the draw library
  195. * do it for us: use a full ellipse as the source of color
  196. * for drawing the lines.
  197. */
  198. tmp = allocimage(img->display, d, img->chan, 0, DNofill);
  199. if(tmp == nil)
  200. return;
  201. /* copy dest to tmp so lines don't spill beyond edge of ellipse */
  202. drawop(tmp, d, img, nil, d.min, S);
  203. fillellipse(tmp, c, dx, dy, col, Pt(0,0));
  204. icossin(s, &s1, &s0);
  205. icossin(s+ext, &e1, &e0);
  206. if(dx > dy)
  207. l = 2*dx+1;
  208. else
  209. l = 2*dy+1;
  210. p0 = Pt(c.x+l*s1/ICOSSCALE, c.y-l*s0/ICOSSCALE);
  211. p1 = Pt(c.x+l*e1/ICOSSCALE, c.y-l*e0/ICOSSCALE);
  212. line(img, c, p0, Endsquare, Endsquare, w, tmp, c);
  213. line(img, c, p1, Endsquare, Endsquare, w, tmp, c);
  214. freeimage(tmp);
  215. }
  216. }
  217. char*
  218. tkcvsarccoord(TkCitem *i, char *arg, int x, int y)
  219. {
  220. char *e;
  221. TkCpoints p;
  222. if(arg == nil) {
  223. tkxlatepts(i->p.parampt, i->p.npoint, x, y);
  224. tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
  225. i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
  226. }
  227. else {
  228. e = tkparsepts(i->env->top, &p, &arg, 0);
  229. if(e != nil)
  230. return e;
  231. if(p.npoint != 2) {
  232. tkfreepoint(&p);
  233. return TkFewpt;
  234. }
  235. tkfreepoint(&i->p);
  236. i->p = p;
  237. tkcvsarcsize(i);
  238. }
  239. return nil;
  240. }