home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fonts 1 / freshfonts1.bin / programs / amiga / pastex / pastex14-beta-6 / specialhost / source / tpic.c < prev    next >
C/C++ Source or Header  |  1994-05-27  |  8KB  |  383 lines

  1. /*
  2. **    SpecialHost for PasTeX
  3. **
  4. **    Copyright © by Olaf Barthel & Georg Heßmann
  5. */
  6.  
  7. #include "Global.h"
  8.  
  9. /** tpic.c **/
  10.  
  11.  
  12. static void flushPath    (int invis);
  13. static void flushDashed     (int dotted);
  14. static void flushSpline     (void);
  15. static void arc         (int invis);
  16.  
  17. static void dot_at       (int x, int y);
  18. static void line_btw     (int x0, int y0, int x1, int y1);
  19. static void draw_ellipse (int xc, int yc, int xr, int yr);
  20.  
  21.  
  22. struct tpic_msg   *tp;
  23. struct driver_map *dm;
  24.  
  25. long hres, vres;
  26. long path_len;
  27.  
  28. #define xRESOLUTION    hres
  29. #define yRESOLUTION    vres
  30.  
  31. struct bitmap     map;
  32. long          upper_limit;
  33. long          lower_limit;
  34.  
  35.  
  36.  
  37.  
  38. /*
  39.  * APPROXIMATE integer distance between two points
  40.  */
  41. #define    dist(x0, y0, x1, y1)    (abs(x0-x1)+abs(y0-y1))
  42.  
  43. #define    TWOPI        (3.14159265359*2.0)
  44.  
  45. #define xCONV_PT(x) \
  46.   ((x) < 0 ? -((-(x) * hres + 500) / 1000) \
  47.        : (((x) * hres + 500) / 1000) )
  48. #define yCONV_PT(y) \
  49.   ((y) < 0 ? -((-(y) * vres + 500) / 1000) \
  50.        : (((y) * vres + 500) / 1000) )
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57. void work_with_tpic(struct tpic_msg *tpic, struct driver_map *dmap,
  58.             long hresolution, long vresolution)
  59. {
  60.   tp = tpic;
  61.   dm = dmap;
  62.  
  63.   hres = hresolution;
  64.   vres = vresolution;
  65.   path_len = tp->path_len;
  66.   
  67.   /* Initialisierung fuer 'graphics.c' */
  68.   map.width  = dm->width;
  69.   map.height = dm->height;
  70.   map.pixptr = dm->pixptr;
  71.   upper_limit = dm->upper_limit;
  72.   lower_limit = dm->lower_limit;
  73.  
  74.   device_SetPenSize(xCONV_PT(tpic->pen_size), yCONV_PT(tpic->pen_size));
  75.  
  76.   switch (tpic->tpic_com) {
  77.     case TPIC_FP:
  78.     flushPath(FALSE);
  79.     case TPIC_IP:
  80.     flushPath(TRUE);
  81.     break;
  82.     case TPIC_DA:
  83.     flushDashed(FALSE);
  84.     break;
  85.     case TPIC_DT:
  86.     flushDashed(TRUE);
  87.     break;
  88.     case TPIC_SP:
  89.     case TPIC_SPB:
  90.     flushSpline();
  91.     break;
  92.     case TPIC_AR:
  93.     arc(FALSE);
  94.     break;
  95.     case TPIC_IA:
  96.     arc(TRUE);
  97.     break;
  98.     default:
  99.     break;
  100.   }
  101. }
  102.  
  103.  
  104.  
  105. /*----------------------------------------------------------------*/
  106.  
  107.  
  108. static void flushPath(int invis)
  109. {
  110.   int i, x, y;
  111.  
  112.   if (tp->path_len == 1) {
  113.     PrintLine("FP/IP path with less than 2 points ignored");
  114.   }
  115.   else {
  116.     if (invis) {
  117.       /* not jet implemented */
  118.       ;
  119.     }
  120.     else {
  121.       x = dm->x;
  122.       y = dm->y;
  123.       for (i=1; i<tp->path_len; i++) {
  124.         device_DrawLine(
  125.           x + xCONV_PT(tp->xx[i]), y + yCONV_PT(tp->yy[i]),
  126.           x + xCONV_PT(tp->xx[i+1]), y + yCONV_PT(tp->yy[i+1]));
  127.       }
  128.     }
  129.   }
  130. }
  131.  
  132.  
  133. static void flushDashed(int dotted)
  134. {
  135.   long *xx = &(tp->xx[0]);
  136.   long *yy = &(tp->yy[0]);
  137.   int i, numdots, x0, y0, x1, y1;
  138.   int cx0, cy0, cx1, cy1;
  139.   float d, spacesize, a, b, dx, dy, milliperdash;
  140.   float inchesperdash;
  141.  
  142.   inchesperdash = atof(tp->opt_float[0]);
  143.  
  144.   if (tp->path_len <= 1 || inchesperdash <= 0.0) {
  145.     PrintLine("\33bIllegal conditions for dotted/dashed line (%ld,%ld).\33n",tp->path_len, inchesperdash);
  146.     return;
  147.   }
  148.  
  149.     milliperdash = inchesperdash * 1000.0;
  150.     x0 = xx[1];    y0 = yy[1];
  151.     x1 = xx[2];    y1 = yy[2];
  152.     dx = x1 - x0;
  153.     dy = y1 - y0;
  154.     if (dotted) {
  155.     numdots = sqrt(dx*dx + dy*dy) / milliperdash + 0.5;
  156.     if (numdots == 0) numdots = 1;
  157.     for (i=0; i <= numdots; i++) {
  158.         a = (float) i / (float) numdots;
  159.         cx0 = x0 + a*dx + 0.5;
  160.         cy0 = y0 + a*dy + 0.5;
  161.         dot_at(cx0, cy0);
  162.     }
  163.     } else {
  164.     d = sqrt(dx*dx + dy*dy);
  165.     if (d <= 2.0*milliperdash)
  166.         line_btw(x0, y0, x1, y1);
  167.     else {
  168.         numdots = d / (2.0*milliperdash) + 1.0;
  169.         spacesize = (d - numdots * milliperdash) / (numdots - 1);
  170.         for (i=0; i<numdots-1; i++) {
  171.         a = i * (milliperdash + spacesize) / d;
  172.         b = a + milliperdash / d;
  173.         cx0 = x0 + a*dx + 0.5;
  174.         cy0 = y0 + a*dy + 0.5;
  175.         cx1 = x0 + b*dx + 0.5;
  176.         cy1 = y0 + b*dy + 0.5;
  177.         line_btw(cx0, cy0, cx1, cy1);
  178.         b += spacesize / d;
  179.         }
  180.         cx0 = x0 + b*dx + 0.5;
  181.         cy0 = y0 + b*dy + 0.5;
  182.         line_btw(cx0, cy0, x1, y1);
  183.     }
  184.     }
  185. }
  186.  
  187. static void flushSpline(void)
  188. {
  189.   long *xx = &(tp->xx[0]);
  190.   long *yy = &(tp->yy[0]);
  191.   int xp, yp, N, lastx, lasty;
  192.   int t1, t2, t3, steps, j;
  193.   int i, w;
  194.  
  195. #if 0
  196.   int ipd;
  197.  
  198.   if( *cp ) {
  199.     float inchesPerDash;
  200.  
  201.     inchesPerDash = atof(cp);
  202.  
  203.     ipd = (int)(1000.0 * inchesPerDash);    /* to get milli-inches */
  204.   }
  205.  
  206.   if( ipd < 0 )    {    /* dotted */
  207.   } else {        /* dashed */
  208.   }
  209. #endif
  210.  
  211.   N = path_len + 1;
  212.   xx[0] = xx[1];    yy[0] = yy[1];
  213.   xx[N] = xx[N-1];    yy[N] = yy[N-1];
  214.   for (i=0; i<N-1; i++) {    /* interval */
  215.     /* original was:
  216.      * steps = (dist(xx[i], yy[i], xx[i+1], yy[i+1]) +
  217.      *     dist(xx[i+1], yy[i+1], xx[i+2], yy[i+2])) / 80;
  218.      */
  219.     steps = (dist(xx[i], yy[i], xx[i+1], yy[i+1]) +
  220.          dist(xx[i+1], yy[i+1], xx[i+2], yy[i+2])) * xRESOLUTION / 4000;
  221.  
  222.      w  = 500 / steps;
  223.     t1 = w * w / 20;
  224.     w -= 500;
  225.     t2 = (750000 - w * w) / 10;
  226.     w -= 500;
  227.     t3 = w * w / 20;
  228.     lastx = (t1*xx[i+2] + t2*xx[i+1] + t3*xx[i] + 50000) / 100000;
  229.     lasty = (t1*yy[i+2] + t2*yy[i+1] + t3*yy[i] + 50000) / 100000;
  230.  
  231.     for (j=1; j<steps; j++) {    /* points within */
  232.         w  = (j*1000 + 500) / steps;
  233.         t1 = w * w / 20;
  234.         w -= 500;
  235.         t2 = (750000 - w * w) / 10;
  236.         w -= 500;
  237.         t3 = w * w / 20;
  238.         xp = (t1*xx[i+2] + t2*xx[i+1] + t3*xx[i] + 50000) / 100000;
  239.         yp = (t1*yy[i+2] + t2*yy[i+1] + t3*yy[i] + 50000) / 100000;
  240.         line_btw(lastx, lasty, xp, yp);
  241.         lastx = xp;
  242.         lasty = yp;
  243.     }
  244.   }
  245. }
  246.  
  247. static void arc(int invis)
  248. {
  249.   int xc, yc, xrad, yrad, n;
  250.   int lastx, lasty;
  251.   float start_angle, end_angle, angle, theta, r;
  252.   float xradius, yradius;
  253.  
  254.   xc   = tp->opt_long[0];
  255.   yc   = tp->opt_long[1];
  256.   xrad = tp->opt_long[2];
  257.   yrad = tp->opt_long[3];
  258.  
  259.   start_angle = atof(tp->opt_float[0]);
  260.   end_angle   = atof(tp->opt_float[1]);
  261.  
  262.   /* fuer `invis' == true sollte die Ellipse nicht gezeichnet, sondern
  263.    * nur ausgefuellt werden.... wir machen nichts...
  264.    */
  265.   if( invis )
  266.     return;
  267.  
  268.   /* ... und Warnung fuer folgende Faelle ?? */
  269.   if( start_angle > end_angle ) {
  270.     angle = start_angle;  start_angle = end_angle;  end_angle = angle;
  271.   }
  272.   if( xrad < 0 ) xrad = -xrad;
  273.   if( yrad < 0 ) yrad = -yrad;
  274.  
  275.   /* We have a specialized fast way to draw closed circles/ellipses */
  276.   if (start_angle <= 0.0 && end_angle >= 6.283) {
  277.     draw_ellipse(xc, yc, xrad, yrad);
  278.     return;
  279.   }
  280.  
  281.   r = ((float) (xrad + yrad)) / 2.0;
  282.   theta = sqrt(1.0 / r);
  283.   n = 0.3 * TWOPI / theta + 0.5;
  284.   if (n < 12)
  285.     n = 12;
  286.   else if (n > 80)
  287.     n = 80;
  288.   /* n /= 2; */
  289.   theta = TWOPI / n;
  290.  
  291.   xradius = xrad;
  292.   yradius = yrad;
  293.   lastx = xc + (int)(xradius * cos(start_angle) + 0.5);
  294.   lasty = yc + (int)(yradius * sin(start_angle) + 0.5);
  295.  
  296. #ifdef __GNUC__
  297.   /* GCC lib fuer den ST hat in _addsf3() anscheinend einen Fehler :-( */
  298.   angle = (float)start_angle + theta;
  299. #else
  300.   angle = start_angle + theta;
  301. #endif
  302.  
  303.   n += 10;
  304.   while (--n > 0 && angle < end_angle) {
  305.     xrad = xc + (int) (xradius*cos(angle) + 0.5);
  306.     yrad = yc + (int) (yradius*sin(angle) + 0.5);
  307.     line_btw(lastx, lasty, xrad, yrad);
  308.     lastx = xrad;
  309.     lasty = yrad;
  310.     angle += theta;
  311.   }
  312.  
  313.   if( n <= 0 ) {
  314.     PrintLine("\33bError in ellipse, start angle %f, end angle %f, theta %f.\33n",start_angle, end_angle, theta);
  315.   }
  316.  
  317.   xrad = xc + (int)(xradius*cos(end_angle) + 0.5);
  318.   yrad = yc + (int)(yradius*sin(end_angle) + 0.5);
  319.   line_btw(lastx, lasty, xrad, yrad);
  320. }
  321.  
  322.  
  323.  
  324. /*-------------------------------------------------------------------*/
  325.  
  326.   static void
  327. dot_at(int x, int y)
  328. {
  329.   x = dm->x + xCONV_PT(x);
  330.   y = dm->y + yCONV_PT(y);
  331.  
  332.   device_DrawPoint(x, y);
  333. }
  334.  
  335.  
  336.   static void
  337. line_btw(int x0, int y0, int x1, int y1)
  338. {
  339.   x0 = dm->x + xCONV_PT(x0);
  340.   y0 = dm->y + yCONV_PT(y0);
  341.   x1 = dm->x + xCONV_PT(x1);
  342.   y1 = dm->y + yCONV_PT(y1);
  343.  
  344.   device_DrawLine(x0, y0, x1, y1);
  345. }
  346.  
  347.  
  348.  
  349.  
  350. /*
  351.  * Draw an ellipse with the indicated center and radices.
  352.  */
  353.   static void
  354. draw_ellipse(int xc, int yc, int xr, int yr)
  355. { float angle, theta;
  356.   int n, px0, py0, px1, py1;
  357.  
  358.   angle = (xr + yr) / 2.0;
  359.   theta = sqrt(1.0 / angle);
  360.   n = TWOPI / theta + 0.5;
  361.   if (n < 12)
  362.     n = 12;
  363.   else if (n > 80)
  364.     n = 80;
  365.   n /= 2;
  366.   theta = TWOPI / n;
  367.  
  368.   px0 = xc + xr;    /* cos(0) = 1 */
  369.   py0 = yc;        /* Sin(0) = 0 */
  370.   angle = theta;
  371.  
  372.   while (angle <= TWOPI) {
  373.     px1 = xc + xr*cos(angle) + 0.5;
  374.     py1 = yc + yr*sin(angle) + 0.5;
  375.     line_btw(px0, py0, px1, py1);
  376.     px0 = px1;
  377.     py0 = py1;
  378.     angle += theta;
  379.   }
  380.   line_btw(px0, py0, xc + xr, yc);
  381. }
  382.  
  383.