home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / dev / genibmgl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-03  |  25.5 KB  |  1,017 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.  *    genibmgl.c :    IBMGL driver for fig2dev
  26.  *            IBM 6180 Color Plotter with
  27.  *            IBM Graphics Enhancement Cartridge
  28.  *     Author E. Robert Tisdale, University of California, 1/92
  29.  *    (edwin@cs.ucla.edu)
  30.  *
  31.  *        adapted from:
  32.  *
  33.  *    genpictex.c :    PiCTeX driver for fig2dev
  34.  *
  35.  *     Author Micah Beck, Cornell University, 4/88
  36.  *    Color, rotated text and ISO-chars added by Herbert Bauer 11/91
  37. */
  38.  
  39. #if defined(hpux) || defined(SYSV)
  40. #include <sys/types.h>
  41. #endif
  42. #include <sys/file.h>
  43. #ifdef SYSV
  44. #include <string.h>
  45. #else
  46. #include <strings.h>
  47. #endif
  48. #include <stdio.h>
  49. #include <math.h>
  50. #include "object.h"
  51. #include "fig2dev.h"
  52. #include "pi.h"
  53.  
  54. #define        FALSE            0
  55. #define        TRUE            1
  56. #define        FONTS             35
  57. #define        COLORS             8
  58. #define        PATTERNS         21
  59. #define        DPR         180.0/M_PI    /*       degrees/radian    */
  60. #define        DELTA         M_PI/36.0    /* radians        */
  61. #define        DEFAULT_FONT_SIZE    11    /* points        */
  62. #define        POINT_PER_INCH        72.27    /*      points/inch    */
  63. #define        CMPP        254.0/7227.0    /*   centimeters/point    */
  64. #define        UNITS_PER_INCH         1016.0    /* plotter units/inch    */
  65. #define        HEIGHT             7650.0    /* plotter units    */
  66. #define        ISO_A4            10900.0    /* plotter units    */
  67. #define        ANSI_A            10300.0    /* plotter units    */
  68. #define        SPEED_LIMIT        128.0    /* centimeters/second    */
  69.  
  70. #ifdef IBMGEC
  71. static    int    ibmgec         = TRUE;
  72. #else
  73. static    int    ibmgec         = FALSE;
  74. #endif
  75. static    int    portrait     = FALSE;
  76. static    int    reflected     = FALSE;
  77. static    int    fonts         = FONTS;
  78. static    int    colors         = COLORS;
  79. static    int    patterns     = PATTERNS;
  80. static    int    line_color     = DEFAULT;
  81. static    int    line_style     = SOLID_LINE;
  82. static    int    fill_pattern     = DEFAULT;
  83. static    double    dash_length     = DEFAULT;    /* in pixels        */
  84. #ifdef A4
  85. static    double    pagelength     = ISO_A4/UNITS_PER_INCH;
  86. #else
  87. static    double    pagelength     = ANSI_A/UNITS_PER_INCH;
  88. #endif
  89. static    double    pageheight     = HEIGHT/UNITS_PER_INCH;
  90. static    double    pen_speed     = SPEED_LIMIT;
  91. static    double    xz         =  0.0;    /* inches        */
  92. static    double    yz         =  0.0;    /* inches        */
  93. static    double    xl         =  0.0;    /* inches        */
  94. static    double    yl         =  0.0;    /* inches        */
  95. static    double    xu         = 32.25;    /* inches        */
  96. static    double    yu         = 32.25;    /* inches        */
  97.  
  98. static    int    pen_number[]     = { 1, 2, 3, 4, 5, 6, 7, 8, 1};
  99. static    double    pen_thickness[]     = {.3,.3,.3,.3,.3,.3,.3,.3,.3};
  100.  
  101. static    int    line_type[]     =
  102.        {-1, 1, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6,-1,-1,-1,-1,-1,-1,-1,-1};
  103. static    double    line_space[]     =
  104.        {.3,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.5,.3,.3};
  105. static    int    fill_type[]     =
  106.        { 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 1, 2};
  107. static    double    fill_space[]     =
  108.        {.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1};
  109. static    double    fill_angle[]     =
  110.        { 0, 0,-45,0,45,90,-45,0,45,90,-45,0,45,90,-45,0,45,90, 0, 0, 0, 0};
  111.  
  112. static    int    standard[]     = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  113.          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  114. static    int    alternate[]     = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  115.          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
  116. static    double    slant[]         = { 0,10, 0,10, 0,10, 0,10, 0,10, 0,10, 0,10,
  117.          0,10, 0,10, 0,10, 0,10, 0,10, 0,10, 0,10, 0,10, 0,10, 0,10, 0, 0};
  118. static    double    wide[]         = {.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,
  119.         .6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6,.6};
  120. static    double    high[]         = {.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,
  121.         .8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8,.8};
  122.  
  123. static void genibmgl_option(opt, optarg)
  124. char opt, *optarg;
  125. {
  126.     switch (opt) {
  127.  
  128.         case 'a':                /* paper size        */
  129. #ifdef A4
  130.         pagelength     = ANSI_A/UNITS_PER_INCH;
  131. #else
  132.         pagelength     = ISO_A4/UNITS_PER_INCH;
  133. #endif
  134.         break;
  135.  
  136.         case 'c':                /* Graphics Enhancement    */
  137.         ibmgec         = !ibmgec;    /* Cartridge emulation    */
  138.         break;
  139.  
  140.         case 'd':                /* position and window    */
  141.         sscanf(optarg, "%lf,%lf,%lf,%lf", &xl,&yl,&xu,&yu);
  142.                         /* inches        */
  143.         break;
  144.  
  145.         case 'f':                /* user's characters    */
  146.         {
  147.             FILE    *ffp;
  148.             int        font;
  149.             if ((ffp = fopen(optarg, "r")) == NULL)
  150.             fprintf(stderr, "Couldn't open %s\n", optarg);
  151.             else
  152.             for (font = 0; font <= fonts; font++)
  153.                 fscanf(ffp, "%d%d%lf%lf%lf",
  154.                 &standard[font],    /* 0-4 6-9 30-39*/
  155.                 &alternate[font],    /* 0-4 6-9 30-39*/
  156.                 &slant[font],        /*   degrees    */
  157.                 &wide[font],        /*    ~1.0    */
  158.                 &high[font]);        /*    ~1.0    */
  159.             fclose(ffp);
  160.         }
  161.         break;
  162.  
  163.         case 'l':                /* user's fill patterns    */
  164.         {
  165.             FILE    *ffp;
  166.             int        pattern;
  167.             if ((ffp = fopen(optarg, "r")) == NULL)
  168.             fprintf(stderr, "Couldn't open %s\n", optarg);
  169.             else
  170.             for (pattern = 1; pattern <= patterns; pattern++)
  171.                 fscanf(ffp, "%d%lf%d%lf%lf",
  172.                 &line_type[pattern],    /*    -1-6    */
  173.                 &line_space[pattern],    /*   inches    */
  174.                 &fill_type[pattern],    /*     1-5    */
  175.                 &fill_space[pattern],    /*   inches    */
  176.                 &fill_angle[pattern]);    /*   degrees    */
  177.             fclose(ffp);
  178.         }
  179.         break;
  180.  
  181.         case 'L':                /* language        */
  182.         break;
  183.  
  184.         case 'm':                /* magnify and offset    */
  185.         sscanf(optarg, "%lf,%lf,%lf", &mag,&xz,&yz);
  186.                         /* inches        */
  187.         break;
  188.  
  189.         case 'p':                /* user's colors    */
  190.         {
  191.             FILE    *ffp;
  192.             int        color;
  193.             if ((ffp = fopen(optarg, "r")) == NULL)
  194.             fprintf(stderr, "Couldn't open %s\n", optarg);
  195.             else
  196.             for (color = 0; color <= colors; color++)
  197.                 fscanf(ffp, "%d%lf",
  198.                 &pen_number[color],    /*     1-8    */
  199.                 &pen_thickness[color]);    /* millimeters    */
  200.             fclose(ffp);
  201.         }
  202.         break;
  203.  
  204.         case 'P':                /* portrait mode    */
  205.         portrait     = TRUE;
  206.         break;
  207.  
  208.         case 's':                /* set default font size */
  209.         font_size     = atoi(optarg) ?
  210.             atoi(optarg): DEFAULT_FONT_SIZE;
  211.         break;
  212.  
  213.         case 'S':                /* select pen velocity    */
  214.         pen_speed     = atof(optarg);
  215.         break;
  216.  
  217.         case 'v':
  218.         reflected     = TRUE;    /* mirror image        */
  219.         break;
  220.  
  221.         default:
  222.         put_msg(Err_badarg, opt, "ibmgl");
  223.         exit(1);
  224.         break;
  225.     }
  226. }
  227.  
  228. static double        ppi;            /*     pixels/inch    */
  229. static double        cpi;            /*       cent/inch    */
  230. static double        cpp;            /*       cent/pixel    */
  231. static double        wcmpp     = CMPP;    /* centimeter/point    */
  232. static double        hcmpp     = CMPP;    /* centimeter/point    */
  233. static int        flipped     = FALSE;    /* flip Y coordinate    */
  234.  
  235. void genibmgl_start(objects)
  236. F_compound    *objects;
  237. {
  238.     int     P1x, P1y, P2x, P2y;
  239.     int     Xll, Yll, Xur, Yur;
  240.     double    Xmin,Xmax,Ymin,Ymax;
  241.     double    height, length;
  242.  
  243.     if (fabs(mag) < 1.0/2048.0){
  244.         fprintf(stderr, "|mag| < 1/2048\n");
  245.         exit(1);
  246.         }
  247.  
  248.     if (xl < xu)
  249.         if (0.0 < xu)
  250.         if (xl < pagelength) {
  251.             xl     = (0.0 < xl) ? xl: 0.0;
  252.             xu     = (xu < pagelength) ? xu: pagelength;
  253.             }
  254.         else {
  255.             fprintf(stderr, "xll >= %.2f\n", pagelength);
  256.             exit(1);
  257.             }
  258.         else {
  259.         fprintf(stderr, "xur <= 0.0\n");
  260.         exit(1);
  261.         }
  262.     else {
  263.         fprintf(stderr, "xur <= xll\n");
  264.         exit(1);
  265.         }
  266.  
  267.     if (yl < yu)
  268.         if (0.0 < yu)
  269.         if (yl < pageheight) {
  270.             yl     = (0.0 < yl) ? yl: 0.0;
  271.             yu     = (yu < pageheight) ? yu: pageheight;
  272.             }
  273.         else {
  274.             fprintf(stderr, "yll >= %.2f\n", pageheight);
  275.             exit(1);
  276.             }
  277.         else {
  278.         fprintf(stderr, "yur <= 0.0\n");
  279.         exit(1);
  280.         }
  281.     else {
  282.         fprintf(stderr, "yur <= yll\n");
  283.         exit(1);
  284.         }
  285.  
  286.     ppi     = objects->nwcorner.x;
  287.     cpi     = mag*100.0/sqrt((xu-xl)*(xu-xl) + (yu-yl)*(yu-yl));
  288.     cpp     = cpi/ppi;
  289.     if (objects->nwcorner.y == 2)
  290.         flipped     = TRUE;
  291.  
  292.     /* IBMGL start */
  293.     fprintf(tfp, "IN;\n");            /* initialize plotter    */
  294.  
  295.     if (portrait) {                /* portrait mode    */
  296.         fprintf(tfp, "RO90;\n");        /* rotate 90 degrees    */
  297.         Xll     = yl*UNITS_PER_INCH;
  298.         Xur     = yu*UNITS_PER_INCH;
  299.         Yll     = (pagelength - xu)*UNITS_PER_INCH;
  300.         Yur     = (pagelength - xl)*UNITS_PER_INCH;
  301.         length     = yu - yl;
  302.         height     = xu - xl;
  303.         P1x          = Xll;
  304.         P2x         = Xur;
  305.         if (reflected)            /* upside-down text    */
  306.         hcmpp     = -hcmpp;
  307.         if (reflected^flipped) {        /* reflected or flipped */
  308.         P1y     = Yur;            /* but not both        */
  309.         P2y     = Yll;
  310.         }
  311.         else {                /* normal        */
  312.         P1y     = Yll;
  313.         P2y     = Yur;
  314.         }
  315.         Xmin     =  xz;
  316.         Xmax     =  xz + (yu - yl)/mag;
  317.         Ymin     =  yz;
  318.         Ymax     =  yz + (xu - xl)/mag;
  319.         }
  320.     else {                    /* landscape mode    */
  321.         Xll     = xl*UNITS_PER_INCH;
  322.         Yll     = yl*UNITS_PER_INCH;
  323.         Yur     = yu*UNITS_PER_INCH;
  324.         Xur     = xu*UNITS_PER_INCH;
  325.         length     = xu - xl;
  326.         height     = yu - yl;
  327.         if (reflected) {            /* flipped   or not    */
  328.         wcmpp     = -wcmpp;        /* backward text    */
  329.         P1x     = Xur;
  330.         P2x     = Xll;
  331.         }
  332.         else {                /* normal        */
  333.         P1x     = Xll;
  334.         P2x     = Xur;
  335.         }
  336.         if (flipped) {            /* reflected or not    */
  337.         P1y     = Yur;
  338.         P2y     = Yll;
  339.         }
  340.         else {
  341.         P1y      = Yll;
  342.         P2y      = Yur;
  343.         }
  344.         }
  345.  
  346.     Xmin     = xz;
  347.     Ymin     = yz;
  348.     Xmax     = xz + length/mag;
  349.     Ymax     = yz + height/mag;
  350.  
  351.     fprintf(tfp, "IP%d,%d,%d,%d;\n",
  352.         P1x, P1y, P2x, P2y);
  353.     fprintf(tfp, "IW%d,%d,%d,%d;\n",
  354.         Xll, Yll, Xur, Yur);
  355.     fprintf(tfp, "SC%.4f,%.4f,%.4f,%.4f;\n",
  356.         Xmin,Xmax,Ymin,Ymax);
  357.     if (0.0 < pen_speed && pen_speed < SPEED_LIMIT)
  358.         fprintf(tfp, "VS%.2f;\n", pen_speed);
  359. }
  360.  
  361. static arc_tangent(x1, y1, x2, y2, direction, x, y)
  362. double    x1, y1, x2, y2, *x, *y;
  363. int    direction;
  364. {
  365.     if (direction) { /* counter clockwise  */
  366.         *x = x2 - (y2 - y1);
  367.         *y = y2 + (x2 - x1);
  368.         }
  369.     else {
  370.         *x = x2 + (y2 - y1);
  371.         *y = y2 - (x2 - x1);
  372.         }
  373.     }
  374.  
  375. /*    draw arrow heading from (x1, y1) to (x2, y2)    */
  376.  
  377. static draw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
  378. double    x1, y1, x2, y2, arrowht, arrowwid;
  379. {
  380.     double    x, y, xb, yb, dx, dy, l, sina, cosa;
  381.     double    xc, yc, xd, yd;
  382.     int style;
  383.     double length;
  384.  
  385.     dx     = x2 - x1;
  386.     dy     = y1 - y2;
  387.     l     = sqrt(dx*dx+dy*dy);
  388.     sina     = dy/l;
  389.     cosa     = dx/l;
  390.     xb     = x2*cosa - y2*sina;
  391.     yb     = x2*sina + y2*cosa;
  392.     x     = xb - arrowht;
  393.     y     = yb - arrowwid/2.0;
  394.     xc     =  x*cosa + y*sina;
  395.     yc     = -x*sina + y*cosa;
  396.     y     = yb + arrowwid/2.0;
  397.     xd     =  x*cosa + y*sina;
  398.     yd     = -x*sina + y*cosa;
  399.  
  400.     /* save line style and set to solid */
  401.     style     = line_style;
  402.     length     = dash_length;
  403.     set_style(SOLID_LINE, 0.0);
  404.  
  405.     fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f,%.4f,%.4f;PU\n",
  406.         xc, yc, x2, y2, xd, yd);
  407.  
  408.     /* restore line style */
  409.     set_style(style, length);
  410.     }
  411.  
  412. /* 
  413.  * set_style - issue line style commands as appropriate
  414.  */
  415. static set_style(style, length)
  416. int    style;
  417. double    length;
  418. {
  419.     if (style == line_style)
  420.         switch (line_style) {
  421.         case SOLID_LINE:
  422.             break;
  423.  
  424.         case DASH_LINE:
  425.             if (dash_length != length && length > 0.0) {
  426.             dash_length  = length;
  427.             fprintf(tfp, "LT2,%.4f;\n", dash_length*2.0*cpp);
  428.             }
  429.             break;
  430.  
  431.         case DOTTED_LINE:
  432.             if (dash_length != length && length > 0.0) {
  433.             dash_length  = length;
  434.             fprintf(tfp, "LT1,%.4f;\n", dash_length*2.0*cpp);
  435.             }
  436.             break;
  437.         }
  438.     else {
  439.         line_style = style;
  440.         switch (line_style) {
  441.         case SOLID_LINE:
  442.             fprintf(tfp, "LT;\n");
  443.             break;
  444.  
  445.         case DASH_LINE:
  446.             if (dash_length != length && length > 0.0)
  447.             dash_length  = length;
  448.             if (dash_length > 0.0)
  449.             fprintf(tfp, "LT2,%.4f;\n", dash_length*2.0*cpp);
  450.             else
  451.             fprintf(tfp, "LT2,-1.0;\n");
  452.             break;
  453.  
  454.         case DOTTED_LINE:
  455.             if (dash_length != length && length > 0.0)
  456.             dash_length  = length;
  457.             if (dash_length > 0.0)
  458.             fprintf(tfp, "LT1,%.4f;\n", dash_length*2.0*cpp);
  459.             else
  460.             fprintf(tfp, "LT1,-1.0;\n");
  461.             break;
  462.         }
  463.         }
  464.     }
  465.  
  466. /* 
  467.  * set_width - issue line width commands as appropriate
  468.  */
  469. static set_width(w)
  470. int    w;
  471. {
  472. static    int    line_width     = DEFAULT;    /* in pixels         */
  473.     line_width  = w;
  474.     }
  475.  
  476. /* 
  477.  * set_color - issue line color commands as appropriate
  478.  */
  479. static set_color(color)
  480. int    color;
  481. {
  482. static    int    number         = 0;    /* 1 <= number <= 8        */
  483. static    double    thickness     = 0.3;    /* pen thickness in millimeters    */
  484.     if (line_color != color) {
  485.         line_color  = color;
  486.         color    = (colors + color)%colors;
  487.         if (number != pen_number[color]) {
  488.         number  = pen_number[color];
  489.         fprintf(tfp, "SP%d;\n", pen_number[color]);
  490.         }
  491.         if (thickness != pen_thickness[color]) {
  492.         thickness  = pen_thickness[color];
  493.         fprintf(tfp, "PT%.4f;\n", pen_thickness[color]);
  494.         }
  495.         }
  496.     }
  497.  
  498. static fill_polygon(pattern)
  499. int    pattern;
  500. {
  501.     if (1 < pattern && pattern <= patterns) {
  502.         int        style;
  503.         double    length;
  504.         if (fill_pattern != pattern) {
  505.         fill_pattern  = pattern;
  506.         fprintf(tfp, "FT%d,%.4f,%.4f;", fill_type[pattern],
  507.             fill_space[pattern],
  508.             reflected ? -fill_angle[pattern]: fill_angle[pattern]);
  509.         }
  510.         /*    save line style */
  511.         style     = line_style;
  512.         length     = dash_length;
  513.         fprintf(tfp, "LT%d,%.4f;FP;\n",
  514.             line_type[pattern], line_space[pattern]*cpi);
  515.         /* restore line style */
  516.         line_style     = DEFAULT;
  517.         dash_length     = DEFAULT;
  518.         set_style(style, length);
  519.         }
  520.     }
  521.     
  522. void arc(sx, sy, cx, cy, theta, delta)
  523. double    sx, sy, cx, cy, theta, delta;
  524. {
  525.     if (ibmgec)
  526.         if (delta == M_PI/36.0)        /* 5 degrees        */
  527.         fprintf(tfp, "AA%.4f,%.4f,%.4f;",
  528.             cx, cy, theta*DPR);
  529.         else
  530.         fprintf(tfp, "AA%.4f,%.4f,%.4f,%.4f;",
  531.             cx, cy, theta*DPR, delta*DPR);
  532.     else {
  533.         double    alpha;
  534.         if (theta < 0.0)
  535.         delta = -fabs(delta);
  536.         else
  537.         delta = fabs(delta);
  538.         for (alpha = delta; fabs(alpha) < fabs(theta); alpha += delta) {
  539.         fprintf(tfp, "PA%.4f,%.4f;\n",
  540.                 cx + (sx - cx)*cos(alpha) - (sy - cy)*sin(alpha),
  541.                 cy + (sy - cy)*cos(alpha) + (sx - cx)*sin(alpha));
  542.         }
  543.         fprintf(tfp, "PA%.4f,%.4f;\n",
  544.                 cx + (sx - cx)*cos(theta) - (sy - cy)*sin(theta),
  545.                 cy + (sy - cy)*cos(theta) + (sx - cx)*sin(theta));
  546.         }
  547.     }
  548.  
  549. void genibmgl_arc(a)
  550. F_arc    *a;
  551. {
  552.     if (a->thickness != 0 ||
  553.         ibmgec && 1 <= a->area_fill && a->area_fill <= patterns) {
  554.         double    x, y;
  555.         double    cx, cy, sx, sy, ex, ey;
  556.         double    dx1, dy1, dx2, dy2, theta;
  557.  
  558.         set_style(a->style, a->style_val);
  559.         set_width(a->thickness);
  560.         set_color(a->color);
  561.  
  562.         cx         = a->center.x/ppi;
  563.         cy         = a->center.y/ppi;
  564.         sx         = a->point[0].x/ppi;
  565.         sy         = a->point[0].y/ppi;
  566.         ex         = a->point[2].x/ppi;
  567.         ey         = a->point[2].y/ppi;
  568.  
  569.         dx1         = sx - cx;
  570.         dy1         = sy - cy;
  571.         dx2         = ex - cx;
  572.         dy2         = ey - cy;
  573.         
  574.         theta     = atan2(dy2, dx2) - atan2(dy1, dx1);
  575.         if (a->direction^flipped) {
  576.         if (theta < 0.0)
  577.             theta    += 2.0*M_PI;
  578.         }
  579.         else {
  580.         if (theta > 0.0)
  581.             theta    -= 2.0*M_PI;
  582.         }
  583.  
  584.         if (a->thickness != 0 && a->back_arrow) {
  585.         arc_tangent(cx, cy, sx, sy, a->direction^flipped, &x, &y);
  586.         draw_arrow_head(x, y, sx, sy,
  587.         a->back_arrow->ht/ppi, a->back_arrow->wid/ppi);
  588.         }
  589.  
  590.         fprintf(tfp, "PA%.4f,%.4f;PM;PD;", sx, sy);
  591.         arc(sx, sy, cx, cy, theta, DELTA);
  592.         fprintf(tfp, "PU;PM2;\n");
  593.  
  594.         if (a->thickness != 0)
  595.         fprintf(tfp, "EP;\n");
  596.  
  597.         if (a->thickness != 0 && a->for_arrow) {
  598.         arc_tangent(cx, cy, ex, ey, !a->direction^flipped, &x, &y);
  599.         draw_arrow_head(x, y, ex, ey,
  600.             a->for_arrow->ht/ppi, a->for_arrow->wid/ppi);
  601.         }
  602.  
  603.         if (1 < a->area_fill && a->area_fill <= patterns)
  604.         fill_polygon(a->area_fill);
  605.         }
  606.     }
  607.  
  608. void genibmgl_ellipse(e)
  609. F_ellipse    *e;
  610. {
  611.     if (e->thickness != 0 ||
  612.         ibmgec && 1 <= e->area_fill && e->area_fill <= patterns) {
  613.         int        j;
  614.         double    alpha     = 0.0;
  615.         double    angle;
  616.         double    delta;
  617.         double    x0, y0;
  618.         double    a,  b;
  619.         double    x,  y;
  620.  
  621.         set_style(e->style, e->style_val);
  622.         set_width(e->thickness);
  623.         set_color(e->color);
  624.  
  625.         a         = e->radiuses.x/ppi;
  626.         b         = e->radiuses.y/ppi;
  627.         x0         = e->center.x/ppi;
  628.         y0         = e->center.y/ppi;
  629.         angle     = (flipped ? -e->angle: e->angle);
  630.         delta     = (flipped ? -DELTA: DELTA);
  631.  
  632.         x         = x0 + cos(angle)*a;
  633.         y         = y0 + sin(angle)*a;
  634.         fprintf(tfp, "PA%.4f,%.4f;PM;PD;\n", x, y);
  635.         for (j = 1; j <= 72; j++) { alpha     = j*delta;
  636.         x     = x0 + cos(angle)*a*cos(alpha)
  637.                  - sin(angle)*b*sin(alpha);
  638.         y     = y0 + sin(angle)*a*cos(alpha)
  639.                  + cos(angle)*b*sin(alpha);
  640.         fprintf(tfp, "PA%.4f,%.4f;\n", x, y);
  641.         }
  642.         fprintf(tfp, "PU;PM2;\n");
  643.  
  644.         if (e->thickness != 0)
  645.         fprintf(tfp, "EP;\n");
  646.  
  647.         if (1 < e->area_fill && e->area_fill <= patterns)
  648.         fill_polygon((int)e->area_fill);
  649.         }
  650.     }
  651.  
  652. void swap(i, j)
  653. int    *i, *j;
  654. {    int    t; t = *i; *i = *j; *j = t; }
  655.  
  656. void genibmgl_line(l)
  657. F_line    *l;
  658. {
  659.     if (l->thickness != 0 ||
  660.         ibmgec && 1 <= l->area_fill && l->area_fill <= patterns) {
  661.         F_point    *p, *q;
  662.  
  663.         set_style(l->style, l->style_val);
  664.         set_width(l->thickness);
  665.         set_color(l->color);
  666.  
  667.         p     = l->points;
  668.         q     = p->next;
  669.  
  670.         switch (l->type) {
  671.         case    T_POLYLINE:
  672.         case    T_BOX:
  673.         case    T_POLYGON:
  674.             if (q == NULL)        /* A single point line */
  675.             fprintf(tfp, "PA%.4f,%.4f;PD;PU;\n",
  676.                 p->x/ppi, p->y/ppi);
  677.             else {
  678.             if (l->thickness != 0 && l->back_arrow)
  679.                 draw_arrow_head(q->x/ppi, q->y/ppi,
  680.                         p->x/ppi, p->y/ppi,
  681.                     l->back_arrow->ht/ppi,
  682.                     l->back_arrow->wid/ppi);
  683.  
  684.             fprintf(tfp, "PA%.4f,%.4f;PM;PD%.4f,%.4f;\n",
  685.                 p->x/ppi, p->y/ppi,
  686.                 q->x/ppi, q->y/ppi);
  687.             while (q->next != NULL) {
  688.                 p     = q;
  689.                 q     = q->next;
  690.                 fprintf(tfp, "PA%.4f,%.4f;\n",
  691.                     q->x/ppi, q->y/ppi);
  692.                 }
  693.             fprintf(tfp, "PU;PM2;\n");
  694.  
  695.             if (l->thickness != 0)
  696.                 fprintf(tfp, "EP;\n");
  697.  
  698.             if (l->thickness != 0 && l->for_arrow)
  699.                     draw_arrow_head(p->x/ppi, p->y/ppi,
  700.                     q->x/ppi, q->y/ppi,
  701.                     l->for_arrow->ht/ppi,
  702.                     l->for_arrow->wid/ppi);
  703.  
  704.             if (1 < l->area_fill && l->area_fill <= patterns)
  705.                 fill_polygon((int)l->area_fill);
  706.             }
  707.             break;
  708.  
  709.         case    T_ARC_BOX: {
  710.             int        llx, lly, urx, ury;
  711.             double     x0,  y0,  x1,  y1;
  712.             double    dx, dy, angle;
  713.  
  714.             llx     = urx    = p->x;
  715.             lly     = ury    = p->y;
  716.             while ((p = p->next) != NULL) {
  717.             if (llx > p->x)
  718.                 llx = p->x;
  719.             if (urx < p->x)
  720.                 urx = p->x;
  721.             if (lly > p->y)
  722.                 lly = p->y;
  723.             if (ury < p->y)
  724.                 ury = p->y;
  725.             }
  726.  
  727.             x0     = llx/ppi;
  728.             x1     = urx/ppi;
  729.             dx     = l->radius/ppi;
  730.             if (flipped) {
  731.             y0     = ury/ppi;
  732.             y1     = lly/ppi;
  733.             dy     = -dx;
  734.             angle     = -M_PI/2.0;
  735.             }
  736.             else {
  737.             y0     = lly/ppi;
  738.             y1     = ury/ppi;
  739.             dy     =  dx;
  740.             angle     =  M_PI/2.0;
  741.             }
  742.  
  743.             fprintf(tfp, "PA%.4f,%.4f;PM;PD;\n",  x0, y0 + dy);
  744.             arc(x0, y0 + dy, x0 + dx, y0 + dy, angle, DELTA);
  745.             fprintf(tfp, "PA%.4f,%.4f;\n", x1 - dx, y0);
  746.             arc(x1 - dx, y0, x1 - dx, y0 + dy, angle, DELTA);
  747.             fprintf(tfp, "PA%.4f,%.4f;\n", x1, y1 - dy);
  748.             arc(x1, y1 - dy, x1 - dx, y1 - dy, angle, DELTA);
  749.             fprintf(tfp, "PA%.4f,%.4f;\n", x0 + dx, y1);
  750.             arc(x0 + dx, y1, x0 + dx, y1 - dy, angle, DELTA);
  751.             fprintf(tfp, "PA%.4f,%.4f;PU;PM2;\n", x0, y0 + dy);
  752.  
  753.             if (l->thickness != 0)
  754.             fprintf(tfp, "EP;\n");
  755.  
  756.             if (1 < l->area_fill && l->area_fill <= patterns)
  757.             fill_polygon((int)l->area_fill);
  758.             }
  759.             break;
  760.  
  761.         case    T_EPS_BOX:
  762.             break;
  763.         }
  764.         }
  765.     }
  766.  
  767. #define        THRESHOLD    .05    /* inch */
  768.  
  769. static bezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
  770. double    a0, b0, a1, b1, a2, b2, a3, b3;
  771. {
  772.     double    x0, y0, x3, y3;
  773.     double    sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
  774.  
  775.     x0 = a0; y0 = b0;
  776.     x3 = a3; y3 = b3;
  777.     if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD)
  778.         fprintf(tfp, "PA%.4f,%.4f;\n", x3, y3);
  779.  
  780.     else {
  781.         tx   = (a1  + a2 )/2.0;    ty   = (b1  + b2 )/2.0;
  782.         sx1  = (x0  + a1 )/2.0;    sy1  = (y0  + b1 )/2.0;
  783.         sx2  = (sx1 + tx )/2.0;    sy2  = (sy1 + ty )/2.0;
  784.         tx2  = (a2  + x3 )/2.0;    ty2  = (b2  + y3 )/2.0;
  785.         tx1  = (tx2 + tx )/2.0;    ty1  = (ty2 + ty )/2.0;
  786.         xmid = (sx2 + tx1)/2.0;    ymid = (sy2 + ty1)/2.0;
  787.  
  788.         bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
  789.         bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
  790.         }
  791.     }
  792.  
  793. static void genibmgl_itp_spline(s)
  794. F_spline    *s;
  795. {
  796.     F_point        *p1, *p2;
  797.     F_control    *cp1, *cp2;
  798.     double        x1, x2, y1, y2;
  799.  
  800.     p1 = s->points;
  801.     cp1 = s->controls;
  802.     x2 = p1->x/ppi; y2 = p1->y/ppi;
  803.  
  804.     if (s->thickness != 0 && s->back_arrow)
  805.         draw_arrow_head(cp1->rx/ppi, cp1->ry/ppi, x2, y2,
  806.             s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
  807.  
  808.     fprintf(tfp, "PA%.4f,%.4f;PD;\n", x2, y2);
  809.     for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
  810.         p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
  811.         x1     = x2;
  812.         y1     = y2;
  813.         x2     = p2->x/ppi;
  814.         y2     = p2->y/ppi;
  815.         bezier_spline(x1, y1, (double)cp1->rx/ppi, cp1->ry/ppi,
  816.         (double)cp2->lx/ppi, cp2->ly/ppi, x2, y2);
  817.         }
  818.     fprintf(tfp, "PU;\n");
  819.  
  820.     if (s->thickness != 0 && s->for_arrow)
  821.         draw_arrow_head(cp1->lx/ppi, cp1->ly/ppi, x2, y2,
  822.             s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
  823.     }
  824.  
  825. static quadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
  826. double    a1, b1, a2, b2, a3, b3, a4, b4;
  827. {
  828.     double    x1, y1, x4, y4;
  829.     double    xmid, ymid;
  830.  
  831.     x1     = a1; y1 = b1;
  832.     x4     = a4; y4 = b4;
  833.     xmid     = (a2 + a3)/2.0;
  834.     ymid     = (b2 + b3)/2.0;
  835.     if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD)
  836.         fprintf(tfp, "PA%.4f,%.4f;\n", xmid, ymid);
  837.     else {
  838.         quadratic_spline(x1, y1, ((x1+a2)/2.0), ((y1+b2)/2.0),
  839.         ((3.0*a2+a3)/4.0), ((3.0*b2+b3)/4.0), xmid, ymid);
  840.         }
  841.  
  842.     if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD)
  843.         fprintf(tfp, "PA%.4f,%.4f;\n", x4, y4);
  844.     else {
  845.         quadratic_spline(xmid, ymid, ((a2+3.0*a3)/4.0), ((b2+3.0*b3)/4.0),
  846.             ((a3+x4)/2.0), ((b3+y4)/2.0), x4, y4);
  847.         }
  848.     }
  849.  
  850. static void genibmgl_ctl_spline(s)
  851. F_spline    *s;
  852. {
  853.     F_point    *p;
  854.     double    cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  855.     double    x1, y1, x2, y2;
  856.  
  857.     p     = s->points;
  858.     x1     = p->x/ppi;
  859.     y1     = p->y/ppi;
  860.     p     = p->next;
  861.     x2     = p->x/ppi;
  862.     y2     = p->y/ppi;
  863.     cx1     = (x1 + x2)/2.0;
  864.     cy1     = (y1 + y2)/2.0;
  865.     cx2     = (x1 + 3.0*x2)/4.0;
  866.     cy2     = (y1 + 3.0*y2)/4.0;
  867.  
  868.     if (closed_spline(s))
  869.         fprintf(tfp, "PA%.4f,%.4f;PD;\n ", cx1, cy1);
  870.     else {
  871.         if (s->thickness != 0 && s->back_arrow)
  872.         draw_arrow_head(cx1, cy1, x1, y1,
  873.             s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
  874.         fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n",
  875.             x1, y1, cx1, cy1);
  876.         }
  877.  
  878.     for (p = p->next; p != NULL; p = p->next) {
  879.         x1     = x2;
  880.         y1     = y2;
  881.         x2     = p->x/ppi;
  882.         y2     = p->y/ppi;
  883.         cx3     = (3.0*x1 + x2)/4.0;
  884.         cy3     = (3.0*y1 + y2)/4.0;
  885.         cx4     = (x1 + x2)/2.0;
  886.         cy4     = (y1 + y2)/2.0;
  887.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  888.         cx1     = cx4;
  889.         cy1     = cy4;
  890.         cx2     = (x1 + 3.0*x2)/4.0;
  891.         cy2     = (y1 + 3.0*y2)/4.0;
  892.         }
  893.     x1     = x2; 
  894.     y1     = y2;
  895.     p     = s->points->next;
  896.     x2     = p->x/ppi;
  897.     y2     = p->y/ppi;
  898.     cx3     = (3.0*x1 + x2)/4.0;
  899.     cy3     = (3.0*y1 + y2)/4.0;
  900.     cx4     = (x1 + x2)/2.0;
  901.     cy4     = (y1 + y2)/2.0;
  902.     if (closed_spline(s)) {
  903.         quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  904.         fprintf(tfp, "PU;\n");
  905.         }
  906.     else {
  907.         fprintf(tfp, "PA%.4f,%.4f;PU;\n", x1, y1);
  908.         if (s->thickness != 0 && s->for_arrow)
  909.             draw_arrow_head(cx1, cy1, x1, y1,
  910.             s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
  911.         }
  912.     }
  913.  
  914. void genibmgl_spline(s)
  915. F_spline    *s;
  916. {
  917.     if (s->thickness != 0) {
  918.         set_style(s->style, s->style_val);
  919.         set_width(s->thickness);
  920.         set_color(s->color);
  921.  
  922.         if (int_spline(s))
  923.         genibmgl_itp_spline(s);
  924.         else
  925.         genibmgl_ctl_spline(s);
  926.  
  927.         }
  928.     if (1 < s->area_fill && s->area_fill <= patterns)
  929.         fprintf(stderr, "Spline area fill not implemented\n");
  930. }
  931.  
  932. #define    FONT(T) ((-1 < (T) && (T) < fonts) ? (T): fonts)
  933. void genibmgl_text(t)
  934. F_text    *t;
  935. {
  936. static    int    font     = DEFAULT;    /* font                */
  937. static    int    size     = DEFAULT;    /* font size        in points    */
  938. static    int    rigid     = 0;        /* rigid text            */
  939. static    int    cs     = 0;        /* standard  character set    */
  940. static    int    ca     = 0;        /* alternate character set    */
  941. static    double    theta     = 0.0;        /* character slant  in degrees    */
  942. static    double    angle     = 0.0;        /* label direction  in radians    */
  943.     double    width;            /* character width  in centimeters */
  944.     double    height;            /* character height in centimeters */
  945.  
  946.     if (font != FONT(t->font)) {
  947.         font  = FONT(t->font);
  948.         if (cs != standard[font]) {
  949.         cs  = standard[font];
  950.         fprintf(tfp, "CS%d;", cs);
  951.         }
  952.         if (ca != alternate[font]) {
  953.         ca  = alternate[font];
  954.         fprintf(tfp, "CA%d;", ca);
  955.         }
  956.         if (theta != slant[font]) {
  957.         theta  = slant[font];
  958.         fprintf(tfp, "SL%.4f;", tan(theta*M_PI/180.0));
  959.         }
  960.         }
  961.     if (size != t->size || rigid != t->flags&RIGID_TEXT) {
  962.         size  = t->size ? t->size: font_size;
  963.         rigid  = (t->flags&RIGID_TEXT);
  964.         width     = size*wcmpp*wide[font];
  965.         height     = size*hcmpp*high[font];
  966.         rigid     = (t->flags&RIGID_TEXT);
  967.         if (rigid)
  968.         fprintf(tfp, "SI%.4f,%.4f;", width, height);
  969.         else
  970.         fprintf(tfp, "SI%.4f,%.4f;", width*mag, height*mag);
  971.         }
  972.     if (angle != t->angle) {
  973.         angle  = t->angle;
  974.         fprintf(tfp, "DI%.4f,%.4f;",
  975.             cos(angle), sin(reflected ? -angle: angle));
  976.         }
  977.     set_color(t->color);
  978.  
  979.     fprintf(tfp, "PA%.4f,%.4f;\n",
  980.         t->base_x/ppi, t->base_y/ppi);
  981.  
  982.     switch (t->type) {
  983.         case DEFAULT:
  984.         case T_LEFT_JUSTIFIED:
  985.         break;
  986.         case T_CENTER_JUSTIFIED:
  987.         fprintf(tfp, "CP%.4f,0.0;", -(double)(strlen(t->cstring)/2.0));
  988.         break;
  989.         case T_RIGHT_JUSTIFIED:
  990.         fprintf(tfp, "CP%.4f,0.0;", -(double)(strlen(t->cstring)));
  991.         break;
  992.         default:
  993.         fprintf(stderr, "unknown text position type\n");
  994.         exit(1);
  995.         }    
  996.  
  997.     fprintf(tfp, "LB%s\003\n", t->cstring);
  998.     }
  999.  
  1000. void genibmgl_end()
  1001. {
  1002.     /* IBMGL ending */
  1003.     fprintf(tfp, "PU;SP;IN;\n");
  1004. }
  1005.  
  1006. struct driver dev_ibmgl = {
  1007.          genibmgl_option,
  1008.     genibmgl_start,
  1009.     genibmgl_arc,
  1010.     genibmgl_ellipse,
  1011.     genibmgl_line,
  1012.     genibmgl_spline,
  1013.     genibmgl_text,
  1014.     genibmgl_end,
  1015.     EXCLUDE_TEXT
  1016.     };
  1017.