home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / transfig-2.1.8 / part05 < prev    next >
Text File  |  1993-10-05  |  50KB  |  1,806 lines

  1. Newsgroups: comp.sources.unix
  2. From: envbvs@epb12.lbl.gov (Brian V. Smith)
  3. Subject: v27i059: transfig-2.1.8 - a set of tools for creating TeX documents with graphics, Part05/07
  4. References: <1.749903574.10622@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: envbvs@epb12.lbl.gov (Brian V. Smith)
  9. Posting-Number: Volume 27, Issue 59
  10. Archive-Name: transfig-2.1.8/part05
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 5 (of 7)."
  19. # Contents:  fig2dev/dev/genlatex.c fig2dev/dev/gentpic.c
  20. # Wrapped by envbvs@epb12.lbl.gov.lbl.gov on Fri Oct  1 14:55:49 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'fig2dev/dev/genlatex.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'fig2dev/dev/genlatex.c'\"
  24. else
  25. echo shar: Extracting \"'fig2dev/dev/genlatex.c'\" \(23356 characters\)
  26. sed "s/^X//" >'fig2dev/dev/genlatex.c' <<'END_OF_FILE'
  27. X/*
  28. X * TransFig: Facility for Translating Fig code
  29. X * Copyright (c) 1985 Supoj Sutantavibul
  30. X * Copyright (c) 1991 Micah Beck
  31. X *
  32. X * Permission to use, copy, modify, distribute, and sell this software and its
  33. X * documentation for any purpose is hereby granted without fee, provided that
  34. X * the above copyright notice appear in all copies and that both that
  35. X * copyright notice and this permission notice appear in supporting
  36. X * documentation. The authors make no representations about the suitability 
  37. X * of this software for any purpose.  It is provided "as is" without express 
  38. X * or implied warranty.
  39. X *
  40. X * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  41. X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  42. X * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  43. X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  44. X * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  45. X * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  46. X * PERFORMANCE OF THIS SOFTWARE.
  47. X *
  48. X */
  49. X
  50. X/* 
  51. X *    genlatex.c : LaTeX driver for fig2dev
  52. X *
  53. X *    Author: Frank Schmuck, Cornell University 6/88
  54. X *     Converted from fig2latex 5/89 by Micah Beck
  55. X *     Color, rotated text and ISO-chars added by Herbert Bauer 11/91
  56. X *
  57. X */
  58. X#if defined(hpux) || defined(SYSV)
  59. X#include <sys/types.h>
  60. X#endif
  61. X#include <sys/file.h>
  62. X#include <stdio.h>
  63. X#include <math.h>
  64. X#include "object.h"
  65. X#include "fig2dev.h"
  66. X#include "texfonts.h"
  67. X#include "pi.h"
  68. X
  69. X#ifndef fabs
  70. Xextern double fabs();
  71. X#endif
  72. X#ifndef sin
  73. Xextern double sin();
  74. X#endif
  75. X#ifndef cos
  76. Xextern double cos();
  77. X#endif
  78. X#ifndef acos
  79. Xextern double acos();
  80. X#endif
  81. X#ifndef atan
  82. Xextern double atan();
  83. X#endif
  84. Xextern double rad2deg;
  85. Xextern void unpsfont();
  86. X
  87. X#define rint(a) floor((a)+0.5)     /* close enough? */
  88. X
  89. X/* 
  90. X *  Installation dependent constants:
  91. X *
  92. X *  THINDOT    latex command for generating a dot if line width = \thinlines
  93. X *  THICKDOT    latex command for generating a dot if line width = \thicklines
  94. X *  MIN_LEN    shortest slanted line that latex can produce; shorter lines will
  95. X *        we translated into a sequence of dots generated by \multiput.
  96. X *  THICK_LDOT    latex command for generating the dot for making short slanted
  97. X *        lines if line width = \thinlines
  98. X *  THIN_LDOT    ...  if line width = \thicklines
  99. X */
  100. X#define THICKDOT    "\\SetFigFont{10}{12}{rm}."
  101. X#define THINDOT        "\\SetFigFont{7}{8.4}{rm}."
  102. Xdouble    THIN_XOFF =    (0.1/72.0);
  103. Xdouble    THIN_YOFF =    (0.7/72.0);
  104. Xdouble    THICK_XOFF =    (0.4/72.0);
  105. Xdouble    THICK_YOFF =    (0.6/72.0);
  106. X#define THICK_LDOT    "\\SetFigFont{7}{8.4}{rm}."
  107. X#define THIN_LDOT    "\\SetFigFont{5}{6}{rm}."
  108. Xdouble    THIN_LXOFF =    (0.1/72.0);
  109. Xdouble    THIN_LYOFF =    (0.7/72.0);
  110. Xdouble    THICK_LXOFF =    (0.4/72.0);
  111. Xdouble    THICK_LYOFF =    (0.6/72.0);
  112. X#define MIN_LEN        (13.0/72.0)    /* 13  points */
  113. X
  114. X/*
  115. X *  other constants and macros
  116. X */
  117. X#define TOP        840
  118. X#define THINLINES    1
  119. X#define THICKLINES    2
  120. X
  121. X#define MAXCIRCLEDIA    80
  122. X#define MAXCIRCLERAD    ((MAXCIRCLEDIA-0.5)/(2*72.27))
  123. X
  124. X#define    SWAP(x,y)    {tmp=x; x=y; y=tmp;}
  125. X#define TRANS(x,y)        (*translate_coordinates)(&x,&y)
  126. X#define TRANS2(x1,y1,x2,y2)    (*translate_coordinates)(&x1,&y1); \
  127. X                (*translate_coordinates)(&x2,&y2)
  128. X#define TRANSD(x,y)        (*translate_coordinates_d)(&x,&y)
  129. X#ifndef MIN
  130. X#define    MIN(x,y)    (((x) <= (y))? (x): (y))
  131. X#endif
  132. X#ifndef MAX
  133. X#define    MAX(x,y)    (((x) >= (y))? (x): (y))
  134. X#endif
  135. X#define    ABS(x)        (((x) >= 0)? (x): -(x))
  136. X#define round4(x)    ((round(10000.0*(x))/10000.0))
  137. X#define round6(x)    ((round(1000000.0*(x))/1000000.0))
  138. X
  139. Xchar        thindot [] = THINDOT;
  140. Xchar        thickdot[] = THICKDOT;
  141. Xchar        thin_ldot [] = THIN_LDOT;
  142. Xchar        thick_ldot[] = THICK_LDOT;
  143. X
  144. Xstatic    int    coord_system;
  145. Xint        verbose = 0;
  146. Xdouble        dash_mag = 1.0;
  147. Xint        thick_width = 2;
  148. Xdouble        tolerance = 2.0;
  149. Xdouble        arc_tolerance = 1.0;
  150. Xint        (*translate_coordinates)() = NULL;
  151. Xint        (*translate_coordinates_d)() = NULL;
  152. Xdouble        unitlength;
  153. Xstatic int    cur_thickness = -1;
  154. Xdouble        ldot_diameter = 1.0/72.0;
  155. Xchar        *dot_cmd = thindot;
  156. Xchar        *ldot_cmd = thin_ldot;
  157. Xdouble        dot_xoffset;
  158. Xdouble        dot_yoffset;
  159. Xdouble        ldot_xoffset;
  160. Xdouble        ldot_yoffset;
  161. X
  162. Xextern char *ISOtoTeX[];
  163. X
  164. Xstatic translate1(xp, yp)
  165. Xint    *xp, *yp;
  166. X{
  167. X    *xp = *xp + 1;
  168. X    *yp = *yp + 1;
  169. X    }
  170. X
  171. Xstatic translate2(xp, yp)
  172. Xint    *xp, *yp;
  173. X{
  174. X    *xp = *xp + 1;
  175. X    *yp = TOP - *yp -1;
  176. X    }
  177. X
  178. Xstatic translate1_d(xp, yp)
  179. Xdouble    *xp, *yp;
  180. X{
  181. X    *xp = *xp + 1.0;
  182. X    *yp = *yp + 1.0;
  183. X    }
  184. X
  185. Xstatic translate2_d(xp, yp)
  186. Xdouble    *xp, *yp;
  187. X{
  188. X    *xp = *xp + 1.0;
  189. X    *yp = (double)TOP - *yp -1.0;
  190. X    }
  191. X
  192. Xvoid genlatex_option(opt, optarg)
  193. Xchar opt, *optarg;
  194. X{
  195. X    int i;
  196. X
  197. X    switch (opt) {
  198. X    case 'a':
  199. X        fprintf(stderr, "warning: latex option -a obsolete");
  200. X        break;
  201. X
  202. X    case 'd':
  203. X        dash_mag = atof(optarg);    /* set dash magnification */
  204. X        break;
  205. X
  206. X
  207. X    case 'f':        /* set default text font */
  208. X        for ( i = 1; i <= MAX_FONT; i++ )
  209. X        if ( !strcmp(optarg, texfontnames[i]) ) break;
  210. X
  211. X        if ( i > MAX_FONT)
  212. X        fprintf(stderr,
  213. X            "warning: non-standard font name %s\n", optarg);
  214. X        
  215. X        texfontnames[0] = texfontnames[1] = optarg;
  216. X        break;
  217. X
  218. X    case 'l':        /* set thin/thick line threshold */
  219. X        thick_width = atoi(optarg);
  220. X        break;
  221. X
  222. X    case 's':
  223. X        if (font_size <= 0 || font_size > MAXFONTSIZE) {
  224. X        fprintf(stderr,
  225. X            "warning: font size %d out of bounds\n", font_size);
  226. X        }
  227. X        break;
  228. X
  229. X    case 'v':
  230. X        verbose = 1;        /* verbose mode */
  231. X        break;
  232. X
  233. X    case 'm':
  234. X    case 'L':
  235. X        break;
  236. X
  237. X    default:
  238. X        put_msg(Err_badarg, opt, "latex");
  239. X        exit(1);
  240. X        break;
  241. X    }
  242. X}
  243. X
  244. Xvoid genlatex_start(objects)
  245. XF_compound    *objects;
  246. X{
  247. X    int tmp;
  248. X
  249. X    texfontsizes[0] = texfontsizes[1] = TEXFONTSIZE(font_size);
  250. X
  251. X    coord_system = objects->nwcorner.y;
  252. X     unitlength = mag/objects->nwcorner.x;
  253. X
  254. X    switch (coord_system) {
  255. X        case 1:
  256. X        translate_coordinates = translate1;
  257. X        translate_coordinates_d = translate1_d;
  258. X        break;
  259. X        case 2:
  260. X        translate_coordinates = translate2;
  261. X        translate_coordinates_d = translate2_d;
  262. X        break;
  263. X        default:
  264. X        fprintf(stderr, "Wrong coordinate system; cannot continue\n");
  265. X        return;
  266. X        }
  267. X
  268. X    TRANS2(llx, lly, urx, ury);
  269. X    if (llx > urx) SWAP(llx, urx)
  270. X    if (lly > ury) SWAP(lly, ury)
  271. X
  272. X    /* LaTeX start */
  273. X    fprintf(tfp, "\\setlength{\\unitlength}{%.6fin}%%\n",
  274. X                        round6(unitlength));
  275. X    /* define the SetFigFont macro */
  276. X    define_setfigfont(tfp);
  277. X    fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n",
  278. X                      urx-llx, ury-lly, llx, lly);
  279. X}
  280. X
  281. Xvoid genlatex_end()
  282. X{
  283. X    /* LaTeX ending */
  284. X    fprintf(tfp, "\\end{picture}\n");
  285. X}
  286. X
  287. Xstatic set_linewidth(w)
  288. Xint    w;
  289. X{
  290. X    int        latex_w;
  291. X
  292. X    if (w == 0) return;
  293. X    /* latex only knows thin lines or thick lines */
  294. X    latex_w = (w >= thick_width)? THICKLINES: THINLINES;
  295. X    if (latex_w != cur_thickness) {
  296. X        cur_thickness = latex_w;
  297. X        if (cur_thickness == THICKLINES) {
  298. X        fprintf(tfp, "\\thicklines\n");
  299. X        dot_cmd = thickdot;
  300. X        dot_xoffset = round4(THICK_XOFF/unitlength);
  301. X        dot_yoffset = round4(THICK_YOFF/unitlength);
  302. X        ldot_cmd = thick_ldot;
  303. X        ldot_xoffset = round4(THICK_LXOFF/unitlength);
  304. X        ldot_yoffset = round4(THICK_LYOFF/unitlength);
  305. X        }
  306. X        else {
  307. X        fprintf(tfp, "\\thinlines\n");
  308. X        dot_cmd = thin_ldot;
  309. X        dot_xoffset = round4(THIN_XOFF/unitlength);
  310. X        dot_yoffset = round4(THIN_YOFF/unitlength);
  311. X        ldot_cmd = thin_ldot;
  312. X        ldot_xoffset = round4(THIN_LXOFF/unitlength);
  313. X        ldot_yoffset = round4(THIN_LYOFF/unitlength);
  314. X        }
  315. X        }
  316. X    }
  317. X
  318. Xvoid genlatex_line(l)
  319. XF_line    *l;
  320. X{
  321. X    F_point        *p, *q;
  322. X    int        x, y, llx, lly, urx, ury, arrow;
  323. X
  324. X    if (verbose) fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n");
  325. X
  326. X    set_linewidth(l->thickness);
  327. X    set_color(l->color);
  328. X
  329. X    p = l->points;
  330. X    q = p->next;
  331. X
  332. X    if (q == NULL) { /* A single point line */
  333. X        x = p->x; y = p->y;
  334. X        TRANS(x, y);
  335. X        fprintf(tfp, "\\put(%3d,%3d){\\makebox(%.4f,%.4f){%s}}\n",
  336. X          x, y, dot_xoffset, dot_yoffset, dot_cmd);
  337. X        return;
  338. X        }
  339. X
  340. X    if (l->type == T_ARC_BOX) { /* A box with rounded corners */
  341. X      fprintf(stderr, "Arc box not implemented; substituting box.\n");
  342. X      l->type = T_BOX;
  343. X    }
  344. X
  345. X    if (l->type == T_BOX) { /* A box */
  346. X        x = p->x; y = p->y;
  347. X        TRANS(x, y);
  348. X        llx = urx = x;
  349. X        lly = ury = y;
  350. X        while (q != NULL) {
  351. X        x = q->x; y = q->y;
  352. X        TRANS(x, y);
  353. X        if (x < llx) llx = x;
  354. X        if (y < lly) lly = y;
  355. X        if (x > urx) urx = x;
  356. X        if (y > ury) ury = y;
  357. X        q = q->next;
  358. X        }
  359. X        put_box (llx, lly, urx, ury, l->style, l->style_val);
  360. X        return;
  361. X        }
  362. X
  363. X    while (q != NULL) {
  364. X        arrow = 0;
  365. X        if (l->for_arrow  &&  q->next == NULL)
  366. X        arrow = 1;
  367. X        if (l->back_arrow  &&  p == l->points)
  368. X        arrow = (arrow)? 2: -1;
  369. X        single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val);
  370. X        p = q;
  371. X        q = q->next;
  372. X        }
  373. X
  374. X    if (l->area_fill && (int)l->area_fill != DEFAULT)
  375. X        fprintf(stderr, "Line area fill not implemented\n");
  376. X    reset_color(l->color);
  377. X    }
  378. X
  379. Xstatic single_line (x1, y1, x2, y2, arrow, style, val)
  380. Xint    x1, y1, x2, y2, arrow, style;
  381. Xdouble    val;
  382. X{
  383. X    int    dx, dy, sx, sy;
  384. X    double l, m, deviation;
  385. X
  386. X    TRANS2(x1, y1, x2, y2);
  387. X    dx = x2-x1;
  388. X    dy = y2-y1;
  389. X    /*** compute direction vector ***/
  390. X    get_slope(dx, dy, &sx, &sy, arrow);
  391. X    /*** compute line length in x-direction ***/
  392. X    if (sx == 0) {
  393. X        l = (double)abs(dy);
  394. X    } else {
  395. X        m = (double)abs(sy) / (double)abs(sx);
  396. X        l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m);
  397. X        deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy));
  398. X        if (deviation > tolerance)
  399. X        fprintf(stderr,
  400. X          "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n",
  401. X          dx, dy, deviation);
  402. X    }
  403. X    l = round4(l);
  404. X    /*** output letex command ***/
  405. X    switch (style) {
  406. X        case SOLID_LINE:
  407. X        put_solidline(x1, y1, sx, sy, l, arrow);
  408. X        break;
  409. X        case DASH_LINE:
  410. X        put_dashline(x1, y1, sx, sy, l, arrow, val);
  411. X        break;
  412. X        case DOTTED_LINE:
  413. X        put_dotline(x1, y1, sx, sy, l, arrow, val);
  414. X        break;
  415. X        }
  416. X    }
  417. X
  418. X
  419. X/*
  420. X * draw box
  421. X */
  422. Xstatic put_box (llx, lly, urx, ury, style, val)
  423. Xint    llx, lly, urx, ury, style;
  424. Xdouble    val;
  425. X{
  426. X    int    dlen;
  427. X
  428. X    switch (style) {
  429. X        case SOLID_LINE:
  430. X        fprintf(tfp, "\\put(%3d,%3d){\\framebox(%d,%d){}}\n",
  431. X          llx, lly, urx-llx, ury-lly);
  432. X        break;
  433. X        case DASH_LINE:
  434. X        dlen = round(val*dash_mag);
  435. X        fprintf(tfp, "\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n",
  436. X          llx, lly, dlen, urx-llx, ury-lly);
  437. X        break;
  438. X        case DOTTED_LINE:
  439. X        put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val);
  440. X        put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val);
  441. X        put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val);
  442. X        put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val);
  443. X        break;
  444. X        }
  445. X    return;
  446. X    }
  447. X
  448. X/*
  449. X * draw a solid line given latex slope
  450. X */
  451. Xstatic put_solidline (x, y, sx, sy, l, arrow)
  452. Xint    x, y, sx, sy, arrow;
  453. Xdouble    l;
  454. X{
  455. X    double    cosine;        /* cosine of line angle */
  456. X    double    dx, dy;
  457. X    int    x2, y2, n;
  458. X
  459. X    if (sx) {
  460. X        cosine = (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy));
  461. X        x2 = (sx >= 0)? x + round(l): x - round(l);
  462. X        y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx);
  463. X        }
  464. X    else {
  465. X        cosine = 1.0;
  466. X        x2 = x;
  467. X        y2 = (sy >= 0)? y + round(l): y - round(l);
  468. X        }
  469. X    if (sx == 0  ||  sy == 0  ||  (l/cosine)*unitlength >= MIN_LEN) {
  470. X        switch (arrow) {
  471. X        case 0:  /* simple line */
  472. X        fprintf(tfp, "\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy);
  473. X        break;
  474. X        case 1:  /* forward arrow */
  475. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy);
  476. X        break;
  477. X        case -1: /* backward arrow */
  478. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy);
  479. X        break;
  480. X        case 2:  /* double arrow */
  481. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){  0}}\n", x,y,-sx,-sy);
  482. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy);
  483. X        break;
  484. X        }
  485. X        if (l == floor(l))
  486. X        fprintf(tfp, "{%3.0f}}\n", l);
  487. X        else
  488. X        fprintf(tfp, "{%7.3f}}\n", l);
  489. X        }
  490. X    else {
  491. X        n = 2 * (l/cosine) / (ldot_diameter/unitlength);
  492. X        fprintf(stderr, "Line too short; will do %d dots\n", n);
  493. X        dx = l / (double)n;
  494. X        if (sx < 0) dx = -dx;
  495. X        dy = dx * (double)sy / (double)sx;
  496. X        fprintf(tfp, 
  497. X          "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n",
  498. X          x, y, dx, dy, n+1, ldot_xoffset, ldot_yoffset, ldot_cmd);
  499. X        if (arrow == 1  ||  arrow == 2)  /* forward arrow */
  500. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy);
  501. X        if (arrow == -1  ||  arrow == 2) /* backward arrow */
  502. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy);
  503. X        }
  504. X    }
  505. X
  506. X/*
  507. X * draw a dashed line given latex slope
  508. X */
  509. Xstatic put_dashline (x, y, sx, sy, l, arrow, val)
  510. Xint    x, y, sx, sy, arrow;
  511. Xdouble    l;
  512. Xdouble    val;
  513. X{
  514. X    double    cosine;        /* cosine of line angle */
  515. X    double    nd;        /* number of dashes and gaps fitting on line */
  516. X    int    n;        /* nd rounded to the nearest odd integer */
  517. X    double    dl;        /* actual x-length of each dash */
  518. X    double    dg;        /* actual x-length of each gap */
  519. X    double    dx, dy;        /* step between dashes */
  520. X    int    x2, y2;
  521. X
  522. X    if (sx) {
  523. X        cosine = (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy));
  524. X        x2 = (sx >= 0)? x + round(l): x - round(l);
  525. X        y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx );
  526. X        }
  527. X    else {
  528. X        cosine = 1.0;
  529. X        x2 = x;
  530. X        y2 = (sy >= 0)? y + round(l): y - round(l);
  531. X        }
  532. X    /*** compute number of dashes, length of dashes and gaps ***/
  533. X    nd = l / (val*dash_mag*cosine);
  534. X    n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
  535. X    dl = l / (double)n;
  536. X    if (sx  &&  sy  &&  (dl/cosine)*unitlength < MIN_LEN) {
  537. X        fprintf(stderr, "Dash too small; using larger dash\n");
  538. X        dl = MIN_LEN/unitlength * cosine;
  539. X        nd = l / dl;
  540. X        n = (int) (rint((nd + 1.0)/2.0)*2 - 1);
  541. X        }
  542. X    if (2*dl >= l  ||  (sx  &&  sy  &&  (l/cosine)*unitlength < MIN_LEN)) {
  543. X        fprintf(stderr, "Dashed line too short; drawing solid line\n");
  544. X        put_solidline (x, y, sx, sy, l, arrow);
  545. X        return;
  546. X        }
  547. X    dg = (l - (n/2+1)*dl) / (double)(n/2);
  548. X    if (sx) {
  549. X        dx = dl+dg;
  550. X        if (sx < 0) dx = -dx;
  551. X        dy = dx * (double)sy / (double)sx;
  552. X        }
  553. X    else {
  554. X        dx = 0.0;
  555. X        dy = dl+dg;
  556. X        if (sy < 0) dy = -dy;
  557. X        }
  558. X    /*** draw dashed line ***/
  559. X    fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\line(%2d,%2d){%7.3f}}\n",
  560. X        x, y, dx, dy, n/2+1, sx, sy, dl);
  561. X    /*** draw arrow heads ***/
  562. X    if (arrow == 1  ||  arrow == 2)
  563. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
  564. X    if (arrow == -1  ||  arrow == 2)
  565. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
  566. X    }
  567. X
  568. X/*
  569. X * draw a dotted line given latex slope
  570. X */
  571. Xstatic put_dotline (x, y, sx, sy, l, arrow, val)
  572. Xint    x, y, sx, sy, arrow;
  573. Xdouble    l;
  574. Xdouble    val;
  575. X{
  576. X    double    cosine;        /* cosine of line angle */
  577. X    double    nd;        /* number of dots fitting on line */
  578. X    int    n;        /* nd rounded to the nearest integer */
  579. X    double    dx, dy;        /* step between dashes */
  580. X    int    x2, y2;
  581. X
  582. X
  583. X    cosine = (sx)? (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy)): 1.0;
  584. X    /*** compute step width ***/
  585. X    nd = l / (3*val*cosine);
  586. X    n = rint(nd);
  587. X    dx = l / (double)n;
  588. X    if (sx) {
  589. X        dx = l / (double)n;
  590. X        if (sx < 0) dx = -dx;
  591. X        dy = dx * (double)sy / (double)sx;
  592. X        }
  593. X    else {
  594. X        dx = 0.0;
  595. X        dy = l / (double)n;
  596. X        if (sy < 0) dy = -dy;
  597. X        }
  598. X    /*** draw arrow heads ***/
  599. X    if (arrow == 1  ||  arrow == 2) {
  600. X        /* forward arrow */
  601. X        if (sx) {
  602. X        x2 = (sx >= 0)? x + round(l): x - round(l);
  603. X        y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx );
  604. X        }
  605. X        else {
  606. X        x2 = x;
  607. X        y2 = (sy >= 0)? y + round(l): y - round(l);
  608. X        }
  609. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy);
  610. X        n--;
  611. X        }
  612. X    if (arrow == -1  ||  arrow == 2) {
  613. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy);
  614. X        x = round(x + dx);
  615. X        y = round(y + dy);
  616. X        n--;
  617. X        }
  618. X    /*** draw dotted line ***/
  619. X    fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n",
  620. X        x, y, dx, dy, n+1, dot_xoffset, dot_yoffset, dot_cmd);
  621. X    }
  622. X
  623. Xvoid genlatex_spline(s)
  624. XF_spline    *s;
  625. X{
  626. X    fprintf(stderr, "Can't generate spline; omitting object\n");
  627. X    }
  628. X
  629. Xvoid genlatex_ellipse(e)
  630. XF_ellipse    *e;
  631. X{
  632. X    int  x, y, d, dx, dy;
  633. X
  634. X    if (verbose) fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n");
  635. X
  636. X    set_linewidth(e->thickness);
  637. X    switch (e->style) {
  638. X        case SOLID_LINE:
  639. X        break;
  640. X        case DASH_LINE:
  641. X        fprintf(stderr, "Dashed circles and elipses not supported\n");
  642. X        break;
  643. X        case DOTTED_LINE:
  644. X        fprintf(stderr, "Dotted circles and elipses not supported\n");
  645. X        break;
  646. X        }
  647. X
  648. X    x = e->center.x;
  649. X    y = e->center.y;
  650. X    TRANS(x, y);
  651. X    if ((e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA)
  652. X            && e->radiuses.x*unitlength <= MAXCIRCLERAD) {
  653. X
  654. X        d = 2 * e->radiuses.x;
  655. X        if (e->area_fill == BLACK_FILL)
  656. X            fprintf(tfp, "\\put(%3d,%3d){\\circle*{%d}}\n", x, y, d);
  657. X        else {
  658. X              fprintf(tfp, "\\put(%3d,%3d){\\circle{%d}}\n", x, y, d);
  659. X        if (e->area_fill && (int)e->area_fill != DEFAULT)
  660. X            fprintf(stderr, "Circle area fill not implemented\n");
  661. X        }
  662. X
  663. X    } else {        
  664. X        dx = 2 * e->radiuses.x;
  665. X        dy = 2 * e->radiuses.y;
  666. X        fprintf(tfp, "\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy);
  667. X        if (e->area_fill && (int)e->area_fill != DEFAULT)
  668. X        fprintf(stderr, "Ellipse area fill not implemented\n");
  669. X    }
  670. X      }
  671. X
  672. Xvoid genlatex_text(t)
  673. XF_text    *t;
  674. X{
  675. X    int       x, y;
  676. X    char    *tpos;
  677. X    unsigned char    *cp;
  678. X
  679. X    if (verbose) fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n");
  680. X
  681. X    x = t->base_x;
  682. X    y = t->base_y;
  683. X    TRANS(x, y);
  684. X
  685. X    switch (t->type) {
  686. X
  687. X        case T_LEFT_JUSTIFIED:
  688. X        case DEFAULT:
  689. X            tpos = "[lb]";
  690. X        break;
  691. X
  692. X        case T_CENTER_JUSTIFIED:
  693. X            tpos = "[b]";
  694. X        break;
  695. X
  696. X        case T_RIGHT_JUSTIFIED:
  697. X            tpos = "[rb]";
  698. X        break;
  699. X
  700. X        default:
  701. X        fprintf(stderr, "Text incorrectly positioned\n");
  702. X        }
  703. X
  704. X    /* smash is used to position text at baseline */
  705. X    unpsfont(t);
  706. X    fprintf(tfp, 
  707. X      "\\put(%3d,%3d){\\makebox(0,0)%s{\\smash{",
  708. X      x, y, tpos);
  709. X
  710. X#ifdef DVIPS
  711. X        if(t->angle && t->type == T_LEFT_JUSTIFIED)
  712. X          fprintf(tfp, "\\special{ps:gsave currentpoint currentpoint translate\n%.1f rotate neg exch neg exch translate}", -t->angle*180/M_PI);
  713. X#endif
  714. X
  715. X        { int texsize;
  716. X          double baselineskip;
  717. X
  718. X      texsize = TEXFONTMAG(t);
  719. X      baselineskip = (texsize * 1.2);
  720. X
  721. X       fprintf(tfp, "\\SetFigFont{%d}{%.1f}{%s}",
  722. X        texsize, baselineskip, TEXFONT(t->font));
  723. X    }
  724. X
  725. X    set_color(t->color);
  726. X
  727. X    if (!special_text(t))
  728. X
  729. X        /* this loop escapes characters "$&%#_{}" */
  730. X        /* and deleted characters "~^\" */
  731. X        for(cp = (unsigned char*)t->cstring; *cp; cp++) {
  732. X                  if (strchr("$&%#_{}", *cp)) (void)fputc('\\', tfp);
  733. X                  if (strchr("~^\\", *cp))
  734. X            fprintf(stderr,
  735. X                "Bad character in text object '%c'\n" ,*cp);
  736. X            else
  737. X            (void)fputc(*cp, tfp);
  738. X              }
  739. X    else 
  740. X        for(cp = (unsigned char*)t->cstring; *cp; cp++) {
  741. X            if (*cp >= 0xa0)
  742. X             fprintf(tfp, "%s", ISOtoTeX[(int)*cp-0xa0]);
  743. X        else
  744. X            fputc(*cp, tfp);
  745. X        }
  746. X
  747. X    reset_color(t->color);
  748. X
  749. X#ifdef DVIPS
  750. X        if(t->angle)
  751. X    {
  752. X      if (t->type == T_LEFT_JUSTIFIED)
  753. X             fprintf(tfp, "\\special{ps:currentpoint grestore moveto}");
  754. X      else
  755. X         fprintf(stderr, "Rotated Text only for left justified text\n");
  756. X    }
  757. X#endif
  758. X     fprintf(tfp, "}}}\n");
  759. X    }
  760. X
  761. Xvoid genlatex_arc(a)
  762. XF_arc    *a;
  763. X/*
  764. X *  Approximates an arc by a sequence of quarter ovals.
  765. X *
  766. X *  Example:
  767. X *
  768. X *    Arc with center at (0,0) and radius 10 from +45 degree to +225 degree
  769. X *    (arc from p1 = (7.07, 7.07) to p2 = (-7.07, -7.07) counterclockwise).
  770. X *    This arc is approximated by three quarter ovals, one for each quadrant
  771. X *    through which the arc goes:
  772. X *
  773. X *     1. quarter oval from p1 to the intersection of arc and y-axis,
  774. X *        i.e., from (7.07, 7.07) to (0, 10) in quadrant 0
  775. X *
  776. X *        \put(0, 7.07){\oval(14.14, 5.86)[tr]}
  777. X *
  778. X *     2. quarter oval from intersection arc/y-axis to intersection arc/x-axis
  779. X *        i.e., from (0, 10) to (-10, 0) in quadrant 1
  780. X *
  781. X *        \put(0, 0){\oval(20,20)[tl]}
  782. X *
  783. X *     3. quarter oval from p1 to the intersection of arc and y-axis,
  784. X *        i.e., from (-10, 0) to (-7.07, -7.07) in quadrant 2
  785. X *
  786. X *        \put(-7.07, 0){\oval(5.86, 14.14)[bl]}
  787. X */
  788. X{
  789. X    F_pos        p1, p2, pq[4];
  790. X    double        cx, cy;
  791. X    double        v1x, v1y, v2x, v2y;
  792. X    double        r, angle1, angle2;
  793. X    int        q1, q2;
  794. X    int        p1_arrow, p2_arrow;
  795. X    static char    *ad1[4] = { " 0,-1", " 1, 0", " 0, 1", "-1, 0" };
  796. X    static char    *ad2[4] = { "-1, 0", " 0,-1", " 1, 0", " 0, 1" };
  797. X
  798. X    set_linewidth(a->thickness);
  799. X    set_color(a->color);
  800. X    switch (a->style) {
  801. X        case SOLID_LINE:
  802. X        break;
  803. X        case DASH_LINE:
  804. X        fprintf(stderr, "Dashed arcs not supported\n");
  805. X        break;
  806. X        case DOTTED_LINE:
  807. X        fprintf(stderr, "Dotted arcs not supported\n");
  808. X        break;
  809. X        }
  810. X    if (a->direction == 1) {
  811. X        p1 = a->point[0];
  812. X        p2 = a->point[2];
  813. X        p1_arrow = (a->back_arrow != NULL);
  814. X        p2_arrow = (a->for_arrow != NULL);
  815. X        }
  816. X    else {
  817. X        p1 = a->point[2];
  818. X        p2 = a->point[0];
  819. X        p1_arrow = (a->for_arrow != NULL);
  820. X        p2_arrow = (a->back_arrow != NULL);
  821. X        }
  822. X    cx = a->center.x;
  823. X    cy = a->center.y;
  824. X    TRANS2(p1.x, p1.y, p2.x, p2.y);
  825. X    TRANSD(cx, cy);
  826. X    /*** compute vectors and angles from arc center to p1, p2 ***/
  827. X    v1x = (double)p1.x - cx;
  828. X    v1y = (double)p1.y - cy;
  829. X    v2x = (double)p2.x - cx;
  830. X    v2y = (double)p2.y - cy;
  831. X    angle1 = atan2(v1y, v1x) * rad2deg;
  832. X    angle2 = atan2(v2y, v2x) * rad2deg;
  833. X    if (angle1 < 0.0)
  834. X        angle1 += 360.0; 
  835. X    if (angle2 < 0.0)
  836. X        angle2 += 360.0; 
  837. X    /* compute arc radius */
  838. X    r = sqrt(v1x*v1x+v1y*v1y);
  839. X    /*** compute intersection of arc with x and y axis (origin at cx, cy) */
  840. X    pq[0].x = round(cx);
  841. X    pq[0].y = round(cy + r);
  842. X    pq[1].x = round(cx - r);
  843. X    pq[1].y = round(cy);
  844. X    pq[2].x = round(cx);
  845. X    pq[2].y = round(cy - r);
  846. X    pq[3].x = round(cx + r);
  847. X    pq[3].y = round(cy);
  848. X    /*** compute in which quadrants p1 and p2 are located ***/
  849. X    q1 = (int)(angle1/90.0);
  850. X    q2 = (int)(angle2/90.0);
  851. X    if (fabs(angle1 - 90.0*q1) > arc_tolerance 
  852. X     || fabs(angle2 - 90.0*q2) > arc_tolerance)
  853. X        fprintf(stderr, "Approximating arc by ovals\n");
  854. X    /*** Draw arc ***/
  855. X    if (p1_arrow)
  856. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p1.x, p1.y, ad1[q1]);
  857. X    while (q1 != q2) {
  858. X        put_quarter(p1, pq[q1], q1);
  859. X        p1 = pq[q1];
  860. X        q1 = (q1 + 1) % 4;
  861. X        }
  862. X    put_quarter(p1, p2, q1);
  863. X    if (p2_arrow)
  864. X        fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p2.x, p2.y, ad2[q2]);
  865. X
  866. X    if (a->area_fill && (int)a->area_fill != DEFAULT)
  867. X        fprintf(stderr, "Arc area fill not implemented\n");
  868. X    reset_color(a->color);
  869. X    }
  870. X
  871. Xstatic put_quarter(p1, p2, q)
  872. XF_pos    p1, p2;
  873. Xint    q;
  874. X/*
  875. X *  Draw quarter oval from p1 to p2 in quadrant q
  876. X */
  877. X{
  878. X    char    *opt;
  879. X    int    px, py, dx, dy;
  880. X
  881. X    dx = 2*ABS(p1.x - p2.x);
  882. X    dy = 2*ABS(p1.y - p2.y);
  883. X    if (dx == 0  &&  dy == 0)
  884. X        return;
  885. X    switch (q) {
  886. X        case 0:
  887. X        px = MIN(p1.x, p2.x);
  888. X        py = MIN(p1.y, p2.y);
  889. X        opt = "tr";
  890. X        break;
  891. X        case 1:
  892. X        px = MAX(p1.x, p2.x);
  893. X        py = MIN(p1.y, p2.y);
  894. X        opt = "tl";
  895. X        break;
  896. X        case 2:
  897. X        px = MAX(p1.x, p2.x);
  898. X        py = MAX(p1.y, p2.y);
  899. X        opt = "bl";
  900. X        break;
  901. X        case 3:
  902. X        px = MIN(p1.x, p2.x);
  903. X        py = MAX(p1.y, p2.y);
  904. X        opt = "br";
  905. X        break;
  906. X        }
  907. X    fprintf(tfp, "\\put(%3d,%3d){\\oval(%3d,%3d)[%s]}\n", px, py, dx, dy, opt);
  908. X    }
  909. X
  910. X#define  MAXCOLORS 8
  911. X
  912. Xset_color(col)
  913. Xint col;
  914. X{
  915. X   static char *colors[] = {
  916. X   "0 0 0",    /* black */
  917. X   "0 0 1",    /* blue */
  918. X   "0 1 0",    /* green */
  919. X   "0 1 1",    /* cyan */
  920. X   "1 0 0",    /* red */
  921. X   "1 0 1",    /* magenta */
  922. X   "1 1 0",    /* yellow */
  923. X   "1 1 1",    /* white */
  924. X   };
  925. X   
  926. X#ifdef DVIPS
  927. X   if (col != -1 && col < MAXCOLORS)
  928. X      fprintf(tfp, "\\special{ps: gsave %s setrgbcolor}", colors[col]);
  929. X#endif
  930. X   return;
  931. X}
  932. X
  933. Xreset_color(col)
  934. Xint col;
  935. X{
  936. X#ifdef DVIPS
  937. X   if (col != -1 && col < MAXCOLORS)
  938. X      fprintf(tfp, "\\special{ps: grestore}");
  939. X#endif
  940. X   return;
  941. X}
  942. X
  943. X
  944. Xstruct driver dev_latex = {
  945. X         genlatex_option,
  946. X    genlatex_start,
  947. X    genlatex_arc,
  948. X    genlatex_ellipse,
  949. X    genlatex_line,
  950. X    genlatex_spline,
  951. X    genlatex_text,
  952. X    genlatex_end,
  953. X    EXCLUDE_TEXT
  954. X};
  955. END_OF_FILE
  956. if test 23356 -ne `wc -c <'fig2dev/dev/genlatex.c'`; then
  957.     echo shar: \"'fig2dev/dev/genlatex.c'\" unpacked with wrong size!
  958. fi
  959. # end of 'fig2dev/dev/genlatex.c'
  960. fi
  961. if test -f 'fig2dev/dev/gentpic.c' -a "${1}" != "-c" ; then 
  962.   echo shar: Will not clobber existing file \"'fig2dev/dev/gentpic.c'\"
  963. else
  964. echo shar: Extracting \"'fig2dev/dev/gentpic.c'\" \(22577 characters\)
  965. sed "s/^X//" >'fig2dev/dev/gentpic.c' <<'END_OF_FILE'
  966. X/*
  967. X * TransFig: Facility for Translating Fig code
  968. X * Copyright (c) 1985 Supoj Sutantavibul
  969. X * Copyright (c) 1991 Micah Beck
  970. X *
  971. X * Permission to use, copy, modify, distribute, and sell this software and its
  972. X * documentation for any purpose is hereby granted without fee, provided that
  973. X * the above copyright notice appear in all copies and that both that
  974. X * copyright notice and this permission notice appear in supporting
  975. X * documentation. The authors make no representations about the suitability 
  976. X * of this software for any purpose.  It is provided "as is" without express 
  977. X * or implied warranty.
  978. X *
  979. X * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  980. X * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  981. X * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  982. X * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  983. X * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  984. X * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  985. X * PERFORMANCE OF THIS SOFTWARE.
  986. X *
  987. X */
  988. X
  989. X/* 
  990. X *    gentpic : TPIC driver for fig2dev
  991. X *
  992. X *    Author: Conrad Kwok, UC Davis, 12/88
  993. X *      Modified: Richard Auletta, George Mason Univ., 6/21/89
  994. X *        Added code comments are marked with "rja".
  995. X *          Added: Support for native pic arrowheads.
  996. X *          Added: Support for arrowheads at both ends of lines, arc, splines.
  997. X *    Modified: Modified from pic to tpic. Baron Grey, UCLA. 10/2/90.
  998. X *
  999. X *        This driver supports TeX's virtual font mechanism. Any Fig
  1000. X *        font whose ordinal number is greater than 6 is treated as
  1001. X *        a TeX virtual PostScript font. Virtual PostScript font
  1002. X *        names are defined in tpicfonts.h (you should define
  1003. X *        corresponding names in Fig in file change.c). Customize to
  1004. X *        suit your virtual font availability or your name preferences.
  1005. X *
  1006. X *        There are no restrictions on font sizes in this driver, but
  1007. X *        keep in mind that TeX only supports fonts up to 2048 points!
  1008. X *        Since PostScript fonts are scaleable, virtual PS fonts can have
  1009. X *        any point size within the limits imposed by TeX or by your
  1010. X *        PostScript interpreter. If you are using
  1011. X *        standard predefined LaTeX fonts (assumed to be the first
  1012. X *        6 positions in Fig's ordinal font numbering scheme), font
  1013. X *        sizes are mapped into the nearest valid normally-available
  1014. X *        LaTeX font sizes -- look at tpicfonts.h to see how this is
  1015. X *        done; you can modify it for fonts at your site.
  1016. X *
  1017. X *        Additional features of this driver are:
  1018. X *        1) Support for all Fig features except text at nonzero
  1019. X *           angles.  (In fact, any limitations of this driver are
  1020. X *           actually tpic limitations.)
  1021. X *        2) Boxes with rounded corners are supported in two ways.
  1022. X *           If (when) tpic is extended to use the "radius" attribute
  1023. X *           with a "box" specification, the driver will generate the
  1024. X *           appropriate box specification. Otherwise, it creates
  1025. X *           rounded-corner boxes from line and arc segments using
  1026. X *           existing tpic primitives. In the former case, rounded-
  1027. X *           corner boxes can be shaded; in the latter, they can't.
  1028. X *           Define TPIC_ARC_BOX for the first case (the default);
  1029. X *           undefine it otherwise.
  1030. X *        3) Supports Fig's ability to texture (shade) objects.
  1031. X *           Bitmapped PostScript texture patterns are supported;
  1032. X *           they are defined in "tpicfonts.h". The tpic ".tx"
  1033. X *           primitive is used for this. Your dvi-to-PostScript
  1034. X *           driver must be adapted to support them.
  1035. X *        4) If an object's line "thickness" is 0, it is given tpic's
  1036. X *           `invis' attribute. That is, tpic will treat it as an
  1037. X *           invisible object in the normal tpic sense.
  1038. X *        5) This driver supports tpic 2.0. It will work with tpic 1.0,
  1039. X *           but some object attributes will not be available.
  1040. X *        6) The default line thickness is 8 milli inches (in tpic
  1041. X *           units). This corresponds to 1 pixel width in Fig. The
  1042. X *           formula is: line_thickness = Fig_line_thickness *
  1043. X *           default_tpic_line_thickness.
  1044. X *        7) The default font size is (assumed to be) 10 points!
  1045. X */
  1046. X
  1047. X#include <stdio.h>
  1048. X#include <math.h>
  1049. X#include "object.h"
  1050. X#include "fig2dev.h"
  1051. X#include "tpicfonts.h"
  1052. X
  1053. X/*
  1054. X * Define TPIC_ARC_BOX if your tpic supports rounded-corner boxes
  1055. X * via a "radius" attribute of a box specification.
  1056. X */
  1057. X#define TPIC_ARC_BOX
  1058. X
  1059. X#define            TOP    10.5    /* top of page is 10.5 inch */
  1060. Xstatic double        ppi;
  1061. Xstatic int        CONV = 0;
  1062. Xstatic int        line_width = 8;    /* milli-inches */
  1063. Xstatic int        vfont = 0; /* true if using a virtual TeX font */
  1064. X
  1065. Xvoid gentpic_ctl_spline(), gentpic_itp_spline();
  1066. Xvoid gentpic_open_spline(), gentpic_closed_spline();
  1067. Xvoid gentpic_spline(), gentpic_ellipse(), gentpic_text();
  1068. Xvoid gentpic_arc(), gentpic_line(), newline();
  1069. X
  1070. Xvoid gentpic_option(opt, optarg)
  1071. Xchar opt, *optarg;
  1072. X{
  1073. X    switch (opt) {
  1074. X
  1075. X    case 'f':        /* set default text font */
  1076. X            {   int i;
  1077. X
  1078. X            for ( i = 1; i <= MAX_TPICFONT; i++ )
  1079. X            if ( !strcmp(optarg, texfontnames[i]) ) break;
  1080. X
  1081. X            if ( i > MAX_FONT)
  1082. X                vfont = 1; /* assume a virtual font */
  1083. X        }
  1084. X        
  1085. X        texfontnames[0] = optarg;
  1086. X        break;
  1087. X
  1088. X    case 's':
  1089. X    case 'm':
  1090. X    case 'L':
  1091. X        break;
  1092. X
  1093. X     default:
  1094. X        put_msg(Err_badarg, opt, "tpic");
  1095. X        exit(1);
  1096. X    }
  1097. X}
  1098. X
  1099. Xstatic double convy(a)
  1100. Xdouble    a;
  1101. X{
  1102. X    return((double)(CONV ? TOP-a : a));
  1103. X}
  1104. X
  1105. Xvoid gentpic_start(objects)
  1106. XF_compound    *objects;
  1107. X{
  1108. X    int        coord_system;
  1109. X
  1110. X    ppi = objects->nwcorner.x/mag;
  1111. X    coord_system = objects->nwcorner.y;
  1112. X    if (coord_system == 2) CONV = 1;
  1113. X
  1114. X    fprintf(tfp, ".PS\n");    /* PIC preamble */
  1115. X
  1116. X}
  1117. X
  1118. Xvoid gentpic_end()
  1119. X{
  1120. X      fprintf(tfp, ".PE\n");                /* PIC ending */
  1121. X}
  1122. X
  1123. X/*
  1124. X * tpic's line thickness is given in milli-inches with a default of 8
  1125. X * milli-inches. We simply multiply this default with the Fig pixel width.
  1126. X */
  1127. Xstatic set_linewidth(w)
  1128. Xint    w;
  1129. X{
  1130. X    static int    cur_thickness = -1;
  1131. X
  1132. X    if (w == 0) return;
  1133. X    if (w != cur_thickness) {
  1134. X        cur_thickness = w;
  1135. X        fprintf(tfp, ".ps %d\n", cur_thickness * line_width);
  1136. X        }
  1137. X    }
  1138. X
  1139. Xstatic set_style(s, v)
  1140. Xint    s;
  1141. Xfloat    v;
  1142. X{
  1143. X    static float    style_val = -1;
  1144. X
  1145. X    if (s == DASH_LINE || s == DOTTED_LINE) {
  1146. X        if (v == style_val || v == 0.0) return;
  1147. X        style_val = v;
  1148. X        fprintf(tfp, "dashwid = %.3fi\n", style_val/ppi);
  1149. X        }
  1150. X    }
  1151. X
  1152. Xstatic set_baseline(b)
  1153. Xint    b;
  1154. X{
  1155. X    static int    cur_baseline = -1;
  1156. X
  1157. X    if (b != cur_baseline) {
  1158. X        fprintf(tfp, ".baseline %d\n", b);
  1159. X        cur_baseline = b;
  1160. X    }
  1161. X}
  1162. X
  1163. Xstatic set_texture(cur_texture)
  1164. Xint    cur_texture;
  1165. X{
  1166. X    /*
  1167. X     * This applies only to bitmapped texture patterns defined in
  1168. X     * tpicfonts.h. See set_fill() below for normal shading.
  1169. X     */
  1170. X    if (cur_texture <= BLACK_FILL || cur_texture > MAXPATTERNS + BLACK_FILL)
  1171. X        return;
  1172. X    fprintf(tfp, ".tx 16 %s\n",
  1173. X        texture_patterns[cur_texture - BLACK_FILL - 1]);
  1174. X}
  1175. X
  1176. X/*
  1177. X * Set the shade for filling an object. Your dvi-to-postscript driver must
  1178. X * distinguish between a "shaded" attribute with or without a parameter.
  1179. X * If there is no parameter, then it should do a bitmap texture fill;
  1180. X * otherwise, it should do a normal gray-scale fill. Note that the gray-
  1181. X * scale fill parameter is wired for fig2.X (the constant 0.05).
  1182. X */
  1183. Xstatic set_fill(cur_fill)
  1184. Xint    cur_fill;
  1185. X{
  1186. X    if(cur_fill < WHITE_FILL ||
  1187. X       cur_fill > BLACK_FILL + MAXPATTERNS)
  1188. X        return;
  1189. X    switch(cur_fill) {
  1190. X    case BLACK_FILL:
  1191. X        fprintf(tfp, " black");
  1192. X        break;
  1193. X    case WHITE_FILL:
  1194. X        fprintf(tfp, " white");
  1195. X        break;
  1196. X    default:
  1197. X        if (cur_fill > BLACK_FILL)
  1198. X            fprintf (tfp, " shaded");
  1199. X        else
  1200. X            fprintf(tfp, " shaded %0.3f", (cur_fill-1)*0.05);
  1201. X        break;
  1202. X    }
  1203. X}
  1204. X
  1205. X#ifdef TPIC_ARC_BOX
  1206. Xvoid gentpic_line(l)
  1207. XF_line    *l;
  1208. X{
  1209. X    F_point        *p, *q;
  1210. X    int    llx, lly, urx, ury;
  1211. X
  1212. X    set_linewidth(l->thickness);
  1213. X    set_style(l->style, l->style_val);
  1214. X    set_texture(l->area_fill);
  1215. X    p = l->points;
  1216. X    q = p->next;
  1217. X    if (q == NULL) { /* A single point line */
  1218. X        fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f",
  1219. X            p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi));
  1220. X        newline();
  1221. X        return;
  1222. X        }
  1223. X
  1224. X    if (l->type == T_BOX || l->type == T_ARC_BOX) {
  1225. X        llx = urx = p->x;
  1226. X        lly = ury = p->y;
  1227. X        while (q != NULL) {
  1228. X            p = q;
  1229. X            if (p->x < llx) {
  1230. X                llx = p->x;
  1231. X            } else if (p->x > urx) {
  1232. X                urx = p->x;
  1233. X            }
  1234. X            if (p->y < lly) {
  1235. X                lly = p->y;
  1236. X            } else if (p->y > ury) {
  1237. X                ury = p->y;
  1238. X            }
  1239. X            q = q->next;
  1240. X        }
  1241. X        fprintf(tfp, "box height %.3f width %.3f", (ury-lly)/ppi,
  1242. X            (urx-llx)/ppi);
  1243. X        switch(l->style) {
  1244. X        case SOLID_LINE:
  1245. X            break;
  1246. X        case DASH_LINE:
  1247. X            fprintf(tfp, " dashed");
  1248. X            break;
  1249. X        case DOTTED_LINE:
  1250. X            fprintf(tfp, " dotted");
  1251. X            break;
  1252. X        default:
  1253. X            put_msg("Program error! No other line styles allowed.\n");
  1254. X            return;
  1255. X        }
  1256. X        if (l->thickness == 0)
  1257. X            fprintf(tfp, " invis");
  1258. X        fprintf(tfp, " radius %.3f", l->radius/ppi);
  1259. X        set_fill(l->area_fill);
  1260. X        fprintf(tfp, " with .nw at %.3f,%.3f", llx/ppi, convy(lly/ppi));
  1261. X        newline();
  1262. X        return;
  1263. X    }
  1264. X
  1265. X    if (l->style == DASH_LINE && l->style_val > 0.0)
  1266. X        fprintf(tfp, "line dashed");
  1267. X    else if (l->style == DOTTED_LINE && l->style_val > 0.0)
  1268. X        fprintf(tfp, "line dotted");
  1269. X    else
  1270. X        fprintf(tfp, "line");
  1271. X
  1272. X    /*rja: Place arrowheads or lack there of on the line*/
  1273. X    if ((l->for_arrow) && (l->back_arrow))
  1274. X        fprintf(tfp, " <-> from");
  1275. X    else if (l->back_arrow)
  1276. X        fprintf(tfp, " <- from");
  1277. X    else if (l->for_arrow)
  1278. X        fprintf(tfp, " -> from");
  1279. X        else
  1280. X        fprintf(tfp, " from ");
  1281. X
  1282. X    fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  1283. X    while (q->next != NULL) {
  1284. X        p = q;
  1285. X        q = q->next;
  1286. X        fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  1287. X        }
  1288. X    fprintf(tfp, " %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  1289. X    if (l->thickness == 0)
  1290. X        fprintf(tfp, " invis");
  1291. X    if (l->type == T_POLYGON)
  1292. X        set_fill(l->area_fill);
  1293. X    newline();
  1294. X    }
  1295. X
  1296. X#else
  1297. Xvoid gentpic_line(l)
  1298. XF_line    *l;
  1299. X{
  1300. X    F_point        *p, *q;
  1301. X    int        radius = l->radius;
  1302. X    char        attr[80];
  1303. X
  1304. X    attr[0] = '\0';
  1305. X    set_linewidth(l->thickness);
  1306. X    set_style(l->style, l->style_val);
  1307. X    set_texture(l->area_fill);
  1308. X    p = l->points;
  1309. X    q = p->next;
  1310. X    if (q == NULL) { /* A single point line */
  1311. X        fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f",
  1312. X            p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi));
  1313. X        newline();
  1314. X        return;
  1315. X        }
  1316. X
  1317. X    if (l->style == DASH_LINE && l->style_val > 0.0)
  1318. X        strcat(attr, "dashed");
  1319. X    else if (l->style == DOTTED_LINE && l->style_val > 0.0)
  1320. X        strcat(attr, "dotted");
  1321. X    if (l->thickness == 0)
  1322. X        strcat(attr, " invis");
  1323. X
  1324. X    if (radius > 0) {    /* T_ARC_BOX */
  1325. X                register int xmin,xmax,ymin,ymax;
  1326. X
  1327. X                xmin = xmax = p->x;
  1328. X                ymin = ymax = p->y;
  1329. X                while (p->next != NULL) { /* find lower left and upper right corners */
  1330. X                        p=p->next;
  1331. X                        if (xmin > p->x)
  1332. X                                xmin = p->x;
  1333. X                        else if (xmax < p->x)
  1334. X                                xmax = p->x;
  1335. X                        if (ymin > p->y)
  1336. X                                ymin = p->y;
  1337. X                        else if (ymax < p->y)
  1338. X                                ymax = p->y;
  1339. X        }
  1340. X                fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  1341. X            (xmin+radius)/ppi, convy(ymin/ppi),
  1342. X            (xmax-radius)/ppi, convy(ymin/ppi));
  1343. X                fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n",
  1344. X            attr, (xmax-radius)/ppi, convy(ymin/ppi),
  1345. X            (xmax/ppi), convy((ymin+radius)/ppi), radius/ppi);
  1346. X                fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  1347. X            xmax/ppi, convy((ymin+radius)/ppi),
  1348. X            xmax/ppi, convy((ymax-radius)/ppi));
  1349. X                fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n",
  1350. X            attr, xmax/ppi, convy((ymax-radius)/ppi),
  1351. X            (xmax-radius)/ppi, convy(ymax/ppi), radius/ppi);
  1352. X                fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  1353. X            (xmax-radius)/ppi, convy(ymax/ppi),
  1354. X            (xmin+radius)/ppi, convy(ymax/ppi));
  1355. X                fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n",
  1356. X            attr, (xmin+radius)/ppi, convy(ymax/ppi),
  1357. X            xmin/ppi, convy((ymax-radius)/ppi), radius/ppi);
  1358. X                fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  1359. X            xmin/ppi, convy((ymax-radius)/ppi),
  1360. X            xmin/ppi, convy((ymin+radius)/ppi));
  1361. X                fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f",
  1362. X            attr, xmin/ppi, convy((ymin+radius)/ppi),
  1363. X            (xmin+radius)/ppi, convy(ymin/ppi), radius/ppi);
  1364. X    } else {
  1365. X        /*rja: Place arrowheads or lack there of on the line*/
  1366. X        fprintf(tfp, "line %s", attr);
  1367. X        if ((l->for_arrow) && (l->back_arrow))
  1368. X            fprintf(tfp, " <-> from");
  1369. X        else if (l->back_arrow)
  1370. X            fprintf(tfp, " <- from");
  1371. X        else if (l->for_arrow)
  1372. X            fprintf(tfp, " -> from");
  1373. X        else
  1374. X            fprintf(tfp, " from ");
  1375. X
  1376. X        fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  1377. X        while (q->next != NULL) {
  1378. X            p = q;
  1379. X            q = q->next;
  1380. X            fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  1381. X        }
  1382. X        fprintf(tfp, " %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  1383. X    }
  1384. X    if (l->type != T_POLYLINE)
  1385. X        set_fill(l->area_fill);
  1386. X    newline();
  1387. X    }
  1388. X#endif
  1389. X
  1390. Xvoid gentpic_spline(s)
  1391. XF_spline    *s;
  1392. X{
  1393. X    if (int_spline(s))
  1394. X        gentpic_itp_spline(s);
  1395. X    else
  1396. X        gentpic_ctl_spline(s);
  1397. X    }
  1398. X
  1399. Xvoid gentpic_ctl_spline(s)
  1400. XF_spline    *s;
  1401. X{
  1402. X    if (closed_spline(s))
  1403. X        gentpic_closed_spline(s);
  1404. X    else
  1405. X        gentpic_open_spline(s);
  1406. X    }
  1407. X
  1408. Xvoid gentpic_open_spline(s)
  1409. XF_spline    *s;
  1410. X{
  1411. X    double        x1, y1, x2, y2;
  1412. X    F_point        *p, *q;
  1413. X
  1414. X    p = s->points;
  1415. X    x1 = p->x/ppi; y1 = convy(p->y/ppi);
  1416. X    p = p->next;
  1417. X    x2 = p->x/ppi; y2 = convy(p->y/ppi);
  1418. X
  1419. X    set_style(s->style, s->style_val);
  1420. X    set_linewidth(s->thickness);
  1421. X
  1422. X    if (p->next == NULL) {
  1423. X        fprintf(tfp, "line");
  1424. X        if (s->style == DASH_LINE && s->style_val > 0.0)
  1425. X            fprintf(tfp, " dashed");
  1426. X        else if (s->style == DOTTED_LINE && s->style_val > 0.0)
  1427. X            fprintf(tfp, " dotted");
  1428. X
  1429. X
  1430. X           /*rja: Attach arrowhead as required */
  1431. X        if ((s->for_arrow) && (s->back_arrow))
  1432. X           fprintf(tfp, " <->");
  1433. X        else if (s->back_arrow)
  1434. X           fprintf(tfp, " <-");
  1435. X        else if (s->for_arrow)
  1436. X           fprintf(tfp, " ->");
  1437. X
  1438. X        fprintf(tfp, " from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2);
  1439. X        newline();
  1440. X        return;
  1441. X        }
  1442. X
  1443. X    fprintf(tfp, "spline"); 
  1444. X    if (s->style == DASH_LINE && s->style_val > 0.0)
  1445. X        fprintf(tfp, " dashed");
  1446. X    else if (s->style == DOTTED_LINE && s->style_val > 0.0)
  1447. X        fprintf(tfp, " dotted");
  1448. X
  1449. X
  1450. X           /*rja: Attach arrowhead as required */
  1451. X        if ((s->for_arrow) && (s->back_arrow))
  1452. X           fprintf(tfp, " <->");
  1453. X        else if (s->back_arrow)
  1454. X           fprintf(tfp, " <-");
  1455. X        else if (s->for_arrow)
  1456. X           fprintf(tfp, " ->");
  1457. X
  1458. X    fprintf(tfp, " from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2);
  1459. X
  1460. X    for (q = p->next; q->next != NULL; p = q, q = q->next)
  1461. X        fprintf(tfp, " to %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  1462. X    fprintf(tfp, " to %.3f,%.3f", (x2=q->x/ppi), (y2=convy(q->y/ppi)));
  1463. X
  1464. X    newline();
  1465. X    }
  1466. X
  1467. Xvoid gentpic_ellipse(e)
  1468. XF_ellipse    *e;
  1469. X{
  1470. X    set_linewidth(e->thickness);
  1471. X    set_texture(e->area_fill);
  1472. X    set_style(e->style, e->style_val);
  1473. X
  1474. X    fprintf(tfp, "ellipse");
  1475. X
  1476. X    if (e->style == DASH_LINE && e->style_val > 0.0)
  1477. X        fprintf(tfp, " dashed");
  1478. X    else if (e->style == DOTTED_LINE && e->style_val > 0.0)
  1479. X        fprintf(tfp, " dotted");
  1480. X
  1481. X    fprintf(tfp, " at %.3f,%.3f wid %.3f ht %.3f",
  1482. X        e->center.x/ppi, convy(e->center.y/ppi),
  1483. X        2 * e->radiuses.x/ppi, 2 * e->radiuses.y/ppi);
  1484. X    if (e->thickness == 0)
  1485. X        fprintf(tfp, " invis");
  1486. X    set_fill(e->area_fill);
  1487. X    newline();
  1488. X    }
  1489. X
  1490. X/*
  1491. XText is displayed on the screen with the base line starting at
  1492. X(base_x, base_y); some characters extend below this line.
  1493. XPic displays the center of the height of text at the given
  1494. Xcoordinate. HT_OFFSET is used to compensate all the above factors
  1495. Xso text position in fig should be at the same position on
  1496. Xthe screen as on the hard copy.
  1497. X
  1498. XTHIS IS A HACK. tpic should be modified to put text with its
  1499. Xbaseline at the given coordinates as does fig -- Baron.
  1500. X*/
  1501. X#define            HT_OFFSET    (0.25 / 72.0)
  1502. X
  1503. Xvoid gentpic_text(t)
  1504. XF_text    *t;
  1505. X{
  1506. X    float    y;
  1507. X        char    *tpos;
  1508. X    int    virtual_font = 0;
  1509. X
  1510. X    /*
  1511. X     * If a font size is specified and the current text font size
  1512. X     * is the default, then use the specified font size.
  1513. X     */
  1514. X    if (t->size == 0 && font_size)
  1515. X        t->size = font_size;
  1516. X
  1517. X    /*
  1518. X     * tpic is informed of the baseline spacing here. Not particularly
  1519. X     * useful in this version of the driver.
  1520. X     */
  1521. X    set_baseline((int)t->size);
  1522. X
  1523. X    unpsfont(t);
  1524. X
  1525. X    if (t->font > MAX_FONT || vfont)
  1526. X        virtual_font = 1;    /* must be a virtual font */
  1527. X
  1528. X    if (virtual_font)
  1529. X        /*
  1530. X         * NOTE. Virtual fonts are defined dynamically using
  1531. X         * TeX's font definition machinery.
  1532. X         */
  1533. X        fprintf(tfp, "\"\\font\\fig%s=%s at %dpt \\fig%s ",
  1534. X            TEXFONT(t->font), TEXFONT(t->font), t->size,
  1535. X            TEXFONT(t->font));
  1536. X    else
  1537. X#ifdef FST
  1538. X        fprintf(tfp, "\"\\%spt\\%s ", TEXFONTMAG(t), TEXFONT(t->font));
  1539. X#else
  1540. X        fprintf(tfp, "\"\\%s%s ", TEXFONTMAG(t), TEXFONT(t->font));
  1541. X#endif
  1542. X
  1543. X        switch (t->type) {
  1544. X        case T_LEFT_JUSTIFIED:
  1545. X        case DEFAULT:
  1546. X            tpos = "ljust";
  1547. X            break;
  1548. X        case T_CENTER_JUSTIFIED:
  1549. X            tpos = "";
  1550. X            break;
  1551. X        case T_RIGHT_JUSTIFIED:
  1552. X            tpos = "rjust";
  1553. X            break;
  1554. X        default:
  1555. X            fprintf(stderr, "unknown text position type\n");
  1556. X            exit(1);
  1557. X        }    
  1558. X    y = convy(t->base_y/ppi) + (TEXFONTMAGINT(t)
  1559. X        * HT_OFFSET);
  1560. X
  1561. X    fprintf(tfp, "%s\" at %.3f,%.3f %s",
  1562. X        t->cstring, t->base_x/ppi, y, tpos);
  1563. X    newline();
  1564. X}
  1565. X
  1566. Xvoid gentpic_arc(a)
  1567. XF_arc    *a;
  1568. X{
  1569. X    double        x, y;
  1570. X    double        cx, cy, sx, sy, ex, ey;
  1571. X
  1572. X    cx = a->center.x/ppi; cy = convy(a->center.y/ppi);
  1573. X    sx = a->point[0].x/ppi; sy = convy(a->point[0].y/ppi);
  1574. X    ex = a->point[2].x/ppi; ey = convy(a->point[2].y/ppi);
  1575. X
  1576. X    set_texture(a->area_fill);
  1577. X    set_linewidth(a->thickness);
  1578. X    set_style(a->style, a->style_val);
  1579. X
  1580. X    fprintf(tfp, "arc");
  1581. X
  1582. X    if (a->style == DASH_LINE && a->style_val > 0.0)
  1583. X        fprintf(tfp, " dashed");
  1584. X    else if (a->style == DOTTED_LINE && a->style_val > 0.0)
  1585. X        fprintf(tfp, " dotted");
  1586. X
  1587. X    /*rja: Attach arrowhead as required */
  1588. X    if ((a->for_arrow) && (a->back_arrow))
  1589. X        fprintf(tfp, " <->");
  1590. X    else if (a->back_arrow)
  1591. X        fprintf(tfp, " <-");
  1592. X    else if (a->for_arrow)
  1593. X        fprintf(tfp, " ->");
  1594. X
  1595. X
  1596. X    if (a->direction)
  1597. X        fprintf(tfp, " at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f",
  1598. X            cx, cy, sx, sy, ex, ey);
  1599. X    else
  1600. X        fprintf(tfp, " at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f cw",
  1601. X            cx, cy, sx, sy, ex, ey);
  1602. X    if (a->thickness == 0)
  1603. X        fprintf(tfp, " invis");
  1604. X    set_fill(a->area_fill);
  1605. X    newline();
  1606. X
  1607. X    }
  1608. X
  1609. Xstatic arc_tangent(x1, y1, x2, y2, direction, x, y)
  1610. Xdouble    x1, y1, x2, y2, *x, *y;
  1611. Xint    direction;
  1612. X{
  1613. X    if (direction) { /* counter clockwise  */
  1614. X        *x = x2 + (y2 - y1);
  1615. X        *y = y2 - (x2 - x1);
  1616. X        }
  1617. X    else {
  1618. X        *x = x2 - (y2 - y1);
  1619. X        *y = y2 + (x2 - x1);
  1620. X        }
  1621. X    }
  1622. X
  1623. X#define        THRESHOLD    .05    /* inch */
  1624. X
  1625. Xstatic quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  1626. Xdouble    a1, b1, a2, b2, a3, b3, a4, b4;
  1627. X{
  1628. X    double    x1, y1, x4, y4;
  1629. X    double    xmid, ymid;
  1630. X
  1631. X    x1 = a1; y1 = b1;
  1632. X    x4 = a4; y4 = b4;
  1633. X
  1634. X    xmid = (a2 + a3) / 2;
  1635. X    ymid = (b2 + b3) / 2;
  1636. X    if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD) {
  1637. X        fprintf(tfp, "\tto %.3f,%.3f\\\n", xmid, ymid);
  1638. X        }
  1639. X    else {
  1640. X        quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
  1641. X            ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
  1642. X        }
  1643. X
  1644. X    if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
  1645. X        fprintf(tfp, "\tto %.3f,%.3f\\\n", x4, y4);
  1646. X        }
  1647. X    else {
  1648. X        quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
  1649. X            ((a3+x4)/2), ((b3+y4)/2), x4, y4);
  1650. X        }
  1651. X    }
  1652. X
  1653. Xvoid gentpic_closed_spline(s)
  1654. XF_spline    *s;
  1655. X{
  1656. X    F_point    *p;
  1657. X    double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  1658. X    double    x1, y1, x2, y2;
  1659. X
  1660. X    p = s->points;
  1661. X    x1 = p->x/ppi;  y1 = convy(p->y/ppi);
  1662. X    p = p->next;
  1663. X    x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  1664. X    cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
  1665. X    cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  1666. X
  1667. X    set_linewidth(s->thickness);
  1668. X    set_texture(s->area_fill); /* probably won't work! */
  1669. X    set_style(s->style, s->style_val);
  1670. X
  1671. X    for (p = p->next; p != NULL; p = p->next) {
  1672. X        fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
  1673. X        x1 = x2;  y1 = y2;
  1674. X        x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  1675. X        cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  1676. X        cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  1677. X        quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  1678. X        newline();
  1679. X        /* fprintf(tfp, "\n"); */
  1680. X        cx1 = cx4;  cy1 = cy4;
  1681. X        cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  1682. X        }
  1683. X    x1 = x2;  y1 = y2;
  1684. X    p = s->points->next;
  1685. X    x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  1686. X    cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  1687. X    cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  1688. X    fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
  1689. X    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  1690. X    if (s->thickness == 0)
  1691. X        fprintf(tfp, " invis");
  1692. X    set_fill(s->area_fill);
  1693. X    newline();
  1694. X    /* fprintf(tfp, "\n"); */
  1695. X    }
  1696. X
  1697. Xvoid gentpic_itp_spline(s)
  1698. XF_spline    *s;
  1699. X{
  1700. X    F_point        *p1, *p2, *pfirst;
  1701. X    F_control    *cp1, *cp2;
  1702. X    double        x1, x2, y1, y2;
  1703. X
  1704. X    set_style(s->style, s->style_val);
  1705. X    set_texture(s->area_fill); /* probably won't work! */
  1706. X    set_linewidth(s->thickness);
  1707. X
  1708. X    p1 = s->points;
  1709. X    cp1 = s->controls;
  1710. X    cp2 = cp1->next;
  1711. X    x2 = p1->x/ppi; y2 = convy(p1->y/ppi);
  1712. X
  1713. X         pfirst = p1->next;/*save first to test in loop*/
  1714. X    for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  1715. X        p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  1716. X
  1717. X        fprintf(tfp, "line ");
  1718. X
  1719. X           /*rja: Attach arrowhead as required */
  1720. X
  1721. X        if ((s->back_arrow) && (p2 == pfirst))
  1722. X           fprintf(tfp, " <- ");
  1723. X        else if ((s->for_arrow) && (p2->next == NULL))
  1724. X           fprintf(tfp, " -> ");
  1725. X
  1726. X        fprintf(tfp, " from %.3f,%.3f ", x2, y2);
  1727. X
  1728. X        x1 = x2; y1 = y2;
  1729. X        x2 = p2->x/ppi; y2 = convy(p2->y/ppi);
  1730. X        bezier_spline(x1, y1, (double)cp1->rx/ppi, convy(cp1->ry/ppi),
  1731. X        (double)cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2);
  1732. X        /* fprintf(tfp, "\n"); */
  1733. X        newline();
  1734. X        }
  1735. X
  1736. X    }
  1737. X
  1738. Xstatic bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  1739. Xdouble    a0, b0, a1, b1, a2, b2, a3, b3;
  1740. X{
  1741. X    double    x0, y0, x3, y3;
  1742. X    double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  1743. X
  1744. X    x0 = a0; y0 = b0;
  1745. X    x3 = a3; y3 = b3;
  1746. X    if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD) {
  1747. X        fprintf(tfp, "\tto %.3f,%.3f\\\n", x3, y3);
  1748. X        }
  1749. X    else {
  1750. X        tx = (a1 + a2) / 2;        ty = (b1 + b2) / 2;
  1751. X        sx1 = (x0 + a1) / 2;    sy1 = (y0 + b1) / 2;
  1752. X        sx2 = (sx1 + tx) / 2;    sy2 = (sy1 + ty) / 2;
  1753. X        tx2 = (a2 + x3) / 2;    ty2 = (b2 + y3) / 2;
  1754. X        tx1 = (tx2 + tx) / 2;    ty1 = (ty2 + ty) / 2;
  1755. X        xmid = (sx2 + tx1) / 2;    ymid = (sy2 + ty1) / 2;
  1756. X
  1757. X        bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  1758. X        bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  1759. X        }
  1760. X    }
  1761. X
  1762. Xstatic void
  1763. Xnewline()
  1764. X{
  1765. X    /*
  1766. X     * A vestige from another version of this driver.
  1767. X     */
  1768. X    fprintf(tfp, "\n");
  1769. X}
  1770. X
  1771. Xstruct driver dev_tpic = {
  1772. X         gentpic_option,
  1773. X    gentpic_start,
  1774. X    gentpic_arc,
  1775. X    gentpic_ellipse,
  1776. X    gentpic_line,
  1777. X    gentpic_spline,
  1778. X    gentpic_text,
  1779. X    gentpic_end,
  1780. X    INCLUDE_TEXT
  1781. X};
  1782. X
  1783. END_OF_FILE
  1784. if test 22577 -ne `wc -c <'fig2dev/dev/gentpic.c'`; then
  1785.     echo shar: \"'fig2dev/dev/gentpic.c'\" unpacked with wrong size!
  1786. fi
  1787. # end of 'fig2dev/dev/gentpic.c'
  1788. fi
  1789. echo shar: End of archive 5 \(of 7\).
  1790. cp /dev/null ark5isdone
  1791. MISSING=""
  1792. for I in 1 2 3 4 5 6 7 ; do
  1793.     if test ! -f ark${I}isdone ; then
  1794.     MISSING="${MISSING} ${I}"
  1795.     fi
  1796. done
  1797. if test "${MISSING}" = "" ; then
  1798.     echo You have unpacked all 7 archives.
  1799.     rm -f ark[1-9]isdone
  1800. else
  1801.     echo You still need to unpack the following archives:
  1802.     echo "        " ${MISSING}
  1803. fi
  1804. ##  End of shell archive.
  1805. exit 0
  1806.