pltroff.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <string.h>
  4. #include "pic.h"
  5. extern int dbg;
  6. #define abs(n) (n >= 0 ? n : -(n))
  7. #define max(x,y) ((x)>(y) ? (x) : (y))
  8. char *textshift = "\\v'.2m'"; /* move text this far down */
  9. /* scaling stuff defined by s command as X0,Y0 to X1,Y1 */
  10. /* output dimensions set by -l,-w options to 0,0 to hmax, vmax */
  11. /* default output is 6x6 inches */
  12. double xscale;
  13. double yscale;
  14. double hpos = 0; /* current horizontal position in output coordinate system */
  15. double vpos = 0; /* current vertical position; 0 is top of page */
  16. double htrue = 0; /* where we really are */
  17. double vtrue = 0;
  18. double X0, Y0; /* left bottom of input */
  19. double X1, Y1; /* right top of input */
  20. double hmax; /* right end of output */
  21. double vmax; /* top of output (down is positive) */
  22. extern double deltx;
  23. extern double delty;
  24. extern double xmin, ymin, xmax, ymax;
  25. double xconv(double), yconv(double), xsc(double), ysc(double);
  26. void space(double, double, double, double);
  27. void hgoto(double), vgoto(double), hmot(double), vmot(double);
  28. void move(double, double), movehv(double, double);
  29. void cont(double, double);
  30. void openpl(char *s) /* initialize device; s is residue of .PS invocation line */
  31. {
  32. double maxw, maxh, ratio = 1;
  33. double odeltx = deltx, odelty = delty;
  34. hpos = vpos = 0;
  35. maxw = getfval("maxpswid");
  36. maxh = getfval("maxpsht");
  37. if (deltx > maxw) { /* shrink horizontal */
  38. ratio = maxw / deltx;
  39. deltx *= ratio;
  40. delty *= ratio;
  41. }
  42. if (delty > maxh) { /* shrink vertical */
  43. ratio = maxh / delty;
  44. deltx *= ratio;
  45. delty *= ratio;
  46. }
  47. if (ratio != 1) {
  48. fprintf(stderr, "pic: %g X %g picture shrunk to", odeltx, odelty);
  49. fprintf(stderr, " %g X %g\n", deltx, delty);
  50. }
  51. space(xmin, ymin, xmax, ymax);
  52. printf("... %g %g %g %g\n", xmin, ymin, xmax, ymax);
  53. printf("... %.3fi %.3fi %.3fi %.3fi\n",
  54. xconv(xmin), yconv(ymin), xconv(xmax), yconv(ymax));
  55. printf(".nr 00 \\n(.u\n");
  56. printf(".nf\n");
  57. printf(".PS %.3fi %.3fi %s", yconv(ymin), xconv(xmax), s);
  58. /* assumes \n comes as part of s */
  59. }
  60. void space(double x0, double y0, double x1, double y1) /* set limits of page */
  61. {
  62. X0 = x0;
  63. Y0 = y0;
  64. X1 = x1;
  65. Y1 = y1;
  66. xscale = deltx == 0.0 ? 1.0 : deltx / (X1-X0);
  67. yscale = delty == 0.0 ? 1.0 : delty / (Y1-Y0);
  68. }
  69. double xconv(double x) /* convert x from external to internal form */
  70. {
  71. return (x-X0) * xscale;
  72. }
  73. double xsc(double x) /* convert x from external to internal form, scaling only */
  74. {
  75. return (x) * xscale;
  76. }
  77. double yconv(double y) /* convert y from external to internal form */
  78. {
  79. return (Y1-y) * yscale;
  80. }
  81. double ysc(double y) /* convert y from external to internal form, scaling only */
  82. {
  83. return (y) * yscale;
  84. }
  85. void closepl(char *PEline) /* clean up after finished */
  86. {
  87. movehv(0.0, 0.0); /* get back to where we started */
  88. if (strchr(PEline, 'F') == NULL) {
  89. printf(".sp 1+%.3fi\n", yconv(ymin));
  90. }
  91. printf("%s\n", PEline);
  92. printf(".if \\n(00 .fi\n");
  93. }
  94. void move(double x, double y) /* go to position x, y in external coords */
  95. {
  96. hgoto(xconv(x));
  97. vgoto(yconv(y));
  98. }
  99. void movehv(double h, double v) /* go to internal position h, v */
  100. {
  101. hgoto(h);
  102. vgoto(v);
  103. }
  104. void hmot(double n) /* generate n units of horizontal motion */
  105. {
  106. hpos += n;
  107. }
  108. void vmot(double n) /* generate n units of vertical motion */
  109. {
  110. vpos += n;
  111. }
  112. void hgoto(double n)
  113. {
  114. hpos = n;
  115. }
  116. void vgoto(double n)
  117. {
  118. vpos = n;
  119. }
  120. double fabs(double x)
  121. {
  122. return x < 0 ? -x : x;
  123. }
  124. void hvflush(void) /* get to proper point for output */
  125. {
  126. if (fabs(hpos-htrue) >= 0.0005) {
  127. printf("\\h'%.3fi'", hpos - htrue);
  128. htrue = hpos;
  129. }
  130. if (fabs(vpos-vtrue) >= 0.0005) {
  131. printf("\\v'%.3fi'", vpos - vtrue);
  132. vtrue = vpos;
  133. }
  134. }
  135. void flyback(void) /* return to upper left corner (entry point) */
  136. {
  137. printf(".sp -1\n");
  138. htrue = vtrue = 0;
  139. }
  140. void printlf(int n, char *f)
  141. {
  142. if (f)
  143. printf(".lf %d %s\n", n, f);
  144. else
  145. printf(".lf %d\n", n);
  146. }
  147. void troff(char *s) /* output troff right here */
  148. {
  149. printf("%s\n", s);
  150. }
  151. void label(char *s, int t, int nh) /* text s of type t nh half-lines up */
  152. {
  153. int q;
  154. char *p;
  155. if (!s)
  156. return;
  157. hvflush();
  158. dprintf("label: %s %o %d\n", s, t, nh);
  159. printf("%s", textshift); /* shift down and left */
  160. if (t & ABOVE)
  161. nh++;
  162. else if (t & BELOW)
  163. nh--;
  164. if (nh)
  165. printf("\\v'%du*\\n(.vu/2u'", -nh);
  166. /* just in case the text contains a quote: */
  167. q = 0;
  168. for (p = s; *p; p++)
  169. if (*p == '\'') {
  170. q = 1;
  171. break;
  172. }
  173. t &= ~(ABOVE|BELOW);
  174. if (t & LJUST) {
  175. printf("%s", s);
  176. } else if (t & RJUST) {
  177. if (q)
  178. printf("\\h\\(ts-\\w\\(ts%s\\(tsu\\(ts%s", s, s);
  179. else
  180. printf("\\h'-\\w'%s'u'%s", s, s);
  181. } else { /* CENTER */
  182. if (q)
  183. printf("\\h\\(ts-\\w\\(ts%s\\(tsu/2u\\(ts%s", s, s);
  184. else
  185. printf("\\h'-\\w'%s'u/2u'%s", s, s);
  186. }
  187. printf("\n");
  188. flyback();
  189. }
  190. void line(double x0, double y0, double x1, double y1) /* draw line from x0,y0 to x1,y1 */
  191. {
  192. move(x0, y0);
  193. cont(x1, y1);
  194. }
  195. void arrow(double x0, double y0, double x1, double y1, double w, double h,
  196. double ang, int nhead) /* draw arrow (without shaft) */
  197. {
  198. double alpha, rot, drot, hyp;
  199. double dx, dy;
  200. int i;
  201. rot = atan2(w / 2, h);
  202. hyp = sqrt(w/2 * w/2 + h * h);
  203. alpha = atan2(y1-y0, x1-x0) + ang;
  204. if (nhead < 2)
  205. nhead = 2;
  206. dprintf("rot=%g, hyp=%g, alpha=%g\n", rot, hyp, alpha);
  207. for (i = nhead-1; i >= 0; i--) {
  208. drot = 2 * rot / (double) (nhead-1) * (double) i;
  209. dx = hyp * cos(alpha + PI - rot + drot);
  210. dy = hyp * sin(alpha + PI - rot + drot);
  211. dprintf("dx,dy = %g,%g\n", dx, dy);
  212. line(x1+dx, y1+dy, x1, y1);
  213. }
  214. }
  215. double lastgray = 0;
  216. void fillstart(double v) /* this works only for postscript, obviously. */
  217. { /* uses drechsler's dpost conventions... */
  218. hvflush();
  219. printf("\\X'BeginObject %g setgray'\n", v);
  220. lastgray = v;
  221. flyback();
  222. }
  223. void fillend(int vis, int fill)
  224. {
  225. hvflush();
  226. printf("\\X'EndObject gsave eofill grestore %g setgray %s'\n",
  227. !vis ? lastgray : 0.0,
  228. vis ? "stroke" : "");
  229. /* for dashed: [50] 0 setdash just before stroke. */
  230. lastgray = 0;
  231. flyback();
  232. }
  233. void box(double x0, double y0, double x1, double y1)
  234. {
  235. move(x0, y0);
  236. cont(x0, y1);
  237. cont(x1, y1);
  238. cont(x1, y0);
  239. cont(x0, y0);
  240. }
  241. void cont(double x, double y) /* continue line from here to x,y */
  242. {
  243. double h1, v1;
  244. double dh, dv;
  245. h1 = xconv(x);
  246. v1 = yconv(y);
  247. dh = h1 - hpos;
  248. dv = v1 - vpos;
  249. hvflush();
  250. printf("\\D'l%.3fi %.3fi'\n", dh, dv);
  251. flyback(); /* expensive */
  252. hpos = h1;
  253. vpos = v1;
  254. }
  255. void circle(double x, double y, double r)
  256. {
  257. move(x-r, y);
  258. hvflush();
  259. printf("\\D'c%.3fi'\n", xsc(2 * r));
  260. flyback();
  261. }
  262. void spline(double x, double y, double n, ofloat *p, int dashed, double ddval)
  263. {
  264. int i;
  265. double dx, dy;
  266. double xerr, yerr;
  267. move(x, y);
  268. hvflush();
  269. xerr = yerr = 0.0;
  270. printf("\\D'~");
  271. for (i = 0; i < 2 * n; i += 2) {
  272. dx = xsc(xerr += p[i]);
  273. xerr -= dx/xscale;
  274. dy = ysc(yerr += p[i+1]);
  275. yerr -= dy/yscale;
  276. printf(" %.3fi %.3fi", dx, -dy); /* WATCH SIGN */
  277. }
  278. printf("'\n");
  279. flyback();
  280. }
  281. void ellipse(double x, double y, double r1, double r2)
  282. {
  283. double ir1, ir2;
  284. move(x-r1, y);
  285. hvflush();
  286. ir1 = xsc(r1);
  287. ir2 = ysc(r2);
  288. printf("\\D'e%.3fi %.3fi'\n", 2 * ir1, 2 * abs(ir2));
  289. flyback();
  290. }
  291. void arc(double x, double y, double x0, double y0, double x1, double y1) /* draw arc with center x,y */
  292. {
  293. move(x0, y0);
  294. hvflush();
  295. printf("\\D'a%.3fi %.3fi %.3fi %.3fi'\n",
  296. xsc(x-x0), -ysc(y-y0), xsc(x1-x), -ysc(y1-y)); /* WATCH SIGNS */
  297. flyback();
  298. }
  299. void dot(void) {
  300. hvflush();
  301. /* what character to draw here depends on what's available. */
  302. /* on the 202, l. is good but small. */
  303. /* in general, use a smaller, shifted period and hope */
  304. printf("\\&\\f1\\h'-.1m'\\v'.03m'\\s-3.\\s+3\\fP\n");
  305. flyback();
  306. }