home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume23 / transfig / part04 < prev    next >
Text File  |  1991-06-19  |  42KB  |  1,574 lines

  1. Path: j.cc.purdue.edu!mentor.cc.purdue.edu!noose.ecn.purdue.edu!samsung!zaphod.mps.ohio-state.edu!usc!apple!bbn.com!papaya.bbn.com!rsalz
  2. From: rsalz@bbn.com (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v23i017:  Tools for creating TeX documents with portable graphics, Part04/06
  5. Message-ID: <2814@litchi.bbn.com>
  6. Date: 31 Aug 90 13:43:20 GMT
  7. Organization: BBN Systems and Technologies, Cambridge MA
  8. Lines: 1562
  9. Approved: rsalz@uunet.UU.NET
  10. X-Checksum-Snefru: ae3f8421 b1d964da adbd526c 6f318e10
  11.  
  12. Submitted-by: Micah Beck <beck@cs.cornell.edu>
  13. Posting-number: Volume 23, Issue 17
  14. Archive-name: transfig/part04
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 4 (of 6)."
  23. # Contents:  transfig/fig2dev/dev/genlatex.c
  24. #   transfig/fig2dev/dev/genps.c
  25. # Wrapped by beck@rocky on Thu May 17 15:56:13 1990
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'transfig/fig2dev/dev/genlatex.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'transfig/fig2dev/dev/genlatex.c'\"
  29. else
  30. echo shar: Extracting \"'transfig/fig2dev/dev/genlatex.c'\" \(20332 characters\)
  31. sed "s/^X//" >'transfig/fig2dev/dev/genlatex.c' <<'END_OF_FILE'
  32. X/* 
  33. X *    genlatex.c : LaTeX driver for fig2dev
  34. X *
  35. X *    Author: Frank Schmuck, Cornell University 6/88
  36. X *     Converted from fig2latex 5/89 by Micah Beck
  37. X *
  38. X*/
  39. X#ifdef hpux
  40. X#include <sys/types.h>
  41. X#endif
  42. X#include <sys/file.h>
  43. X#include <stdio.h>
  44. X#include <math.h>
  45. X#include "object.h"
  46. X#include "fig2dev.h"
  47. X#include "texfonts.h"
  48. X
  49. Xextern char *strchr();
  50. Xextern void printf(), fprintf();
  51. Xextern double rad2deg, sin(), cos(), acos(), fabs(), atan();
  52. X
  53. X#ifdef hpux
  54. X#define rint(a) floor((a)+0.5)     /* close enough? */
  55. X#endif
  56. X
  57. X#ifdef gould
  58. X#define rint(a) floor((a)+0.5)     /* close enough? */
  59. X#endif
  60. X
  61. X/* 
  62. X *  Installation dependent constants:
  63. X *
  64. X *  THINDOT    latex command for generating a dot if line width = \thinlines
  65. X *  THICKDOT    latex command for generating a dot if line width = \thicklines
  66. X *  MIN_LEN    shortest slanted line that latex can produce; shorter lines will
  67. X *        we translated into a sequence of dots generated by \multiput.
  68. X *  THICK_LDOT    latex command for generating the dot for making short slanted
  69. X *        lines if line width = \thinlines
  70. X *  THIN_LDOT    ...  if line width = \thicklines
  71. X */
  72. X#define THICKDOT    "\\tenrm ."
  73. X#define THINDOT        "\\sevrm ."
  74. Xdouble    THIN_XOFF =    (0.1/72.0);
  75. Xdouble    THIN_YOFF =    (0.7/72.0);
  76. Xdouble    THICK_XOFF =    (0.4/72.0);
  77. Xdouble    THICK_YOFF =    (0.6/72.0);
  78. X#define THICK_LDOT    "\\sevrm ."
  79. X#define THIN_LDOT    "\\fivrm ."
  80. Xdouble    THIN_LXOFF =    (0.1/72.0);
  81. Xdouble    THIN_LYOFF =    (0.7/72.0);
  82. Xdouble    THICK_LXOFF =    (0.4/72.0);
  83. Xdouble    THICK_LYOFF =    (0.6/72.0);
  84. X#define MIN_LEN        (13.0/72.0)    /* 13  points */
  85. X
  86. X/*
  87. X *  other constants and macros
  88. X */
  89. X#define TOP        840
  90. X#define THINLINES    1
  91. X#define THICKLINES    2
  92. X
  93. X/*
  94. X * Cornell DVI-to-IP has trouble with circles of radius greater than 8pt.
  95. X */
  96. X#ifdef CORNELL
  97. X#define MAXCIRCLEDIA    16
  98. X#else
  99. X#define MAXCIRCLEDIA    80
  100. X#endif
  101. X#define MAXCIRCLERAD    ((MAXCIRCLEDIA-0.5)/(2*72.27))
  102. X
  103. X#define    SWAP(x,y)    {tmp=x; x=y; y=tmp;}
  104. X#define TRANS(x,y)        (*translate_coordinates)(&x,&y)
  105. X#define TRANS2(x1,y1,x2,y2)    (*translate_coordinates)(&x1,&y1); \
  106. X                (*translate_coordinates)(&x2,&y2)
  107. X#define TRANSD(x,y)        (*translate_coordinates_d)(&x,&y)
  108. X#define    MIN(x,y)    (((x) <= (y))? (x): (y))
  109. X#define    MAX(x,y)    (((x) >= (y))? (x): (y))
  110. X#define    ABS(x)        (((x) >= 0)? (x): -(x))
  111. X#define round(x)    ((int) ((x) + ((x >= 0)? 0.5: -0.5)))
  112. X#define round4(x)    ((round(10000.0*(x))/10000.0))
  113. X
  114. Xchar        thindot [] = THINDOT;
  115. Xchar        thickdot[] = THICKDOT;
  116. Xchar        thin_ldot [] = THIN_LDOT;
  117. Xchar        thick_ldot[] = THICK_LDOT;
  118. X
  119. Xint        coord_system;
  120. Xint        verbose = 0;
  121. Xdouble        dash_mag = 1.0;
  122. Xint        thick_width = 1;
  123. Xdouble        tolerance = 2.0;
  124. Xdouble        arc_tolerance = 1.0;
  125. Xint        (*translate_coordinates)() = NULL;
  126. Xint        (*translate_coordinates_d)() = NULL;
  127. Xdouble        unitlength;
  128. Xint        cur_thickness = -1;
  129. Xdouble        ldot_diameter = 1.0/72.0;
  130. Xchar        *dot_cmd = thindot;
  131. Xchar        *ldot_cmd = thin_ldot;
  132. Xdouble        dot_xoffset;
  133. Xdouble        dot_yoffset;
  134. Xdouble        ldot_xoffset;
  135. Xdouble        ldot_yoffset;
  136. X
  137. Xstatic translate1(xp, yp)
  138. Xint    *xp, *yp;
  139. X{
  140. X    *xp = *xp + 1;
  141. X    *yp = *yp + 1;
  142. X    }
  143. X
  144. Xstatic translate2(xp, yp)
  145. Xint    *xp, *yp;
  146. X{
  147. X    *xp = *xp + 1;
  148. X    *yp = TOP - *yp -1;
  149. X    }
  150. X
  151. Xstatic translate1_d(xp, yp)
  152. Xdouble    *xp, *yp;
  153. X{
  154. X    *xp = *xp + 1.0;
  155. X    *yp = *yp + 1.0;
  156. X    }
  157. X
  158. Xstatic translate2_d(xp, yp)
  159. Xdouble    *xp, *yp;
  160. X{
  161. X    *xp = *xp + 1.0;
  162. X    *yp = (double)TOP - *yp -1.0;
  163. X    }
  164. X
  165. Xvoid genlatex_option(opt, optarg)
  166. Xchar opt, *optarg;
  167. X{
  168. X    switch (opt) {
  169. X    case 'f':        /* set default text font */
  170. X    {   int i;
  171. X
  172. X        for ( i = 1; i <= MAXFONT + 1; i++ )
  173. X        if ( !strcmp(optarg, fontnames[i]) ) break;
  174. X
  175. X        if ( i > MAXFONT + 1 )
  176. X        fprintf(stderr,
  177. X            "warning: non-standard font name %s\n", optarg);
  178. X    }
  179. X        
  180. X        fontnames[0] = fontnames[1] = optarg;
  181. X        break;
  182. X
  183. X    case 'l':        /* set thin/thick line threshold */
  184. X        thick_width = atoi(optarg);
  185. X        break;
  186. X
  187. X    case 'd':
  188. X        dash_mag = atof(optarg);    /* set dash magnification */
  189. X        break;
  190. X
  191. X    case 'v':
  192. X        verbose = 1;        /* verbose mode */
  193. X        break;
  194. X
  195. X    case 's':
  196. X        if (font_size <= 0 || font_size > MAXFONTSIZE) {
  197. X        fprintf(stderr,
  198. X            "warning: font size %d out of bounds\n", font_size);
  199. X        }
  200. X        break;
  201. X
  202. X    case 'm':
  203. X    case 'L':
  204. X        break;
  205. X
  206. X    default:
  207. X        put_msg(Err_badarg, opt, "latex");
  208. X        exit(1);
  209. X        break;
  210. X    }
  211. X}
  212. X
  213. Xvoid genlatex_start(objects)
  214. XF_compound    *objects;
  215. X{
  216. X    int tmp;
  217. X
  218. X    fontsizes[0] = fontsizes[1] = TEXFONTSIZE(font_size);
  219. X
  220. X    coord_system = objects->nwcorner.y;
  221. X     unitlength = mag/objects->nwcorner.x;
  222. X
  223. X    switch (coord_system) {
  224. X        case 1:
  225. X        translate_coordinates = translate1;
  226. X        translate_coordinates_d = translate1_d;
  227. X        break;
  228. X        case 2:
  229. X        translate_coordinates = translate2;
  230. X        translate_coordinates_d = translate2_d;
  231. X        break;
  232. X        default:
  233. X        fprintf(stderr, "Wrong coordinate system; cannot continue\n");
  234. X        return;
  235. X        }
  236. X
  237. X    TRANS2(llx, lly, urx, ury);
  238. X    if (llx > urx) SWAP(llx, urx)
  239. X    if (lly > ury) SWAP(lly, ury)
  240. X
  241. X    /* LaTeX start */
  242. X    fprintf(tfp, "\\setlength{\\unitlength}{%.4fin}%%\n",
  243. X                        round4(unitlength));
  244. X    fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n",
  245. X                      urx-llx, ury-lly, llx, lly);
  246. X}
  247. X
  248. Xvoid genlatex_end()
  249. X{
  250. X    /* LaTeX ending */
  251. X    fprintf(tfp, "\\end{picture}\n");
  252. X}
  253. X
  254. Xstatic set_linewidth(w)
  255. Xint    w;
  256. X{
  257. X    int        latex_w;
  258. X
  259. X    if (w == 0) return;
  260. X    /* latex only knows thin lines or thick lines */
  261. X    latex_w = (w >= thick_width)? THICKLINES: THINLINES;
  262. X    if (latex_w != cur_thickness) {
  263. X        cur_thickness = latex_w;
  264. X        if (cur_thickness == THICKLINES) {
  265. X        fprintf(tfp, "\\thicklines\n");
  266. X        dot_cmd = thickdot;
  267. X        dot_xoffset = round4(THICK_XOFF/unitlength);
  268. X        dot_yoffset = round4(THICK_YOFF/unitlength);
  269. X        ldot_cmd = thick_ldot;
  270. X        ldot_xoffset = round4(THICK_LXOFF/unitlength);
  271. X        ldot_yoffset = round4(THICK_LYOFF/unitlength);
  272. X        }
  273. X        else {
  274. X        fprintf(tfp, "\\thinlines\n");
  275. X        dot_cmd = thin_ldot;
  276. X        dot_xoffset = round4(THIN_XOFF/unitlength);
  277. X        dot_yoffset = round4(THIN_YOFF/unitlength);
  278. X        ldot_cmd = thin_ldot;
  279. X        ldot_xoffset = round4(THIN_LXOFF/unitlength);
  280. X        ldot_yoffset = round4(THIN_LYOFF/unitlength);
  281. X        }
  282. X        }
  283. X    }
  284. X
  285. Xvoid genlatex_line(l)
  286. XF_line    *l;
  287. X{
  288. X    F_point        *p, *q;
  289. X    int        x, y, llx, lly, urx, ury, arrow;
  290. X
  291. X    if (verbose) fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n");
  292. X
  293. X    set_linewidth(l->thickness);
  294. X
  295. X    p = l->points;
  296. X    q = p->next;
  297. X
  298. X    if (q == NULL) { /* A single point line */
  299. X        x = p->x; y = p->y;
  300. X        TRANS(x, y);
  301. X        fprintf(tfp, "\\put(%3d,%3d){\\makebox(%.4f,%.4f){%s}}\n",
  302. X          x, y, dot_xoffset, dot_yoffset, dot_cmd);
  303. X        return;
  304. X        }
  305. X
  306. X    if (l->type == T_BOX) { /* A box */
  307. X        x = p->x; y = p->y;
  308. X        TRANS(x, y);
  309. X        llx = urx = x;
  310. X        lly = ury = y;
  311. X        while (q != NULL) {
  312. X        x = q->x; y = q->y;
  313. X        TRANS(x, y);
  314. X        if (x < llx) llx = x;
  315. X        if (y < lly) lly = y;
  316. X        if (x > urx) urx = x;
  317. X        if (y > ury) ury = y;
  318. X        q = q->next;
  319. X        }
  320. X        put_box (llx, lly, urx, ury, l->style, l->style_val);
  321. X        return;
  322. X        }
  323. X
  324. X    while (q != NULL) {
  325. X        arrow = 0;
  326. X        if (l->for_arrow  &&  q->next == NULL)
  327. X        arrow = 1;
  328. X        if (l->back_arrow  &&  p == l->points)
  329. X        arrow = (arrow)? 2: -1;
  330. X        single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val);
  331. X        p = q;
  332. X        q = q->next;
  333. X        }
  334. X
  335. X    if (l->area_fill && (int)l->area_fill != DEFAULT)
  336. X        fprintf(stderr, "Line area fill not implemented\n");
  337. X    }
  338. X
  339. Xstatic single_line (x1, y1, x2, y2, arrow, style, val)
  340. Xint    x1, y1, x2, y2, arrow, style;
  341. Xdouble    val;
  342. X{
  343. X    int    dx, dy, sx, sy;
  344. X    double l, m, deviation;
  345. X
  346. X    TRANS2(x1, y1, x2, y2);
  347. X    dx = x2-x1;
  348. X    dy = y2-y1;
  349. X    /*** compute direction vector ***/
  350. X    get_slope(dx, dy, &sx, &sy, arrow);
  351. X    /*** compute line length in x-direction ***/
  352. X    if (sx == 0) {
  353. X        l = (double)abs(dy);
  354. X    } else {
  355. X        m = (double)abs(sy) / (double)abs(sx);
  356. X        l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m);
  357. X        deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy));
  358. X        if (deviation > tolerance)
  359. X        fprintf(stderr,
  360. X          "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n",
  361. X          dx, dy, deviation);
  362. X    }
  363. X    l = round4(l);
  364. X    /*** output letex command ***/
  365. X    switch (style) {
  366. X        case SOLID_LINE:
  367. X        put_solidline(x1, y1, sx, sy, l, arrow);
  368. X        break;
  369. X        case DASH_LINE:
  370. X        put_dashline(x1, y1, sx, sy, l, arrow, val);
  371. X        break;
  372. X        case DOTTED_LINE:
  373. X        put_dotline(x1, y1, sx, sy, l, arrow, val);
  374. X        break;
  375. X        }
  376. X    }
  377. X
  378. X
  379. X/*
  380. X * draw box
  381. X */
  382. Xstatic put_box (llx, lly, urx, ury, style, val)
  383. Xint    llx, lly, urx, ury, style;
  384. Xdouble    val;
  385. X{
  386. X    int    dlen;
  387. X
  388. X    switch (style) {
  389. X        case SOLID_LINE:
  390. X        fprintf(tfp, "\\put(%3d,%3d){\\framebox(%d,%d){}}\n",
  391. X          llx, lly, urx-llx, ury-lly);
  392. X        break;
  393. X        case DASH_LINE:
  394. X        dlen = round(val*dash_mag);
  395. X        fprintf(tfp, "\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n",
  396. X          llx, lly, dlen, urx-llx, ury-lly);
  397. X        break;
  398. X        case DOTTED_LINE:
  399. X        put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val);
  400. X        put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val);
  401. X        put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val);
  402. X        put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val);
  403. X        break;
  404. X        }
  405. X    return;
  406. X    }
  407. X
  408. X/*
  409. X * draw a solid line given latex slope
  410. X */
  411. Xstatic put_solidline (x, y, sx, sy, l, arrow)
  412. Xint    x, y, sx, sy, arrow;
  413. Xdouble    l;
  414. X{
  415. X    double    cosine;        /* cosine of line angle */
  416. X    double    dx, dy;
  417. X    int    x2, y2, n;
  418. X
  419. X    if (sx) {
  420. X        cosine = (double)abs(sx) / hypot((double)sx, (double)sy);
  421. X        x2 = (sx >= 0)? x + round(l): x - round(l);
  422. X        y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx);
  423. X        }
  424. X    else {
  425. X        cosine = 1.0;
  426. X        x2 = x;
  427. X        y2 = (sy >= 0)? y + round(l): y - round(l);
  428. X        }
  429. X    if (sx == 0  ||  sy == 0  ||  (l/cosine)*unitlength >= MIN_LEN) {
  430. X        switch (arrow) {
  431. X        case 0:  /* simple line */
  432. X        fprintf(tfp, "\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy);
  433. X        break;
  434. X        case 1:  /* forward arrow */
  435. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy);
  436. X        break;
  437. X        case -1: /* backward arrow */
  438. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy);
  439. X        break;
  440. X        case 2:  /* double arrow */
  441. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){  0}}\n", x,y,-sx,-sy);
  442. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy);
  443. X        break;
  444. X        }
  445. X        if (l == floor(l))
  446. X        fprintf(tfp, "{%3.0f}}\n", l);
  447. X        else
  448. X        fprintf(tfp, "{%7.3f}}\n", l);
  449. X        }
  450. X    else {
  451. X        n = 2 * (l/cosine) / (ldot_diameter/unitlength);
  452. X        fprintf(stderr, "Line too short; will do %d dots\n", n);
  453. X        dx = l / (double)n;
  454. X        if (sx < 0) dx = -dx;
  455. X        dy = dx * (double)sy / (double)sx;
  456. X        fprintf(tfp, 
  457. X          "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n",
  458. X          x, y, dx, dy, n+1, ldot_xoffset, ldot_yoffset, ldot_cmd);
  459. X        if (arrow == 1  ||  arrow == 2)  /* forward arrow */
  460. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy);
  461. X        if (arrow == -1  ||  arrow == 2) /* backward arrow */
  462. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy);
  463. X        }
  464. X    }
  465. X
  466. X/*
  467. X * draw a dashed line given latex slope
  468. X */
  469. Xstatic put_dashline (x, y, sx, sy, l, arrow, val)
  470. Xint    x, y, sx, sy, arrow;
  471. Xdouble    l;
  472. Xdouble    val;
  473. X{
  474. X    double    cosine;        /* cosine of line angle */
  475. X    double    nd;        /* number of dashes and gaps fitting on line */
  476. X    int    n;        /* nd rounded to the nearest odd integer */
  477. X    double    dl;        /* actual x-length of each dash */
  478. X    double    dg;        /* actual x-length of each gap */
  479. X    double    dx, dy;        /* step between dashes */
  480. X    int    x2, y2;
  481. X
  482. X
  483. X    if (sx) {
  484. X        cosine = (double)abs(sx) / hypot((double)sx, (double)sy);
  485. X        x2 = (sx >= 0)? x + round(l): x - round(l);
  486. X        y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx );
  487. X        }
  488. X    else {
  489. X        cosine = 1.0;
  490. X        x2 = x;
  491. X        y2 = (sy >= 0)? y + round(l): y - round(l);
  492. X        }
  493. X    /*** compute number of dashes, length of dashes and gaps ***/
  494. X    nd = l / (val*dash_mag*cosine);
  495. X    n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
  496. X    dl = l / (double)n;
  497. X    if (sx  &&  sy  &&  (dl/cosine)*unitlength < MIN_LEN) {
  498. X        fprintf(stderr, "Dash too small; using larger dash\n");
  499. X        dl = MIN_LEN/unitlength * cosine;
  500. X        nd = l / dl;
  501. X        n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
  502. X        }
  503. X    if (2*dl >= l  ||  (sx  &&  sy  &&  (l/cosine)*unitlength < MIN_LEN)) {
  504. X        fprintf(stderr, "Dashed line too short; drawing solid line\n");
  505. X        put_solidline (x, y, sx, sy, l, arrow);
  506. X        return;
  507. X        }
  508. X    dg = (l - (n/2+1)*dl) / (double)(n/2);
  509. X    if (sx) {
  510. X        dx = dl+dg;
  511. X        if (sx < 0) dx = -dx;
  512. X        dy = dx * (double)sy / (double)sx;
  513. X        }
  514. X    else {
  515. X        dx = 0.0;
  516. X        dy = dl+dg;
  517. X        if (sy < 0) dy = -dy;
  518. X        }
  519. X    /*** draw dashed line ***/
  520. X    fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\line(%2d,%2d){%7.3f}}\n",
  521. X        x, y, dx, dy, n/2+1, sx, sy, dl);
  522. X    /*** draw arrow heads ***/
  523. X    if (arrow == 1  ||  arrow == 2)
  524. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
  525. X    if (arrow == -1  ||  arrow == 2)
  526. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
  527. X    }
  528. X
  529. X/*
  530. X * draw a dotted line given latex slope
  531. X */
  532. Xstatic put_dotline (x, y, sx, sy, l, arrow, val)
  533. Xint    x, y, sx, sy, arrow;
  534. Xdouble    l;
  535. Xdouble    val;
  536. X{
  537. X    double    cosine;        /* cosine of line angle */
  538. X    double    nd;        /* number of dots fitting on line */
  539. X    int    n;        /* nd rounded to the nearest integer */
  540. X    double    dx, dy;        /* step between dashes */
  541. X    int    x2, y2;
  542. X
  543. X
  544. X    cosine = (sx)? (double)abs(sx) / hypot((double)sx, (double)sy): 1.0;
  545. X    /*** compute step width ***/
  546. X    nd = l / (3*val*cosine);
  547. X    n = rint(nd);
  548. X    dx = l / (double)n;
  549. X    if (sx) {
  550. X        dx = l / (double)n;
  551. X        if (sx < 0) dx = -dx;
  552. X        dy = dx * (double)sy / (double)sx;
  553. X        }
  554. X    else {
  555. X        dx = 0.0;
  556. X        dy = l / (double)n;
  557. X        if (sy < 0) dy = -dy;
  558. X        }
  559. X    /*** draw arrow heads ***/
  560. X    if (arrow == 1  ||  arrow == 2) {
  561. X        /* forward arrow */
  562. X        if (sx) {
  563. X        x2 = (sx >= 0)? x + round(l): x - round(l);
  564. X        y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx );
  565. X        }
  566. X        else {
  567. X        x2 = x;
  568. X        y2 = (sy >= 0)? y + round(l): y - round(l);
  569. X        }
  570. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
  571. X        n--;
  572. X        }
  573. X    if (arrow == -1  ||  arrow == 2) {
  574. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
  575. X        x = round(x + dx);
  576. X        y = round(y + dy);
  577. X        n--;
  578. X        }
  579. X    /*** draw dotted line ***/
  580. X    fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n",
  581. X        x, y, dx, dy, n+1, dot_xoffset, dot_yoffset, dot_cmd);
  582. X    }
  583. X
  584. Xvoid genlatex_spline(s)
  585. XF_spline    *s;
  586. X{
  587. X    fprintf(stderr, "Can't generate spline; omitting object\n");
  588. X    }
  589. X
  590. Xvoid genlatex_ellipse(e)
  591. XF_ellipse    *e;
  592. X{
  593. X    int  x, y, d, dx, dy;
  594. X
  595. X    if (verbose) fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n");
  596. X
  597. X    set_linewidth(e->thickness);
  598. X    switch (e->style) {
  599. X        case SOLID_LINE:
  600. X        break;
  601. X        case DASH_LINE:
  602. X        fprintf(stderr, "Dashed circles and elipses not supported\n");
  603. X        break;
  604. X        case DOTTED_LINE:
  605. X        fprintf(stderr, "Dotted circles and elipses not supported\n");
  606. X        break;
  607. X        }
  608. X
  609. X    x = e->center.x;
  610. X    y = e->center.y;
  611. X    TRANS(x, y);
  612. X    if ((e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA)
  613. X            && e->radiuses.x*unitlength <= MAXCIRCLERAD) {
  614. X
  615. X        d = 2 * e->radiuses.x;
  616. X        if (e->area_fill == BLACK_FILL)
  617. X            fprintf(tfp, "\\put(%3d,%3d){\\circle*{%d}}\n", x, y, d);
  618. X        else {
  619. X              fprintf(tfp, "\\put(%3d,%3d){\\circle{%d}}\n", x, y, d);
  620. X        if (e->area_fill && (int)e->area_fill != DEFAULT)
  621. X            fprintf(stderr, "Circle area fill not implemented\n");
  622. X        }
  623. X
  624. X    } else {        
  625. X        dx = 2 * e->radiuses.x;
  626. X        dy = 2 * e->radiuses.y;
  627. X        fprintf(tfp, "\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy);
  628. X        if (e->area_fill && (int)e->area_fill != DEFAULT)
  629. X        fprintf(stderr, "Ellipse area fill not implemented\n");
  630. X    }
  631. X      }
  632. X
  633. Xvoid genlatex_text(t)
  634. XF_text    *t;
  635. X{
  636. X    int       x, y;
  637. X    char    *tpos, *cp;
  638. X
  639. X    if (verbose) fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n");
  640. X
  641. X    x = t->base_x;
  642. X    y = t->base_y;
  643. X    TRANS(x, y);
  644. X
  645. X    switch (t->type) {
  646. X
  647. X        case T_LEFT_JUSTIFIED:
  648. X        case DEFAULT:
  649. X            tpos = "[lb]";
  650. X        break;
  651. X
  652. X        case T_CENTER_JUSTIFIED:
  653. X            tpos = "[b]";
  654. X        break;
  655. X
  656. X        case T_RIGHT_JUSTIFIED:
  657. X            tpos = "[rb]";
  658. X        break;
  659. X
  660. X        default:
  661. X        fprintf(stderr, "Text incorrectly positioned\n");
  662. X        }
  663. X
  664. X    /* raisebox is used to position text at baseline */
  665. X    fprintf(tfp, 
  666. X      "\\put(%3d,%3d){\\makebox(0,0)%s{\\raisebox{0pt}[0pt][0pt]",
  667. X      x, y, tpos);
  668. X    fprintf(tfp, "{\\%s%s ", TEXFONTSIZE(t->size), TEXFONT(t->font));
  669. X
  670. X    if (t->font && t->font !=DEFAULT)
  671. X
  672. X        /* this loop escapes characters "$&%#_{}" */
  673. X        /* and deleted characters "~^\" */
  674. X        for(cp = t->cstring; *cp; cp++) {
  675. X                  if (strchr("$&%#_{}", *cp)) (void)fputc('\\', tfp);
  676. X                  if (strchr("~^\\", *cp))
  677. X            fprintf(stderr,
  678. X                "Bad character in text object '%c'\n" ,*cp);
  679. X            else
  680. X            (void)fputc(*cp, tfp);
  681. X              }
  682. X    else 
  683. X        fprintf(tfp, "%s", t->cstring);
  684. X
  685. X     fprintf(tfp, "}}}\n");
  686. X    }
  687. X
  688. Xvoid genlatex_arc(a)
  689. XF_arc    *a;
  690. X/*
  691. X *  Approximates an arc by a sequence of quarter ovals.
  692. X *
  693. X *  Example:
  694. X *
  695. X *    Arc with center at (0,0) and radius 10 from +45 degree to +225 degree
  696. X *    (arc from p1 = (7.07, 7.07) to p2 = (-7.07, -7.07) counterclockwise).
  697. X *    This arc is approximated by three quarter ovals, one for each quadrant
  698. X *    through which the arc goes:
  699. X *
  700. X *     1. quarter oval from p1 to the intersection of arc and y-axis,
  701. X *        i.e., from (7.07, 7.07) to (0, 10) in quadrant 0
  702. X *
  703. X *        \put(0, 7.07){\oval(14.14, 5.86)[tr]}
  704. X *
  705. X *     2. quarter oval from intersection arc/y-axis to intersection arc/x-axis
  706. X *        i.e., from (0, 10) to (-10, 0) in quadrant 1
  707. X *
  708. X *        \put(0, 0){\oval(20,20)[tl]}
  709. X *
  710. X *     3. quarter oval from p1 to the intersection of arc and y-axis,
  711. X *        i.e., from (-10, 0) to (-7.07, -7.07) in quadrant 2
  712. X *
  713. X *        \put(-7.07, 0){\oval(5.86, 14.14)[bl]}
  714. X */
  715. X{
  716. X    F_pos        p1, p2, pq[4];
  717. X    double        cx, cy;
  718. X    double        v1x, v1y, v2x, v2y;
  719. X    double        r, angle1, angle2;
  720. X    int        q1, q2;
  721. X    int        p1_arrow, p2_arrow;
  722. X    static char    *ad1[4] = { " 0,-1", " 1, 0", " 0, 1", "-1, 0" };
  723. X    static char    *ad2[4] = { "-1, 0", " 0,-1", " 1, 0", " 0, 1" };
  724. X
  725. X    set_linewidth(a->thickness);
  726. X    switch (a->style) {
  727. X        case SOLID_LINE:
  728. X        break;
  729. X        case DASH_LINE:
  730. X        fprintf(stderr, "Dashed arcs not supported\n");
  731. X        break;
  732. X        case DOTTED_LINE:
  733. X        fprintf(stderr, "Dotted arcs not supported\n");
  734. X        break;
  735. X        }
  736. X    if (a->direction == 1) {
  737. X        p1 = a->point[0];
  738. X        p2 = a->point[2];
  739. X        p1_arrow = (a->back_arrow != NULL);
  740. X        p2_arrow = (a->for_arrow != NULL);
  741. X        }
  742. X    else {
  743. X        p1 = a->point[2];
  744. X        p2 = a->point[0];
  745. X        p1_arrow = (a->for_arrow != NULL);
  746. X        p2_arrow = (a->back_arrow != NULL);
  747. X        }
  748. X    cx = a->center.x;
  749. X    cy = a->center.y;
  750. X    TRANS2(p1.x, p1.y, p2.x, p2.y);
  751. X    TRANSD(cx, cy);
  752. X    /*** compute vectors and angles from arc center to p1, p2 ***/
  753. X    v1x = (double)p1.x - cx;
  754. X    v1y = (double)p1.y - cy;
  755. X    v2x = (double)p2.x - cx;
  756. X    v2y = (double)p2.y - cy;
  757. X    angle1 = atan2(v1y, v1x) * rad2deg;
  758. X    angle2 = atan2(v2y, v2x) * rad2deg;
  759. X    if (angle1 < 0.0)
  760. X        angle1 += 360.0; 
  761. X    if (angle2 < 0.0)
  762. X        angle2 += 360.0; 
  763. X    /* compute arc radius */
  764. X    r = hypot(v1x, v1y);
  765. X    /*** compute intersection of arc with x and y axis (origin at cx, cy) */
  766. X    pq[0].x = round(cx);
  767. X    pq[0].y = round(cy + r);
  768. X    pq[1].x = round(cx - r);
  769. X    pq[1].y = round(cy);
  770. X    pq[2].x = round(cx);
  771. X    pq[2].y = round(cy - r);
  772. X    pq[3].x = round(cx + r);
  773. X    pq[3].y = round(cy);
  774. X    /*** compute in which quadrants p1 and p2 are located ***/
  775. X    q1 = (int)(angle1/90.0);
  776. X    q2 = (int)(angle2/90.0);
  777. X    if (fabs(angle1 - 90.0*q1) > arc_tolerance 
  778. X     || fabs(angle2 - 90.0*q2) > arc_tolerance)
  779. X        fprintf(stderr, "Approximating arc by ovals\n");
  780. X    /*** Draw arc ***/
  781. X    if (p1_arrow)
  782. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p1.x, p1.y, ad1[q1]);
  783. X    while (q1 != q2) {
  784. X        put_quarter(p1, pq[q1], q1);
  785. X        p1 = pq[q1];
  786. X        q1 = (q1 + 1) % 4;
  787. X        }
  788. X    put_quarter(p1, p2, q1);
  789. X    if (p2_arrow)
  790. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p2.x, p2.y, ad2[q2]);
  791. X
  792. X    if (a->area_fill && (int)a->area_fill != DEFAULT)
  793. X        fprintf(stderr, "Arc area fill not implemented\n");
  794. X    }
  795. X
  796. Xstatic put_quarter(p1, p2, q)
  797. XF_pos    p1, p2;
  798. Xint    q;
  799. X/*
  800. X *  Draw quarter oval from p1 to p2 in quadrant q
  801. X */
  802. X{
  803. X    char    *opt;
  804. X    int    px, py, dx, dy;
  805. X
  806. X    dx = 2*ABS(p1.x - p2.x);
  807. X    dy = 2*ABS(p1.y - p2.y);
  808. X    if (dx == 0  &&  dy == 0)
  809. X        return;
  810. X    switch (q) {
  811. X        case 0:
  812. X        px = MIN(p1.x, p2.x);
  813. X        py = MIN(p1.y, p2.y);
  814. X        opt = "tr";
  815. X        break;
  816. X        case 1:
  817. X        px = MAX(p1.x, p2.x);
  818. X        py = MIN(p1.y, p2.y);
  819. X        opt = "tl";
  820. X        break;
  821. X        case 2:
  822. X        px = MAX(p1.x, p2.x);
  823. X        py = MAX(p1.y, p2.y);
  824. X        opt = "bl";
  825. X        break;
  826. X        case 3:
  827. X        px = MIN(p1.x, p2.x);
  828. X        py = MAX(p1.y, p2.y);
  829. X        opt = "br";
  830. X        break;
  831. X        }
  832. X    fprintf(tfp, "\\put(%3d,%3d){\\oval(%3d,%3d)[%s]}\n", px, py, dx, dy, opt);
  833. X    }
  834. X
  835. Xstruct driver dev_latex = {
  836. X         genlatex_option,
  837. X    genlatex_start,
  838. X    genlatex_arc,
  839. X    genlatex_ellipse,
  840. X    genlatex_line,
  841. X    genlatex_spline,
  842. X    genlatex_text,
  843. X    genlatex_end,
  844. X    EXCLUDE_TEXT
  845. X};
  846. END_OF_FILE
  847. if test 20332 -ne `wc -c <'transfig/fig2dev/dev/genlatex.c'`; then
  848.     echo shar: \"'transfig/fig2dev/dev/genlatex.c'\" unpacked with wrong size!
  849. fi
  850. # end of 'transfig/fig2dev/dev/genlatex.c'
  851. fi
  852. if test -f 'transfig/fig2dev/dev/genps.c' -a "${1}" != "-c" ; then 
  853.   echo shar: Will not clobber existing file \"'transfig/fig2dev/dev/genps.c'\"
  854. else
  855. echo shar: Extracting \"'transfig/fig2dev/dev/genps.c'\" \(17407 characters\)
  856. sed "s/^X//" >'transfig/fig2dev/dev/genps.c' <<'END_OF_FILE'
  857. X/* 
  858. X *    genps.c: PostScript driver for fig2dev
  859. X *
  860. X*/
  861. X#ifdef hpux
  862. X#include <sys/types.h>
  863. X#endif
  864. X#include <sys/file.h>
  865. X#include <stdio.h>
  866. X#include <math.h>
  867. X#include "pi.h"
  868. X#include <pwd.h>
  869. X#include "object.h"
  870. X#include "fig2dev.h"
  871. X
  872. Xextern            x_flag;
  873. X
  874. X#define        PAGE_WIDTH        612    /* points; 8.5" */
  875. X#define        PAGE_HEIGHT        792    /* points; 11" */
  876. X#define        TRUE            1
  877. X#define        FALSE            0
  878. X#define        POINT_PER_INCH        72
  879. X#define        ULIMIT_FONT_SIZE    300
  880. X
  881. Xint        coord_system;
  882. Xint        show_page = 0;
  883. Xint        cur_thickness;
  884. Xint        center = 0;
  885. Xint        landscape = 0;
  886. X
  887. Xstatic char        *fontnames_x[] = {
  888. X            "Times-Roman", "Times-Roman",    /* default */
  889. X            "Times-Italic",            /* italic */
  890. X            "Times-Bold",            /* bold */
  891. X            "Times-BoldItalic",
  892. X            "AvantGarde",
  893. X            "AvantGarde-BookOblique",
  894. X            "AvantGarde-Demi",
  895. X            "AvantGarde-DemiOblique",
  896. X            "Bookman-Light",
  897. X            "Bookman-LightItalic",
  898. X            "Bookman-Demi",
  899. X            "Bookman-DemiItalic",
  900. X            "Courier",    
  901. X            "Courier-Oblique",
  902. X            "Courier-Bold",
  903. X            "Courier-BoldItalic",
  904. X            "Helvetica",
  905. X            "Helvetica-Oblique",
  906. X            "Helvetica-Bold",
  907. X            "Helvetica-BoldOblique",
  908. X            "Helvetica-Narrow",
  909. X            "Helvetica-Narrow-Oblique",
  910. X            "Helvetica-Narrow-Bold",
  911. X            "Helvetica-Narrow-BoldOblique",
  912. X            "NewCenturySchlbk-Roman",
  913. X            "NewCenturySchlbk-Italic",
  914. X            "NewCenturySchlbk-Bold",
  915. X            "NewCenturySchlbk-BoldItalic",
  916. X            "Palatino-Roman",
  917. X            "Palatino-Italic",
  918. X            "Palatino-Bold",
  919. X            "Palatino-BoldItalic",
  920. X            "Symbol",
  921. X            "ZapfChancery-MediumItalic",
  922. X            "ZapfDingbats"
  923. X        };
  924. X
  925. Xstatic char        *fontnames_sv[] = {
  926. X            "Times-Roman", "Times-Roman",    /* default */
  927. X            "Times-Roman",            /* roman */
  928. X            "Times-Bold",            /* bold */
  929. X            "Times-Italic",            /* italic */
  930. X            "Helvetica",            /* sans serif */
  931. X            "Courier"            /* typewriter */
  932. X        };
  933. X#define MAXFONT (x_flag ? 35 : 5)
  934. X
  935. X#define PS_FONTNAMES    (x_flag ? fontnames_x : fontnames_sv)
  936. X
  937. X#define PSFONT(F) \
  938. X     ((F) <= MAXFONT ? PS_FONTNAMES[(F)+1] : PS_FONTNAMES[0])
  939. X
  940. X#define PSFONTSIZE(S)    (((S) > 0 ? \
  941. X                ((S) <= ULIMIT_FONT_SIZE ? \
  942. X                     (S) : \
  943. X                    ULIMIT_FONT_SIZE) : \
  944. X                font_size)/mag)
  945. X
  946. X#define GRAYVAL(F)    (x_flag ? ((int)(F) <= 21 ? \
  947. X                (21 - (int)(F))/20.0 : 0.0) : \
  948. X                ((int)(F) <= 5 ? ((int)(F) - 1)/4.0 : 0.0))
  949. X
  950. X#define        BEGIN_PROLOG    "\
  951. X/$F2psDict 32 dict def \
  952. X$F2psDict begin\
  953. X    $F2psDict /mtrx matrix put\
  954. X"
  955. X#define        ELLIPSE_PS    " \
  956. X/DrawEllipse {\
  957. X    /endangle exch def\
  958. X    /startangle exch def\
  959. X    /yrad exch def\
  960. X    /xrad exch def\
  961. X    /y exch def\
  962. X    /x exch def\
  963. X    /savematrix mtrx currentmatrix def\
  964. X    x y translate xrad yrad scale 0 0 1 startangle endangle arc\
  965. X    savematrix setmatrix\
  966. X    } def\
  967. X"
  968. X/* The original PostScript definition for adding a spline section to the
  969. X * current path uses recursive bisection.  The following definition using the
  970. X * curveto operator is more efficient since it executes at compiled rather
  971. X * than interpreted code speed.  The Bezier control points are 2/3 of the way
  972. X * from z1 (and z3) to z2.
  973. X *
  974. X * ---Rene Llames, 21 July 1988.
  975. X */
  976. X#define        SPLINE_PS    " \
  977. X/DrawSplineSection {\
  978. X    /y3 exch def\
  979. X    /x3 exch def\
  980. X    /y2 exch def\
  981. X    /x2 exch def\
  982. X    /y1 exch def\
  983. X    /x1 exch def\
  984. X    /xa x1 x2 x1 sub 0.666667 mul add def\
  985. X    /ya y1 y2 y1 sub 0.666667 mul add def\
  986. X    /xb x3 x2 x3 sub 0.666667 mul add def\
  987. X    /yb y3 y2 y3 sub 0.666667 mul add def\
  988. X    x1 y1 lineto\
  989. X    xa ya xb yb x3 y3 curveto\
  990. X    } def\
  991. X"
  992. X#define        END_PROLOG    "\
  993. X    end\
  994. X    /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def\
  995. X    /$F2psEnd {$F2psEnteredState restore end} def\
  996. X    %%EndProlog\
  997. X"
  998. X
  999. Xvoid genps_option(opt, optarg)
  1000. Xchar opt;
  1001. Xchar *optarg;
  1002. X{
  1003. X    int i;
  1004. X
  1005. X    switch (opt) {
  1006. X
  1007. X    case 'f':
  1008. X        for ( i = 1; i <= MAXFONT + 1; i++ )
  1009. X            if ( !strcmp(optarg, PS_FONTNAMES[i]) ) break;
  1010. X
  1011. X        if ( i > MAXFONT + 1 )
  1012. X            fprintf(stderr,
  1013. X                "warning: non-standard font name %s\n", optarg);
  1014. X
  1015. X            fontnames_sv[0] = fontnames_sv[1] = optarg;
  1016. X            fontnames_x[0] = fontnames_x[1] = optarg;
  1017. X            break;
  1018. X
  1019. X    case 'c':
  1020. X            center = 1;
  1021. X        break;
  1022. X
  1023. X    case 's':
  1024. X        if (font_size <= 0 || font_size > ULIMIT_FONT_SIZE) {
  1025. X            fprintf(stderr,
  1026. X                "warning: font size %d out of bounds\n", font_size);
  1027. X        }
  1028. X        break;
  1029. X
  1030. X    case 'P':
  1031. X        show_page = 1;
  1032. X        break;
  1033. X
  1034. X          case 'm':
  1035. X          case 'L':
  1036. X        break;
  1037. X
  1038. X          case 'l':
  1039. X        landscape = 1;
  1040. X        break;
  1041. X
  1042. X    default:
  1043. X        put_msg(Err_badarg, opt, "ps");
  1044. X        exit(1);
  1045. X        break;
  1046. X    }
  1047. X}
  1048. X
  1049. Xvoid genps_start(objects)
  1050. XF_compound    *objects;
  1051. X{
  1052. X    char        host[256];
  1053. X    struct passwd    *who;
  1054. X    long        when;
  1055. X    extern char    *ctime(), *strcpy();
  1056. X    extern long    time();
  1057. X    double        tx, scalex, scaley;
  1058. X    double        dx, dy, origx, origy;
  1059. X    int        itmp;
  1060. X
  1061. X    coord_system = objects->nwcorner.y;
  1062. X    scalex = scaley = mag * POINT_PER_INCH / (double)objects->nwcorner.x;
  1063. X    /* convert to point unit */
  1064. X    llx = (int)ceil(llx * scalex); lly = (int)ceil(lly * scaley);
  1065. X    urx = (int)ceil(urx * scalex); ury = (int)ceil(ury * scaley);
  1066. X    if (landscape)          /* swap x,y */
  1067. X        {
  1068. X        itmp = llx; llx = lly; lly = itmp;
  1069. X        itmp = urx; urx = ury; ury = itmp;
  1070. X        }
  1071. X    if (center) {
  1072. X        dx = urx - llx;
  1073. X        dy = ury - lly;
  1074. X        tx = (PAGE_WIDTH - dx) / 2.0;
  1075. X        if (landscape)
  1076. X        origx=0;
  1077. X        else
  1078. X        origx = tx - llx;
  1079. X        urx = (llx=tx) + dx;
  1080. X        ury = (PAGE_HEIGHT + dy) / 2.0;
  1081. X        if (coord_system == 2)
  1082. X        origy = ury + lly;
  1083. X        else
  1084. X        origy = ury - dy - lly;
  1085. X        lly = ury - dy;
  1086. X        }
  1087. X    else {
  1088. X        origx = 0.0;
  1089. X        origy = PAGE_HEIGHT;
  1090. X        }
  1091. X
  1092. X    if (coord_system == 2) scaley = -scaley;
  1093. X
  1094. X    fprintf(tfp, "%%!\n");    /* PostScript magic strings */
  1095. X    who = getpwuid(getuid());
  1096. X    if (-1 == gethostname(host, sizeof(host)))
  1097. X        (void)strcpy(host, "unknown-host!?!?");
  1098. X    (void) time(&when);
  1099. X    fprintf(tfp, "%%%%Title: %s\n", ((from) ? from : "stdin"));
  1100. X    fprintf(tfp, "%%%%Creator: %s\n", prog);
  1101. X    fprintf(tfp, "%%%%CreationDate: %s", ctime(&when));
  1102. X    fprintf(tfp, "%%%%For: %s@%s (%s)\n",
  1103. X            who->pw_name, host, who->pw_gecos);
  1104. X    fprintf(tfp, "%%%%Pages: %d\n", show_page);
  1105. X
  1106. X    if (show_page)
  1107. X      fprintf(tfp, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury);
  1108. X    else
  1109. X      fprintf(tfp, "%%%%BoundingBox: 0 0 %d %d\n", urx-llx, ury-lly);
  1110. X
  1111. X    fprintf(tfp, "%%%%EndComments\n");
  1112. X    fprintf(tfp, "%s\n", BEGIN_PROLOG);
  1113. X    if (ellipse_exist(objects)) fprintf(tfp, "%s\n", ELLIPSE_PS);
  1114. X    if (normal_spline_exist(objects)) fprintf(tfp, "%s\n", SPLINE_PS);
  1115. X    fprintf(tfp, "%s\n", END_PROLOG);
  1116. X    fprintf(tfp, "$F2psBegin\n");
  1117. X    fprintf(tfp, "1 setlinecap 1 setlinejoin\n");
  1118. X
  1119. X    if (!show_page) fprintf(tfp, "%d %d translate\n", -llx, lly);
  1120. X    fprintf(tfp, "%f %f translate %.3f %.3f scale\n",
  1121. X        origx, (show_page ? origy : ury-lly), scalex, scaley);
  1122. X
  1123. X    /* **** Land scape mode ****/
  1124. X    if (landscape)
  1125. X        fprintf(tfp, "%d 0 translate 90 rotate\n", PAGE_WIDTH);
  1126. X
  1127. X    /*    if ((t = PAGE_HEIGHT / SCALE / WIDTH) < 1.0)
  1128. X    *    fprintf(tfp, "%f %f scale\n", t, t);
  1129. X    *   }
  1130. X    *else if ((t = PAGE_HEIGHT / SCALE / HEIGHT) < 1.0)
  1131. X    *    fprintf(tfp, "%f %f scale\n", t, t);
  1132. X    */
  1133. X
  1134. X    }
  1135. X
  1136. Xvoid genps_end()
  1137. X{
  1138. X    if (show_page) fprintf(tfp, "showpage\n");
  1139. X    fprintf(tfp, "$F2psEnd\n");
  1140. X    }
  1141. X
  1142. Xstatic set_style(s, v)
  1143. Xint    s;
  1144. Xdouble    v;
  1145. X{
  1146. X    if (s == DASH_LINE) {
  1147. X        if (v > 0.0) fprintf(tfp, "\t[%f] 0 setdash\n", v);
  1148. X        }
  1149. X    else if (s == DOTTED_LINE) {
  1150. X        if (v > 0.0) fprintf(tfp, "\t[1 %f] 0 setdash\n", v);
  1151. X        }
  1152. X    }
  1153. X
  1154. Xstatic reset_style(s, v)
  1155. Xint    s;
  1156. Xdouble    v;
  1157. X{
  1158. X    if (s == DASH_LINE) {
  1159. X        if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n");
  1160. X        }
  1161. X    else if (s == DOTTED_LINE) {
  1162. X        if (v > 0.0) fprintf(tfp, "\t[] 0 setdash\n");
  1163. X        }
  1164. X    }
  1165. X
  1166. Xstatic set_linewidth(w)
  1167. Xint    w;
  1168. X{
  1169. X    extern int    cur_thickness;
  1170. X
  1171. X    if (w != cur_thickness) {
  1172. X        cur_thickness = w;
  1173. X        fprintf(tfp, "%.3f setlinewidth\n", 1.0 * cur_thickness);
  1174. X        }
  1175. X    }
  1176. X
  1177. Xvoid genps_line(l)
  1178. XF_line    *l;
  1179. X{
  1180. X    F_point        *p, *q;
  1181. X    /* JNT */
  1182. X    int        radius;
  1183. X    
  1184. X    set_linewidth(l->thickness);
  1185. X    radius = l->radius;                /* radius of rounded-corner boxes */
  1186. X    p = l->points;
  1187. X    q = p->next;
  1188. X    if (q == NULL) { /* A single point line */
  1189. X        fprintf(tfp, "newpath %d %d moveto %d %d lineto stroke\n",
  1190. X            p->x, p->y, p->x, p->y);
  1191. X        return;
  1192. X        }
  1193. X    if (l->back_arrow)
  1194. X        draw_arrow_head((double)q->x, (double)q->y, (double)p->x,
  1195. X            (double)p->y, l->back_arrow->ht, l->back_arrow->wid);
  1196. X    set_style(l->style, l->style_val);
  1197. X    fprintf(tfp, "%% Polyline\n");
  1198. X    /* JNT */
  1199. X            if (l->type == T_ARC_BOX)
  1200. X                {
  1201. X                register int xmin,xmax,ymin,ymax;
  1202. X
  1203. X                xmin = xmax = p->x;
  1204. X                ymin = ymax = p->y;
  1205. X                while (p->next != NULL) /* find lower left and upper right corne
  1206. Xrs */
  1207. X                        {
  1208. X                        p=p->next;
  1209. X                        if (xmin > p->x)
  1210. X                                xmin = p->x;
  1211. X                        else if (xmax < p->x)
  1212. X                                xmax = p->x;
  1213. X                        if (ymin > p->y)
  1214. X                                ymin = p->y;
  1215. X                        else if (ymax < p->y)
  1216. X                                ymax = p->y;
  1217. X            }
  1218. X                fprintf(tfp, "newpath %d %d moveto",xmin+radius, ymin);
  1219. X                fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat",
  1220. X                                xmin, ymin, xmin, ymax-radius, radius);
  1221. X                fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro
  1222. Xugh bl to br */
  1223. X                                xmin, ymax, xmax-radius, ymax, radius);
  1224. X                fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro
  1225. Xugh br to tr */
  1226. X                                xmax, ymax, xmax, ymin+radius, radius);
  1227. X                fprintf(tfp, " %d %d %d %d %d arcto 4 {pop} repeat", /* arc thro
  1228. Xugh tr to tl */
  1229. X                                xmax, ymin, xmin+radius, ymin, radius);
  1230. X        }
  1231. X        else
  1232. X                {
  1233. X    fprintf(tfp, "newpath %d %d moveto", p->x, p->y);
  1234. X    while (q->next != NULL) {
  1235. X        p = q;
  1236. X        q = q->next;
  1237. X        fprintf(tfp, " %d %d lineto", p->x, p->y);
  1238. X        }
  1239. X        }
  1240. X    if (l->type == T_POLYLINE)
  1241. X        fprintf(tfp, " %d %d lineto stroke\n", q->x, q->y);
  1242. X    else
  1243. X        fprintf(tfp, " closepath ");
  1244. X    if (l->area_fill && (int)l->area_fill != DEFAULT)
  1245. X        fprintf(tfp, "gsave %6.3f setgray fill grestore ",
  1246. X            GRAYVAL(l->area_fill));
  1247. X    fprintf(tfp, "stroke\n");
  1248. X    reset_style(l->style, l->style_val);
  1249. X    if (l->for_arrow)
  1250. X        draw_arrow_head((double)p->x, (double)p->y, (double)q->x,
  1251. X            (double)q->y, l->for_arrow->ht, l->for_arrow->wid);
  1252. X    }
  1253. X
  1254. Xvoid genps_spline(s)
  1255. XF_spline    *s;
  1256. X{
  1257. X    if (int_spline(s))
  1258. X        genps_itp_spline(s);
  1259. X    else
  1260. X        genps_ctl_spline(s);
  1261. X    }
  1262. X
  1263. Xgenps_itp_spline(s)
  1264. XF_spline    *s;
  1265. X{
  1266. X    F_point        *p, *q;
  1267. X    F_control    *a, *b;
  1268. X
  1269. X    set_linewidth(s->thickness);
  1270. X    a = s->controls;
  1271. X    p = s->points;
  1272. X    if (s->back_arrow)
  1273. X        draw_arrow_head(a->rx, a->ry, (double)p->x,
  1274. X            (double)p->y, s->back_arrow->ht, s->back_arrow->wid);
  1275. X
  1276. X    set_style(s->style, s->style_val);
  1277. X    fprintf(tfp, "%% Interpolated spline\n");
  1278. X    fprintf(tfp, "newpath %d %d moveto\n", p->x, p->y);
  1279. X    for (q = p->next; q != NULL; p = q, q = q->next) {
  1280. X        b = a->next;
  1281. X        fprintf(tfp, "\t%.3f %.3f %.3f %.3f %d %d curveto\n",
  1282. X            a->rx, a->ry, b->lx, b->ly, q->x, q->y);
  1283. X        a = b;
  1284. X        b = b->next;
  1285. X        }
  1286. X    if (closed_spline(s)) fprintf(tfp, " closepath ");
  1287. X    if (s->area_fill && (int)s->area_fill != DEFAULT)
  1288. X        fprintf(tfp, "gsave %6.3f setgray fill grestore ",
  1289. X            GRAYVAL(s->area_fill));
  1290. X    fprintf(tfp, " stroke\n");
  1291. X    reset_style(s->style, s->style_val);
  1292. X
  1293. X    if (s->for_arrow)
  1294. X        draw_arrow_head(a->lx, a->ly, (double)p->x,
  1295. X            (double)p->y, s->for_arrow->ht, s->for_arrow->wid);
  1296. X    }
  1297. X
  1298. Xgenps_ctl_spline(s)
  1299. XF_spline    *s;
  1300. X{
  1301. X    double        a, b, c, d, x1, y1, x2, y2, x3, y3;
  1302. X    F_point        *p, *q;
  1303. X
  1304. X    /*
  1305. X    if (first) {
  1306. X        first = FALSE;
  1307. X        fprintf(tfp, "%s\n", SPLINE_PS);
  1308. X        }
  1309. X    */
  1310. X
  1311. X    p = s->points;
  1312. X    x1 = p->x; y1 = p->y;
  1313. X    p = p->next;
  1314. X    c = p->x; d = p->y;
  1315. X    set_linewidth(s->thickness);
  1316. X    x3 = a = (x1 + c) / 2;
  1317. X    y3 = b = (y1 + d) / 2;
  1318. X    if (s->back_arrow) {
  1319. X        draw_arrow_head(c, d, x1, y1, s->back_arrow->ht, s->back_arrow->wid);
  1320. X        }
  1321. X    set_style(s->style, s->style_val);
  1322. X    if (! closed_spline(s)) {
  1323. X        fprintf(tfp, "%% Open spline\n");
  1324. X        fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto\n",
  1325. X            x1, y1, x3, y3);
  1326. X        }
  1327. X    else {
  1328. X        fprintf(tfp, "%% Closed spline\n");
  1329. X        fprintf(tfp, "newpath %.3f %.3f moveto\n", a, b);
  1330. X        }
  1331. X    for (q = p->next; q != NULL; p = q, q = q->next) {
  1332. X        x1 = x3; y1 = y3;
  1333. X        x2 = c;  y2 = d;
  1334. X        c = q->x; d = q->y;
  1335. X        x3 = (x2 + c) / 2;
  1336. X        y3 = (y2 + d) / 2;
  1337. X        fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection\n",
  1338. X            x1, y1, x2, y2, x3, y3);
  1339. X        }
  1340. X    /*
  1341. X    * At this point, (x2,y2) and (c,d) are the position of the 
  1342. X    * next-to-last and last point respectively, in the point list
  1343. X    */
  1344. X    if (closed_spline(s)) {
  1345. X        fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection closepath ",
  1346. X            x3, y3, c, d, a, b);
  1347. X        }
  1348. X    else {
  1349. X        fprintf(tfp, "\t%.3f %.3f lineto ", c, d);
  1350. X        }
  1351. X    if (s->area_fill && (int)s->area_fill != DEFAULT)
  1352. X        fprintf(tfp, "gsave %6.3f setgray fill grestore ",
  1353. X            GRAYVAL(s->area_fill));
  1354. X    fprintf(tfp, "stroke\n");
  1355. X    reset_style(s->style, s->style_val);
  1356. X    if (s->for_arrow) {
  1357. X        draw_arrow_head(x2, y2, c, d, s->for_arrow->ht,
  1358. X                s->for_arrow->wid);
  1359. X        }
  1360. X    }
  1361. X
  1362. Xvoid genps_ellipse(e)
  1363. XF_ellipse    *e;
  1364. X{
  1365. X    set_linewidth(e->thickness);
  1366. X    set_style(e->style, e->style_val);
  1367. X    if (e->angle == 0)
  1368. X    {
  1369. X        fprintf(tfp, "%% Ellipse\n");
  1370. X        fprintf(tfp, "newpath %d %d %d %d 0 360 DrawEllipse ",
  1371. X              e->center.x, e->center.y, e->radiuses.x, e->radiuses.y);
  1372. X    }
  1373. X    else
  1374. X    {
  1375. X        fprintf(tfp, "%% Rotated Ellipse\n");
  1376. X        fprintf(tfp, "gsave\n");
  1377. X        fprintf(tfp, "%d %d translate\n",e->center.x, e->center.y);
  1378. X        fprintf(tfp, "%6.3f rotate\n",e->angle*180/M_PI);
  1379. X        fprintf(tfp, "newpath 0 0 %d %d 0 360 DrawEllipse ",
  1380. X         e->radiuses.x, e->radiuses.y);
  1381. X    }
  1382. X    if (e->area_fill && (int)e->area_fill != DEFAULT)
  1383. X        fprintf(tfp, "gsave %6.3f setgray fill grestore ",
  1384. X            GRAYVAL(e->area_fill));
  1385. X    fprintf(tfp, "stroke\n");
  1386. X    if (e->angle != 0)
  1387. X        fprintf(tfp, "grestore\n");
  1388. X    reset_style(e->style, e->style_val);
  1389. X    }
  1390. X
  1391. X#define    TEXT_PS        "\
  1392. X/%s findfont %.3f scalefont setfont\n\
  1393. X"
  1394. Xvoid genps_text(t)
  1395. XF_text    *t;
  1396. X{
  1397. X    char        *cp;
  1398. X
  1399. X    fprintf(tfp, TEXT_PS, PSFONT(t->font), PSFONTSIZE(t->size));
  1400. X
  1401. X    fprintf(tfp, "%d %d moveto \n", t->base_x,  t->base_y);
  1402. X    if (coord_system == 2) fprintf(tfp, "1 -1 scale\n");
  1403. X
  1404. X    /* this loop escapes characters '(', ')', and '\' */
  1405. X    fputc('(', tfp);
  1406. X    for(cp = t->cstring; *cp; cp++) {
  1407. X          if (strchr("()\\", *cp)) fputc('\\', tfp);
  1408. X          fputc(*cp, tfp);
  1409. X          }
  1410. X    fputc(')', tfp);
  1411. X
  1412. X    if ((t->type == T_CENTER_JUSTIFIED) || (t->type == T_RIGHT_JUSTIFIED)){
  1413. X
  1414. X          fprintf(tfp, "dup stringwidth pop ");
  1415. X        if (t->type == T_CENTER_JUSTIFIED) fprintf(tfp, "2 div ");
  1416. X        fprintf(tfp, "neg 0 rmoveto ");
  1417. X              }
  1418. X
  1419. X    else if ((t->type != T_LEFT_JUSTIFIED) && (t->type != DEFAULT))
  1420. X        fprintf(stderr, "Text incorrectly positioned\n");
  1421. X
  1422. X    fprintf(tfp, " gsave %6.3f rotate show grestore ", t->angle*180/M_PI);
  1423. X    if (coord_system == 2) fprintf(tfp, "1 -1 scale\n");
  1424. X
  1425. X    }
  1426. X
  1427. Xvoid genps_arc(a)
  1428. XF_arc    *a;
  1429. X{
  1430. X    double        angle1, angle2, dx, dy, radius, x, y;
  1431. X    double        cx, cy, sx, sy, ex, ey;
  1432. X    int        direction;
  1433. X
  1434. X    cx = a->center.x; cy = a->center.y;
  1435. X    sx = a->point[0].x; sy = a->point[0].y;
  1436. X    ex = a->point[2].x; ey = a->point[2].y;
  1437. X
  1438. X    if (coord_system == 2)
  1439. X        direction = !a->direction;
  1440. X    else
  1441. X        direction = a->direction;
  1442. X    set_linewidth(a->thickness);
  1443. X    if (a->for_arrow) {
  1444. X        arc_tangent(cx, cy, ex, ey, direction, &x, &y);
  1445. X        draw_arrow_head(x, y, ex, ey, a->for_arrow->ht, a->for_arrow->wid);
  1446. X        }
  1447. X    if (a->back_arrow) {
  1448. X        arc_tangent(cx, cy, sx, sy, !direction, &x, &y);
  1449. X        draw_arrow_head(x, y, sx, sy, a->back_arrow->ht, a->back_arrow->wid);
  1450. X        }
  1451. X    dx = cx - sx;
  1452. X    dy = cy - sy;
  1453. X    radius = hypot(dx, dy);
  1454. X    angle1 = atan2(sy-cy, sx-cx) * 180 / M_PI;
  1455. X    angle2 = atan2(ey-cy, ex-cx) * 180 / M_PI;
  1456. X    /* direction = 1 -> Counterclockwise */
  1457. X    set_style(a->style, a->style_val);
  1458. X    fprintf(tfp, "newpath %.3f %.3f %.3f %.3f %.3f %s\n",
  1459. X        cx, cy, radius, angle1, angle2,
  1460. X        ((direction == 1) ? "arc" : "arcn"));
  1461. X    if (a->area_fill && (int)a->area_fill != DEFAULT)
  1462. X        fprintf(tfp, "gsave %6.3f setgray fill grestore ",
  1463. X            GRAYVAL(a->area_fill));
  1464. X    fprintf(tfp, "stroke\n");
  1465. X    reset_style(a->style, a->style_val);
  1466. X    }
  1467. X
  1468. Xstatic arc_tangent(x1, y1, x2, y2, direction, x, y)
  1469. Xdouble    x1, y1, x2, y2, *x, *y;
  1470. Xint    direction;
  1471. X{
  1472. X    if (direction) { /* counter clockwise  */
  1473. X        *x = x2 + (y2 - y1);
  1474. X        *y = y2 - (x2 - x1);
  1475. X        }
  1476. X    else {
  1477. X        *x = x2 - (y2 - y1);
  1478. X        *y = y2 + (x2 - x1);
  1479. X        }
  1480. X    }
  1481. X
  1482. X/*    draw arrow heading from (x1, y1) to (x2, y2)    */
  1483. X
  1484. Xstatic draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
  1485. Xdouble    x1, y1, x2, y2, arrowht, arrowwid;
  1486. X{
  1487. X    double    x, y, xb, yb, dx, dy, l, sina, cosa;
  1488. X    double    xc, yc, xd, yd;
  1489. X
  1490. X    dx = x2 - x1;  dy = y1 - y2;
  1491. X    l = hypot(dx, dy);
  1492. X    sina = dy / l;  cosa = dx / l;
  1493. X    xb = x2*cosa - y2*sina;
  1494. X    yb = x2*sina + y2*cosa;
  1495. X    x = xb - arrowht;
  1496. X    y = yb - arrowwid / 2;
  1497. X    xc = x*cosa + y*sina;
  1498. X    yc = -x*sina + y*cosa;
  1499. X    y = yb + arrowwid / 2;
  1500. X    xd = x*cosa + y*sina;
  1501. X    yd = -x*sina + y*cosa;
  1502. X    fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto %.3f %.3f lineto stroke\n",
  1503. X        xc, yc, x2, y2, xd, yd);
  1504. X    }
  1505. X
  1506. Xstatic ellipse_exist(ob)
  1507. XF_compound    *ob;
  1508. X{
  1509. X    F_compound    *c;
  1510. X
  1511. X    if (NULL != ob->ellipses) return(1);
  1512. X
  1513. X    for (c = ob->compounds; c != NULL; c = c->next) {
  1514. X        if (ellipse_exist(c)) return(1);
  1515. X        }
  1516. X
  1517. X    return(0);
  1518. X    }
  1519. X
  1520. Xstatic normal_spline_exist(ob)
  1521. XF_compound    *ob;
  1522. X{
  1523. X    F_spline    *s;
  1524. X    F_compound    *c;
  1525. X
  1526. X    for (s = ob->splines; s != NULL; s = s->next) {
  1527. X        if (normal_spline(s)) return(1);
  1528. X        }
  1529. X
  1530. X    for (c = ob->compounds; c != NULL; c = c->next) {
  1531. X        if (normal_spline_exist(c)) return(1);
  1532. X        }
  1533. X
  1534. X    return(0);
  1535. X    }
  1536. X
  1537. Xstruct driver dev_ps = {
  1538. X         genps_option,
  1539. X    genps_start,
  1540. X    genps_arc,
  1541. X    genps_ellipse,
  1542. X    genps_line,
  1543. X    genps_spline,
  1544. X    genps_text,
  1545. X    genps_end,
  1546. X    INCLUDE_TEXT
  1547. X};
  1548. END_OF_FILE
  1549. if test 17407 -ne `wc -c <'transfig/fig2dev/dev/genps.c'`; then
  1550.     echo shar: \"'transfig/fig2dev/dev/genps.c'\" unpacked with wrong size!
  1551. fi
  1552. # end of 'transfig/fig2dev/dev/genps.c'
  1553. fi
  1554. echo shar: End of archive 4 \(of 6\).
  1555. cp /dev/null ark4isdone
  1556. MISSING=""
  1557. for I in 1 2 3 4 5 6 ; do
  1558.     if test ! -f ark${I}isdone ; then
  1559.     MISSING="${MISSING} ${I}"
  1560.     fi
  1561. done
  1562. if test "${MISSING}" = "" ; then
  1563.     echo You have unpacked all 6 archives.
  1564.     rm -f ark[1-9]isdone
  1565. else
  1566.     echo You still need to unpack the following archives:
  1567.     echo "        " ${MISSING}
  1568. fi
  1569. ##  End of shell archive.
  1570. exit 0
  1571. -- 
  1572. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  1573. Use a domain-based address or give alternate paths, or you may lose out.
  1574.