home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / dev / gentextyl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-06  |  14.1 KB  |  596 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.  *    gentextyl.c : TeXtyl driver for fig2dev
  26.  *
  27.  *     Author: Gary Beihl, MCC 8/90
  28.  *    (beihl@mcc.com)
  29.  *
  30.  *      Based on the pictex driver by Micah Beck
  31.  *
  32.  */
  33.  
  34. #if defined(hpux) || defined(SYSV)
  35. #include <sys/types.h>
  36. #endif
  37. #include <sys/file.h>
  38. #include <stdio.h>
  39. #include <math.h>
  40. #include "pi.h"
  41. #include "object.h"
  42. #include "fig2dev.h"
  43. #include "texfonts.h"
  44.  
  45. #ifndef sin
  46. extern double sin();
  47. #endif
  48. #ifndef cos
  49. extern double cos();
  50. #endif
  51. #ifndef acos
  52. extern double acos();
  53. #endif
  54. #ifndef fabs
  55. extern double fabs();
  56. #endif
  57.  
  58. void gentextyl_ctl_spline(), gentextyl_itp_spline();
  59.  
  60. static int        coord_system;
  61. static double        dash_length = -1;
  62. static int        line_style = 0; /* Textyl solid line style */
  63. static int         linethick = 2;  /* Range is 1-12 `pixels' */
  64.  
  65.  
  66. static void gentextyl_option(opt, optarg)
  67. char opt, *optarg;
  68. {
  69.     switch (opt) {
  70.         case 'a':
  71.             /* capfonts = 1; */
  72.             break;
  73.  
  74.         case 'f':            /* set default text font */
  75.             texfontnames[0] = texfontnames[1] = optarg;
  76.             break;
  77.  
  78.         case 'l':            /* set line thickness */
  79.             linethick = atoi(optarg);
  80.                     if (linethick < 1 || linethick > 12) {
  81.                       put_msg(Err_badarg, opt, "textyl");
  82.                       exit(1);
  83.                     }
  84.             break;
  85.  
  86.         case 'p':
  87.         case 's':
  88.         case 'm':
  89.         case 'L':
  90.             break;
  91.  
  92.     default:
  93.         put_msg(Err_badarg, opt, "textyl");
  94.         exit(1);
  95.         break;
  96.     }
  97. }
  98.  
  99. #define            TOP    (10.5)    /* top of page is 10.5 inch */
  100. #define SCALE (65536.0*72.27)
  101. static double        ppi;
  102. static int        CONV = 0;
  103. #define measure 'S'
  104.  
  105. convy(a)
  106. double a;
  107. {
  108.    return (int)(((ury - a) * SCALE) / ppi);
  109. }
  110.  
  111. convx(a)
  112. double a; {
  113.   float f;
  114.   f = a * SCALE;
  115.   return (int)(f / ppi);
  116. }
  117.  
  118. void gentextyl_start(objects)
  119. F_compound    *objects;
  120. {
  121.  
  122.     texfontsizes[0] = texfontsizes[1] = texfontsizes[font_size+1];
  123.     coord_system = objects->nwcorner.y;
  124.     ppi = objects->nwcorner.x;
  125.  
  126.     if (coord_system == 2) CONV = 1;
  127.     /* Textyl start */
  128.     fprintf(tfp, "\\begintyl{%fsp}\n",ury/ppi*SCALE);
  129. }
  130.  
  131. void gentextyl_end()
  132. {
  133.   fprintf(tfp,"\\endtyl\n");
  134. }
  135.  
  136.  
  137. static set_linewidth(w)
  138. int    w;
  139. {
  140. /* Nop */
  141. }
  142.  
  143. void gentextyl_line(l)
  144. F_line    *l;
  145. {
  146.     F_point        *p, *q;
  147.  
  148.     fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n");
  149.  
  150.     set_linewidth(l->thickness);
  151.     set_style(l->style, l->style_val);
  152.  
  153.     p = l->points;
  154.     q = p->next;
  155.         
  156.  
  157.     if (q == NULL) { /* A single point line */
  158.         fprintf(tfp, "\\special{tyl line %c %d L %d %u %u; %u %u}\n", 
  159.                measure,linethick,line_style,
  160.             convx((double)p->x), convy((double)p->y), 
  161.                         convx((double)p->x), convy((double)p->y));
  162.         return;
  163.         }
  164.     if (l->back_arrow)
  165.         draw_arrow_head((double)q->x, (double)q->y, (double)p->x,
  166.         (double)p->y, l->back_arrow->ht, l->back_arrow->wid);
  167.     set_style(l->style, l->style_val);
  168.  
  169.     while (q->next != NULL) {
  170.  
  171.         putline(p->x, p->y, q->x, q->y);
  172.         p = q;
  173.         q = q->next;
  174.         }
  175.  
  176.     putline(p->x, p->y, q->x, q->y);
  177.     if (l->for_arrow)
  178.         draw_arrow_head((double)p->x, (double)p->y, (double)q->x,
  179.         (double)q->y, l->for_arrow->ht, l->for_arrow->wid);
  180.  
  181.     if (l->area_fill && (int)l->area_fill != DEFAULT)
  182.         fprintf(stderr, "Line area fill not implemented\n");
  183.     }
  184.  
  185. /* 
  186.  * set_style - issue style commands as appropriate
  187.  */
  188. static set_style(style, dash_len)
  189.      int style;
  190.      double dash_len;
  191. {
  192.   
  193.   switch (style) {
  194.   case SOLID_LINE:
  195.     line_style = 0;
  196.     break;
  197.     
  198.   case DASH_LINE:
  199.     line_style = 2;
  200.     break;
  201.     
  202.   case DOTTED_LINE:
  203.     line_style = 1;
  204.     break;
  205.   }
  206. }
  207.  
  208. /*
  209.  * putline
  210.  */
  211. static putline (start_x, start_y, end_x, end_y)
  212. int    start_x, start_y, end_x, end_y;
  213. {
  214.  
  215.    fprintf(tfp, "\\special{tyl line %c %d L %d %u %u; %u %u}\n", 
  216.         measure, linethick,line_style,
  217.     convx((double)start_x), convy((double)start_y), 
  218.         convx((double)end_x), convy((double)end_y));
  219.  
  220. }
  221.  
  222.  
  223. void gentextyl_spline(s)
  224. F_spline    *s;
  225. {
  226.  
  227.     set_linewidth(s->thickness);
  228.     set_style(s->style, s->style_val);
  229.  
  230.     if (int_spline(s))
  231.         gentextyl_itp_spline(s);
  232.     else
  233.         gentextyl_ctl_spline(s);
  234.  
  235.     if (s->area_fill && (int)s->area_fill != DEFAULT)
  236.         fprintf(stderr, "Spline area fill not implemented\n");
  237. }
  238.  
  239. void gentextyl_ellipse(e)
  240. F_ellipse    *e;
  241. {
  242.    int sx, sy;
  243.    int radius;
  244.     fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n");
  245.  
  246.     set_linewidth(e->thickness);
  247.     set_style(e->style, e->style_val);
  248.  
  249.     if (e->radiuses.x == e->radiuses.y) {
  250.           fprintf(tfp, "\\special{tyl arc %c %d L 0 %u @ %u,%u 0 360}\n",
  251.             measure,linethick,convx((double)e->radiuses.x),
  252.             convx((double)e->center.x),convy((double)e->center.y));
  253.         }
  254.     else {
  255.           if (e->radiuses.x > e->radiuses.y) {
  256.             sy = 100;
  257.             sx = ((float)e->radiuses.x/(float)e->radiuses.y) * 100.0;
  258.             radius = e->radiuses.y;
  259.           }
  260.           else {
  261.             sx = 100;
  262.             sy = ((float)e->radiuses.y/(float)e->radiuses.x) * 100.0;
  263.             radius = e->radiuses.x;            
  264.           }
  265.                 fprintf(tfp, 
  266.                  "\\special{tyl arc %c T %u %u 0 0 0 %d L 0 %u @ %u,%u 0 360}\n",
  267.                   measure,sx,sy,linethick,convx((double)radius),
  268.             convx((double)e->center.x),convy((double)e->center.y));
  269.         if (e->area_fill && (int)e->area_fill != DEFAULT)
  270.             fprintf(stderr, "Ellipse area fill not implemented\n");
  271.         }
  272.     }
  273.  
  274. #define            HT_OFFSET    (0.2 / 72.0)
  275.  
  276. void gentextyl_text(t)
  277. F_text    *t;
  278. {
  279.     double    x, y;
  280.     char *cp;
  281.  
  282.         fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n");
  283.  
  284.     x = t->base_x;
  285.     y = t->base_y;
  286.  
  287.     switch (t->type) {
  288.  
  289.         case T_LEFT_JUSTIFIED:
  290.         case DEFAULT:
  291.         break;
  292.         default:
  293.         fprintf(stderr, "Warning: Text incorrectly positioned\n");
  294.             break;
  295.         }
  296.  
  297.         fprintf(tfp,"\\special{tyl label %c 1 %u %u \"%s\"}\n",
  298.           measure,convx(x),convy(y),t->cstring);
  299.  
  300. }
  301.  
  302. void gentextyl_arc(a)
  303. F_arc    *a;
  304. {
  305.     double        x, y;
  306.     double        cx, cy, sx, sy, ex, ey;
  307.     double        dx1, dy1, dx2, dy2, r1, r2, th1, th2, theta;
  308.  
  309.     set_linewidth(a->thickness);
  310.     set_style(a->style, a->style_val);
  311.  
  312.     cx = a->center.x; cy = a->center.y;
  313.     sx = a->point[0].x; sy = a->point[0].y;
  314.     ex = a->point[2].x; ey = a->point[2].y;
  315.  
  316.     if (a->for_arrow) {
  317.         arc_tangent(cx, cy, ex, ey, !a->direction, &x, &y);
  318.         draw_arrow_head(x, y, ex, ey,
  319.             a->for_arrow->ht, a->for_arrow->wid);
  320.         }
  321.     if (a->back_arrow) {
  322.         arc_tangent(cx, cy, sx, sy, a->direction, &x, &y);
  323.         draw_arrow_head(x, y, sx, sy,
  324.             a->back_arrow->ht, a->back_arrow->wid);
  325.         }
  326.  
  327.  
  328.     cy = ury - a->center.y;
  329.     sy = ury - a->point[0].y;
  330.     ey = ury - a->point[2].y;
  331.  
  332.     dx1 = sx - cx;
  333.     dy1 = sy - cy;
  334.     dx2 = ex - cx;
  335.     dy2 = ey - cy;
  336.  
  337.     cy = a->center.y;
  338.     sy = a->point[0].y;
  339.     ey = a->point[2].y;
  340.         
  341.     rtop(dx1, dy1, &r1, &th1);
  342.     rtop(dx2, dy2, &r2, &th2);
  343.     theta = th2 - th1;
  344.     if (theta > 0) theta -= 2*M_PI;
  345.  
  346.     set_linewidth(a->thickness);
  347.  
  348.     if (a->direction) { /* Counterclockwise */
  349.               fprintf(tfp,"\\special{tyl arc %c %d L 0 %u @ %u,%u %d %d}\n",
  350.                 measure,linethick,convx(r1),convx(cx),convy(cy),
  351.                 (int)(180/M_PI * th1), (int)(180/M_PI * th2));
  352.           }
  353.     else {
  354.               fprintf(tfp,"\\special{tyl arc %c %d L 0 %u @ %u,%u %d %d}\n",
  355.                 measure,linethick,convx(r1),convx(cx),convy(cy),
  356.                 (int)(180/M_PI * th2), (int)(180/M_PI * th1));
  357.           }
  358.  
  359.     if (a->area_fill && (int)a->area_fill != DEFAULT)
  360.         fprintf(stderr, "Arc area fill not implemented\n");
  361.     }
  362.  
  363.  
  364.  
  365. /*
  366.  * rtop - rectangular to polar conversion
  367.  */
  368. static rtop(x, y, r, th)
  369. double x, y, *r, *th;
  370. {
  371.     *r = sqrt(x*x+y*y);
  372.     *th = acos(x/(*r));
  373.  
  374.     if (y < 0) *th = 2*M_PI - *th;
  375. }
  376.  
  377. static arc_tangent(x1, y1, x2, y2, direction, x, y)
  378. double    x1, y1, x2, y2, *x, *y;
  379. int    direction;
  380. {
  381.     if (direction) { /* counter clockwise  */
  382.         *x = x2 + (y2 - y1);
  383.         *y = y2 - (x2 - x1);
  384.         }
  385.     else {
  386.         *x = x2 - (y2 - y1);
  387.         *y = y2 + (x2 - x1);
  388.         }
  389.     }
  390.  
  391. /*    draw arrow heading from (x1, y1) to (x2, y2)    */
  392.  
  393. static draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
  394. double    x1, y1, x2, y2;
  395. double  arrowht, arrowwid;
  396. {
  397.     double    x, y, xb, yb, dx, dy, l, sina, cosa;
  398.     double    xc, yc, xd, yd;
  399.     int style;
  400.     double dash;
  401.  
  402.     dx = x2 - x1;  dy = y1 - y2;
  403.     l = sqrt(dx*dx+dy*dy);
  404.     if (l == 0) {
  405.          return;
  406.     }
  407.     else {
  408.          sina = dy / l;  cosa = dx / l;
  409.     }
  410.     xb = x2*cosa - y2*sina;
  411.     yb = x2*sina + y2*cosa;
  412.     x = xb - arrowht;
  413.     y = yb - arrowwid / 2;
  414.     xc = x*cosa + y*sina;
  415.     yc = -x*sina + y*cosa;
  416.     y = yb + arrowwid / 2;
  417.     xd = x*cosa + y*sina;
  418.     yd = -x*sina + y*cosa;
  419.  
  420.         fprintf(tfp, "%%\n%% arrow head\n%%\n");
  421.  
  422.     fprintf(tfp, "\\special{tyl line %c %d %u %u; %u %u}\n",measure,linethick,
  423.         convx(xc), convy(yc), convx(x2), convy(y2));
  424.     fprintf(tfp, "\\special{tyl line %c %d %u %u; %u %u}\n",measure,linethick,
  425.                 convx(x2), convy(y2), convx(xd), convy(yd));
  426.  
  427.     }
  428.  
  429. #define THRESHOLD (10.0)
  430. double last_x, last_y;
  431.  
  432. static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  433. double    a1, b1, a2, b2, a3, b3, a4, b4;
  434. {
  435.     double    x1, y1, x4, y4;
  436.     double    xmid, ymid;
  437.  
  438.     x1 = a1; y1 = b1;
  439.     x4 = a4; y4 = b4;
  440.     xmid = (a2 + a3) / 2;
  441.     ymid = (b2 + b3) / 2;
  442.     if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD) {
  443.         fprintf(tfp, "\\special{tyl line %c %d %u %u; %u %u}\n", 
  444.               measure, linethick,convx(last_x),convy(last_y),
  445.               convx(xmid), convy(ymid));
  446.             last_x = xmid; last_y = ymid;
  447.     }
  448.  
  449.     else {
  450.         quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
  451.             ((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
  452.         }
  453.  
  454.     if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
  455.         fprintf(tfp, "\\special{tyl line %c %d %u %u; %u %u}\n", 
  456.               measure, linethick,convx(last_x),convy(last_y),convx(x4), convy(y4));
  457.             last_x = x4; last_y = y4;
  458.     }
  459.  
  460.     else {
  461.         quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
  462.             ((a3+x4)/2), ((b3+y4)/2), x4, y4);
  463.         }
  464.     }
  465.  
  466. static void gentextyl_ctl_spline(s)
  467. F_spline    *s;
  468. {
  469.     F_point    *p;
  470.     double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  471.     double    x1, y1, x2, y2;
  472.  
  473.         fprintf(tfp, "%%\n%% Fig CONTROL PT SPLINE\n%%\n");
  474.  
  475.     p = s->points;
  476.     x1 = p->x;  y1 = p->y;
  477.     p = p->next;
  478.     x2 = p->x;  y2 = p->y;
  479.     cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
  480.     cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  481.  
  482.     if (closed_spline(s)) {
  483.         fprintf(tfp, "%% closed spline\n%%\n");
  484.             last_x = cx1; last_y = cy1;
  485.         }
  486.     else {
  487.         fprintf(tfp, "%% open spline\n%%\n");
  488.         if (s->back_arrow)
  489.             draw_arrow_head(cx1, cy1, x1, y1,
  490.             s->back_arrow->ht, s->back_arrow->wid);
  491.             fprintf(tfp, "\\special{tyl line %c %d %u %u;%u %u}\n",
  492.               measure,linethick,
  493.               convx(x1),convy(y1),convx(cx1),convy(cy1));
  494.             last_x = cx1; last_y = cy1;
  495.         }
  496.  
  497.     for (p = p->next; p != NULL; p = p->next) {
  498.         x1 = x2;  y1 = y2;
  499.         x2 = p->x;  y2 = p->y;
  500.         cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  501.         cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  502.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  503.         cx1 = cx4;  cy1 = cy4;
  504.         cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
  505.         }
  506.     x1 = x2;  y1 = y2;
  507.     p = s->points->next;
  508.     x2 = p->x;  y2 = p->y;
  509.     cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
  510.     cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
  511.     if (closed_spline(s)) {
  512.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  513.         }
  514.     else {
  515.             fprintf(tfp,"\\special{tyl line %c %d %u %u;%u %u}\n",
  516.               measure,linethick,
  517.               convx(cx1),convy(cy1),convx(x1),convy(y1));
  518.         if (s->for_arrow)
  519.             draw_arrow_head(cx1, cy1, x1, y1,
  520.             s->for_arrow->ht, s->for_arrow->wid);
  521.         }
  522.  
  523.     }
  524.  
  525. static void gentextyl_itp_spline(s)
  526. F_spline    *s;
  527. {
  528.   F_point        *p1, *p2;
  529.   F_control    *cp1, *cp2;
  530.   double        x1, x2, y1, y2;
  531.   
  532.   
  533.   p1 = s->points;
  534.   cp1 = s->controls;
  535.   x2 = p1->x; y2 = p1->y;
  536.   
  537.   if (s->back_arrow)
  538.     draw_arrow_head(cp1->rx, cp1->ry, x2, y2,
  539.             s->back_arrow->ht, s->back_arrow->wid);
  540.   
  541.   last_x = x2; last_y = y2;
  542.   
  543.   fprintf(tfp, "%%\n%% Fig INTERPOLATED SPLINE\n%%\n");
  544.   for (p2 = p1->next, cp2 = s->controls->next; 
  545.        p2 != NULL; 
  546.        cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  547.     x1 = x2; y1 = y2; x2 = p2->x; y2 = p2->y;
  548.     bezier_spline(x1,y1,cp1->rx,cp1->ry,
  549.           cp2->lx,cp2->ly,x2,y2);
  550.   }
  551.   
  552.   if (s->for_arrow)
  553.     draw_arrow_head(cp1->lx, cp1->ly, x2, y2,
  554.             s->for_arrow->ht, s->for_arrow->wid);
  555. }
  556.  
  557. static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  558. double    a0, b0, a1, b1, a2, b2, a3, b3;
  559. {
  560.   double    x0, y0, x3, y3;
  561.   double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  562.   
  563.   x0 = a0; y0 = b0;
  564.   x3 = a3; y3 = b3;
  565.   if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD)  {
  566.     fprintf(tfp,"\\special{tyl line %c %d %u %u ; %u %u}\n",measure,linethick,
  567.         convx(last_x),convy(last_y),convx(x3),convy(y3));
  568.     last_x = x3; last_y = y3; 
  569.   }
  570.   
  571.   else {
  572.     tx = (a1 + a2) / 2;        ty = (b1 + b2) / 2;
  573.     sx1 = (x0 + a1) / 2;    sy1 = (y0 + b1) / 2;
  574.     sx2 = (sx1 + tx) / 2;    sy2 = (sy1 + ty) / 2;
  575.     tx2 = (a2 + x3) / 2;    ty2 = (b2 + y3) / 2;
  576.     tx1 = (tx2 + tx) / 2;    ty1 = (ty2 + ty) / 2;
  577.     xmid = (sx2 + tx1) / 2;    ymid = (sy2 + ty1) / 2;
  578.     
  579.     bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  580.     bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  581.   }
  582. }
  583.  
  584. struct driver dev_textyl = {
  585.          gentextyl_option,
  586.     gentextyl_start,
  587.     gentextyl_arc,
  588.     gentextyl_ellipse,
  589.     gentextyl_line,
  590.     gentextyl_spline,
  591.     gentextyl_text,
  592.     gentextyl_end,
  593.     EXCLUDE_TEXT
  594. };
  595.  
  596.