home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume8 / xfig2.8 / part13 / f2hp.c next >
C/C++ Source or Header  |  1990-07-03  |  18KB  |  811 lines

  1. /* 
  2.  *    f2hp : Fig-to-HPGL translator
  3.  *
  4.  *      Original Copyright (c) 1986 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  5.  *
  6.  *    Created from f2ps by B.V. Smith 5/90
  7.  *
  8.  *    %W%    %G%
  9. */
  10. #include "fig.h"
  11. #include "object.h"
  12. #include "resources.h"
  13.  
  14. #define        PAGE_WIDTH        (10.250-0.250)    /* 10"  X plot area (7475A) */
  15. #define        PAGE_HEIGHT        (7.796-0.596)    /* 7.2" Y plot area */
  16. #define        POINT_PER_INCH        72        /* text ppi */
  17. #define        MAX_COLORS        6        /* number of pens */
  18. #define        DEFAULT_COLOR        0        /* black */
  19. #define        UP            0
  20. #define        DOWN            1
  21.  
  22. #define TRANSF_X(x)    (x)*scalex
  23. #define TRANSF_Y(y)    (coord_system==2? (ury-(y))*scaley: (y)*scaley)
  24.  
  25. char        Usage[] = "Usage: %s [-P][-L][-debug][-e scale] [input [output]]\n";
  26. char        *prog;
  27. int        cur_thickness;
  28. int        cur_color= -9;
  29. int        cur_areafill=0;
  30. int        debug = 0;
  31. int        landscape = 1;
  32. int        pen=UP;
  33. extern int    num_object;
  34. char        *from = NULL, *to = NULL;
  35. FILE        *tfp = NULL;
  36. char        Err_incomp[] = "Incomplete %s object at line %d.";
  37. char        Err_mem[] = "Running out of memory.";
  38. double        scale = 1.0;
  39. double        scalex, scaley;
  40. int        coord_system;
  41. int        ppi;
  42. int        llx, lly, urx, ury;
  43.  
  44. int        fill_type[NUMFILLPATS] = {4, 3, 4, 3, 4, 3, 4, 3, 4, 3,
  45.                       4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 1};
  46. int        fill_spacing[NUMFILLPATS] = {8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6,
  47.                          4, 4, 4, 4, 4, 4, 2, 2, 0};
  48. int        fill_angle[NUMFILLPATS] = {0, 0, 45, 45, 90, 90, 0, 0, 45, 45, 
  49.                        90, 90, 0, 0, 45, 45, 90, 90, 0, 0, 0};
  50. int        line_thickness; /* not needed for f2ps, arrow.c needs it for fig */
  51.  
  52. get_args(argc, argv)
  53. int     argc;
  54. char    *argv[];
  55. {
  56.     char    *a;
  57.     int    first = 1;
  58.  
  59.     prog = *argv;
  60.     while (--argc) {
  61.         a = *++argv;
  62.         if (*a == '-') {
  63.         if (*++a == 'l' || *a == 'L') {    /* Landscape */
  64.             landscape = 1;
  65.             }
  66.         else if (*a == 'p' || *a == 'P') {    /* Portrait */
  67.             landscape = 0;
  68.             }
  69.         else if (*a == 'd')    /* debug printing */
  70.             debug = 1;
  71.         else if (*a == 'e') {    /* Enlarging factor followed */
  72.             if (--argc)
  73.             scale = atof(*++argv);
  74.             else
  75.             goto error_exit;
  76.             }
  77.         else
  78.             goto error_exit;
  79.         }
  80.         else if (first) {
  81.         from = a;    /*  from file  */
  82.         first = 0;
  83.         }
  84.         else if (first == 0) {
  85.         to = a;        /*  to file  */
  86.         first = -1;
  87.         }
  88.         else
  89.         goto error_exit;
  90.         }
  91.     return;
  92.  
  93.     error_exit:
  94.     fprintf(stderr, Usage, prog);
  95.     exit(1);
  96.     }
  97.  
  98. main(argc, argv)
  99. int     argc;
  100. char    *argv[];
  101. {
  102.     F_compound    objects;
  103.     int        status;
  104.  
  105.     get_args(argc, argv);
  106.  
  107.     if (to == NULL)
  108.         tfp = stdout;
  109.     else if ((tfp = fopen(to, "w")) == NULL) {
  110.         fprintf(stderr, "%s: Couldn't open %s", prog, to);
  111.         fprintf(stderr, Usage, prog);
  112.         exit(1);
  113.         }
  114.  
  115.     if (from)
  116.         status = read_fig(from, &objects);
  117.     else     /* read from stdin */
  118.         status = readfp_fig(stdin, &objects);
  119.  
  120.     if (status != 0) {
  121.         if (from) read_fail_message(from, status);
  122.         fprintf(stderr,"\n");
  123.         exit(1);
  124.         }
  125.     genhp_objects(&objects);
  126.     if (tfp != stdout) 
  127.         (void)fclose(tfp);
  128.     exit(0);
  129.     }
  130.  
  131. prolog(objects)
  132. F_compound    *objects;
  133.     {
  134.     plotter_on();
  135.     fprintf(tfp, "\033.I80;;17:");    /* set x-on/x-off */
  136.     fprintf(tfp, "\033.N;19:");
  137.     /* **** rotate for portrait mode **** */
  138.     if (!landscape)     /* must reset clip window and plotter limits with rotaton */
  139.         fprintf(tfp, "RO 90;IW;IP;\n");
  140.     fprintf(tfp, "SC %d %d %d %d;\n", llx, urx, lly, ury);
  141.     }
  142.  
  143. epilog()
  144.     {
  145.     penup();
  146.     fprintf(tfp,"PA %d %d; ",urx,ury);
  147.     fprintf(tfp, "SP;\n");
  148.     plotter_off();
  149.     }
  150.  
  151. plotter_on()
  152.     {
  153.     fprintf(tfp,"\033.(\n");
  154.     }
  155.  
  156. plotter_off()
  157.     {
  158.     fprintf(tfp,"\033.)\n");
  159.     }
  160.  
  161. genhp_objects(objects)
  162. F_compound    *objects;
  163. {
  164.     F_arc        *a;
  165.     F_compound    *c;
  166.     F_ellipse    *e;
  167.     F_line        *l;
  168.     F_spline    *s;
  169.     F_text        *t;
  170.     int        itmp;
  171.     int        color;
  172.  
  173.     /* Compute bounding box of objects */
  174.     compound_bound(objects, &llx, &lly, &urx, &ury);
  175.     if (llx > urx) {
  176.         fprintf(stderr, "%s: No object",prog);
  177.         return;
  178.         }
  179.  
  180.     ppi = objects->nwcorner.x;        /* ppi */
  181.     coord_system = objects->nwcorner.y;    /* 1=y normal, 2=y flipped */
  182.  
  183.     scalex = scaley = scale;        /* user enlarging factor */
  184.  
  185.     /*************************************************************************/
  186.     /* we will just set llx lly etc to plotter area              */
  187.     /*************************************************************************/
  188.  
  189.     llx = lly = 0;            /* lower left */
  190.     urx = PAGE_WIDTH*ppi;
  191.     ury = PAGE_HEIGHT*ppi;
  192.  
  193.     if (!landscape)            /* swap x,y */
  194.         {
  195.         itmp = llx; llx = lly; lly = itmp;
  196.         itmp = urx; urx = ury; ury = itmp;
  197.         }
  198.  
  199.     prolog(objects);
  200.  
  201.     /* plot color 0 first then 1, ... */
  202.     for (color=-1; color < MAX_COLORS; color++)
  203.         {
  204.         for (a = objects->arcs; a != NULL; a = a->next) 
  205.             genhp_arc(a,color);
  206.         for (c = objects->compounds; c != NULL; c = c->next) 
  207.             genhp_compound(c,color);
  208.         for (e = objects->ellipses; e != NULL; e = e->next) 
  209.             genhp_ellipse(e,color);
  210.         for (l = objects->lines; l != NULL; l = l->next) 
  211.             genhp_line(l,color);
  212.         for (s = objects->splines; s != NULL; s = s->next) 
  213.             genhp_spline(s,color);
  214.         for (t = objects->texts; t != NULL; t = t->next) 
  215.             genhp_text(t,color);
  216.         }
  217.     epilog();
  218.     }
  219.  
  220. set_style(s, v)
  221. int    s;
  222. double    v;
  223. {
  224.     if (s == DASH_LINE) {
  225.         if (v > 0.0) fprintf(tfp, "LT 2;\n");
  226.         }
  227.     else if (s == DOTTED_LINE) {
  228.         if (v > 0.0) fprintf(tfp, "LT 1;\n");
  229.         }
  230.     }
  231.  
  232. reset_style(s, v)
  233. int    s;
  234. double    v;
  235. {
  236.     if (s == DASH_LINE) {
  237.         if (v > 0.0) fprintf(tfp, "LT;\n");
  238.         }
  239.     else if (s == DOTTED_LINE) {
  240.         if (v > 0.0) fprintf(tfp, "LT;\n");
  241.         }
  242.     }
  243.  
  244. set_areafill(a)
  245. int a;
  246.     {
  247.     if (cur_areafill == a)
  248.         return;
  249.     cur_areafill = a;
  250.     fprintf(tfp, "FT %d %d %d;\n",
  251.             fill_type[a-1],fill_spacing[a-1],fill_angle[a-1]);
  252.     }
  253.  
  254. set_linewidth(w)
  255. int    w;
  256.     {
  257.     cur_thickness = w;
  258.     }
  259.  
  260. set_color(c)
  261. int    c;
  262.     {
  263.     if (c < 0)
  264.         c = DEFAULT_COLOR;
  265.     if (cur_color == c)
  266.         return;
  267.     cur_color = c;
  268.     fprintf(tfp,"SP %d;\n",c+1);
  269.     }
  270.  
  271. moveto(x,y)
  272. int x,y;
  273.     {
  274.     penup();
  275.     fprintf(tfp,"PA %.2f %.2f;\n",TRANSF_X(x),TRANSF_Y(y));
  276.     }
  277.  
  278. drawto(x,y)
  279. int x,y;
  280.     {
  281.     pendown();
  282.     fprintf(tfp,"PA %.2f %.2f;\n",TRANSF_X(x),TRANSF_Y(y));
  283.     }
  284.  
  285. f_moveto(x,y)
  286. double x,y;
  287.     {
  288.     penup();
  289.     fprintf(tfp,"PA %.2lf %.2lf;\n",TRANSF_X(x),TRANSF_Y(y));
  290.     }
  291.  
  292. f_drawto(x,y)
  293. double x,y;
  294.     {
  295.     pendown();
  296.     fprintf(tfp,"PA %.2lf %.2lf;\n",TRANSF_X(x),TRANSF_Y(y));
  297.     }
  298.  
  299. penup()
  300.     {
  301.     if (pen != UP)
  302.         fprintf(tfp,"PU; ");
  303.     pen = UP;
  304.     }
  305.  
  306. pendown()
  307.     {
  308.     if (pen != DOWN)
  309.         fprintf(tfp,"PD; ");
  310.     pen = DOWN;
  311.     }
  312.  
  313. genhp_compound(com,color)
  314. F_compound    *com;
  315. int color;
  316. {
  317.     F_arc        *a;
  318.     F_compound    *c;
  319.     F_ellipse    *e;
  320.     F_line        *l;
  321.     F_spline    *s;
  322.     F_text        *t;
  323.  
  324.     for (a = com->arcs; a != NULL; a = a->next) 
  325.         genhp_arc(a,color);
  326.     for (c = com->compounds; c != NULL; c = c->next) 
  327.         genhp_compound(c,color);
  328.     for (e = com->ellipses; e != NULL; e = e->next) 
  329.         genhp_ellipse(e,color);
  330.     for (l = com->lines; l != NULL; l = l->next) 
  331.         genhp_line(l,color);
  332.     for (s = com->splines; s != NULL; s = s->next) 
  333.         genhp_spline(s,color);
  334.     for (t = com->texts; t != NULL; t = t->next) 
  335.         genhp_text(t,color);
  336.     }
  337.  
  338. #define FILL_RECT(x,y)    fprintf(tfp,"RA %.2f %.2f; ",TRANSF_X((x)),TRANSF_Y((y)))
  339. #define EDGE_RECT(x,y)    fprintf(tfp,"EA %.2f %.2f; ",TRANSF_X((x)),TRANSF_Y((y)))
  340. #define FILL_WEDGE(r,angle,sweep) fprintf(tfp,"WG %.2f %d %d; ", \
  341.                 TRANSF_X(r),(angle),(sweep))
  342. #define ARC_TO(x,y,angle) fprintf(tfp,"AA %.2f %.2f %d; ", \
  343.                 TRANSF_X((x)),TRANSF_Y((y)),(angle))
  344. #define F_FILL_WEDGE(r,angle,sweep) fprintf(tfp,"WG %.2lf %d %d; ", \
  345.                 TRANSF_X(r),(angle),(sweep))
  346. #define F_ARC_TO(x,y,angle) fprintf(tfp,"AA %.2lf %.2lf %d; ", \
  347.                 TRANSF_X((x)),TRANSF_Y((y)),(angle))
  348. #define CIRCLE(r)    fprintf(tfp,"CI %.2f;",TRANSF_X(r))
  349.  
  350. genhp_line(l,color)
  351. F_line    *l;
  352. int color;
  353.     {
  354.     F_point    *p, *q;
  355.     int    radius,tmp;
  356.     int    xmin,xmax,ymin,ymax;
  357.  
  358.     if (color != l->color)
  359.         return;
  360.  
  361.     set_linewidth(l->thickness);
  362.     set_color(l->color);
  363.     radius = l->radius;        /* radius of rounded-corner boxes */
  364.     p = l->points;
  365.     q = p->next;
  366.     if (q == NULL) { /* A single point line */
  367.         if (l->thickness > 0)
  368.         {
  369.         moveto(p->x,p->y);
  370.         pendown();
  371.         penup();
  372.         }
  373.         return;
  374.         }
  375.     if (l->back_arrow)
  376.         draw_arrow_head((double)q->x, (double)q->y, (double)p->x,
  377.             (double)p->y, l->back_arrow->ht, l->back_arrow->wid);
  378.     set_style(l->style, l->style_val);
  379.     if (l->area_fill)
  380.         set_areafill(l->area_fill);
  381.     xmin = xmax = p->x;
  382.     ymin = ymax = p->y;
  383.  
  384.     while ((l->type == T_BOX || l->type == T_ARC_BOX) &&
  385.           p->next != NULL)    /* find lower left and upper right corners */
  386.         {
  387.         p=p->next;
  388.         if (xmin > p->x)
  389.             xmin = p->x;
  390.         else if (xmax < p->x)
  391.             xmax = p->x;
  392.         if (ymin > p->y)
  393.             ymin = p->y;
  394.         else if (ymax < p->y)
  395.             ymax = p->y;
  396.         }
  397.     if (l->type == T_ARC_BOX)    /* rounded-corner box */
  398.         {
  399.         if (l->area_fill)
  400.             {
  401.             moveto(xmin+radius,ymin);
  402.             FILL_RECT(xmax-radius,ymin+radius);
  403.             moveto(xmin,ymin+radius);
  404.             FILL_RECT(xmax,ymax-radius);
  405.             moveto(xmin+radius,ymax-radius);
  406.             FILL_RECT(xmax-radius,ymax);
  407.  
  408.             /* now do the corner wedges */
  409.             moveto(xmin+radius,ymin+radius);
  410.             FILL_WEDGE(radius,90,90);
  411.             moveto(xmin+radius,ymax-radius);
  412.             FILL_WEDGE(radius,180,90);
  413.             moveto(xmax-radius,ymax-radius);
  414.             FILL_WEDGE(radius,270,90);
  415.             moveto(xmax-radius,ymin+radius);
  416.             FILL_WEDGE(radius,0,90);
  417.             }
  418.         /* draw the outline of the box */
  419.         moveto(xmin+radius,ymin);
  420.         pendown();
  421.         ARC_TO(xmin+radius,ymin+radius,90);
  422.         drawto(xmin,ymax-radius);
  423.         ARC_TO(xmin+radius,ymax-radius,90);
  424.         drawto(xmax-radius,ymax);
  425.         ARC_TO(xmax-radius,ymax-radius,90);
  426.         drawto(xmax,ymin+radius);
  427.         ARC_TO(xmax-radius,ymin+radius,90);
  428.         drawto(xmin+radius,ymin);
  429.         } /* T_ARC_BOX */
  430.     else if (l->type == T_BOX)
  431.         {
  432.         moveto(xmin,ymin);
  433.         if (l->area_fill)
  434.             FILL_RECT(xmax,ymax);
  435.         EDGE_RECT(xmax,ymax);
  436.         }
  437.     else /* POLYGON or POLYLINE */
  438.         {
  439.         moveto(p->x, p->y);
  440.         while (q->next != NULL)
  441.             {
  442.             p = q;
  443.             q = q->next;
  444.             drawto(p->x, p->y);
  445.             }
  446.         drawto(q->x, q->y);
  447.         }
  448.     penup();
  449.  
  450.     reset_style(l->style, l->style_val);
  451.     if (l->for_arrow && l->thickness > 0)
  452.         draw_arrow_head((double)p->x, (double)p->y, (double)q->x,
  453.             (double)q->y, l->for_arrow->ht, l->for_arrow->wid);
  454.     }
  455.  
  456. genhp_spline(s,color)
  457. F_spline    *s;
  458. int color;
  459. {
  460.     if (color != s->color)
  461.         return;
  462.  
  463.     set_color(s->color);
  464. #ifndef notdef
  465.     fprintf(stderr,"No spline yet\n");
  466. #else
  467.     if (int_spline(s))
  468.         genhp_itp_spline(s);
  469.     else
  470.         genhp_ctl_spline(s);
  471. #endif
  472.     }
  473.  
  474. genhp_itp_spline(s)
  475. F_spline    *s;
  476. {
  477.     F_point        *p, *q;
  478.     F_control    *a, *b;
  479.  
  480.     set_linewidth(s->thickness);
  481.     a = s->controls;
  482.     b = a->next;
  483.     p = s->points;
  484.     if (s->back_arrow && s->thickness > 0)
  485.         draw_arrow_head(b->lx, b->ly, (double)p->x,
  486.             (double)p->y, s->back_arrow->ht, s->back_arrow->wid);
  487.  
  488.     set_style(s->style, s->style_val);
  489.     fprintf(tfp, "%% Interpolated spline\n");
  490.     fprintf(tfp, "newpath %d %d moveto\n", p->x, p->y);
  491.     for (q = p->next; q != NULL; p = q, q = q->next) {
  492.         b = a->next;
  493.         fprintf(tfp, "\t%.3f %.3f %.3f %.3f %d %d curveto\n",
  494.             a->rx, a->ry, b->lx, b->ly, q->x, q->y);
  495.         a = b;
  496.         }
  497.     if (closed_spline(s)) 
  498.         {
  499.         fprintf(tfp, " closepath ");
  500.         if (s->area_fill)
  501.             {
  502.             set_areafill(s->area_fill);
  503.             fprintf(tfp, " gsave fill grestore ");
  504.             set_areafill(NUMFILLPATS);    /* back to black for line */
  505.             }
  506.         }
  507.     if (s->thickness > 0)
  508.         fprintf(tfp, " stroke\n");
  509.     reset_style(s->style, s->style_val);
  510.  
  511.     if (s->for_arrow && s->thickness > 0)
  512.         draw_arrow_head(a->lx, a->ly, (double)p->x,
  513.             (double)p->y, s->for_arrow->ht, s->for_arrow->wid);
  514.     }
  515.  
  516. genhp_ctl_spline(s)
  517. F_spline    *s;
  518. {
  519.     double        a, b, c, d, x1, y1, x2, y2, x3, y3;
  520.     F_point        *p, *q;
  521.  
  522.     p = s->points;
  523.     x1 = p->x; y1 = p->y;
  524.     p = p->next;
  525.     c = p->x; d = p->y;
  526.     set_linewidth(s->thickness);
  527.     x3 = a = (x1 + c) / 2;
  528.     y3 = b = (y1 + d) / 2;
  529.     if (s->back_arrow && s->thickness > 0) {
  530.         draw_arrow_head(c, d, x1, y1, s->back_arrow->ht, s->back_arrow->wid);
  531.         }
  532.     set_style(s->style, s->style_val);
  533.     if (! closed_spline(s)) {
  534.         fprintf(tfp, "%% Open spline\n");
  535.         fprintf(tfp, "newpath %.3f %.3f moveto %.3f %.3f lineto\n",
  536.             x1, y1, x3, y3);
  537.         }
  538.     else {
  539.         fprintf(tfp, "%% Closed spline\n");
  540.         fprintf(tfp, "newpath %.3f %.3f moveto\n", a, b);
  541.         }
  542.     for (q = p->next; q != NULL; q = q->next) {
  543.         x1 = x3; y1 = y3;
  544.         x2 = c;  y2 = d;
  545.         c = q->x; d = q->y;
  546.         x3 = (x2 + c) / 2;
  547.         y3 = (y2 + d) / 2;
  548.         fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection\n",
  549.             x1, y1, x2, y2, x3, y3);
  550.         }
  551.     /*
  552.     * At this point, (x2,y2) and (c,d) are the position of the 
  553.     * next-to-last and last point respectively, in the point list
  554.     */
  555.     if (closed_spline(s)) {
  556.         fprintf(tfp, "\t%.3f %.3f %.3f %.3f %.3f %.3f DrawSplineSection closepath ",
  557.             x3, y3, c, d, a, b);
  558.         if (s->area_fill)
  559.         {
  560.         set_areafill(s->area_fill);
  561.         fprintf(tfp, " gsave fill grestore\n");
  562.         set_areafill(NUMFILLPATS);    /* back to black for line */
  563.         }
  564.         if (s->thickness > 0)
  565.         fprintf(tfp, " stroke\n");
  566.         }
  567.     else {
  568.         if (s->thickness > 0)
  569.         fprintf(tfp, "\t%.3f %.3f lineto stroke\n", c, d);
  570.         else
  571.         fprintf(tfp, "\t%.3f %.3f lineto\n", c, d);
  572.         }
  573.     reset_style(s->style, s->style_val);
  574.     if (s->for_arrow && s->thickness > 0) 
  575.         {
  576.         draw_arrow_head(x2, y2, c, d, s->for_arrow->ht,
  577.                 s->for_arrow->wid);
  578.         }
  579.     }
  580.  
  581. genhp_ellipse(e,color)
  582. F_ellipse    *e;
  583. int color;
  584.     {
  585.     int    rx,ry,cx,cy;
  586.     double    x,y;
  587.     int    npts;
  588.     double    theta,inc;
  589.  
  590.     if (color != e->color)
  591.         return;
  592.  
  593.     set_linewidth(e->thickness);
  594.     set_color(e->color);
  595.     set_style(e->style, e->style_val);
  596.     if (e->area_fill)
  597.         set_areafill(e->area_fill);
  598.     rx = e->radiuses.x;
  599.     ry = e->radiuses.y;
  600.     cx = e->center.x;
  601.     cy = e->center.y;
  602.     if (rx == ry)
  603.         {  /* CIRCLE */
  604.         moveto(cx, cy);
  605.         if (e->area_fill)
  606.             FILL_WEDGE(rx, 0, 360);
  607.         /* outline the circle */
  608.         CIRCLE(rx);
  609.         }
  610.     else /* ellipse */
  611.         {
  612.         npts = (rx+ry)*2;    /* pick some number of points proportional
  613.                        to the size of the ellipse to plot */
  614.         inc = 2.0*M_PI/npts;
  615.         moveto(cx+rx,cy);
  616.         for (theta = 0.0; theta <= 2*M_PI; theta += inc)
  617.             {
  618.             x = cx + rx*cos(theta);
  619.             y = cy + ry*sin(theta);
  620.             f_drawto(x,y);
  621.             }
  622.         drawto(cx+rx, cy);
  623.         }
  624.     penup();
  625.     reset_style(e->style, e->style_val);
  626.     }
  627.  
  628.  
  629. #define IS_ITALICS(f) ((f)&1)
  630.  
  631. genhp_text(t,color)
  632. F_text    *t;
  633. int color;
  634.     {
  635.     double    height;
  636.     int    len;
  637.  
  638.     if (color != t->color)
  639.         return;
  640.  
  641.     set_color(t->color);
  642.     height = (double) t->size/POINT_PER_INCH*2.54;    /* height in cm */
  643.  
  644.     height = height*scale;
  645.     height = height/1.5;        /* kludge for now */
  646.     fprintf(tfp,"SI %.2lf %.2lf;",height/2.54,height);
  647.     len = strlen(t->cstring);
  648.     if (IS_ITALICS(t->font))    /* slant for Italics font */
  649.         fprintf(tfp,"SL %.2f;",tan((double)30.0*M_PI/180.0));    /* 30 degrees */
  650.     moveto(t->base_x,t->base_y);
  651.     if (t->type == T_RIGHT_JUSTIFIED)
  652.         fprintf(tfp,"CP %d 0; ",-len);
  653.     else if (t->type == T_CENTER_JUSTIFIED)
  654.         fprintf(tfp,"CP %.1f 0; ",-len/2.0);
  655.     fprintf(tfp,"LB%s\003;\n",t->cstring);
  656.     if (IS_ITALICS(t->font))
  657.         fprintf(tfp,"SL;");
  658.     }
  659.  
  660. genhp_arc(a,color)
  661. F_arc    *a;
  662. int color;
  663. {
  664.     double        angle1, angle2, dx, dy, radius, x, y;
  665.     double        cx, cy, sx, sy, ex, ey;
  666.     int        sweep;
  667.     int        direction;
  668.  
  669.     if (color != a->color)
  670.         return;
  671.  
  672.     cx = a->center.x; cy = a->center.y;
  673.     sx = a->point[0].x; sy = a->point[0].y;
  674.     ex = a->point[2].x; ey = a->point[2].y;
  675.  
  676.     if (coord_system == 2)
  677.         direction = !a->direction;
  678.     else
  679.         direction = a->direction;
  680.     set_linewidth(a->thickness);
  681.     set_color(a->color);
  682.     if (a->for_arrow && a->thickness > 0) {
  683.         arc_tangent(cx, cy, ex, ey, direction, &x, &y);
  684.         draw_arrow_head(x, y, ex, ey, a->for_arrow->ht, a->for_arrow->wid);
  685.         }
  686.     if (a->back_arrow && a->thickness > 0) {
  687.         arc_tangent(cx, cy, sx, sy, !direction, &x, &y);
  688.         draw_arrow_head(x, y, sx, sy, a->back_arrow->ht, a->back_arrow->wid);
  689.         }
  690.     dx = cx - sx;
  691.     dy = cy - sy;
  692.     radius = sqrt(dx*dx + dy*dy);
  693.     angle1 = atan2(sy-cy, sx-cx) * 180 / M_PI;
  694.     angle2 = atan2(ey-cy, ex-cx) * 180 / M_PI;
  695.     /* make the angles go from 0 to 2PI */
  696.     if (angle1 < 0.0)
  697.         angle1 += 360.0;
  698.     if (angle2 < 0.0)
  699.         angle2 += 360.0;
  700.     /* direction 1 -> Counter-Clockwise */
  701.     if (direction == 1) /* ccw */
  702.         {
  703.         if (angle1 > angle2)
  704.             sweep = 360.0 - angle1 + angle2;
  705.         else
  706.             sweep = angle2 - angle1;
  707.         }
  708.     else /* cw */
  709.         {
  710.         if (angle1 > angle2)
  711.             sweep = - (angle1 - angle2);
  712.         else
  713.             sweep = - (360.0 - angle2 + angle1);
  714.         }
  715.     if (debug)
  716.         fprintf(stderr,"#%d: dir=%s, a1 = %.1f, a2 = %.1f, sweep = %d\n",
  717.         a->thickness,direction==0?"cw ":"ccw",cx,cy,angle1,angle2,sweep);
  718.     set_style(a->style, a->style_val);
  719.     if (a->area_fill)
  720.         {
  721.         set_areafill(a->area_fill);
  722.         f_moveto(cx,cy);
  723.         F_FILL_WEDGE(radius,(int)angle1,sweep);
  724.         }
  725.     f_moveto(ex,ey);
  726.     pendown();
  727.     F_ARC_TO(cx,cy,sweep);
  728.     penup();
  729.  
  730.     reset_style(a->style, a->style_val);
  731.     }
  732.  
  733. arc_tangent(x1, y1, x2, y2, direction, x, y)
  734. double    x1, y1, x2, y2, *x, *y;
  735. int    direction;
  736. {
  737.     if (direction) { /* counter clockwise  */
  738.         *x = x2 + (y2 - y1);
  739.         *y = y2 - (x2 - x1);
  740.         }
  741.     else {
  742.         *x = x2 - (y2 - y1);
  743.         *y = y2 + (x2 - x1);
  744.         }
  745.     }
  746.  
  747. /*    draw arrow heading from (x1, y1) to (x2, y2)    */
  748.  
  749. draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
  750. double    x1, y1, x2, y2, arrowht, arrowwid;
  751. {
  752.     double    x, y, xb, yb, dx, dy, l, sina, cosa;
  753.     double    xc, yc, xd, yd;
  754.  
  755.     dx = x2 - x1;  dy = y1 - y2;
  756.     l = sqrt((double)(dx*dx + dy*dy));    /* length of line */
  757.     sina = dy / l;  cosa = dx / l;
  758.     xb = x2*cosa - y2*sina;
  759.     yb = x2*sina + y2*cosa;
  760.     x = xb - arrowht;
  761.     y = yb - arrowwid / 2;
  762.     xc = x*cosa + y*sina;            /* one tail of arrow */
  763.     yc = -x*sina + y*cosa;
  764.     y = yb + arrowwid / 2;
  765.     xd = x*cosa + y*sina;            /* other tail of arrow */
  766.     yd = -x*sina + y*cosa;
  767.     f_moveto(xc,yc);
  768.     f_drawto(x2,y2);
  769.     f_drawto(xd,yd);
  770.     penup();
  771.     }
  772.  
  773. ellipse_exist(ob)
  774. F_compound    *ob;
  775. {
  776.     F_compound    *c;
  777.  
  778.     if (NULL != ob->ellipses) return(1);
  779.  
  780.     for (c = ob->compounds; c != NULL; c = c->next) {
  781.         if (ellipse_exist(c)) return(1);
  782.         }
  783.  
  784.     return(0);
  785.     }
  786.  
  787. normal_spline_exist(ob)
  788. F_compound    *ob;
  789. {
  790.     F_spline    *s;
  791.     F_compound    *c;
  792.  
  793.     for (s = ob->splines; s != NULL; s = s->next) {
  794.         if (normal_spline(s)) return(1);
  795.         }
  796.  
  797.     for (c = ob->compounds; c != NULL; c = c->next) {
  798.         if (normal_spline_exist(c)) return(1);
  799.         }
  800.  
  801.     return(0);
  802.     }
  803.  
  804. /*VARARGS1*/
  805. put_msg(format, arg1, arg2, arg3, arg4, arg5)
  806.     char    *format;
  807.     int     arg1, arg2, arg3, arg4, arg5;
  808. {
  809.     fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5);
  810. }
  811.