home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / dev / gentpic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-10  |  22.0 KB  |  818 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.  *    gentpic : TPIC driver for fig2dev
  26.  *
  27.  *    Author: Conrad Kwok, UC Davis, 12/88
  28.  *      Modified: Richard Auletta, George Mason Univ., 6/21/89
  29.  *        Added code comments are marked with "rja".
  30.  *          Added: Support for native pic arrowheads.
  31.  *          Added: Support for arrowheads at both ends of lines, arc, splines.
  32.  *    Modified: Modified from pic to tpic. Baron Grey, UCLA. 10/2/90.
  33.  *
  34.  *        This driver supports TeX's virtual font mechanism. Any Fig
  35.  *        font whose ordinal number is greater than 6 is treated as
  36.  *        a TeX virtual PostScript font. Virtual PostScript font
  37.  *        names are defined in tpicfonts.h (you should define
  38.  *        corresponding names in Fig in file change.c). Customize to
  39.  *        suit your virtual font availability or your name preferences.
  40.  *
  41.  *        There are no restrictions on font sizes in this driver, but
  42.  *        keep in mind that TeX only supports fonts up to 2048 points!
  43.  *        Since PostScript fonts are scaleable, virtual PS fonts can have
  44.  *        any point size within the limits imposed by TeX or by your
  45.  *        PostScript interpreter. If you are using
  46.  *        standard predefined LaTeX fonts (assumed to be the first
  47.  *        6 positions in Fig's ordinal font numbering scheme), font
  48.  *        sizes are mapped into the nearest valid normally-available
  49.  *        LaTeX font sizes -- look at tpicfonts.h to see how this is
  50.  *        done; you can modify it for fonts at your site.
  51.  *
  52.  *        Additional features of this driver are:
  53.  *        1) Support for all Fig features except text at nonzero
  54.  *           angles.  (In fact, any limitations of this driver are
  55.  *           actually tpic limitations.)
  56.  *        2) Boxes with rounded corners are supported in two ways.
  57.  *           If (when) tpic is extended to use the "radius" attribute
  58.  *           with a "box" specification, the driver will generate the
  59.  *           appropriate box specification. Otherwise, it creates
  60.  *           rounded-corner boxes from line and arc segments using
  61.  *           existing tpic primitives. In the former case, rounded-
  62.  *           corner boxes can be shaded; in the latter, they can't.
  63.  *           Define TPIC_ARC_BOX for the first case (the default);
  64.  *           undefine it otherwise.
  65.  *        3) Supports Fig's ability to texture (shade) objects.
  66.  *           Bitmapped PostScript texture patterns are supported;
  67.  *           they are defined in "tpicfonts.h". The tpic ".tx"
  68.  *           primitive is used for this. Your dvi-to-PostScript
  69.  *           driver must be adapted to support them.
  70.  *        4) If an object's line "thickness" is 0, it is given tpic's
  71.  *           `invis' attribute. That is, tpic will treat it as an
  72.  *           invisible object in the normal tpic sense.
  73.  *        5) This driver supports tpic 2.0. It will work with tpic 1.0,
  74.  *           but some object attributes will not be available.
  75.  *        6) The default line thickness is 8 milli inches (in tpic
  76.  *           units). This corresponds to 1 pixel width in Fig. The
  77.  *           formula is: line_thickness = Fig_line_thickness *
  78.  *           default_tpic_line_thickness.
  79.  *        7) The default font size is (assumed to be) 10 points!
  80.  */
  81.  
  82. #include <stdio.h>
  83. #include <math.h>
  84. #include "object.h"
  85. #include "fig2dev.h"
  86. #include "tpicfonts.h"
  87.  
  88. /*
  89.  * Define TPIC_ARC_BOX if your tpic supports rounded-corner boxes
  90.  * via a "radius" attribute of a box specification.
  91.  */
  92. #define TPIC_ARC_BOX
  93.  
  94. #define            TOP    10.5    /* top of page is 10.5 inch */
  95. static double        ppi;
  96. static int        CONV = 0;
  97. static int        line_width = 8;    /* milli-inches */
  98. static int        vfont = 0; /* true if using a virtual TeX font */
  99.  
  100. void gentpic_ctl_spline(), gentpic_itp_spline();
  101. void gentpic_open_spline(), gentpic_closed_spline();
  102. void gentpic_spline(), gentpic_ellipse(), gentpic_text();
  103. void gentpic_arc(), gentpic_line(), newline();
  104.  
  105. void gentpic_option(opt, optarg)
  106. char opt, *optarg;
  107. {
  108.     switch (opt) {
  109.  
  110.     case 'f':        /* set default text font */
  111.             {   int i;
  112.  
  113.             for ( i = 1; i <= MAX_TPICFONT; i++ )
  114.             if ( !strcmp(optarg, texfontnames[i]) ) break;
  115.  
  116.             if ( i > MAX_FONT)
  117.                 vfont = 1; /* assume a virtual font */
  118.         }
  119.         
  120.         texfontnames[0] = optarg;
  121.         break;
  122.  
  123.     case 's':
  124.     case 'm':
  125.     case 'L':
  126.         break;
  127.  
  128.      default:
  129.         put_msg(Err_badarg, opt, "tpic");
  130.         exit(1);
  131.     }
  132. }
  133.  
  134. static double convy(a)
  135. double    a;
  136. {
  137.     return((double)(CONV ? TOP-a : a));
  138. }
  139.  
  140. void gentpic_start(objects)
  141. F_compound    *objects;
  142. {
  143.     int        coord_system;
  144.  
  145.     ppi = objects->nwcorner.x/mag;
  146.     coord_system = objects->nwcorner.y;
  147.     if (coord_system == 2) CONV = 1;
  148.  
  149.     fprintf(tfp, ".PS\n");    /* PIC preamble */
  150.  
  151. }
  152.  
  153. void gentpic_end()
  154. {
  155.       fprintf(tfp, ".PE\n");                /* PIC ending */
  156. }
  157.  
  158. /*
  159.  * tpic's line thickness is given in milli-inches with a default of 8
  160.  * milli-inches. We simply multiply this default with the Fig pixel width.
  161.  */
  162. static set_linewidth(w)
  163. int    w;
  164. {
  165.     static int    cur_thickness = -1;
  166.  
  167.     if (w == 0) return;
  168.     if (w != cur_thickness) {
  169.         cur_thickness = w;
  170.         fprintf(tfp, ".ps %d\n", cur_thickness * line_width);
  171.         }
  172.     }
  173.  
  174. static set_style(s, v)
  175. int    s;
  176. float    v;
  177. {
  178.     static float    style_val = -1;
  179.  
  180.     if (s == DASH_LINE || s == DOTTED_LINE) {
  181.         if (v == style_val || v == 0.0) return;
  182.         style_val = v;
  183.         fprintf(tfp, "dashwid = %.3fi\n", style_val/ppi);
  184.         }
  185.     }
  186.  
  187. static set_baseline(b)
  188. int    b;
  189. {
  190.     static int    cur_baseline = -1;
  191.  
  192.     if (b != cur_baseline) {
  193.         fprintf(tfp, ".baseline %d\n", b);
  194.         cur_baseline = b;
  195.     }
  196. }
  197.  
  198. static set_texture(cur_texture)
  199. int    cur_texture;
  200. {
  201.     /*
  202.      * This applies only to bitmapped texture patterns defined in
  203.      * tpicfonts.h. See set_fill() below for normal shading.
  204.      */
  205.     if (cur_texture <= BLACK_FILL || cur_texture > MAXPATTERNS + BLACK_FILL)
  206.         return;
  207.     fprintf(tfp, ".tx 16 %s\n",
  208.         texture_patterns[cur_texture - BLACK_FILL - 1]);
  209. }
  210.  
  211. /*
  212.  * Set the shade for filling an object. Your dvi-to-postscript driver must
  213.  * distinguish between a "shaded" attribute with or without a parameter.
  214.  * If there is no parameter, then it should do a bitmap texture fill;
  215.  * otherwise, it should do a normal gray-scale fill. Note that the gray-
  216.  * scale fill parameter is wired for fig2.X (the constant 0.05).
  217.  */
  218. static set_fill(cur_fill)
  219. int    cur_fill;
  220. {
  221.     if(cur_fill < WHITE_FILL ||
  222.        cur_fill > BLACK_FILL + MAXPATTERNS)
  223.         return;
  224.     switch(cur_fill) {
  225.     case BLACK_FILL:
  226.         fprintf(tfp, " black");
  227.         break;
  228.     case WHITE_FILL:
  229.         fprintf(tfp, " white");
  230.         break;
  231.     default:
  232.         if (cur_fill > BLACK_FILL)
  233.             fprintf (tfp, " shaded");
  234.         else
  235.             fprintf(tfp, " shaded %0.3f", (cur_fill-1)*0.05);
  236.         break;
  237.     }
  238. }
  239.  
  240. #ifdef TPIC_ARC_BOX
  241. void gentpic_line(l)
  242. F_line    *l;
  243. {
  244.     F_point        *p, *q;
  245.     int    llx, lly, urx, ury;
  246.  
  247.     set_linewidth(l->thickness);
  248.     set_style(l->style, l->style_val);
  249.     set_texture(l->area_fill);
  250.     p = l->points;
  251.     q = p->next;
  252.     if (q == NULL) { /* A single point line */
  253.         fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f",
  254.             p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi));
  255.         newline();
  256.         return;
  257.         }
  258.  
  259.     if (l->type == T_BOX || l->type == T_ARC_BOX) {
  260.         llx = urx = p->x;
  261.         lly = ury = p->y;
  262.         while (q != NULL) {
  263.             p = q;
  264.             if (p->x < llx) {
  265.                 llx = p->x;
  266.             } else if (p->x > urx) {
  267.                 urx = p->x;
  268.             }
  269.             if (p->y < lly) {
  270.                 lly = p->y;
  271.             } else if (p->y > ury) {
  272.                 ury = p->y;
  273.             }
  274.             q = q->next;
  275.         }
  276.         fprintf(tfp, "box height %.3f width %.3f", (ury-lly)/ppi,
  277.             (urx-llx)/ppi);
  278.         switch(l->style) {
  279.         case SOLID_LINE:
  280.             break;
  281.         case DASH_LINE:
  282.             fprintf(tfp, " dashed");
  283.             break;
  284.         case DOTTED_LINE:
  285.             fprintf(tfp, " dotted");
  286.             break;
  287.         default:
  288.             put_msg("Program error! No other line styles allowed.\n");
  289.             return;
  290.         }
  291.         if (l->thickness == 0)
  292.             fprintf(tfp, " invis");
  293.         fprintf(tfp, " radius %.3f", l->radius/ppi);
  294.         set_fill(l->area_fill);
  295.         fprintf(tfp, " with .nw at %.3f,%.3f", llx/ppi, convy(lly/ppi));
  296.         newline();
  297.         return;
  298.     }
  299.  
  300.     if (l->style == DASH_LINE && l->style_val > 0.0)
  301.         fprintf(tfp, "line dashed");
  302.     else if (l->style == DOTTED_LINE && l->style_val > 0.0)
  303.         fprintf(tfp, "line dotted");
  304.     else
  305.         fprintf(tfp, "line");
  306.  
  307.     /*rja: Place arrowheads or lack there of on the line*/
  308.     if ((l->for_arrow) && (l->back_arrow))
  309.         fprintf(tfp, " <-> from");
  310.     else if (l->back_arrow)
  311.         fprintf(tfp, " <- from");
  312.     else if (l->for_arrow)
  313.         fprintf(tfp, " -> from");
  314.         else
  315.         fprintf(tfp, " from ");
  316.  
  317.     fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  318.     while (q->next != NULL) {
  319.         p = q;
  320.         q = q->next;
  321.         fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  322.         }
  323.     fprintf(tfp, " %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  324.     if (l->thickness == 0)
  325.         fprintf(tfp, " invis");
  326.     if (l->type == T_POLYGON)
  327.         set_fill(l->area_fill);
  328.     newline();
  329.     }
  330.  
  331. #else
  332. void gentpic_line(l)
  333. F_line    *l;
  334. {
  335.     F_point        *p, *q;
  336.     int        radius = l->radius;
  337.     char        attr[80];
  338.  
  339.     attr[0] = '\0';
  340.     set_linewidth(l->thickness);
  341.     set_style(l->style, l->style_val);
  342.     set_texture(l->area_fill);
  343.     p = l->points;
  344.     q = p->next;
  345.     if (q == NULL) { /* A single point line */
  346.         fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f",
  347.             p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi));
  348.         newline();
  349.         return;
  350.         }
  351.  
  352.     if (l->style == DASH_LINE && l->style_val > 0.0)
  353.         strcat(attr, "dashed");
  354.     else if (l->style == DOTTED_LINE && l->style_val > 0.0)
  355.         strcat(attr, "dotted");
  356.     if (l->thickness == 0)
  357.         strcat(attr, " invis");
  358.  
  359.     if (radius > 0) {    /* T_ARC_BOX */
  360.                 register int xmin,xmax,ymin,ymax;
  361.  
  362.                 xmin = xmax = p->x;
  363.                 ymin = ymax = p->y;
  364.                 while (p->next != NULL) { /* find lower left and upper right corners */
  365.                         p=p->next;
  366.                         if (xmin > p->x)
  367.                                 xmin = p->x;
  368.                         else if (xmax < p->x)
  369.                                 xmax = p->x;
  370.                         if (ymin > p->y)
  371.                                 ymin = p->y;
  372.                         else if (ymax < p->y)
  373.                                 ymax = p->y;
  374.         }
  375.                 fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  376.             (xmin+radius)/ppi, convy(ymin/ppi),
  377.             (xmax-radius)/ppi, convy(ymin/ppi));
  378.                 fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n",
  379.             attr, (xmax-radius)/ppi, convy(ymin/ppi),
  380.             (xmax/ppi), convy((ymin+radius)/ppi), radius/ppi);
  381.                 fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  382.             xmax/ppi, convy((ymin+radius)/ppi),
  383.             xmax/ppi, convy((ymax-radius)/ppi));
  384.                 fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n",
  385.             attr, xmax/ppi, convy((ymax-radius)/ppi),
  386.             (xmax-radius)/ppi, convy(ymax/ppi), radius/ppi);
  387.                 fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  388.             (xmax-radius)/ppi, convy(ymax/ppi),
  389.             (xmin+radius)/ppi, convy(ymax/ppi));
  390.                 fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f\n",
  391.             attr, (xmin+radius)/ppi, convy(ymax/ppi),
  392.             xmin/ppi, convy((ymax-radius)/ppi), radius/ppi);
  393.                 fprintf(tfp, "line %s from  %.3f,%.3f to %.3f, %.3f\n", attr,
  394.             xmin/ppi, convy((ymax-radius)/ppi),
  395.             xmin/ppi, convy((ymin+radius)/ppi));
  396.                 fprintf(tfp, "arc cw %s from %.3f, %.3f to %.3f,%.3f radius %.3f",
  397.             attr, xmin/ppi, convy((ymin+radius)/ppi),
  398.             (xmin+radius)/ppi, convy(ymin/ppi), radius/ppi);
  399.     } else {
  400.         /*rja: Place arrowheads or lack there of on the line*/
  401.         fprintf(tfp, "line %s", attr);
  402.         if ((l->for_arrow) && (l->back_arrow))
  403.             fprintf(tfp, " <-> from");
  404.         else if (l->back_arrow)
  405.             fprintf(tfp, " <- from");
  406.         else if (l->for_arrow)
  407.             fprintf(tfp, " -> from");
  408.         else
  409.             fprintf(tfp, " from ");
  410.  
  411.         fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  412.         while (q->next != NULL) {
  413.             p = q;
  414.             q = q->next;
  415.             fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  416.         }
  417.         fprintf(tfp, " %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  418.     }
  419.     if (l->type != T_POLYLINE)
  420.         set_fill(l->area_fill);
  421.     newline();
  422.     }
  423. #endif
  424.  
  425. void gentpic_spline(s)
  426. F_spline    *s;
  427. {
  428.     if (int_spline(s))
  429.         gentpic_itp_spline(s);
  430.     else
  431.         gentpic_ctl_spline(s);
  432.     }
  433.  
  434. void gentpic_ctl_spline(s)
  435. F_spline    *s;
  436. {
  437.     if (closed_spline(s))
  438.         gentpic_closed_spline(s);
  439.     else
  440.         gentpic_open_spline(s);
  441.     }
  442.  
  443. void gentpic_open_spline(s)
  444. F_spline    *s;
  445. {
  446.     double        x1, y1, x2, y2;
  447.     F_point        *p, *q;
  448.  
  449.     p = s->points;
  450.     x1 = p->x/ppi; y1 = convy(p->y/ppi);
  451.     p = p->next;
  452.     x2 = p->x/ppi; y2 = convy(p->y/ppi);
  453.  
  454.     set_style(s->style, s->style_val);
  455.     set_linewidth(s->thickness);
  456.  
  457.     if (p->next == NULL) {
  458.         fprintf(tfp, "line");
  459.         if (s->style == DASH_LINE && s->style_val > 0.0)
  460.             fprintf(tfp, " dashed");
  461.         else if (s->style == DOTTED_LINE && s->style_val > 0.0)
  462.             fprintf(tfp, " dotted");
  463.  
  464.  
  465.            /*rja: Attach arrowhead as required */
  466.         if ((s->for_arrow) && (s->back_arrow))
  467.            fprintf(tfp, " <->");
  468.         else if (s->back_arrow)
  469.            fprintf(tfp, " <-");
  470.         else if (s->for_arrow)
  471.            fprintf(tfp, " ->");
  472.  
  473.         fprintf(tfp, " from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2);
  474.         newline();
  475.         return;
  476.         }
  477.  
  478.     fprintf(tfp, "spline"); 
  479.     if (s->style == DASH_LINE && s->style_val > 0.0)
  480.         fprintf(tfp, " dashed");
  481.     else if (s->style == DOTTED_LINE && s->style_val > 0.0)
  482.         fprintf(tfp, " dotted");
  483.  
  484.  
  485.            /*rja: Attach arrowhead as required */
  486.         if ((s->for_arrow) && (s->back_arrow))
  487.            fprintf(tfp, " <->");
  488.         else if (s->back_arrow)
  489.            fprintf(tfp, " <-");
  490.         else if (s->for_arrow)
  491.            fprintf(tfp, " ->");
  492.  
  493.     fprintf(tfp, " from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2);
  494.  
  495.     for (q = p->next; q->next != NULL; p = q, q = q->next)
  496.         fprintf(tfp, " to %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  497.     fprintf(tfp, " to %.3f,%.3f", (x2=q->x/ppi), (y2=convy(q->y/ppi)));
  498.  
  499.     newline();
  500.     }
  501.  
  502. void gentpic_ellipse(e)
  503. F_ellipse    *e;
  504. {
  505.     set_linewidth(e->thickness);
  506.     set_texture(e->area_fill);
  507.     set_style(e->style, e->style_val);
  508.  
  509.     fprintf(tfp, "ellipse");
  510.  
  511.     if (e->style == DASH_LINE && e->style_val > 0.0)
  512.         fprintf(tfp, " dashed");
  513.     else if (e->style == DOTTED_LINE && e->style_val > 0.0)
  514.         fprintf(tfp, " dotted");
  515.  
  516.     fprintf(tfp, " at %.3f,%.3f wid %.3f ht %.3f",
  517.         e->center.x/ppi, convy(e->center.y/ppi),
  518.         2 * e->radiuses.x/ppi, 2 * e->radiuses.y/ppi);
  519.     if (e->thickness == 0)
  520.         fprintf(tfp, " invis");
  521.     set_fill(e->area_fill);
  522.     newline();
  523.     }
  524.  
  525. /*
  526. Text is displayed on the screen with the base line starting at
  527. (base_x, base_y); some characters extend below this line.
  528. Pic displays the center of the height of text at the given
  529. coordinate. HT_OFFSET is used to compensate all the above factors
  530. so text position in fig should be at the same position on
  531. the screen as on the hard copy.
  532.  
  533. THIS IS A HACK. tpic should be modified to put text with its
  534. baseline at the given coordinates as does fig -- Baron.
  535. */
  536. #define            HT_OFFSET    (0.25 / 72.0)
  537.  
  538. void gentpic_text(t)
  539. F_text    *t;
  540. {
  541.     float    y;
  542.         char    *tpos;
  543.     int    virtual_font = 0;
  544.  
  545.     /*
  546.      * If a font size is specified and the current text font size
  547.      * is the default, then use the specified font size.
  548.      */
  549.     if (t->size == 0 && font_size)
  550.         t->size = font_size;
  551.  
  552.     /*
  553.      * tpic is informed of the baseline spacing here. Not particularly
  554.      * useful in this version of the driver.
  555.      */
  556.     set_baseline((int)t->size);
  557.  
  558.     unpsfont(t);
  559.  
  560.     if (t->font > MAX_FONT || vfont)
  561.         virtual_font = 1;    /* must be a virtual font */
  562.  
  563.     if (virtual_font)
  564.         /*
  565.          * NOTE. Virtual fonts are defined dynamically using
  566.          * TeX's font definition machinery.
  567.          */
  568.         fprintf(tfp, "\"\\font\\fig%s=%s at %dpt \\fig%s ",
  569.             TEXFONT(t->font), TEXFONT(t->font), t->size,
  570.             TEXFONT(t->font));
  571.     else
  572. #ifdef FST
  573.         fprintf(tfp, "\"\\%spt\\%s ", TEXFONTMAG(t), TEXFONT(t->font));
  574. #else
  575.         fprintf(tfp, "\"\\%s%s ", TEXFONTMAG(t), TEXFONT(t->font));
  576. #endif
  577.  
  578.         switch (t->type) {
  579.         case T_LEFT_JUSTIFIED:
  580.         case DEFAULT:
  581.             tpos = "ljust";
  582.             break;
  583.         case T_CENTER_JUSTIFIED:
  584.             tpos = "";
  585.             break;
  586.         case T_RIGHT_JUSTIFIED:
  587.             tpos = "rjust";
  588.             break;
  589.         default:
  590.             fprintf(stderr, "unknown text position type\n");
  591.             exit(1);
  592.         }    
  593.     y = convy(t->base_y/ppi) + (TEXFONTMAGINT(t)
  594.         * HT_OFFSET);
  595.  
  596.     fprintf(tfp, "%s\" at %.3f,%.3f %s",
  597.         t->cstring, t->base_x/ppi, y, tpos);
  598.     newline();
  599. }
  600.  
  601. void gentpic_arc(a)
  602. F_arc    *a;
  603. {
  604.     double        x, y;
  605.     double        cx, cy, sx, sy, ex, ey;
  606.  
  607.     cx = a->center.x/ppi; cy = convy(a->center.y/ppi);
  608.     sx = a->point[0].x/ppi; sy = convy(a->point[0].y/ppi);
  609.     ex = a->point[2].x/ppi; ey = convy(a->point[2].y/ppi);
  610.  
  611.     set_texture(a->area_fill);
  612.     set_linewidth(a->thickness);
  613.     set_style(a->style, a->style_val);
  614.  
  615.     fprintf(tfp, "arc");
  616.  
  617.     if (a->style == DASH_LINE && a->style_val > 0.0)
  618.         fprintf(tfp, " dashed");
  619.     else if (a->style == DOTTED_LINE && a->style_val > 0.0)
  620.         fprintf(tfp, " dotted");
  621.  
  622.     /*rja: Attach arrowhead as required */
  623.     if ((a->for_arrow) && (a->back_arrow))
  624.         fprintf(tfp, " <->");
  625.     else if (a->back_arrow)
  626.         fprintf(tfp, " <-");
  627.     else if (a->for_arrow)
  628.         fprintf(tfp, " ->");
  629.  
  630.  
  631.     if (a->direction)
  632.         fprintf(tfp, " at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f",
  633.             cx, cy, sx, sy, ex, ey);
  634.     else
  635.         fprintf(tfp, " at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f cw",
  636.             cx, cy, sx, sy, ex, ey);
  637.     if (a->thickness == 0)
  638.         fprintf(tfp, " invis");
  639.     set_fill(a->area_fill);
  640.     newline();
  641.  
  642.     }
  643.  
  644. static arc_tangent(x1, y1, x2, y2, direction, x, y)
  645. double    x1, y1, x2, y2, *x, *y;
  646. int    direction;
  647. {
  648.     if (direction) { /* counter clockwise  */
  649.         *x = x2 + (y2 - y1);
  650.         *y = y2 - (x2 - x1);
  651.         }
  652.     else {
  653.         *x = x2 - (y2 - y1);
  654.         *y = y2 + (x2 - x1);
  655.         }
  656.     }
  657.  
  658. #define        THRESHOLD    .05    /* inch */
  659.  
  660. static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  661. double    a1, b1, a2, b2, a3, b3, a4, b4;
  662. {
  663.     double    x1, y1, x4, y4;
  664.     double    xmid, ymid;
  665.  
  666.     x1 = a1; y1 = b1;
  667.     x4 = a4; y4 = b4;
  668.  
  669.     xmid = (a2 + a3) / 2;
  670.     ymid = (b2 + b3) / 2;
  671.     if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD) {
  672.         fprintf(tfp, "\tto %.3f,%.3f\\\n", xmid, ymid);
  673.         }
  674.     else {
  675.         quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
  676.             ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
  677.         }
  678.  
  679.     if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
  680.         fprintf(tfp, "\tto %.3f,%.3f\\\n", x4, y4);
  681.         }
  682.     else {
  683.         quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
  684.             ((a3+x4)/2), ((b3+y4)/2), x4, y4);
  685.         }
  686.     }
  687.  
  688. void gentpic_closed_spline(s)
  689. F_spline    *s;
  690. {
  691.     F_point    *p;
  692.     double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  693.     double    x1, y1, x2, y2;
  694.  
  695.     p = s->points;
  696.     x1 = p->x/ppi;  y1 = convy(p->y/ppi);
  697.     p = p->next;
  698.     x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  699.     cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
  700.     cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  701.  
  702.     set_linewidth(s->thickness);
  703.     set_texture(s->area_fill); /* probably won't work! */
  704.     set_style(s->style, s->style_val);
  705.  
  706.     for (p = p->next; p != NULL; p = p->next) {
  707.         fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
  708.         x1 = x2;  y1 = y2;
  709.         x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  710.         cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  711.         cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  712.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  713.         newline();
  714.         /* fprintf(tfp, "\n"); */
  715.         cx1 = cx4;  cy1 = cy4;
  716.         cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  717.         }
  718.     x1 = x2;  y1 = y2;
  719.     p = s->points->next;
  720.     x2 = p->x/ppi;  y2 = convy(p->y/ppi);
  721.     cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  722.     cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  723.     fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
  724.     quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  725.     if (s->thickness == 0)
  726.         fprintf(tfp, " invis");
  727.     set_fill(s->area_fill);
  728.     newline();
  729.     /* fprintf(tfp, "\n"); */
  730.     }
  731.  
  732. void gentpic_itp_spline(s)
  733. F_spline    *s;
  734. {
  735.     F_point        *p1, *p2, *pfirst;
  736.     F_control    *cp1, *cp2;
  737.     double        x1, x2, y1, y2;
  738.  
  739.     set_style(s->style, s->style_val);
  740.     set_texture(s->area_fill); /* probably won't work! */
  741.     set_linewidth(s->thickness);
  742.  
  743.     p1 = s->points;
  744.     cp1 = s->controls;
  745.     cp2 = cp1->next;
  746.     x2 = p1->x/ppi; y2 = convy(p1->y/ppi);
  747.  
  748.          pfirst = p1->next;/*save first to test in loop*/
  749.     for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  750.         p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  751.  
  752.         fprintf(tfp, "line ");
  753.  
  754.            /*rja: Attach arrowhead as required */
  755.  
  756.         if ((s->back_arrow) && (p2 == pfirst))
  757.            fprintf(tfp, " <- ");
  758.         else if ((s->for_arrow) && (p2->next == NULL))
  759.            fprintf(tfp, " -> ");
  760.  
  761.         fprintf(tfp, " from %.3f,%.3f ", x2, y2);
  762.  
  763.         x1 = x2; y1 = y2;
  764.         x2 = p2->x/ppi; y2 = convy(p2->y/ppi);
  765.         bezier_spline(x1, y1, (double)cp1->rx/ppi, convy(cp1->ry/ppi),
  766.         (double)cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2);
  767.         /* fprintf(tfp, "\n"); */
  768.         newline();
  769.         }
  770.  
  771.     }
  772.  
  773. static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  774. double    a0, b0, a1, b1, a2, b2, a3, b3;
  775. {
  776.     double    x0, y0, x3, y3;
  777.     double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  778.  
  779.     x0 = a0; y0 = b0;
  780.     x3 = a3; y3 = b3;
  781.     if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD) {
  782.         fprintf(tfp, "\tto %.3f,%.3f\\\n", x3, y3);
  783.         }
  784.     else {
  785.         tx = (a1 + a2) / 2;        ty = (b1 + b2) / 2;
  786.         sx1 = (x0 + a1) / 2;    sy1 = (y0 + b1) / 2;
  787.         sx2 = (sx1 + tx) / 2;    sy2 = (sy1 + ty) / 2;
  788.         tx2 = (a2 + x3) / 2;    ty2 = (b2 + y3) / 2;
  789.         tx1 = (tx2 + tx) / 2;    ty1 = (ty2 + ty) / 2;
  790.         xmid = (sx2 + tx1) / 2;    ymid = (sy2 + ty1) / 2;
  791.  
  792.         bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  793.         bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  794.         }
  795.     }
  796.  
  797. static void
  798. newline()
  799. {
  800.     /*
  801.      * A vestige from another version of this driver.
  802.      */
  803.     fprintf(tfp, "\n");
  804. }
  805.  
  806. struct driver dev_tpic = {
  807.          gentpic_option,
  808.     gentpic_start,
  809.     gentpic_arc,
  810.     gentpic_ellipse,
  811.     gentpic_line,
  812.     gentpic_spline,
  813.     gentpic_text,
  814.     gentpic_end,
  815.     INCLUDE_TEXT
  816. };
  817.  
  818.