home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fonts 1 / freshfonts1.bin / programs / amiga / pastex / src / specialhost / graphics.c < prev    next >
C/C++ Source or Header  |  1991-06-07  |  8KB  |  309 lines

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