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

  1. /* 
  2.  *    F2p : Fig-to-pic translator
  3.  *
  4.  *    Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  5.  *    January 1985.
  6.  *    1st revision : October 1985.
  7.  *    2nd revision : March 1988 - read fig 1.4
  8.  *    Support for fonts and point sizes added by daved@physiol.su.oz.au
  9.  *        March 1990
  10.  *
  11.  *    %W%    %G%
  12. */
  13. #include "fig.h"
  14. #include "object.h"
  15. #include "troff_fonts.h"
  16. #include "psfonts.h"
  17.  
  18. char        Usage[] = "Usage: f2p [ -f font_file ] [ input_file [ output_file ] ]\n";
  19. char        *from = NULL,
  20.         *to = NULL;
  21. FILE        *tfp = NULL;
  22. char        Err_incomp[] = "Incomplete %s object at line %d.";
  23. char        Err_mem[] = "Running out of memory.";
  24.  
  25. int        line_thickness; /* not for f2ps - arrow.c needs it for fig */
  26. extern    struct    _fstruct fontnames[];        /* printer font names */
  27. int        dotps,        /* most recent size passed to .ps */
  28.         dotft;        /* one more than num of font passed to .ft */
  29.  
  30. /*VARARGS1*/
  31. put_msg(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
  32. char   *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8;
  33. {
  34.     fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  35.     fputc('\n',stderr);
  36. }
  37.  
  38. get_args(argc, argv)
  39. int     argc;
  40. char    *argv[];
  41. {
  42.     char    *a;
  43.     int    first = 1;
  44.  
  45.     while (--argc)
  46.     {
  47.         a = *++argv;
  48.         if (*a == '-')
  49.         {
  50.             if (*++a == 'f')
  51.             {
  52.                 if (--argc)
  53.                     font_file = *++argv;
  54.                 else
  55.                 {
  56.                     fprintf(stderr, Usage);
  57.                     exit(1);
  58.                 }
  59.             }
  60.             else
  61.             {
  62.                 fprintf(stderr, Usage);
  63.                 exit(1);
  64.             }
  65.         }
  66.         else if (first)
  67.         {
  68.             from = a;    /*  from file  */
  69.             first = 0;
  70.         }
  71.         else if (first == 0)
  72.         {
  73.             to = a;        /*  to file  */
  74.             first = -1;
  75.         }
  76.         else
  77.         {
  78.             fprintf(stderr, Usage);
  79.             exit(1);
  80.         }
  81.     }
  82. }
  83.  
  84. main(argc, argv)
  85. int     argc;
  86. char    *argv[];
  87. {
  88.     F_compound    objects;
  89.     int        status;
  90.  
  91.     get_args(argc, argv);
  92.     troff_init();
  93.     if (to == NULL)
  94.         tfp = stdout;
  95.     else if ((tfp = fopen(to, "w")) == NULL)
  96.     {
  97.         fprintf(stderr, "Couldn't open %s\n", to);
  98.         fprintf(stderr, Usage);
  99.         exit(1);
  100.     }
  101.  
  102.     if (from)
  103.         status = read_fig(from, &objects);
  104.     else     /* read from stdin */
  105.     status = readfp_fig(stdin, &objects);
  106.  
  107.     if (status != 0)
  108.     {
  109.         if (from) read_fail_message(from, status);
  110.         exit(1);
  111.     }
  112.     genpic_objects(&objects);
  113.     if (tfp != stdout) fclose(tfp);
  114.     exit(0);
  115. }
  116.  
  117. #define            TOP    10.5    /* top of page is 10.5 inch */
  118. static double        ppi;
  119. static int        CONV = 0;
  120.  
  121. double
  122. convy(a)
  123. double    a;
  124. {
  125.     return((double)(CONV ? TOP-a : a));
  126. }
  127.  
  128. genpic_objects(objects)
  129. F_compound    *objects;
  130. {
  131.     int        coord_system;
  132.     F_arc        *a;
  133.     F_compound    *c;
  134.     F_ellipse    *e;
  135.     F_line        *l;
  136.     F_spline    *s;
  137.     F_text        *t;
  138.  
  139.     if (0 == (ppi = (double)objects->nwcorner.x))
  140.     {
  141.         fprintf(stderr, "Resolution is zero!! default to 80 ppi\n");
  142.         ppi = 80.0;
  143.     }
  144.     coord_system = objects->nwcorner.y;
  145.     if (coord_system != 1 && coord_system != 2)
  146.     {
  147.         fprintf(stderr, "Wrong coordinate system; cannot continue\n");
  148.         return;
  149.     }
  150.     if (coord_system == 2) CONV = 1;
  151.  
  152.     fprintf(tfp, ".PS\n");    /* start of pic macro */
  153.  
  154.     for (a = objects->arcs; a != NULL; a = a->next) genpic_arc(a);
  155.     for (c = objects->compounds; c != NULL; c = c->next) genpic_compound(c);
  156.     for (e = objects->ellipses; e != NULL; e = e->next) genpic_ellipse(e);
  157.     for (l = objects->lines; l != NULL; l = l->next) genpic_line(l);
  158.     for (s = objects->splines; s != NULL; s = s->next) genpic_spline(s);
  159.     for (t = objects->texts; t != NULL; t = t->next) genpic_text(t);
  160.     if(dotps)
  161.         fprintf(tfp, ".ps\n");    /* back to initial point size */
  162.     if(dotft)
  163.         fprintf(tfp, ".ft\n");    /* back to initial font */
  164.     fprintf(tfp, ".PE\n");
  165. }
  166.  
  167. /*
  168. ** linewidth can be controlled with pointsize, but this means we have
  169. ** to be rigorous about using a .ps (null) every time, so a real point size
  170. ** request can revert to previous size
  171. */
  172. set_linewidth(w)
  173. int    w;
  174. {
  175.     if (w == 0 || w*10 == dotps) return;
  176.     fprintf(tfp,".ps\n.ps %d\n",dotps = 10*w);
  177. }
  178.  
  179. set_style(s, v)
  180. int    s;
  181. float    v;
  182. {
  183.     static float    style_val = -1;
  184.  
  185.     if (s == DASH_LINE || s == DOTTED_LINE)
  186.     {
  187.         if (v == style_val) return;
  188.         if (v == 0.0) return;
  189.         style_val = v;
  190.         fprintf(tfp, "dashwid = %.3fi\n", style_val/ppi);
  191.     }
  192. }
  193.  
  194. genpic_compound(com)
  195. F_compound    *com;
  196. {
  197.     F_arc        *a;
  198.     F_compound    *c;
  199.     F_ellipse    *e;
  200.     F_line        *l;
  201.     F_spline    *s;
  202.     F_text        *t;
  203.  
  204.     for (a = com->arcs; a != NULL; a = a->next) genpic_arc(a);
  205.     for (c = com->compounds; c != NULL; c = c->next) genpic_compound(c);
  206.     for (e = com->ellipses; e != NULL; e = e->next) genpic_ellipse(e);
  207.     for (l = com->lines; l != NULL; l = l->next) genpic_line(l);
  208.     for (s = com->splines; s != NULL; s = s->next) genpic_spline(s);
  209.     for (t = com->texts; t != NULL; t = t->next) genpic_text(t);
  210. }
  211.  
  212. genpic_line(l)
  213. F_line    *l;
  214. {
  215.     F_point        *p, *q;
  216.  
  217.     set_linewidth(l->thickness);
  218.     set_style(l->style, l->style_val);
  219.     p = l->points;
  220.     q = p->next;
  221.     if (q == NULL)
  222.     { /* A single point line */
  223.         fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f\n",
  224.         p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi));
  225.         return;
  226.     }
  227.     if (l->back_arrow)
  228.         draw_arrow_head(q->x/ppi, convy(q->y/ppi), p->x/ppi,
  229.         convy(p->y/ppi), l->back_arrow->ht/ppi, l->back_arrow->wid/ppi);
  230.     if (l->style == DASH_LINE && l->style_val > 0.0)
  231.         fprintf(tfp, "line dashed from");
  232.     else if (l->style == DOTTED_LINE && l->style_val > 0.0)
  233.         fprintf(tfp, "line dotted from");
  234.     else
  235.         fprintf(tfp, "line from");
  236.     fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  237.     while (q->next != NULL)
  238.     {
  239.         p = q;
  240.         q = q->next;
  241.         fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
  242.     }
  243.     fprintf(tfp, " %.3f,%.3f\n", q->x/ppi, convy(q->y/ppi));
  244.     if (l->for_arrow)
  245.         draw_arrow_head(p->x/ppi, convy(p->y/ppi), q->x/ppi,
  246.         convy(q->y/ppi), l->for_arrow->ht/ppi, l->for_arrow->wid/ppi);
  247. }
  248.  
  249. genpic_spline(s)
  250. F_spline    *s;
  251. {
  252.     set_linewidth(s->thickness);
  253.     if (int_spline(s))
  254.         genpic_itp_spline(s);
  255.     else
  256.         genpic_ctl_spline(s);
  257. }
  258.  
  259. genpic_ctl_spline(s)
  260. F_spline    *s;
  261. {
  262.     if (closed_spline(s))
  263.         genpic_closed_spline(s);
  264.     else
  265.         genpic_open_spline(s);
  266. }
  267.  
  268. genpic_open_spline(s)
  269. F_spline    *s;
  270. {
  271.     double        x1, y1, x2, y2;
  272.     F_point        *p, *q;
  273.  
  274.     p = s->points;
  275.     x1 = p->x/ppi; 
  276.     y1 = convy(p->y/ppi);
  277.     p = p->next;
  278.     x2 = p->x/ppi; 
  279.     y2 = convy(p->y/ppi);
  280.  
  281.     if (s->back_arrow)
  282.         draw_arrow_head(x2, y2, x1, y1,
  283.         s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
  284.  
  285.     /* Pic's spline supports only solid line style */
  286.  
  287.     if (p->next == NULL)
  288.     {
  289.         fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f\n", x1, y1, x2, y2);
  290.         if (s->for_arrow)
  291.             draw_arrow_head(x1, y1, x2, y2, s->for_arrow->ht/ppi,
  292.             s->for_arrow->wid/ppi);
  293.         return;
  294.     }
  295.  
  296.     fprintf(tfp, "spline from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2);
  297.  
  298.     for (q = p->next; q->next != NULL; p = q, q = q->next)
  299.         fprintf(tfp, " to %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
  300.     fprintf(tfp, " to %.3f,%.3f\n", (x2=q->x/ppi), (y2=convy(q->y/ppi)));
  301.  
  302.     if (s->for_arrow)
  303.         draw_arrow_head(p->x/ppi, convy(p->y/ppi), x2, y2,
  304.         s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
  305. }
  306.  
  307. genpic_ellipse(e)
  308. F_ellipse    *e;
  309. {
  310.     set_linewidth(e->thickness);
  311.     fprintf(tfp, "ellipse at %.3f,%.3f wid %.3f ht %.3f\n",
  312.     e->center.x/ppi, convy(e->center.y/ppi),
  313.     2 * e->radiuses.x/ppi, 2 * e->radiuses.y/ppi);
  314. }
  315.  
  316. /*
  317. Text is display on the screen with the base line starting at
  318. (base_x, base_y); some characters extend below this line.
  319. Pic displays the center of the height of text at the given
  320. coordinate. HT_OFFSET is use to compensate all the above factors
  321. so text position in fig 1.4 should be at the same position on
  322. the screen as on the hard copy.
  323. */
  324. #define            HT_OFFSET    (0.2 / 72.0)
  325.  
  326. genpic_text(t)
  327. F_text    *t;
  328. {
  329.     float    y;
  330.     static    char fontcode[NUMFONTS][3];
  331.     int    i;
  332.  
  333.     if(fontcode[t->font][0] == '\0')
  334.         for(i=0; *troff_fonts[i].lwname != '\0'; i++)
  335.         {
  336.             if(strcmp(troff_fonts[i].lwname,fontnames[t->font].psfont)==0)
  337.             {
  338.                 strncpy(&fontcode[t->font][0],troff_fonts[i].trname,2);
  339.                 break;
  340.             }
  341.         }
  342.     if(fontcode[t->font][0] == '\0')
  343.         fontcode[t->font][0] = 'R';    /* default */
  344.  
  345.     if(t->size != dotps)
  346.         fprintf(tfp, ".ps\n.ps %d\n", dotps = t->size);
  347.     if(t->font != dotft - 1)
  348.     {
  349.         fprintf(tfp, ".ft\n.ft %s\n", &fontcode[t->font][0]);
  350.         dotft = t->font + 1;
  351.     }
  352.  
  353.     y = convy(t->base_y/ppi) + t->size * HT_OFFSET;
  354.     fprintf(tfp, "\"%s\" at %.3f,%.3f",
  355.     t->cstring, t->base_x/ppi, y);
  356.  
  357.     switch(t->type)
  358.     {
  359.     case T_RIGHT_JUSTIFIED:
  360.         fprintf(tfp, " rjust\n");
  361.         break;
  362.     case T_LEFT_JUSTIFIED:
  363.         fprintf(tfp, " ljust\n");
  364.         break;
  365.     default:
  366.         putc('\n',tfp);
  367.     }
  368. }
  369.  
  370. genpic_arc(a)
  371. F_arc    *a;
  372. {
  373.     double        x, y;
  374.     double        cx, cy, sx, sy, ex, ey;
  375.  
  376.     cx = a->center.x/ppi; 
  377.     cy = convy(a->center.y/ppi);
  378.     sx = a->point[0].x/ppi; 
  379.     sy = convy(a->point[0].y/ppi);
  380.     ex = a->point[2].x/ppi; 
  381.     ey = convy(a->point[2].y/ppi);
  382.  
  383.     set_linewidth(a->thickness);
  384.  
  385.     if (a->for_arrow)
  386.     {
  387.         arc_tangent(cx, cy, ex, ey, a->direction, &x, &y);
  388.         draw_arrow_head(x, y, ex, ey,
  389.         a->for_arrow->ht/ppi, a->for_arrow->wid/ppi);
  390.     }
  391.     if (a->back_arrow)
  392.     {
  393.         arc_tangent(cx, cy, sx, sy, !a->direction, &x, &y);
  394.         draw_arrow_head(x, y, sx, sy,
  395.         a->back_arrow->ht/ppi, a->back_arrow->wid/ppi);
  396.     }
  397.  
  398.     if (a->direction)
  399.         fprintf(tfp, "arc at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f\n",
  400.         cx, cy, sx, sy, ex, ey);
  401.     else
  402.         fprintf(tfp, "arc at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f cw\n",
  403.         cx, cy, sx, sy, ex, ey);
  404.  
  405. }
  406.  
  407. arc_tangent(x1, y1, x2, y2, direction, x, y)
  408. double    x1, y1, x2, y2, *x, *y;
  409. int    direction;
  410. {
  411.     if (direction)
  412.     { /* counter clockwise  */
  413.         *x = x2 + (y2 - y1);
  414.         *y = y2 - (x2 - x1);
  415.     }
  416.     else
  417.     {
  418.         *x = x2 - (y2 - y1);
  419.         *y = y2 + (x2 - x1);
  420.     }
  421. }
  422.  
  423. /*    draw arrow heading from (x1, y1) to (x2, y2)    */
  424.  
  425. draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
  426. double    x1, y1, x2, y2, arrowht, arrowwid;
  427. {
  428.     double    x, y, xb, yb, dx, dy, l, sina, cosa;
  429.     double    xc, yc, xd, yd;
  430.  
  431.     dx = x2 - x1;  
  432.     dy = y1 - y2;
  433.     l = sqrt((dx*dx + dy*dy));
  434.     sina = dy / l;  
  435.     cosa = dx / l;
  436.     xb = x2*cosa - y2*sina;
  437.     yb = x2*sina + y2*cosa;
  438.     x = xb - arrowht;
  439.     y = yb - arrowwid / 2;
  440.     xc = x*cosa + y*sina;
  441.     yc = -x*sina + y*cosa;
  442.     y = yb + arrowwid / 2;
  443.     xd = x*cosa + y*sina;
  444.     yd = -x*sina + y*cosa;
  445.     fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f to %.3f,%.3f\n",
  446.     xc, yc, x2, y2, xd, yd);
  447. }
  448.  
  449. #define        THRESHOLD    .05    /* inch */
  450.  
  451. quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  452. double    a1, b1, a2, b2, a3, b3, a4, b4;
  453. {
  454.     double    x1, y1, x4, y4;
  455.     double    xmid, ymid;
  456.  
  457.     x1 = a1; 
  458.     y1 = b1;
  459.     x4 = a4; 
  460.     y4 = b4;
  461.  
  462.     xmid = (a2 + a3) / 2;
  463.     ymid = (b2 + b3) / 2;
  464.     if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD)
  465.     {
  466.         fprintf(tfp, "\tto %.3f,%.3f\\\n", xmid, ymid);
  467.     }
  468.     else
  469.     {
  470.         quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
  471.         ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
  472.     }
  473.  
  474.     if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD)
  475.     {
  476.         fprintf(tfp, "\tto %.3f,%.3f\\\n", x4, y4);
  477.     }
  478.     else
  479.     {
  480.         quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
  481.         ((a3+x4)/2), ((b3+y4)/2), x4, y4);
  482.     }
  483. }
  484.  
  485. genpic_closed_spline(s)
  486. F_spline    *s;
  487. {
  488.     F_point    *p;
  489.     double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  490.     double    x1, y1, x2, y2;
  491.  
  492.     set_linewidth(s->thickness);
  493.     p = s->points;
  494.     x1 = p->x/ppi;  
  495.     y1 = convy(p->y/ppi);
  496.     p = p->next;
  497.     x2 = p->x/ppi;  
  498.     y2 = convy(p->y/ppi);
  499.     cx1 = (x1 + x2) / 2;      
  500.     cy1 = (y1 + y2) / 2;
  501.     cx2 = (x1 + 3 * x2) / 4;  
  502.     cy2 = (y1 + 3 * y2) / 4;
  503.  
  504.     for (p = p->next; p != NULL; p = p->next)
  505.     {
  506.         fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
  507.         x1 = x2;  
  508.         y1 = y2;
  509.         x2 = p->x/ppi;  
  510.         y2 = convy(p->y/ppi);
  511.         cx3 = (3 * x1 + x2) / 4;  
  512.         cy3 = (3 * y1 + y2) / 4;
  513.         cx4 = (x1 + x2) / 2;      
  514.         cy4 = (y1 + y2) / 2;
  515.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  516.         fprintf(tfp, "\n");
  517.         cx1 = cx4;  
  518.         cy1 = cy4;
  519.         cx2 = (x1 + 3 * x2) / 4;  
  520.         cy2 = (y1 + 3 * y2) / 4;
  521.     }
  522.     x1 = x2;  
  523.     y1 = y2;
  524.     p = s->points->next;
  525.     x2 = p->x/ppi;  
  526.     y2 = convy(p->y/ppi);
  527.     cx3 = (3 * x1 + x2) / 4;  
  528.     cy3 = (3 * y1 + y2) / 4;
  529.     cx4 = (x1 + x2) / 2;      
  530.     cy4 = (y1 + y2) / 2;
  531.     fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
  532.     quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  533.     fprintf(tfp, "\n");
  534. }
  535.  
  536. genpic_itp_spline(s)
  537. F_spline    *s;
  538. {
  539.     F_point        *p1, *p2;
  540.     F_control    *cp1, *cp2;
  541.     double        x1, x2, y1, y2;
  542.  
  543.     p1 = s->points;
  544.     cp1 = s->controls;
  545.     cp2 = cp1->next;
  546.     x2 = p1->x/ppi; 
  547.     y2 = convy(p1->y/ppi);
  548.  
  549.     if (s->back_arrow)
  550.         draw_arrow_head(cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2,
  551.         s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
  552.  
  553.     for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  554.         cp1 = cp2, p2 = p2->next, cp2 = cp2->next)
  555.         {
  556.             fprintf(tfp, "line from %.3f,%.3f ", x2, y2);
  557.         x1 = x2; 
  558.         y1 = y2;
  559.         x2 = p2->x/ppi; 
  560.         y2 = convy(p2->y/ppi);
  561.         bezier_spline(x1, y1, (double)cp1->rx/ppi, convy(cp1->ry/ppi),
  562.         (double)cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2);
  563.         fprintf(tfp, "\n");
  564.     }
  565.  
  566.     if (s->for_arrow)
  567.         draw_arrow_head((double)cp1->lx/ppi, convy(cp1->ly/ppi), x1, y1,
  568.         (double)s->for_arrow->ht/ppi, (double)s->for_arrow->wid/ppi);
  569. }
  570.  
  571. bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  572. double    a0, b0, a1, b1, a2, b2, a3, b3;
  573. {
  574.     double    x0, y0, x3, y3;
  575.     double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  576.  
  577.     x0 = a0; 
  578.     y0 = b0;
  579.     x3 = a3; 
  580.     y3 = b3;
  581.     if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD)
  582.     {
  583.         fprintf(tfp, "\tto %.3f,%.3f\\\n", x3, y3);
  584.     }
  585.     else
  586.     {
  587.         tx = (a1 + a2) / 2;        
  588.         ty = (b1 + b2) / 2;
  589.         sx1 = (x0 + a1) / 2;    
  590.         sy1 = (y0 + b1) / 2;
  591.         sx2 = (sx1 + tx) / 2;    
  592.         sy2 = (sy1 + ty) / 2;
  593.         tx2 = (a2 + x3) / 2;    
  594.         ty2 = (b2 + y3) / 2;
  595.         tx1 = (tx2 + tx) / 2;    
  596.         ty1 = (ty2 + ty) / 2;
  597.         xmid = (sx2 + tx1) / 2;    
  598.         ymid = (sy2 + ty1) / 2;
  599.  
  600.         bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  601.         bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  602.     }
  603. }
  604.  
  605.