home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / SpecHost / graphics.c < prev    next >
C/C++ Source or Header  |  1994-05-27  |  8KB  |  315 lines

  1. /*
  2. **    SpecialHost for PasTeX
  3. **
  4. **    Copyright © by Olaf Barthel & Georg Heßmann
  5. */
  6.  
  7. #include "Global.h"
  8.  
  9. /* graphics.c
  10.  *
  11.  * Routinen zum Zeichnen in die Seiten-Bitmap:
  12.  *    device_SetPenSize(x,y)        - setze Pinselstaerke auf x/y
  13.  *    device_DrawPoint(x,y)        - Punkt bei (x,y)
  14.  *    device_DrawLine(x,y,x1,y1)    - Linie von (x,y) nach (x1,y1)
  15.  *
  16.  * Mit v_pline, etc. kann nur auf den Bildschirm geschrieben werden,
  17.  * Linien, Punkte, etc. sollten jedoch in die Bitmap.
  18.  *
  19.  * Die hier verwendeten Koordinaten sind schon Bildschirmpunkte !!!
  20.  */
  21.  
  22.  
  23. /*
  24.  *    externe Variablen
  25.  */
  26. extern struct bitmap map;
  27. extern long upper_limit;
  28. extern long lower_limit;
  29.  
  30. static void CopyBitArray(int x, int y, int w, int h, unsigned short *p);
  31.  
  32. /*----------------------------------------------------------------------*/
  33.  
  34. static void CopyBitArray(int x, int y, int w, int h, unsigned short *p)
  35. {
  36.   register unsigned long     reg;
  37.   unsigned short        *char_adr;
  38.   unsigned short        *start_adr, *adr;
  39.   long                nr_sh, length_row;
  40.   long                c, l;
  41.  
  42.   long            words;
  43.  
  44.  
  45.   length_row = map.width >> 4;        /* Laenge einer Zeile in Woerter */
  46.  
  47.   start_adr = ((unsigned short *)map.pixptr) 
  48.                 + ((y - upper_limit) * length_row)
  49.                 + (x >> 4);
  50.   /* Adresse des ersten Wortes */
  51.  
  52.   nr_sh = x & 15;            /* Anzahl benoetigter Shifte */
  53.   words = (w + 15) / 16;        /* Anzahl Words des Chars pro Zeile */
  54.  
  55.   char_adr = p;
  56.  
  57.  
  58.    if (words == 1) {                /* width char <= width word */
  59.      for (l=0; l<h; l++) {
  60.         reg = ((long)(*char_adr++)) << 16;
  61.         reg >>= nr_sh;
  62.         *(unsigned long *)start_adr |= reg;
  63.         start_adr += length_row;
  64.     }                        /* end for l        */
  65.    }
  66.    else {
  67.     adr = start_adr;
  68.     for (l=0; l<h; l++) {
  69.       for (c=0; c<words; c++) {
  70.         reg = ((long)(*char_adr++)) << 16;
  71.         reg >>= nr_sh;
  72.         *(unsigned long *)(adr++) |= reg;
  73.       }                        /* end for c        */
  74.       start_adr += length_row;
  75.       adr = start_adr;
  76.     }                        /* end for l        */
  77.   }                        /* end else w<16    */
  78. }
  79.  
  80. /*----------------------------------------------------------------------*/
  81.  
  82.  
  83.  
  84. /*************************************************************
  85.  ********************  device_SetPenSize  ********************
  86.  *************************************************************/
  87. /*
  88.  * Hier werden jetzt die Formen der Pinselpunkte definiert.
  89.  * Bei unsymmetrischen Punkten sollte man die Bitmaps (=Ellipsen) besser
  90.  * in device_SetPenSize() direkt berechnen. Allgemein sollte man besser
  91.  * die Bitmap und deren Eigenschaften (Breite, Hoehe, HotSpot) in
  92.  * device_SetPenSize() berechnen. (Evtl. kann man auch fuer grosse Pens
  93.  * die Schrittweite in draw_line > 1 setzen.)
  94.  */
  95.  
  96. #define    MAX_PEN_SIZE    4     /* Max pixels of pen width */
  97.  
  98. static unsigned short bitmap1[] = { 0x8000, 0x0000 };
  99. static unsigned short bitmap2[] = { 0xc000, 0xc000, 0x0000 };
  100. static unsigned short bitmap3[] = { 0x4000, 0xe000, 0x4000, 0x0000 };
  101. static unsigned short bitmap4[] = { 0x6000, 0xf000, 0xf000, 0x6000, 0x0000 };
  102.  
  103. static struct pens {
  104.   unsigned short *map;
  105.   char height, width;
  106.   char x_offset, y_offset;    /* Hot Spot Location von links oben */
  107. } pens[MAX_PEN_SIZE] = {
  108.   bitmap1, 1, 1, 0, 0,
  109.   bitmap2, 2, 2, 1, 1,
  110.   bitmap3, 3, 3, 1, 1,
  111.   bitmap4, 4, 4, 2, 2
  112. };
  113.  
  114. static struct pens *actual_pen = &pens[0];
  115.  
  116.  
  117. /* Set actual drawing pen to xpen/ypen (both in device points) */
  118.   void
  119. device_SetPenSize(long xpen, long ypen)
  120. { long pen;
  121.  
  122.   /* for screen: xpen == ypen (normally) */
  123.   pen = (xpen + ypen + 1) / 2;
  124.   if( pen < 1 )
  125.     pen = 1;
  126.   else if( pen > MAX_PEN_SIZE )
  127.     pen = MAX_PEN_SIZE;
  128.  
  129.   --pen;    /* Index in pens[] */
  130.   actual_pen = &pens[pen];
  131. }
  132.  
  133.  
  134. /**************************************************************
  135.  *********************  device_DrawPoint  *********************
  136.  **************************************************************/
  137.  
  138.   void            /* Koordinaten des Pen-Mittelpunkts in device points */
  139. device_DrawPoint(long x, long y)
  140. { long h, w;
  141.  
  142.   /* Der aktuelle Pen ist in bitmap_pen eingetragen
  143.    * und ist pen_height hoch und pen_width breit.
  144.    * Der Mittelpunkt liegt bei pen_xoffset/pen_yoffset.
  145.    */
  146.  
  147.   x -= actual_pen->x_offset;
  148.   y -= actual_pen->y_offset;
  149.     /* Falls man Hot Spot von links unten angibt, so muesste man
  150.      * hier  y -= pen_height - pen_yoffset;  schreiben.
  151.      */
  152.  
  153.   /*
  154.    *  Jetzt noch alle Punkte, die nicht auf der Seite liegen, aussieben.
  155.    */
  156.   w = actual_pen->width;
  157.   if( x < 0L || x + w >= map.width )
  158.     return;
  159.  
  160.   h = actual_pen->height;
  161.   if( y < upper_limit || y + h >= lower_limit )
  162.     return;
  163.  
  164. #ifdef ATARI
  165.   AtCopyBitArray(x, y-upper_limit, w, h, actual_pen->map);
  166. #else
  167.   CopyBitArray(x, y, w, h, actual_pen->map);
  168. #endif
  169. }
  170.  
  171.  
  172. /*************************************************************
  173.  *********************  device_DrawLine  *********************
  174.  *************************************************************/
  175.  
  176. #if 1
  177. /*
  178.  * Zeichne Linie nach der "Quadrantal DDA" Methode.
  179.  *
  180.  * ergibt dickere Linien, da Diagonalen so gezeichnet werden:
  181.  *
  182.  *            *****
  183.  *         ****
  184.  *     *****
  185.  */
  186.  
  187.   void            /* Anfangs- und Endpunktkoordinaten in device points */
  188. device_DrawLine(long x, long y, long x1, long y1)
  189. { short dx, dy;
  190.   short xstep=0, ystep=0;
  191.   short diff;
  192. #define STEP    1    /* oder in Abhaengigkeit der pensize auch groesser */
  193.  
  194.   /* als erstes: dx sollte >= 0 sein, d.h. x1 >= x */
  195.   dx = x1 - x;  dy = y1 - y;
  196.   if( dx < 0 ) {
  197.     dx = -dx;  dy = -dy;
  198.     x = x1;    y = y1;
  199.   }
  200.  
  201.   /* jetzt: dx >= 0, also nur 1. oder 4.Quadrant moeglich */
  202.   device_DrawPoint(x, y);
  203.  
  204.   if( dy < 0 ) {    /* 4.Quadrant */
  205.     diff = ( dx > -dy ) ? -dx/2 : -dy/2;
  206.     do {
  207.     if( diff > 0 ) {
  208.       ystep -= STEP;    diff -= dx;
  209.     } else {
  210.       xstep += STEP;    diff -= dy;
  211.     }
  212.     device_DrawPoint(x + xstep, y + ystep);
  213.     } while( xstep < dx || ystep > dy );
  214.   } else {        /* 1.Quadrant */
  215.     diff = ( dx > dy ) ? -dx/2 : dy/2;
  216.     do {
  217.     if( diff > 0 ) {
  218.       ystep += STEP;    diff -= dx;
  219.     } else {
  220.       xstep += STEP;    diff += dy;
  221.     }
  222.     device_DrawPoint(x + xstep, y + ystep);
  223.     } while( xstep < dx || ystep < dy );
  224.   }
  225. }
  226.  
  227. #else
  228.  
  229. /*
  230.  * Zeichne Linie nach der "Octantal DDA" Methode.
  231.  *
  232.  * ergibt duennere Linien, da Diagonalen so gezeichnet werden:
  233.  *
  234.  *             ****
  235.  *         ****
  236.  *     ****
  237.  */
  238.  
  239.   void            /* Anfangs- und Endpunktkoordinaten in device points */
  240. device_DrawLine(long x, long y, long x1, long y1)
  241. { short dx, dy;
  242.   short xstep=0, ystep=0;
  243.   short diff;
  244. #define STEP    1
  245.  
  246.   /* als erstes: dx sollte >= 0 sein, d.h. x1 >= x */
  247.   dx = x1 - x;  dy = y1 - y;
  248.   if( dx < 0 ) {
  249.     dx = -dx;  dy = -dy;
  250.     x = x1;    y = y1;
  251.   }
  252.  
  253.   /* jetzt: dx >= 0, also nur 1. oder 4.Quadrant moeglich */
  254.   device_DrawPoint(x, y);
  255.  
  256.   if( dy < 0 ) {
  257.     if( dx > -dy ) {    /* 8. Octant */
  258.       diff = -dx/2;
  259.       do {
  260.     xstep += STEP;
  261.     if( diff > 0 ) {
  262.       ystep -= STEP;
  263.       diff = diff - dy - dx;
  264.     } else {
  265.       diff = diff - dy;
  266.     }
  267.     device_DrawPoint(x + xstep, y + ystep);
  268.       } while(xstep < dx);
  269.     } else {        /* 7. Octant */
  270.       diff = (dx == -dy) ? 0 : -dy/2;
  271.       do {
  272.     ystep -= STEP;
  273.     if( diff > 0 ) {
  274.       diff = diff - dx;
  275.     } else {
  276.       xstep += STEP;
  277.       diff = diff - dy - dx;
  278.     }
  279.     device_DrawPoint(x + xstep, y + ystep);
  280.       } while(ystep > dy);
  281.     }
  282.   } else {
  283.     if( dx > dy ) {    /* 1. Octant */
  284.       diff = -dx/2;
  285.       do {
  286.     xstep += STEP;
  287.     if( diff > 0 ) {
  288.       ystep += STEP;
  289.       diff = diff + dy - dx;
  290.     } else {
  291.       diff = diff + dy;
  292.     }
  293.     device_DrawPoint(x + xstep, y + ystep);
  294.       } while(xstep < dx);
  295.     } else {        /* 2. Octant */
  296.       diff = (dx == dy) ? 0 : dy/2;
  297.       do {
  298.     ystep += STEP;
  299.     if( diff > 0 ) {
  300.       diff = diff - dx;
  301.     } else {
  302.       xstep += STEP;
  303.       diff = diff + dy - dx;
  304.     }
  305.     device_DrawPoint(x + xstep, y + ystep);
  306.       } while(ystep < dy);
  307.     }
  308.   }
  309. }
  310. #endif
  311.  
  312. /********************  end of graphics.c  ********************/
  313.  
  314.  
  315.