print.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 <math.h>
  11. #include "pic.h"
  12. #include "y.tab.h"
  13. void dotext(obj *);
  14. void dotline(double, double, double, double, int, double);
  15. void dotbox(double, double, double, double, int, double);
  16. void ellipse(double, double, double, double);
  17. void circle(double, double, double);
  18. void arc(double, double, double, double, double, double);
  19. void arrow(double, double, double, double, double, double, double, int);
  20. void line(double, double, double, double);
  21. void box(double, double, double, double);
  22. void spline(double x, double y, double n, ofloat *p, int dashed, double ddval);
  23. void move(double, double);
  24. void troff(char *);
  25. void dot(void);
  26. void fillstart(double), fillend(int vis, int noedge);
  27. void print(void)
  28. {
  29. obj *p;
  30. int i, j, k, m;
  31. int fill, vis, invis;
  32. double x0, y0, x1, y1, ox, oy, dx, dy, ndx, ndy;
  33. for (i = 0; i < nobj; i++) {
  34. p = objlist[i];
  35. ox = p->o_x;
  36. oy = p->o_y;
  37. if (p->o_count >= 1)
  38. x1 = p->o_val[0];
  39. if (p->o_count >= 2)
  40. y1 = p->o_val[1];
  41. m = p->o_mode;
  42. fill = p->o_attr & FILLBIT;
  43. invis = p->o_attr & INVIS;
  44. vis = !invis;
  45. switch (p->o_type) {
  46. case TROFF:
  47. troff(text[p->o_nt1].t_val);
  48. break;
  49. case BOX:
  50. case BLOCK:
  51. x0 = ox - x1 / 2;
  52. y0 = oy - y1 / 2;
  53. x1 = ox + x1 / 2;
  54. y1 = oy + y1 / 2;
  55. if (fill) {
  56. move(x0, y0);
  57. fillstart(p->o_fillval);
  58. }
  59. if (p->o_type == BLOCK){
  60. ; /* nothing at all */
  61. }else if (invis && !fill){
  62. ; /* nothing at all */
  63. }else if (p->o_attr & (DOTBIT|DASHBIT))
  64. dotbox(x0, y0, x1, y1, p->o_attr, p->o_ddval);
  65. else
  66. box(x0, y0, x1, y1);
  67. if (fill)
  68. fillend(vis, fill);
  69. move(ox, oy);
  70. dotext(p); /* if there are any text strings */
  71. if (ishor(m))
  72. move(isright(m) ? x1 : x0, oy); /* right side */
  73. else
  74. move(ox, isdown(m) ? y0 : y1); /* bottom */
  75. break;
  76. case BLOCKEND:
  77. break;
  78. case CIRCLE:
  79. if (fill)
  80. fillstart(p->o_fillval);
  81. if (vis || fill)
  82. circle(ox, oy, x1);
  83. if (fill)
  84. fillend(vis, fill);
  85. move(ox, oy);
  86. dotext(p);
  87. if (ishor(m))
  88. move(ox + isright(m) ? x1 : -x1, oy);
  89. else
  90. move(ox, oy + isup(m) ? x1 : -x1);
  91. break;
  92. case ELLIPSE:
  93. if (fill)
  94. fillstart(p->o_fillval);
  95. if (vis || fill)
  96. ellipse(ox, oy, x1, y1);
  97. if (fill)
  98. fillend(vis, fill);
  99. move(ox, oy);
  100. dotext(p);
  101. if (ishor(m))
  102. move(ox + isright(m) ? x1 : -x1, oy);
  103. else
  104. move(ox, oy - isdown(m) ? y1 : -y1);
  105. break;
  106. case ARC:
  107. if (fill) {
  108. move(ox, oy);
  109. fillstart(p->o_fillval);
  110. }
  111. if (p->o_attr & HEAD1)
  112. arrow(x1 - (y1 - oy), y1 + (x1 - ox),
  113. x1, y1, p->o_val[4], p->o_val[5], p->o_val[5]/p->o_val[6]/2, p->o_nhead);
  114. if (invis && !fill)
  115. /* probably wrong when it's cw */
  116. move(x1, y1);
  117. else
  118. arc(ox, oy, x1, y1, p->o_val[2], p->o_val[3]);
  119. if (p->o_attr & HEAD2)
  120. arrow(p->o_val[2] + p->o_val[3] - oy, p->o_val[3] - (p->o_val[2] - ox),
  121. p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5], -p->o_val[5]/p->o_val[6]/2, p->o_nhead);
  122. if (fill)
  123. fillend(vis, fill);
  124. if (p->o_attr & CW_ARC)
  125. move(x1, y1); /* because drawn backwards */
  126. move(ox, oy);
  127. dotext(p);
  128. break;
  129. case LINE:
  130. case ARROW:
  131. case SPLINE:
  132. if (fill) {
  133. move(ox, oy);
  134. fillstart(p->o_fillval);
  135. }
  136. if (vis && p->o_attr & HEAD1)
  137. arrow(ox + p->o_val[5], oy + p->o_val[6], ox, oy, p->o_val[2], p->o_val[3], 0.0, p->o_nhead);
  138. if (invis && !fill)
  139. move(x1, y1);
  140. else if (p->o_type == SPLINE)
  141. spline(ox, oy, p->o_val[4], &p->o_val[5], p->o_attr & (DOTBIT|DASHBIT), p->o_ddval);
  142. else {
  143. dx = ox;
  144. dy = oy;
  145. for (k=0, j=5; k < p->o_val[4]; k++, j += 2) {
  146. ndx = dx + p->o_val[j];
  147. ndy = dy + p->o_val[j+1];
  148. if (p->o_attr & (DOTBIT|DASHBIT))
  149. dotline(dx, dy, ndx, ndy, p->o_attr, p->o_ddval);
  150. else
  151. line(dx, dy, ndx, ndy);
  152. dx = ndx;
  153. dy = ndy;
  154. }
  155. }
  156. if (vis && p->o_attr & HEAD2) {
  157. dx = ox;
  158. dy = oy;
  159. for (k = 0, j = 5; k < p->o_val[4] - 1; k++, j += 2) {
  160. dx += p->o_val[j];
  161. dy += p->o_val[j+1];
  162. }
  163. arrow(dx, dy, x1, y1, p->o_val[2], p->o_val[3], 0.0, p->o_nhead);
  164. }
  165. if (fill)
  166. fillend(vis, fill);
  167. move((ox + x1)/2, (oy + y1)/2); /* center */
  168. dotext(p);
  169. break;
  170. case MOVE:
  171. move(ox, oy);
  172. break;
  173. case TEXT:
  174. move(ox, oy);
  175. if (vis)
  176. dotext(p);
  177. break;
  178. }
  179. }
  180. }
  181. void dotline(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted line */
  182. {
  183. static double prevval = 0.05; /* 20 per inch by default */
  184. int i, numdots;
  185. double a, b, dx, dy;
  186. if (ddval == 0)
  187. ddval = prevval;
  188. prevval = ddval;
  189. /* don't save dot/dash value */
  190. dx = x1 - x0;
  191. dy = y1 - y0;
  192. if (ddtype & DOTBIT) {
  193. numdots = sqrt(dx*dx + dy*dy) / prevval + 0.5;
  194. if (numdots > 0)
  195. for (i = 0; i <= numdots; i++) {
  196. a = (double) i / (double) numdots;
  197. move(x0 + (a * dx), y0 + (a * dy));
  198. dot();
  199. }
  200. } else if (ddtype & DASHBIT) {
  201. double d, dashsize, spacesize;
  202. d = sqrt(dx*dx + dy*dy);
  203. if (d <= 2 * prevval) {
  204. line(x0, y0, x1, y1);
  205. return;
  206. }
  207. numdots = d / (2 * prevval) + 1; /* ceiling */
  208. dashsize = prevval;
  209. spacesize = (d - numdots * dashsize) / (numdots - 1);
  210. for (i = 0; i < numdots-1; i++) {
  211. a = i * (dashsize + spacesize) / d;
  212. b = a + dashsize / d;
  213. line(x0 + (a*dx), y0 + (a*dy), x0 + (b*dx), y0 + (b*dy));
  214. a = b;
  215. b = a + spacesize / d;
  216. move(x0 + (a*dx), y0 + (a*dy));
  217. }
  218. line(x0 + (b * dx), y0 + (b * dy), x1, y1);
  219. }
  220. prevval = 0.05;
  221. }
  222. void dotbox(double x0, double y0, double x1, double y1, int ddtype, double ddval) /* dotted or dashed box */
  223. {
  224. dotline(x0, y0, x1, y0, ddtype, ddval);
  225. dotline(x1, y0, x1, y1, ddtype, ddval);
  226. dotline(x1, y1, x0, y1, ddtype, ddval);
  227. dotline(x0, y1, x0, y0, ddtype, ddval);
  228. }
  229. void dotext(obj *p) /* print text strings of p in proper vertical spacing */
  230. {
  231. int i, nhalf;
  232. void label(char *, int, int);
  233. nhalf = p->o_nt2 - p->o_nt1 - 1;
  234. for (i = p->o_nt1; i < p->o_nt2; i++) {
  235. label(text[i].t_val, text[i].t_type, nhalf);
  236. nhalf -= 2;
  237. }
  238. }