linegen.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include "pic.h"
  14. #include "y.tab.h"
  15. obj *linegen(int type)
  16. {
  17. static double prevdx = HT;
  18. static double prevdy = 0;
  19. static double prevw = HT10;
  20. static double prevh = HT5;
  21. int i, j, some, head, ddtype, invis, chop, battr, with;
  22. double ddval, chop1, chop2, x0, y0, x1, y1;
  23. double fillval = 0;
  24. double theta;
  25. double defx, defy, xwith, ywith;
  26. obj *p, *ppos;
  27. static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */
  28. static int ytab[] = { 0, 1, 0, -1 };
  29. double dx[500], dy[500];
  30. int ndxy;
  31. double nx, ny;
  32. Attr *ap, *chop_ap[4];
  33. nx = curx;
  34. ny = cury;
  35. defx = getfval("linewid");
  36. defy = getfval("lineht");
  37. prevh = getfval("arrowht");
  38. prevw = getfval("arrowwid");
  39. dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0;
  40. chop = chop1 = chop2 = 0;
  41. ddtype = ddval = xwith = ywith = 0;
  42. for (i = 0; i < nattr; i++) {
  43. ap = &attr[i];
  44. switch (ap->a_type) {
  45. case TEXTATTR:
  46. savetext(ap->a_sub, ap->a_val.p);
  47. break;
  48. case HEAD:
  49. head += ap->a_val.i;
  50. break;
  51. case INVIS:
  52. invis = INVIS;
  53. break;
  54. case NOEDGE:
  55. battr |= NOEDGEBIT;
  56. break;
  57. case DOT:
  58. case DASH:
  59. ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
  60. if (ap->a_sub == DEFAULT)
  61. ddval = getfval("dashwid");
  62. else
  63. ddval = ap->a_val.f;
  64. break;
  65. case SAME:
  66. dx[ndxy] = prevdx;
  67. dy[ndxy] = prevdy;
  68. some++;
  69. break;
  70. case LEFT:
  71. dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
  72. some++;
  73. hvmode = L_DIR;
  74. break;
  75. case RIGHT:
  76. dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
  77. some++;
  78. hvmode = R_DIR;
  79. break;
  80. case UP:
  81. dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
  82. some++;
  83. hvmode = U_DIR;
  84. break;
  85. case DOWN:
  86. dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
  87. some++;
  88. hvmode = D_DIR;
  89. break;
  90. case HEIGHT: /* length of arrowhead */
  91. prevh = ap->a_val.f;
  92. break;
  93. case WIDTH: /* width of arrowhead */
  94. prevw = ap->a_val.f;
  95. break;
  96. case TO:
  97. if (some) {
  98. nx += dx[ndxy];
  99. ny += dy[ndxy];
  100. ndxy++;
  101. dx[ndxy] = dy[ndxy] = some = 0;
  102. }
  103. ppos = attr[i].a_val.o;
  104. if (ppos == NULL)
  105. ERROR "no tag defined for `to'" FATAL;
  106. dx[ndxy] = ppos->o_x - nx;
  107. dy[ndxy] = ppos->o_y - ny;
  108. some++;
  109. break;
  110. case BY:
  111. if (some) {
  112. nx += dx[ndxy];
  113. ny += dy[ndxy];
  114. ndxy++;
  115. dx[ndxy] = dy[ndxy] = some = 0;
  116. }
  117. ppos = ap->a_val.o;
  118. if (ppos == NULL)
  119. ERROR "no tag defined for `by'" FATAL;
  120. dx[ndxy] = ppos->o_x;
  121. dy[ndxy] = ppos->o_y;
  122. some++;
  123. break;
  124. case THEN: /* turn off any previous accumulation */
  125. if (some) {
  126. nx += dx[ndxy];
  127. ny += dy[ndxy];
  128. ndxy++;
  129. dx[ndxy] = dy[ndxy] = some = 0;
  130. }
  131. break;
  132. case FROM:
  133. case AT:
  134. ppos = ap->a_val.o;
  135. if (ppos == NULL)
  136. ERROR "no tag defined for `from' or `at'" FATAL;
  137. nx = curx = ppos->o_x;
  138. ny = cury = ppos->o_y;
  139. break;
  140. case WITH:
  141. with = ap->a_val.i;
  142. break;
  143. case CHOP:
  144. if (ap->a_sub != PLACENAME) {
  145. if( chop == 0)
  146. chop1 = chop2 = ap->a_val.f;
  147. else
  148. chop2 = ap->a_val.f;
  149. }
  150. chop_ap[chop++] = ap;
  151. break;
  152. case FILL:
  153. battr |= FILLBIT;
  154. if (ap->a_sub == DEFAULT)
  155. fillval = getfval("fillval");
  156. else
  157. fillval = ap->a_val.f;
  158. break;
  159. }
  160. }
  161. if (with) { /* this doesn't work at all */
  162. switch (with) {
  163. case CENTER:
  164. xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break;
  165. }
  166. for (i = 0; i < ndxy; i++) {
  167. dx[i] -= xwith;
  168. dy[i] -= ywith;
  169. }
  170. curx += xwith;
  171. cury += ywith;
  172. }
  173. if (some) {
  174. nx += dx[ndxy];
  175. ny += dy[ndxy];
  176. ndxy++;
  177. defx = dx[ndxy-1];
  178. defy = dy[ndxy-1];
  179. } else {
  180. defx *= xtab[hvmode];
  181. defy *= ytab[hvmode];
  182. dx[ndxy] = defx;
  183. dy[ndxy] = defy;
  184. ndxy++;
  185. nx += defx;
  186. ny += defy;
  187. }
  188. prevdx = defx;
  189. prevdy = defy;
  190. if (chop) {
  191. if (chop == 1 && chop1 == 0) /* just said "chop", so use default */
  192. chop1 = chop2 = getfval("circlerad");
  193. theta = atan2(dy[0], dx[0]);
  194. x0 = chop1 * cos(theta);
  195. y0 = chop1 * sin(theta);
  196. curx += x0;
  197. cury += y0;
  198. dx[0] -= x0;
  199. dy[0] -= y0;
  200. theta = atan2(dy[ndxy-1], dx[ndxy-1]);
  201. x1 = chop2 * cos(theta);
  202. y1 = chop2 * sin(theta);
  203. nx -= x1;
  204. ny -= y1;
  205. dx[ndxy-1] -= x1;
  206. dy[ndxy-1] -= y1;
  207. dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
  208. x0, y0, x1, y1, curx, cury, nx, ny);
  209. }
  210. p = makenode(type, 5 + 2 * ndxy);
  211. curx = p->o_val[0] = nx;
  212. cury = p->o_val[1] = ny;
  213. if (head || type == ARROW) {
  214. p->o_nhead = getfval("arrowhead");
  215. p->o_val[2] = prevw;
  216. p->o_val[3] = prevh;
  217. if (head == 0)
  218. head = HEAD2; /* default arrow head */
  219. }
  220. p->o_attr = head | invis | ddtype | battr;
  221. p->o_fillval = fillval;
  222. p->o_val[4] = ndxy;
  223. nx = p->o_x;
  224. ny = p->o_y;
  225. for (i = 0, j = 5; i < ndxy; i++, j += 2) {
  226. p->o_val[j] = dx[i];
  227. p->o_val[j+1] = dy[i];
  228. if (type == LINE || type == ARROW)
  229. extreme(nx += dx[i], ny += dy[i]);
  230. else if (type == SPLINE && i < ndxy-1) {
  231. /* to compute approx extreme of spline at p,
  232. /* compute midway between p-1 and p+1,
  233. /* then go 3/4 from there to p */
  234. double ex, ey, xi, yi, xi1, yi1;
  235. xi = nx + dx[i]; yi = ny + dy[i]; /* p */
  236. xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
  237. ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */
  238. ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
  239. extreme(ex, ey);
  240. nx = xi; ny = yi;
  241. }
  242. }
  243. p->o_ddval = ddval;
  244. if (dbg) {
  245. printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
  246. for (i = 0, j = 5; i < ndxy; i++, j += 2)
  247. printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
  248. }
  249. extreme(p->o_x, p->o_y);
  250. extreme(curx, cury);
  251. return(p);
  252. }