cline.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. /* Line Options (+ means implemented)
  7. +arrow
  8. +arrowshape
  9. +capstyle
  10. +fill
  11. joinstyle
  12. +smooth
  13. +splinesteps
  14. +stipple
  15. +tags
  16. +width
  17. */
  18. static
  19. TkStab tklines[] =
  20. {
  21. "none", 0,
  22. "first", TkCarrowf,
  23. "last", TkCarrowl,
  24. "both", TkCarrowf|TkCarrowl,
  25. nil
  26. };
  27. static
  28. TkStab tkcapstyle[] =
  29. {
  30. "butt", Endsquare,
  31. "projecting", Endsquare,
  32. "round", Enddisc,
  33. nil
  34. };
  35. static
  36. TkOption lineopts[] =
  37. {
  38. "arrow", OPTstab, O(TkCline, arrow), tklines,
  39. "arrowshape", OPTfrac, O(TkCline, shape[0]), IAUX(3),
  40. "width", OPTnnfrac, O(TkCline, width), nil,
  41. "stipple", OPTbmap, O(TkCline, stipple), nil,
  42. "smooth", OPTstab, O(TkCline, smooth), tkbool,
  43. "splinesteps", OPTdist, O(TkCline, steps), nil,
  44. "capstyle", OPTstab, O(TkCline, capstyle), tkcapstyle,
  45. nil
  46. };
  47. static
  48. TkOption itemopts[] =
  49. {
  50. "tags", OPTctag, O(TkCitem, tags), nil,
  51. "fill", OPTcolr, O(TkCitem, env), IAUX(TkCforegnd),
  52. nil
  53. };
  54. void
  55. tkcvslinesize(TkCitem *i)
  56. {
  57. TkCline *l;
  58. int j, w, as, shape[3], arrow;
  59. l = TKobj(TkCline, i);
  60. w = TKF2I(l->width);
  61. i->p.bb = bbnil;
  62. tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb);
  63. l->arrowf = l->capstyle;
  64. l->arrowl = l->capstyle;
  65. if(l->arrow != 0) {
  66. as = w/3;
  67. if(as < 1)
  68. as = 1;
  69. for(j = 0; j < 3; j++) {
  70. shape[j] = l->shape[j];
  71. if(shape[j] == 0)
  72. shape[j] = as * cvslshape[j];
  73. }
  74. arrow = ARROW(TKF2I(shape[0]), TKF2I(shape[1]), TKF2I(shape[2]));
  75. if(l->arrow & TkCarrowf)
  76. l->arrowf = arrow;
  77. if(l->arrow & TkCarrowl)
  78. l->arrowl = arrow;
  79. w += shape[2];
  80. }
  81. i->p.bb = insetrect(i->p.bb, -w);
  82. }
  83. char*
  84. tkcvslinecreat(Tk* tk, char *arg, char **val)
  85. {
  86. char *e;
  87. TkCline *l;
  88. TkCitem *i;
  89. TkCanvas *c;
  90. TkOptab tko[3];
  91. c = TKobj(TkCanvas, tk);
  92. i = tkcnewitem(tk, TkCVline, sizeof(TkCitem)+sizeof(TkCline));
  93. if(i == nil)
  94. return TkNomem;
  95. l = TKobj(TkCline, i);
  96. l->width = TKI2F(1);
  97. e = tkparsepts(tk->env->top, &i->p, &arg, 0);
  98. if(e != nil) {
  99. tkcvsfreeitem(i);
  100. return e;
  101. }
  102. tko[0].ptr = l;
  103. tko[0].optab = lineopts;
  104. tko[1].ptr = i;
  105. tko[1].optab = itemopts;
  106. tko[2].ptr = nil;
  107. e = tkparse(tk->env->top, arg, tko, nil);
  108. if(e != nil) {
  109. tkcvsfreeitem(i);
  110. return e;
  111. }
  112. tkmkpen(&l->pen, i->env, l->stipple);
  113. e = tkcaddtag(tk, i, 1);
  114. if(e != nil) {
  115. tkcvsfreeitem(i);
  116. return e;
  117. }
  118. tkcvslinesize(i);
  119. e = tkvalue(val, "%d", i->id);
  120. if(e != nil) {
  121. tkcvsfreeitem(i);
  122. return e;
  123. }
  124. tkcvsappend(c, i);
  125. tkbbmax(&c->update, &i->p.bb);
  126. tkcvssetdirty(tk);
  127. return nil;
  128. }
  129. char*
  130. tkcvslinecget(TkCitem *i, char *arg, char **val)
  131. {
  132. TkOptab tko[3];
  133. TkCline *l = TKobj(TkCline, i);
  134. tko[0].ptr = l;
  135. tko[0].optab = lineopts;
  136. tko[1].ptr = i;
  137. tko[1].optab = itemopts;
  138. tko[2].ptr = nil;
  139. return tkgencget(tko, arg, val, i->env->top);
  140. }
  141. char*
  142. tkcvslineconf(Tk *tk, TkCitem *i, char *arg)
  143. {
  144. char *e;
  145. TkOptab tko[3];
  146. TkCline *l = TKobj(TkCline, i);
  147. tko[0].ptr = l;
  148. tko[0].optab = lineopts;
  149. tko[1].ptr = i;
  150. tko[1].optab = itemopts;
  151. tko[2].ptr = nil;
  152. e = tkparse(tk->env->top, arg, tko, nil);
  153. tkmkpen(&l->pen, i->env, l->stipple);
  154. tkcvslinesize(i);
  155. return e;
  156. }
  157. void
  158. tkcvslinefree(TkCitem *i)
  159. {
  160. TkCline *l;
  161. l = TKobj(TkCline, i);
  162. if(l->stipple)
  163. freeimage(l->stipple);
  164. if(l->pen)
  165. freeimage(l->pen);
  166. }
  167. void
  168. tkcvslinedraw(Image *img, TkCitem *i, TkEnv *pe)
  169. {
  170. int w;
  171. Point *p;
  172. TkCline *l;
  173. Image *pen;
  174. USED(pe);
  175. l = TKobj(TkCline, i);
  176. pen = l->pen;
  177. if(pen == nil)
  178. pen = tkgc(i->env, TkCforegnd);
  179. w = TKF2I(l->width)/2;
  180. if(w < 0)
  181. return;
  182. p = i->p.drawpt;
  183. if(l->smooth == BoolT && i->p.npoint >= 3)
  184. bezspline(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
  185. else
  186. poly(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]);
  187. }
  188. char*
  189. tkcvslinecoord(TkCitem *i, char *arg, int x, int y)
  190. {
  191. char *e;
  192. TkCpoints p;
  193. if(arg == nil) {
  194. tkxlatepts(i->p.parampt, i->p.npoint, x, y);
  195. tkxlatepts(i->p.drawpt, i->p.npoint, TKF2I(x), TKF2I(y));
  196. i->p.bb = rectaddpt(i->p.bb, Pt(TKF2I(x), TKF2I(y)));
  197. }
  198. else {
  199. e = tkparsepts(i->env->top, &p, &arg, 0);
  200. if(e != nil)
  201. return e;
  202. if(p.npoint < 2) {
  203. tkfreepoint(&p);
  204. return TkFewpt;
  205. }
  206. tkfreepoint(&i->p);
  207. i->p = p;
  208. tkcvslinesize(i);
  209. }
  210. return nil;
  211. }
  212. int
  213. tkcvslinehit(TkCitem *i, Point p)
  214. {
  215. TkCline *l;
  216. int w, np, r;
  217. Point *pp;
  218. l = TKobj(TkCline, i);
  219. w =TKF2I(l->width) + 2; /* 2 for slop */
  220. if (l->smooth == BoolT) {
  221. np = getbezsplinepts(i->p.drawpt, i->p.npoint, &pp);
  222. r = tklinehit(pp, np, w, p);
  223. free(pp);
  224. } else
  225. r = tklinehit(i->p.drawpt, i->p.npoint, w, p);
  226. return r;
  227. }