Main Page Data Structures File List Data Fields Globals Related Pages

# gfxcore.cpp

Go to the documentation of this file.

    00001 /*  gfxcore.cpp
    00002     Display independent graphic primitives
    00003
    00004     Copyright (c)2001 by Thomas Kindler, thomas.kindler@gmx.de
    00005
    00006     This program is free software; you can redistribute it and/or
    00007     modify it under the terms of the GNU General Public License as
    00008     published by the Free Software Foundation; either version 2 of
    00009     the License, or (at your option) any later version. Read the
    00010     full License at http://www.gnu.org/copyleft for more details.
    00011 */
    00012
    00013 // include files -----
    00014 //
    00015 #include <stdio.h>
    00016 #include <stdlib.h>
    00017 #include <malloc.h>
    00018 #include <string.h>
    00019 #include <assert.h>
    00020
    00021 #include "gfxcore.h"
    00022 #include "ztimer.h"
    00023 #include "misc.h"
    00024
    00025
    00026 #include "sysfont.cpp"
    00027
    00028
    00029 static struct {
    00030   Bitmap  bitmap;
    00031   char    bmBits[GFX_SCRATCH_SIZE];
    00032 } scratch = {0, 0, GFX_SCRATCH_SIZE};
    00033
    00034 Bitmap *_gfx_scratch = (Bitmap*)&scratch;
    00035 Font   *_gfx_defaultFont = NULL;
    00036
    00037 // some fillStyles
    00038 //
    00039 char emptyFill[]     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    00040 char solidFill[]     = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    00041 char lineFill[]      = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 };
    00042 char ltSlashFill[]   = { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 };
    00043 char slashFill[]     = { 0x99, 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33 };
    00044 char bkSlashFill[]   = { 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc, 0x99 };
    00045 char ltBkSlashFill[] = { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 };
    00046 char hatchFill[]     = { 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55 };
    00047 char xHatchFill[]    = { 0x55, 0x22, 0x55, 0x88, 0x55, 0x22, 0x55, 0x88 };
    00048 char xLeaveFill[]    = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
    00049 char wDotFill[]      = { 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44 };
    00050 char cDotFill[]      = { 0x11, 0x44, 0x88, 0x22, 0x11, 0x44, 0x88, 0x22 };
    00051
    00061 void GFX_Init(Graphics *gfx, Bitmap *bm)
    00062 {
    00063   memset(gfx, 0, sizeof(Graphics));
    00064   gfx->bitmap    = bm;
    00065   gfx->font      = _font_sysfont;
    00066   gfx->fillStyle = solidFill;
    00067   gfx->color     = 1;
    00068   gfx->blitMode  = BLT_OR;
    00069 }
    00070
    00071
    00081 void GFX_Init(Graphics *gfx, Graphics *gfx2)
    00082 {
    00083   memcpy(gfx, gfx2, sizeof(Graphics));
    00084 }
    00085
    00086
    00092 void GFX_SetFont(Graphics *gfx, Font *font)
    00093 {
    00094   if (!font)
    00095     font = _font_sysfont;
    00096   gfx->font = font;
    00097 }
    00098
    00099
    00104 void GFX_SetFillStyle(Graphics *gfx, char *style)
    00105 {
    00106   gfx->fillStyle = style;
    00107 }
    00108
    00109
    00110 void GFX_SetColor(Graphics *gfx, int color)
    00111 {
    00112   gfx->color = color ? 1 : 0;
    00113 }
    00114
    00115
    00116 void GFX_SetBlitMode(Graphics *gfx, int mode)
    00117 {
    00118   gfx->blitMode = mode & 15;
    00119 }
    00120
    00121
    00126 void GFX_MoveTo(Graphics *gfx, int x, int y)
    00127 {
    00128   gfx->x = x;
    00129   gfx->y = y;
    00130 }
    00131
    00132
    00137 void GFX_MoveRel(Graphics *gfx, int dx, int dy)
    00138 {
    00139   gfx->x += dx;
    00140   gfx->y += dy;
    00141 }
    00142
    00143
    00150 void GFX_HLine(Graphics *gfx, int x, int y, int w)
    00151 {
    00152   // clip coordinates
    00153   //
    00154   if (y<0 || y>= gfx->bitmap->height)
    00155     return;
    00156   if (x<0)
    00157     { w -= -x; x = 0; }
    00158   if (x+w >= gfx->bitmap->width)
    00159     w -= (x+w)-gfx->bitmap->width;
    00160   if (w<=0)
    00161     return;
    00162
    00163   char *dst   = &gfx->bitmap->bmBits[x+(y>>3)*gfx->bitmap->width];
    00164   char  mask  = 1 << (y & 7);
    00165   int   color = gfx->color;
    00166
    00167   asm {
    00168     push  bx
    00169     push  cx
    00170     push  di
    00171     push  es
    00172
    00173     les   di, dst
    00174     mov   cx, w
    00175     mov   bl, mask
    00176     mov   bh, bl
    00177     cmp   color, 0
    00178     je    clr
    00179
    00180 set:
    00181     shr   cx, 1
    00182     lahf          // save carry flag
    00183     jz    set_onepix
    00184 set_loop:
    00185     or    word ptr [es:di], bx
    00186     add   di, 2
    00187     loop  set_loop
    00188     sahf          // restore carry flag
    00189     jnc   done
    00190 set_onepix:
    00191     or    byte ptr [es:di], bl
    00192     stosb
    00193     jmp   done
    00194
    00195 clr:
    00196     not   bx
    00197     shr   cx, 1
    00198     lahf          // save carry flag
    00199     jz    clr_onepix
    00200 clr_loop:
    00201     and   word ptr [es:di], ax
    00202     add   di, 2
    00203     stosw
    00204     loop  clr_loop
    00205     sahf          // restore carry flag
    00206     jnc   done
    00207 clr_onepix:
    00208     and   byte ptr [es:di], bl
    00209     stosb
    00210
    00211 done:
    00212     pop   es
    00213     pop   di
    00214     pop   cx
    00215     pop   bx
    00216   }
    00217 }
    00218
    00219
    00220
    00227 void GFX_VLine(Graphics *gfx, int x, int y, int h)
    00228 {
    00229   // clip coordinates
    00230   //
    00231   if (x<0 || x>= gfx->bitmap->width)
    00232     return;
    00233   if (y<0)
    00234     { h -= -y;  y = 0; }
    00235   if (y+h >= gfx->bitmap->height)
    00236     h -= (y+h)-gfx->bitmap->height;
    00237   if (h<=0)
    00238     return;
    00239
    00240   char *dst = &gfx->bitmap->bmBits[x+(y>>3)*gfx->bitmap->width];
    00241
    00242   // calculate destination masks
    00243   //
    00244   unsigned char fbm, lbm;
    00245   fbm = 0xff << (   y & 7);
    00246   lbm = 0xff >> (-y-h & 7);
    00247
    00248   // calculate number of pages
    00249   //
    00250   int psize = gfx->bitmap->width;
    00251   int pages = ((y+h+7)>>3) - (y>>3);
    00252   if (pages == 1)
    00253     fbm &= lbm;
    00254
    00255   int color = gfx->color;
    00256
    00257   asm {
    00258     push  bx
    00259     push  cx
    00260     push  di
    00261     push  es
    00262
    00263     les   di, dst
    00264     mov   al, fbm
    00265     mov   cx, pages
    00266     mov   bx, psize
    00267
    00268     cmp   color, 0
    00269     je    clr
    00270
    00271 set_loop:
    00272     or    byte ptr [es:di], al
    00273     add   di, bx
    00274     mov   al, 0xff
    00275     dec   cx
    00276     cmp   cx, 1
    00277     jg    set_loop
    00278     mov   al, lbm
    00279     je    set_loop
    00280     jmp   done
    00281
    00282 clr:
    00283     not   al
    00284 clr_loop:
    00285     and   byte ptr [es:di], al
    00286     add   di, bx
    00287     xor   al, al
    00288     dec   cx
    00289     cmp   cx, 1
    00290     jg    clr_loop
    00291     mov   al, lbm
    00292     not   al
    00293     je    clr_loop
    00294
    00295 done:
    00296     pop   es
    00297     pop   di
    00298     pop   cx
    00299     pop   bx
    00300   }
    00301
    00302 }
    00303
    00304
    00318 void GFX_Line(Graphics *gfx, int x1, int y1, int x2, int y2)
    00319 {
    00320   int dy = y2 - y1;
    00321   int dx = x2 - x1;
    00322   int stepx, stepy;
    00323
    00324   if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
    00325   if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
    00326
    00327   if (dx == 0)  GFX_VLine(gfx, min(x1, x2), min(y1, y2), dy);
    00328   if (dy == 0)  GFX_HLine(gfx, min(x1, x2), min(y1, y2), dx);
    00329
    00330   dy <<= 1;                                    // dy is now 2*dy
    00331   dx <<= 1;                                    // dx is now 2*dx
    00332
    00333   BM_PutPixel(gfx->bitmap, x1, y1, gfx->color);
    00334   if (dx > dy) {
    00335     int fraction = dy - (dx >> 1);             // same as 2*dy - dx
    00336     while (x1 != x2) {
    00337       if (fraction >= 0) {
    00338         y1 += stepy;
    00339         fraction -= dx;                        // same as fraction -= 2*dx
    00340       }
    00341       x1 += stepx;
    00342       fraction += dy;                          // same as fraction -= 2*dy
    00343       BM_PutPixel(gfx->bitmap, x1, y1, gfx->color);
    00344     }
    00345   } else {
    00346     int fraction = dx - (dy >> 1);
    00347     while (y1 != y2) {
    00348       if (fraction >= 0) {
    00349         x1 += stepx;
    00350         fraction -= dy;
    00351       }
    00352       y1 += stepy;
    00353       fraction += dx;
    00354       BM_PutPixel(gfx->bitmap, x1, y1, gfx->color);
    00355     }
    00356   }
    00357 }
    00358
    00359
    00366 void GFX_LineRel(Graphics *gfx, int dx, int dy)
    00367 {
    00368   GFX_Line(gfx, gfx->x, gfx->y, gfx->x+dx, gfx->y+dy);
    00369   gfx->x += dx;
    00370   gfx->y += dy;
    00371 }
    00372
    00373
    00381 void GFX_LineTo (Graphics *gfx, int x, int y)
    00382 {
    00383   GFX_Line(gfx, gfx->x, gfx->y, x, y);
    00384   gfx->x = x;
    00385   gfx->y = y;
    00386 }
    00387
    00388
    00398 void GFX_Rectangle(Graphics *gfx, int x, int y, int w, int h)
    00399 {
    00400   if (w<=0 || h<=0)
    00401     return;
    00402   GFX_HLine(gfx, x    , y    , w);
    00403   GFX_HLine(gfx, x    , y+h-1, w);
    00404   GFX_VLine(gfx, x    , y+1  , h-2);
    00405   GFX_VLine(gfx, x+w-1, y+1  , h-2);
    00406 }
    00407
    00408
    00416 void GFX_Circle(Graphics *gfx, int xc, int yc, int r)
    00417 {
    00418   int x = 0;
    00419   int y = r;
    00420   int p = 3 - (r<<1);
    00421
    00422   while (x <= y)  {
    00423     BM_PutPixel(gfx->bitmap, xc+x, yc+y, gfx->color);
    00424     BM_PutPixel(gfx->bitmap, xc+x, yc-y, gfx->color);
    00425     BM_PutPixel(gfx->bitmap, xc-x, yc+y, gfx->color);
    00426     BM_PutPixel(gfx->bitmap, xc-x, yc-y, gfx->color);
    00427     BM_PutPixel(gfx->bitmap, xc+y, yc+x, gfx->color);
    00428     BM_PutPixel(gfx->bitmap, xc+y, yc-x, gfx->color);
    00429     BM_PutPixel(gfx->bitmap, xc-y, yc+x, gfx->color);
    00430     BM_PutPixel(gfx->bitmap, xc-y, yc-x, gfx->color);
    00431     if (p < 0)
    00432       p += (x++ << 2) + 6;
    00433     else
    00434       p += ((x++ - y--)<<2) + 10;
    00435   }
    00436 }
    00437
    00438
    00449 void GFX_FillRect(Graphics *gfx, int x, int y, int w, int h)
    00450 {
    00451   if (x<0) {
    00452     w -= -x;
    00453     x  =  0;
    00454   }
    00455   if (x+w >= gfx->bitmap->width)
    00456     w -= (x+w) - gfx->bitmap->width;
    00457   if (w<=0)
    00458     return;
    00459
    00460   if (y<0) {
    00461     h -= -y;
    00462     y  =  0;
    00463   }
    00464   if (y+h >= gfx->bitmap->height)
    00465     h -= (y+h) - gfx->bitmap->height;
    00466   if (h<=0)
    00467     return;
    00468
    00469   assert(w <= _gfx_scratch->bmBitsSize);
    00470
    00471   // copy pattern to scratch memory and blit
    00472   //
    00473   char *dst = _gfx_scratch->bmBits;
    00474   char *src = gfx->fillStyle;
    00475   asm {
    00476     pushf
    00477     push  cx
    00478     push  si
    00479     push  di
    00480     push  ds
    00481     push  es
    00482     cld
    00483     lds   si, dword ptr src
    00484     les   di, dword ptr dst
    00485     mov   cx, w
    00486     shr   cx, 3
    00487     inc   cx
    00488
    00489 fill_loop:
    00490     movsw
    00491     movsw
    00492     movsw
    00493     movsw
    00494     sub   si, 8
    00495     loop  fill_loop
    00496
    00497     pop   es
    00498     pop   ds
    00499     pop   di
    00500     pop   si
    00501     pop   cx
    00502     popf
    00503   }
    00504
    00505   _gfx_scratch->width  = 0; // always blit the same page..
    00506   BM_FastBlit(gfx->bitmap, x, y, _gfx_scratch, 0, 0, w, h, gfx->blitMode);
    00507 }