home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / dev / genpictex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-10  |  24.9 KB  |  904 lines

  1. /*
  2.  * TransFig: Facility for Translating Fig code
  3.  * Copyright (c) 1985 Supoj Sutantavibul
  4.  * Copyright (c) 1991 Micah Beck
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation. The authors make no representations about the suitability 
  11.  * of this software for any purpose.  It is provided "as is" without express 
  12.  * or implied warranty.
  13.  *
  14.  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  */
  23.  
  24. /* 
  25.  *    genpictex.C : PiCTeX driver for fig2dev
  26.  *
  27.  *     Author Micah Beck, Cornell University, 4/88
  28.  *    Color, rotated text and ISO-chars added by Herbert Bauer 11/91
  29. */
  30. #if defined(hpux) || defined(SYSV)
  31. #include <sys/types.h>
  32. #endif
  33. #include <sys/file.h>
  34. #include <stdio.h>
  35. #include <math.h>
  36. #include "pi.h"
  37. #include "object.h"
  38. #include "fig2dev.h"
  39. #include "texfonts.h"
  40.  
  41. #define UNIT "cm"       /* dip */
  42. #define CONVUNIT 2.54   /* dip */
  43.  
  44. #ifndef fabs
  45. extern double fabs();
  46. #endif
  47. #ifndef sin
  48. extern double sin();
  49. #endif
  50. #ifndef cos
  51. extern double cos();
  52. #endif
  53. #ifndef acos
  54. extern double acos();
  55. #endif
  56. extern char *ISOtoTeX[];
  57.  
  58. void genpictex_ctl_spline(), genpictex_itp_spline();
  59.  
  60. static int        coord_system;
  61. static double        dash_length = -1;
  62. static int        line_style = SOLID_LINE;
  63. static char         *linethick = "1pt";
  64. static char        *plotsymbol = "\\makebox(0,0)[l]{\\tencirc\\symbol{'160}}";
  65. static int        cur_thickness = -1;
  66.  
  67. static void genpictex_option(opt, optarg)
  68. char opt, *optarg;
  69. {
  70.         int i;
  71.  
  72.     switch (opt) {
  73.  
  74.         case 'a':
  75.             fprintf(stderr, "warning: pictex option -a obsolete\n");
  76.             break;
  77.  
  78.         case 'f':            /* set default text font */
  79.             for ( i = 1; i <= MAX_FONT; i++ )
  80.             if ( !strcmp(optarg, texfontnames[i]) ) break;
  81.  
  82.             if ( i > MAX_FONT)
  83.             fprintf(stderr,
  84.             "warning: non-standard font name %s\n", optarg);
  85.         
  86.             texfontnames[0] = texfontnames[1] = optarg;
  87.             break;
  88.  
  89.         case 'l':            /* set line thickness */
  90.             linethick = optarg;
  91.             break;
  92.  
  93.         case 'p':            /* set plot symbol */
  94.             plotsymbol = optarg;
  95.             break;
  96.  
  97.         case 's':
  98.             if (font_size <= 0 || font_size > MAXFONTSIZE) {
  99.             fprintf(stderr,
  100.                 "warning: font size %d out of bounds\n", font_size);
  101.             }
  102.             break;
  103.  
  104.         case 'm':
  105.         case 'L':
  106.             break;
  107.  
  108.     default:
  109.         put_msg(Err_badarg, opt, "pictex");
  110.         exit(1);
  111.         break;
  112.     }
  113. }
  114.  
  115. #define            TOP    10.5    /* top of page is 10.5 inch */
  116. static double        ppi;
  117. static int        CONV = 0;
  118.  
  119. static double convy(a)
  120. double    a;
  121. {
  122.     return((double)(CONV ? TOP-a : a));
  123. }
  124.  
  125. void genpictex_start(objects)
  126. F_compound    *objects;
  127. {
  128.     texfontsizes[0] = texfontsizes[1] = TEXFONTSIZE(font_size);
  129.  
  130.     coord_system = objects->nwcorner.y;
  131.     ppi = objects->nwcorner.x;
  132.     if (coord_system == 2) CONV = 1;
  133.  
  134.     /* PiCTeX start */
  135.     fprintf(tfp, "\\font\\thinlinefont=cmr5\n");
  136.     define_setfigfont(tfp);
  137.     fprintf(tfp, "\\mbox{\\beginpicture\n");
  138.     fprintf(tfp, "\\setcoordinatesystem units <%6.3f%s,%6.3f%s>\n",
  139.             mag, UNIT, mag, UNIT);
  140.     fprintf(tfp, "\\unitlength=%6.3f%s\n", mag, UNIT);
  141.     fprintf(tfp, "\\linethickness=%s\n", linethick);
  142.     fprintf(tfp, "\\setplotsymbol ({%s})\n", plotsymbol);
  143.     fprintf(tfp, "\\setshadesymbol ({\\thinlinefont .})\n");
  144.     fprintf(tfp, "\\setlinear\n");
  145. }
  146.  
  147. void genpictex_end()
  148. {
  149.     /* PiCTeX ending */
  150.     fprintf(tfp, "\\linethickness=0pt\n");
  151.         fprintf(tfp, "\\putrectangle corners at %6.3f %6.3f and %6.3f %6.3f\n",
  152.         (llx/ppi)*CONVUNIT, (convy(lly/ppi))*CONVUNIT, (urx/ppi)*CONVUNIT, (convy(ury/ppi))*CONVUNIT);
  153.     fprintf(tfp, "\\endpicture}\n");
  154. }
  155.  
  156. static set_linewidth(w)
  157. int    w;
  158. {
  159. /*    static int    cur_thickness = -1;*/
  160.  
  161. /*    if (w == 0) return;*/
  162. /*    if (w != cur_thickness) {*/
  163.         if (!w) {
  164.         fprintf(tfp, "\\linethickness=0pt\n");
  165.         cur_thickness = 0;
  166.         }
  167.         else {
  168.         cur_thickness = round(w*mag);
  169.  
  170.         if (!cur_thickness || cur_thickness == 1) {
  171.             cur_thickness = 1;
  172.             fprintf(tfp, "\\linethickness=%6.3fpt\n", 0.5*cur_thickness);
  173.             }
  174.         else {
  175.             fprintf(tfp, "\\linethickness=%dpt\n", cur_thickness-1);
  176.             }
  177.         }
  178.         switch (cur_thickness) {
  179.             case 0:
  180.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\thinlinefont \\ ");
  181.                 break;
  182.             case 1:
  183.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\thinlinefont .");
  184.                 break;
  185.             case 2:
  186.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'160}}");
  187.                 break;
  188.             case 3:
  189.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'161}}");
  190.                 break;
  191.             case 4:
  192.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'162}}");
  193.                 break;
  194.             case 5:
  195.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'163}}");
  196.                 break;
  197.             case 6:
  198.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'164}}");
  199.                 break;
  200.             case 7:
  201.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'165}}");
  202.                 break;
  203.             case 8:
  204.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'166}}");
  205.                 break;
  206.             case 9:
  207.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'167}}");
  208.                 break;
  209.             case 10:
  210.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'170}}");
  211.                 break;
  212.             case 11:
  213.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'171}}");
  214.                 break;
  215.             case 12:
  216.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'172}}");
  217.                 break;
  218.             case 13:
  219.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'173}}");
  220.                 break;
  221.             case 14:
  222.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'174}}");
  223.                 break;
  224.             case 15:
  225.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'175}}");
  226.                 break;
  227.             case 16:
  228.                         fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'176}}");
  229.                 break;
  230.             default:
  231.                 fprintf(tfp, "\\setplotsymbol ({%s})\n", "\\makebox(0,0)[l]{\\tencirc\\symbol{'176}}");
  232.                 break;
  233.         }
  234. /* PIC  fprintf(tfp, "\"D't %.3fi'\"\n", 0.7 * cur_thickness);*/
  235. /*    }*/
  236. }
  237.  
  238. void genpictex_line(l)
  239. F_line    *l;
  240. {
  241.     F_point        *p, *q;
  242.     int        x, y, llx, lly, urx, ury;
  243.  
  244.     fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n");
  245.  
  246.     if (l->type == T_ARC_BOX) { /* A box with rounded corners */
  247.       fprintf(stderr, "Arc box not implemented; substituting box.\n");
  248.       l->type = T_BOX;
  249.     }
  250.  
  251.     set_linewidth(l->thickness);
  252.     set_style(l->style, l->style_val);
  253.     set_color(l->color);
  254.  
  255.     p = l->points;
  256.     q = p->next;
  257.  
  258.     if (q == NULL) { /* A single point line */
  259.         fprintf(tfp, "\\plot %6.3f %6.3f %6.3f %6.3f /\n",
  260.             (p->x/ppi)*CONVUNIT, (convy(p->y/ppi))*CONVUNIT, (p->x/ppi)*CONVUNIT, (convy(p->y/ppi))*CONVUNIT);
  261.         return;
  262.         }
  263.  
  264.     if (l->type == T_BOX || l->type == T_ARC_BOX) /* A (rounded corner) box */
  265.     {
  266.         x = p->x; y=p->y;
  267.         llx =urx = x;
  268.         lly =ury = y;
  269.         while ( q!= NULL )
  270.         {
  271.         x = q->x; y=q->y;
  272.         if (x < llx) llx = x;
  273.         if (y < lly) lly = y;
  274.         if (x > urx) urx = x;
  275.         if (y > ury) ury = y;
  276.         q = q->next;
  277.         }
  278.         put_box (llx, lly, urx, ury, l);
  279.         return; 
  280.     }
  281.  
  282.     if (l->back_arrow)
  283.         draw_arrow_head(q->x/ppi, convy(q->y/ppi), p->x/ppi,
  284.         convy(p->y/ppi), l->back_arrow->ht/ppi, l->back_arrow->wid/ppi);
  285.     set_style(l->style, l->style_val);
  286.  
  287.     while (q->next != NULL) {
  288.  
  289.         putline(p->x, p->y, (double) q->x, (double) q->y,
  290.             (q->next)->x, (q->next)->y, -1, -1, -1, -1);
  291.         p = q;
  292.         q = q->next;
  293.         }
  294.  
  295.     putline(p->x, p->y, (double) q->x, (double) q->y, -1, -1,
  296.         l->points->x, l->points->y,
  297.         l->points->next->x,l->points->next->y);
  298.     if (l->for_arrow)
  299.         draw_arrow_head(p->x/ppi, convy(p->y/ppi), q->x/ppi,
  300.         convy(q->y/ppi), l->for_arrow->ht/ppi, l->for_arrow->wid/ppi);
  301.  
  302.     if (l->area_fill && (int)l->area_fill != DEFAULT)
  303.         fprintf(stderr, "Line area fill not implemented\n");
  304.     reset_color(l->color);
  305.     }
  306.  
  307.  
  308. /*
  309.  * draw box
  310.  */
  311. static put_box (llx, lly, urx, ury, l)
  312. int    llx, lly, urx, ury;
  313. F_line    *l;
  314. {
  315.     int radius;
  316.  
  317.     set_color(l->color);
  318.     if (l->type == T_BOX)
  319.     {
  320.        if (l->area_fill && l->area_fill == BLACK_FILL)
  321.        {
  322.            fprintf(tfp,"\\linethickness=%6.3f%s\n", 
  323.                ((convy(lly/ppi))-(convy(ury/ppi)))*CONVUNIT*mag, UNIT);
  324.            fprintf(tfp,"{\\setsolid"); 
  325.            fprintf(tfp,"\\putrule from %6.3f %6.3f to %6.3f %6.3f }%%\n",
  326.                (llx/ppi)*CONVUNIT,
  327.                ((convy(lly/ppi)+convy(ury/ppi))/2)*CONVUNIT,
  328.                (urx/ppi)*CONVUNIT,
  329.                ((convy(lly/ppi)+convy(ury/ppi))/2)*CONVUNIT);
  330.            fprintf(tfp,"\\linethickness=%dpt\n", l->thickness);
  331.        }
  332.        else if (l->area_fill && l->area_fill > 15)
  333.        {
  334.            fprintf(tfp,"\\setshadegrid span <1pt>\n");
  335.            fprintf(tfp,"\\shaderectangleson\n");
  336.        }
  337.        else if (l->area_fill && l->area_fill > 10)
  338.        {
  339.            fprintf(tfp,"\\setshadegrid span <2pt>\n");
  340.            fprintf(tfp,"\\shaderectangleson\n");
  341.        }
  342.        else if (l->area_fill && l->area_fill > 5)
  343.        {
  344.            fprintf(tfp,"\\setshadegrid span <4pt>\n");
  345.            fprintf(tfp,"\\shaderectangleson\n");
  346.        }
  347.        else if (l->area_fill && l->area_fill == WHITE_FILL)
  348.        {
  349.            fprintf(stderr,"WHITE_FILL not implemeted for boxes\n");
  350.        }
  351.  
  352.        fprintf(tfp,"\\putrectangle corners at %6.3f %6.3f and %6.3f %6.3f\n",
  353.            (llx/ppi)*CONVUNIT, (convy(lly/ppi))*CONVUNIT,
  354.            (urx/ppi)*CONVUNIT, (convy(ury/ppi))*CONVUNIT);
  355.  
  356.        if (l->area_fill
  357.         && l->area_fill != WHITE_FILL && l->area_fill != BLACK_FILL)
  358.        {
  359.            fprintf(tfp,"\\setshadegrid span <5pt>\n");
  360.            fprintf(tfp,"\\shaderectanglesoff\n");
  361.        }
  362.     }
  363.     else if (l->type == T_ARC_BOX)
  364.     {
  365.        radius = l->radius;
  366.  
  367.        if (l->area_fill)
  368.        {
  369.            fprintf(stderr,"area fill not implemeted for rounded corner boxes\n");
  370.        }
  371.  
  372.        fprintf(tfp,"\\putrule from %6.3f %6.3f to %6.3f %6.3f\n",
  373.            ((llx+radius)/ppi)*CONVUNIT, (convy(lly/ppi))*CONVUNIT,
  374.            ((urx-radius)/ppi)*CONVUNIT, (convy(lly/ppi))*CONVUNIT);
  375.        fprintf(tfp,"\\putrule from %6.3f %6.3f to %6.3f %6.3f\n",
  376.            (urx/ppi)*CONVUNIT, (convy((lly+radius)/ppi))*CONVUNIT,
  377.            (urx/ppi)*CONVUNIT, (convy((ury-radius)/ppi))*CONVUNIT);
  378.        fprintf(tfp,"\\putrule from %6.3f %6.3f to %6.3f %6.3f\n",
  379.            ((urx-radius)/ppi)*CONVUNIT, (convy(ury/ppi))*CONVUNIT,
  380.            ((llx+radius)/ppi)*CONVUNIT, (convy(ury/ppi))*CONVUNIT);
  381.        fprintf(tfp,"\\putrule from %6.3f %6.3f to %6.3f %6.3f\n",
  382.            (llx/ppi)*CONVUNIT, (convy((ury-radius)/ppi))*CONVUNIT,
  383.            (llx/ppi)*CONVUNIT, (convy((lly+radius)/ppi))*CONVUNIT);
  384.        fprintf(tfp,"\\circulararc -90 degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
  385.            ((urx-radius)/ppi)*CONVUNIT, (convy(lly/ppi))*CONVUNIT,
  386.            ((urx-radius)/ppi)*CONVUNIT, (convy((lly+radius)/ppi))*CONVUNIT);
  387.        fprintf(tfp,"\\circulararc -90 degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
  388.            (urx/ppi)*CONVUNIT, (convy((ury-radius)/ppi))*CONVUNIT,
  389.            ((urx-radius)/ppi)*CONVUNIT, (convy((ury-radius)/ppi))*CONVUNIT);
  390.        fprintf(tfp,"\\circulararc -90 degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
  391.            ((llx+radius)/ppi)*CONVUNIT, (convy(ury/ppi))*CONVUNIT,
  392.            ((llx+radius)/ppi)*CONVUNIT, (convy((ury-radius)/ppi))*CONVUNIT);
  393.        fprintf(tfp,"\\circulararc -90 degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
  394.            (llx/ppi)*CONVUNIT, (convy((lly+radius)/ppi))*CONVUNIT,
  395.            ((llx+radius)/ppi)*CONVUNIT, (convy((lly+radius)/ppi))*CONVUNIT);
  396.     }
  397.     reset_color(l->color);
  398. }
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408. /* 
  409.  * set_style - issue style commands as appropriate
  410.  */
  411. static set_style(style, dash_len)
  412. int style;
  413. double dash_len;
  414. {
  415.     switch (style) {
  416.      case SOLID_LINE:
  417.         if (line_style == SOLID_LINE) break;
  418.         fprintf(tfp, "\\setsolid\n");
  419.         break;
  420.  
  421.     case DASH_LINE:
  422.         if (line_style == DASH_LINE && dash_length == dash_len)
  423.         break;
  424.         fprintf(tfp, "\\setdashes <%7.4f%s>\n", (0.5*dash_len*(cur_thickness+1)/ppi)*CONVUNIT, UNIT);
  425.         break;
  426.  
  427.     case DOTTED_LINE:
  428.         if (line_style == DOTTED_LINE)
  429.         break;
  430.         fprintf(tfp, "\\setdots <%7.4f%s>\n", (0.5*dash_len*(cur_thickness+1)/ppi)*CONVUNIT, UNIT);
  431.         break;
  432.         }
  433.  
  434.     line_style = style;
  435.     dash_length = dash_len;
  436.     }
  437.  
  438. /*
  439.  * putline - use rules if possible
  440.  */
  441. static putline (start_x, start_y, end_x, end_y, next_x, next_y,
  442.                 first_start_x, first_start_y, first_end_x, first_end_y)
  443. int    start_x, start_y, next_x, next_y;
  444. int    first_start_x, first_start_y, first_end_x, first_end_y;
  445. double    end_x, end_y;
  446. {
  447.     if (line_style == SOLID_LINE &&
  448.         ((start_x == end_x) || (start_y == end_y))) {
  449.     if (next_x != -1) {
  450.         if (start_x == end_x && end_y == next_y) {
  451.         if (end_y > start_y)
  452.             end_y += 0.5*ppi*(cur_thickness-1)/72/mag;
  453.         else
  454.             end_y -= 0.5*ppi*(cur_thickness-1)/72/mag;
  455.         }
  456.         else if (start_y == end_y && end_x == next_x) {
  457.         if (end_x > start_x)
  458.             end_x += 0.5*ppi*(cur_thickness-1)/72/mag;
  459.         else
  460.             end_x -= 0.5*ppi*(cur_thickness-1)/72/mag;
  461.         }
  462.         }
  463.     else if (end_x == first_start_x && end_y == first_start_y) {
  464.         if (start_x == end_x && first_start_y == first_end_y) {
  465.         if (end_y > start_y)
  466.             end_y += 0.5*ppi*(cur_thickness-1)/72/mag;
  467.         else
  468.             end_y -= 0.5*ppi*(cur_thickness-1)/72/mag;
  469.         }
  470.         else if (start_y == end_y && first_start_x == first_end_x) {
  471.         if (end_x > start_x)
  472.             end_x += 0.5*ppi*(cur_thickness-1)/72/mag;
  473.         else
  474.             end_x -= 0.5*ppi*(cur_thickness-1)/72/mag;
  475.         }
  476.         }
  477.  
  478.     fprintf(tfp, "\\putrule from %6.3f %6.3f to %6.3f %6.3f\n",
  479.         (start_x/ppi)*CONVUNIT, (convy(start_y/ppi))*CONVUNIT, (end_x/ppi)*CONVUNIT, (convy(end_y/ppi))*CONVUNIT);
  480.     }
  481.     else {
  482.     fprintf(tfp, "\\plot %6.3f %6.3f %6.3f %6.3f /\n",
  483.         (start_x/ppi)*CONVUNIT, (convy(start_y/ppi))*CONVUNIT, (end_x/ppi)*CONVUNIT, (convy(end_y/ppi))*CONVUNIT);
  484.     }
  485. }
  486.  
  487.  
  488. void genpictex_spline(s)
  489. F_spline    *s;
  490. {
  491.     set_linewidth(s->thickness);
  492.     set_style(s->style, s->style_val);
  493.     set_color(s->color);
  494.  
  495.     if (int_spline(s))
  496.         genpictex_itp_spline(s);
  497.     else
  498.         genpictex_ctl_spline(s);
  499.  
  500.     if (s->area_fill && (int)s->area_fill != DEFAULT)
  501.         fprintf(stderr, "Spline area fill not implemented\n");
  502.     reset_color(s->color);
  503. }
  504.  
  505. #define MAXBLACKDIAM 15 /* pt */
  506.  
  507. void genpictex_ellipse(e)
  508. F_ellipse    *e;
  509. {
  510.     fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n");
  511.  
  512.     set_linewidth(e->thickness);
  513.     set_style(e->style, e->style_val);
  514.     set_color(e->color);
  515.  
  516.     if ((e->area_fill == BLACK_FILL) && (e->radiuses.x == e->radiuses.y)) {
  517.         if (mag*e->radiuses.x > 0.5*ppi/72*MAXBLACKDIAM)
  518.             fprintf(stderr, "Too big black filled circle substituted by a diameter of %dpt\n", MAXBLACKDIAM);
  519.          fprintf(tfp, "\\put{\\makebox(0,0)[l]{\\circle*{%6.3f}}} at %6.3f %6.3f\n",
  520.             (2*e->radiuses.x/ppi)*CONVUNIT,
  521.             ((e->center.x)/ppi)*CONVUNIT, (convy(e->center.y/ppi))*CONVUNIT);
  522.  
  523.         }
  524.     else {
  525.  
  526.         fprintf(tfp, "\\ellipticalarc axes ratio %6.3f:%-6.3f 360 degrees \n",
  527.             (e->radiuses.x/ppi)*CONVUNIT, (e->radiuses.y/ppi)*CONVUNIT);
  528.         fprintf(tfp, "\tfrom %6.3f %6.3f center at %6.3f %6.3f\n",
  529.             ((e->center.x+e->radiuses.x)/ppi)*CONVUNIT, (convy(e->center.y/ppi))*CONVUNIT,
  530.             (e->center.x/ppi)*CONVUNIT, (convy(e->center.y/ppi))*CONVUNIT);
  531.         if (e->area_fill && (int)e->area_fill != DEFAULT)
  532.             fprintf(stderr, "Ellipse area fill not implemented\n");
  533.         }
  534.     reset_color(e->color);
  535.     }
  536.  
  537. #define            HT_OFFSET    (0.2 / 72.0)
  538.  
  539. void genpictex_text(t)
  540. F_text    *t;
  541. {
  542.     double    x, y;
  543.     char *tpos;
  544.     unsigned char *cp;
  545.  
  546.         fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n");
  547.  
  548.     x = t->base_x/ppi;
  549.     y = convy(t->base_y/ppi);
  550.  
  551.     switch (t->type) {
  552.  
  553.         case T_LEFT_JUSTIFIED:
  554.         case DEFAULT:
  555.             tpos = "[lB]";
  556.         break;
  557.  
  558.         case T_CENTER_JUSTIFIED:
  559.             tpos = "[B]";
  560.         break;
  561.  
  562.         case T_RIGHT_JUSTIFIED:
  563.             tpos = "[rB]";
  564.         break;
  565.  
  566.         default:
  567.         fprintf(stderr, "Text incorrectly positioned\n");
  568.         return;
  569.         }
  570.  
  571.     unpsfont(t);
  572.         { int texsize;
  573.           double baselineskip;
  574.  
  575.       texsize = TEXFONTMAG(t);
  576.       baselineskip = (texsize * 1.2);
  577.  
  578.        fprintf(tfp, "\\put{\\SetFigFont{%d}{%.1f}{%s}",
  579.         texsize, baselineskip, TEXFONT(t->font));
  580.     }
  581.  
  582. #ifdef DVIPS
  583.     if(t->angle && t->type == T_LEFT_JUSTIFIED)
  584.       fprintf(tfp, "\\special{ps:gsave currentpoint currentpoint translate\n-%.1f rotate neg exch neg exch translate}", t->angle*180/M_PI);
  585. #endif
  586.  
  587.     set_color(t->color);
  588.  
  589.     if (!special_text(t))
  590.  
  591.         /* this loop escapes characters "$&%#_{}" */
  592.         /* and deleted characters "~^\" */
  593.         for(cp = (unsigned char*)t->cstring; *cp; cp++) {
  594.                   if (strchr("$&%#_{}", *cp)) (void)fputc('\\', tfp);
  595.                   if (strchr("~^\\", *cp))
  596.             fprintf(stderr,
  597.                 "Bad character in text object '%c'\n" ,*cp);
  598.             else
  599.             (void)fputc(*cp, tfp);
  600.               }
  601.     else 
  602.         for(cp = (unsigned char*)t->cstring; *cp; cp++) {
  603.             if (*cp >= 0xa0)
  604.                  fprintf(tfp, "%s", ISOtoTeX[(int)*cp-0xa0]);
  605.         else
  606.             fputc(*cp, tfp);
  607.         }
  608.  
  609.     reset_color(t->color);
  610.  
  611. #ifdef DVIPS
  612.     if(t->angle)
  613.     {
  614.       if (t->type == T_LEFT_JUSTIFIED)
  615.            fprintf(tfp, "\\special{ps:currentpoint grestore moveto}");
  616.       else
  617.          fprintf(stderr, "Rotated Text only for left justified text\n");
  618.     }
  619. #endif
  620.      fprintf(tfp, "} %s at %6.3f %6.3f\n",
  621.         tpos, (x)*CONVUNIT, (y)*CONVUNIT);
  622.     }
  623.  
  624. void genpictex_arc(a)
  625. F_arc    *a;
  626. {
  627.     double        x, y;
  628.     double        cx, cy, sx, sy, ex, ey;
  629.     double        dx1, dy1, dx2, dy2, r1, r2, th1, th2, theta;
  630.  
  631.         fprintf(tfp, "%%\n%% Fig CIRCULAR ARC object\n%%\n");
  632.  
  633.     set_linewidth(a->thickness);
  634.     set_style(a->style, a->style_val);
  635.     set_color(a->color);
  636.  
  637.     cx = a->center.x/ppi; cy = convy(a->center.y/ppi);
  638.     sx = a->point[0].x/ppi; sy = convy(a->point[0].y/ppi);
  639.     ex = a->point[2].x/ppi; ey = convy(a->point[2].y/ppi);
  640.  
  641.     if (a->for_arrow) {
  642.         arc_tangent(cx, cy, ex, ey, a->direction, &x, &y);
  643.         draw_arrow_head(x, y, ex, ey,
  644.             a->for_arrow->ht/ppi, a->for_arrow->wid/ppi);
  645.         }
  646.     if (a->back_arrow) {
  647.         arc_tangent(cx, cy, sx, sy, !a->direction, &x, &y);
  648.         draw_arrow_head(x, y, sx, sy,
  649.             a->back_arrow->ht/ppi, a->back_arrow->wid/ppi);
  650.         }
  651.  
  652.     dx1 = sx - cx;
  653.     dy1 = sy - cy;
  654.     dx2 = ex - cx;
  655.     dy2 = ey - cy;
  656.         
  657.     rtop(dx1, dy1, &r1, &th1);
  658.     rtop(dx2, dy2, &r2, &th2);
  659.     theta = th2 - th1;
  660.     if (theta > 0) theta -= 2*M_PI;
  661.  
  662. /*    set_linewidth(a->thickness); */
  663.  
  664.     if (a->direction)
  665.         fprintf(tfp, "\\circulararc %6.3f degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
  666.             360+(180/M_PI * theta), (sx)*CONVUNIT, (sy)*CONVUNIT, (cx)*CONVUNIT, (cy)*CONVUNIT);
  667.     else
  668.         fprintf(tfp, "\\circulararc %6.3f degrees from %6.3f %6.3f center at %6.3f %6.3f\n",
  669.             -180/M_PI * theta, (ex)*CONVUNIT, (ey)*CONVUNIT, (cx)*CONVUNIT, (cy)*CONVUNIT);
  670.  
  671.     if (a->area_fill && (int)a->area_fill != DEFAULT)
  672.         fprintf(stderr, "Arc area fill not implemented\n");
  673.     reset_color(a->color);
  674.     }
  675.  
  676.  
  677.  
  678. /*
  679.  * rtop - rectangular to polar conversion
  680.  */
  681. static rtop(x, y, r, th)
  682. double x, y, *r, *th;
  683. {
  684.     *r = sqrt(x*x+y*y);
  685.     *th = acos(x/(*r));
  686.  
  687.     if (y < 0) *th = 2*M_PI - *th;
  688. }
  689.  
  690. static arc_tangent(x1, y1, x2, y2, direction, x, y)
  691. double    x1, y1, x2, y2, *x, *y;
  692. int    direction;
  693. {
  694.     if (direction) { /* counter clockwise  */
  695.         *x = x2 + (y2 - y1);
  696.         *y = y2 - (x2 - x1);
  697.         }
  698.     else {
  699.         *x = x2 - (y2 - y1);
  700.         *y = y2 + (x2 - x1);
  701.         }
  702.     }
  703.  
  704. /*    draw arrow heading from (x1, y1) to (x2, y2)    */
  705.  
  706. static draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
  707. double    x1, y1, x2, y2, arrowht, arrowwid;
  708. {
  709.     double    x, y, xb, yb, dx, dy, l, sina, cosa;
  710.     double    xc, yc, xd, yd;
  711.     int style;
  712.     double dash;
  713.  
  714.     dx = x2 - x1;  dy = y1 - y2;
  715.  
  716.     if (!dx && !dy)
  717.         return ;
  718.  
  719.     l = sqrt(dx*dx+dy*dy);
  720.     if (l == 0) {
  721.          return;
  722.     }
  723.     else {
  724.          sina = dy / l;  cosa = dx / l;
  725.     }
  726.     xb = x2*cosa - y2*sina;
  727.     yb = x2*sina + y2*cosa;
  728.     x = xb - arrowht;
  729.     y = yb - arrowwid / 2;
  730.     xc = x*cosa + y*sina;
  731.     yc = -x*sina + y*cosa;
  732.     y = yb + arrowwid / 2;
  733.     xd = x*cosa + y*sina;
  734.     yd = -x*sina + y*cosa;
  735.  
  736.     /* save line style and set to solid */
  737.     style = line_style;
  738.     dash = dash_length;
  739.     set_style(SOLID_LINE, 0.0);
  740.  
  741.         fprintf(tfp, "%%\n%% arrow head\n%%\n");
  742.  
  743.     fprintf(tfp, "\\plot %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f /\n%%\n",
  744.         (xc)*CONVUNIT, (yc)*CONVUNIT, (x2)*CONVUNIT, (y2)*CONVUNIT, (xd)*CONVUNIT, (yd)*CONVUNIT);
  745.  
  746.     /* restore line style */
  747.     set_style(style, dash);
  748.     }
  749.  
  750. #define        THRESHOLD    .05    /* inch */
  751.  
  752. static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  753. double    a1, b1, a2, b2, a3, b3, a4, b4;
  754. {
  755.     double    x1, y1, x4, y4;
  756.     double    xmid, ymid;
  757.  
  758.     x1 = a1; y1 = b1;
  759.     x4 = a4; y4 = b4;
  760.     xmid = (a2 + a3) / 2;
  761.     ymid = (b2 + b3) / 2;
  762.     if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD)
  763.         fprintf(tfp, "\t%6.3f %6.3f\n", (xmid)*CONVUNIT, (ymid)*CONVUNIT);
  764.  
  765.     else {
  766.         quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
  767.             ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
  768.         }
  769.  
  770.     if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD)
  771.         fprintf(tfp, "\t%6.3f %6.3f\n", (x4)*CONVUNIT, (y4)*CONVUNIT);
  772.  
  773.     else {
  774.         quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
  775.             ((a3+x4)/2), ((b3+y4)/2), x4, y4);
  776.         }
  777.     }
  778.  
  779. static void genpictex_ctl_spline(s)
  780. F_spline    *s;
  781. {
  782.     F_point    *p;
  783.     double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  784.     double    x1, y1, x2, y2;
  785.  
  786.         fprintf(tfp, "%%\n%% Fig CONTROL PT SPLINE\n%%\n");
  787.  
  788.     p = s->points;
  789.     x1 = p->x/ppi;  y1 = convy(p->y/ppi);
  790.     p = p->next;
  791.     x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  792.     cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
  793.     cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  794.  
  795.     if (closed_spline(s)) {
  796.         fprintf(tfp, "%% closed spline\n%%\n");
  797.         fprintf(tfp, "\\plot\t%6.3f %6.3f \n ", (cx1)*CONVUNIT, (cy1)*CONVUNIT);
  798.         }
  799.     else {
  800.         fprintf(tfp, "%% open spline\n%%\n");
  801.         if (s->back_arrow)
  802.             draw_arrow_head(cx1, cy1, x1, y1,
  803.             s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
  804.         fprintf(tfp, "\\plot\t%6.3f %6.3f %6.3f %6.3f\n ",
  805.         (x1)*CONVUNIT, (y1)*CONVUNIT, (cx1)*CONVUNIT, (cy1)*CONVUNIT);
  806.         }
  807.  
  808.     for (p = p->next; p != NULL; p = p->next) {
  809.         x1 = x2;  y1 = y2;
  810.         x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  811.         cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  812.         cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  813.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  814.         cx1 = cx4;  cy1 = cy4;
  815.         cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  816.         }
  817.     x1 = x2;  y1 = y2;
  818.     p = s->points->next;
  819.     x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  820.     cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  821.     cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  822.     if (closed_spline(s)) {
  823.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  824.         fprintf(tfp, "\t/\n");
  825.         }
  826.     else {
  827.         fprintf(tfp, "\t /\n\\plot %6.3f %6.3f %6.3f %6.3f /\n",
  828.         (cx1)*CONVUNIT, (cy1)*CONVUNIT, (x1)*CONVUNIT, (y1)*CONVUNIT);
  829.         if (s->for_arrow)
  830.             draw_arrow_head(cx1, cy1, x1, y1,
  831.             s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
  832.         }
  833.  
  834.     }
  835.  
  836. static void genpictex_itp_spline(s)
  837. F_spline    *s;
  838. {
  839.     F_point        *p1, *p2;
  840.     F_control    *cp1, *cp2;
  841.     double        x1, x2, y1, y2;
  842.  
  843.         fprintf(tfp, "%%\n%% Fig INTERPOLATED PT SPLINE\n%%\n");
  844.  
  845.     p1 = s->points;
  846.     cp1 = s->controls;
  847.     x2 = p1->x/ppi; y2 = convy(p1->y/ppi);
  848.  
  849.     if (s->back_arrow)
  850.         draw_arrow_head(cp1->rx/ppi, convy(cp1->ry/ppi), x2, y2,
  851.         s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
  852.  
  853.     fprintf(tfp, "\\plot %6.3f %6.3f ", (x2)*CONVUNIT, (y2)*CONVUNIT);
  854.     for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  855.         p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  856.         x1 = x2; y1 = y2;
  857.         x2 = p2->x/ppi; y2 = convy(p2->y/ppi);
  858.         bezier_spline(x1, y1, (double)cp1->rx/ppi, convy(cp1->ry/ppi),
  859.         (double)cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2);
  860.         }
  861.     fprintf(tfp, "\t/\n");
  862.  
  863.     if (s->for_arrow)
  864.         draw_arrow_head(cp1->lx/ppi, convy(cp1->ly/ppi), x2, y2,
  865.         s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
  866.     }
  867.  
  868. static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  869. double    a0, b0, a1, b1, a2, b2, a3, b3;
  870. {
  871.     double    x0, y0, x3, y3;
  872.     double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  873.  
  874.     x0 = a0; y0 = b0;
  875.     x3 = a3; y3 = b3;
  876.     if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD)
  877.         fprintf(tfp, "\t%6.3f %6.3f\n", (x3)*CONVUNIT, (y3)*CONVUNIT);
  878.  
  879.     else {
  880.         tx = (a1 + a2) / 2;        ty = (b1 + b2) / 2;
  881.         sx1 = (x0 + a1) / 2;    sy1 = (y0 + b1) / 2;
  882.         sx2 = (sx1 + tx) / 2;    sy2 = (sy1 + ty) / 2;
  883.         tx2 = (a2 + x3) / 2;    ty2 = (b2 + y3) / 2;
  884.         tx1 = (tx2 + tx) / 2;    ty1 = (ty2 + ty) / 2;
  885.         xmid = (sx2 + tx1) / 2;    ymid = (sy2 + ty1) / 2;
  886.  
  887.         bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  888.         bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  889.         }
  890.     }
  891.  
  892. struct driver dev_pictex = {
  893.          genpictex_option,
  894.     genpictex_start,
  895.     genpictex_arc,
  896.     genpictex_ellipse,
  897.     genpictex_line,
  898.     genpictex_spline,
  899.     genpictex_text,
  900.     genpictex_end,
  901.     EXCLUDE_TEXT
  902. };
  903.  
  904.