/*! \file basegfx.cpp \brief Platform indepedant graphic functions. */ /* This file is part of Advanced Strategic Command; http://www.asc-hq.de Copyright (C) 1994-2005 Martin Bickel and Marc Schellenberger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "global.h" #include "basegfx.h" #include "newfont.h" #include "misc.h" #ifdef _DOS_ #include "dos/vesa.h" #else #include "sdl/graphics.h" #endif tgraphmodeparameters *agmp = (tgraphmodeparameters *) & activegraphmodeparameters; tgraphmodeparameters *hgmp = (tgraphmodeparameters *) & hardwaregraphmodeparameters; int xlatbuffersize = 66000; void generategrayxlattable( ppixelxlattable tab, char offset, char size, dacpalette256* pal ) { for ( int b = 0; b <= 255; b++) { // (*tab)[b] = (char) (offset + size - 1 - ((*activepalette256)[b][0] + (*activepalette256)[b][1] + (*activepalette256)[b][2]) * size / 192); (*tab)[b] = (char) (offset + size - 1 - ( 0.299 * (*pal)[b][0] + 0.587 * (*pal)[b][1] + 0.114 * (*pal)[b][2]) * size / 64 ); } } void getpicsize( void* hd2, int &width, int &height) { trleheader* hd = (trleheader*) hd2; if (hd->id == 16973) { width = hd->x; height = hd->y; } else { width = hd->id + 1; height = hd->size + 1; } } int getpicsize2( void* hd2 ) { trleheader* hd = (trleheader*) hd2; int width; int height; if (hd->id == 16973) return hd->size + sizeof(*hd); else { width = hd->id + 1; height = hd->size + 1; return height*width+4; } } void rahmen(bool invers, integer x1, integer y1, integer x2, integer y2) { collategraphicoperations cgo ( x1, y1, x2, y2 ); int col = (invers == false) ? white : darkgray; line(x1, y1, x1, y2, col); line(x1, y1, x2, y1, col); col = (invers == true) ? white : darkgray; line(x2, y1, x2, y2, col); line(x1, y2, x2, y2, col); } void tdrawline :: start ( int x1, int y1, int x2, int y2 ) { int i, deltax, deltay, numpixels, d, dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2; /* calculate deltax and deltay for initialisation */ deltax = x2 - x1; if ( deltax < 0 ) deltax = -deltax; deltay = y2 - y1; if ( deltay < 0 ) deltay = -deltay; /* initialize all vars based on which is the independent variable */ if (deltax >= deltay) { /* x is independent variable */ numpixels = deltax + 1; d = (2 * deltay) - deltax; dinc1 = deltay << 1; dinc2 = (deltay - deltax) << 1; xinc1 = 1; xinc2 = 1; yinc1 = 0; yinc2 = 1; } else { /* y is independent variable */ numpixels = deltay + 1; d = (2 * deltax) - deltay; dinc1 = deltax << 1; dinc2 = (deltax - deltay) << 1; xinc1 = 0; xinc2 = 1; yinc1 = 1; yinc2 = 1; } /* make sure x and y move in the right directions */ if (x1 > x2) { xinc1 = -xinc1; xinc2 = -xinc2; } if (y1 > y2) { yinc1 = -yinc1; yinc2 = -yinc2; } /* start drawing at */ x = x1; y = y1; /* draw the pixels */ for (i = 1; i <= numpixels; i++) { putpix( x, y ); if (d < 0) { d = d + dinc1; x = x + xinc1; y = y + yinc1; } else { d = d + dinc2; x = x + xinc2; y = y + yinc2; } } } void line(int x1, int y1, int x2, int y2, char actcol) { collategraphicoperations cgs ( x1, y1, x2, y2 ); float m, b; int w; float yy1, yy2, xx1, xx2; if ( x1 == x2) { for (w=y1;w<=y2 ;w++ ) putpixel(x1, w, actcol ); } else { if ( y1 == y2) { for (w=x1;w<=x2 ;w++ ) putpixel(w, y1, actcol ); } else { yy1 = y1; yy2 = y2; xx1 = x1; xx2 = x2; m = (yy2 - yy1) / (xx2 - xx1); b = y1 - m * x1; if ((m <= 1) && (m >= -1)) { if (x2 < x1) { w = x2; x2 = x1; x1 = w; w = y2; y2 = y1; y1 = w; } for (w = x1; w <= x2; w++) putpixel(w, (int) (m * w + b), actcol); } else { if (y2 < y1) { w = x2; x2 = x1; x1 = w; w = y2; y2 = y1; y1 = w; } for (w = y1; w <= y2; w++) { putpixel((int) ((w - b) / m), w, actcol); } } } /* endif */ } } void xorline(int x1, int y1, int x2, int y2, char actcol) { collategraphicoperations cgs ( x1, y1, x2, y2 ); float m, b; int w; float yy1, yy2, xx1, xx2; if ( x1 == x2) { for (w=y1;w<=y2 ;w++ ) { putpixel( x1, w, getpixel ( x1, w ) ^ actcol); } /* endfor */ } else { yy1 = y1; yy2 = y2; xx1 = x1; xx2 = x2; m = (yy2 - yy1) / (xx2 - xx1); b = y1 - m * x1; if ((m <= 1) && (m >= -1)) { if (x2 < x1) { w = x2; x2 = x1; x1 = w; w = y2; y2 = y1; y1 = w; } for (w = x1; w <= x2; w++) { putpixel(w, (int) (m * w + b), getpixel( w, (int) (m * w + b) ) ^ actcol); } } else { if (y2 < y1) { w = x2; x2 = x1; x1 = w; w = y2; y2 = y1; y1 = w; } for (w = y1; w <= y2; w++) { putpixel((int) ((w - b) / m), w, getpixel ( (int) ((w - b) / m), w ) ^ actcol); } } } } void rectangle(int x1, int y1, int x2, int y2, char color) { collategraphicoperations cgs ( x1, y1, x2, y2 ); line(x1, y1, x1, y2, color); line(x1, y1, x2, y1, color); line(x2, y1, x2, y2, color); line(x1, y2, x2, y2, color); } void xorrectangle(int x1, int y1, int x2, int y2, char color) { collategraphicoperations cgs ( x1, y1, x2, y2 ); xorline(x1,y1,x1,y2,color); xorline(x1,y1,x2,y1,color); xorline(x2,y1,x2,y2,color); xorline(x1,y2,x2,y2,color); } /* void xorrectangle( tmouserect r, byte color) { xorrectangle ( r.x1, r.y1, r.x2, r.y2, color ); } */ void* halfpict ( void* vbuf ) { char* buf = (char*) vbuf; Uint16* wp = (Uint16*) xlatbuffer; char* dest = (char*) xlatbuffer; trleheader* hd = (trleheader*) vbuf; if ( hd->id == 16973 ) { wp[0] = hd->x / 2; wp[1] = hd->y / 2; if ( ( wp[0] + 1 ) * ( wp[1] + 1 ) + 4 >= xlatbuffersize ) throw fatalgraphicserror ( "halfpict : picture larger than buffer ! " ); dest += 4; buf += sizeof ( *hd ); int linecount = 0; int rowcount = 0; for ( int c = 0; c < hd->size; c++ ) { if ( *buf == hd->rle ) { for ( int i = buf[1]; i > 0; i-- ) { if ( !(linecount & 1) && !(rowcount & 1)) { *dest = buf[2]; dest++; } rowcount++; if ( rowcount > hd->x ) { rowcount = 0; linecount++; } } buf += 3; c += 2; } else { if ( !(linecount & 1) && !(rowcount & 1)) { *dest = *buf; dest++; } buf++; rowcount++; if ( rowcount > hd->x ) { rowcount = 0; linecount++; } } if ( (PointerSizedInt)dest - (PointerSizedInt)xlatbuffer > xlatbuffersize ) throw fatalgraphicserror ( "halfpict : picture larger than buffer ! " ); } } else { int linecount = 0; int rowcount = 0; Uint16* wp2 = (Uint16*) vbuf; wp[0] = wp2[0] / 2; wp[1] = wp2[1] / 2; if ( ( wp[0] + 1 ) * ( wp[1] + 1 ) + 4 >= xlatbuffersize ) throw fatalgraphicserror ( "halfpict : picture larger than buffer ! " ); dest += 4; buf += 4; for ( int c = (wp2[0] + 1) * (wp2[1] + 1); c > 0; c-- ) { if ( !(linecount & 1) && !(rowcount & 1)) { *dest = *buf; dest++; } buf++; rowcount++; if ( rowcount > wp2[0] ) { rowcount = 0; linecount++; } } } return xlatbuffer; } void putshadow ( int x1, int y1, void* ptr, ppixelxlattable xl ) { Uint16* w = (Uint16*) ptr; char* c = (char*) ptr + 4; int spacelength = agmp->scanlinelength - *w - 1; collategraphicoperations cgo ( x1, y1, x1 + w[0], y1+w[1] ); if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 + agmp->linearaddress); for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) { if ( *c != 255 ) *buf = (*xl)[*buf]; buf++; c++; } buf+=spacelength; } } } void putpicturemix ( int x1, int y1, void* ptr, int rotation, char* mixbuf ) { Uint16* w = (Uint16*) ptr; char* c = (char*) ptr + 4; int spacelength = agmp->scanlinelength - *w - 1; collategraphicoperations cgo ( x1, y1, x1 + w[0], y1+w[1] ); if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 + agmp->linearaddress); for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) { if ( *c != 255 ) { int o = *buf << 8; if ( *c >= 16 && *c < 24 ) *buf = mixbuf[o + *c + rotation]; else *buf = mixbuf[o + *c]; } buf++; c++; } buf+=spacelength; } } } void putinterlacedrotimage ( int x1, int y1, void* ptr, int rotation ) { Uint16* w = (Uint16*) ptr; char* c = (char*) ptr + 4; int spacelength = agmp->scanlinelength - *w - 1; collategraphicoperations cgo ( x1, y1, x1 + w[0], y1+w[1] ); if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 + agmp->linearaddress); for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) { if ( *c != 255 ) if ( ((PointerSizedInt)(buf+y)) & 1 ) if ( *c >= 16 && *c < 24 ) *buf = *c + rotation; else *buf = *c; buf++; c++; } buf+=spacelength; } } } void rotatepict90 ( void* s, void* d ) { Uint16* sw = (Uint16*) s; char* sc = (char*) s + 4; Uint16* dw = (Uint16*) d; char* dc = (char*) d + 4; dw[0] = sw[1]; dw[1] = sw[0]; int dl = dw[0]+1; // int dh = dw[1]+1; int sl = sw[0]+1; int sh = sw[1]+1; for (int y = 0; y <= dw[1]; y++) for (int x = 0; x <= dw[0]; x++) dc[ y * dl + x] = sc[ ( sh - x - 1 ) * sl + y]; } union tpix { struct { char r,g,b,a; } s; int all; }; typedef tpix timage[ 100 ][ 100 ]; int getimagepixel ( void* image, int x, int y ) { int xs, ys; getpicsize ( image, xs, ys ); y += ys/2; x += xs/2; if ( x < 0 || x >= xs || y < 0 || y >= ys ) return -1; else { char* pc = (char*) image; return pc[ 4 + y * xs + x]; } } const float pi = 3.14159265; char* rotatepict ( void* image, int organgle ) { int fieldxsize, fieldysize; getpicsize(image, fieldxsize, fieldysize ); float angle = ((float)organgle) / 360 * 2 * pi + pi; char* dst = new char[ imagesize ( 0, 0, fieldxsize, fieldysize ) ]; Uint16* wp = (Uint16*) dst; wp[0] = fieldxsize-1; wp[1] = fieldysize-1; char* pnt = dst + 4; for ( int y = 0; y < fieldysize; y++ ) { for ( int x = 0; x < fieldxsize; x++ ) { int dx = x - fieldxsize/2 ; int dy = fieldysize/2 - y; double nx, ny; if ( organgle != 0 && organgle != -180 && organgle != 180) { float wnk ; if ( dx ) wnk = atan2 ( double(dy), double(dx) ); else if ( dy > 0 ) wnk = pi/2; else wnk = -pi/2; wnk -= angle; float radius = sqrt ( double(dx * dx + dy * dy )); nx = radius * cos ( wnk ); ny = radius * sin ( wnk ); } else if ( organgle == 0 ) { nx = -dx; ny = -dy; } else if ( organgle == 180 || organgle == -180) { nx = dx; ny = dy; } int newpix = getimagepixel ( image, (int)-nx, (int)ny ); if ( newpix == -1 ) *pnt = 255; else *pnt = newpix; pnt++; } } return dst; } char* rotatepict_grw ( void* image, int organgle ) { int fieldxsize, fieldysize; getpicsize(image, fieldxsize, fieldysize ); float angle = ((float)organgle) / 360 * 2 * pi + pi; int d = int(sqrt(double(fieldxsize*fieldxsize + fieldysize*fieldysize ))); char* dst = new char[ imagesize ( 0, 0, d,d ) ]; Uint16* wp = (Uint16*) dst; wp[0] = d-1; wp[1] = d-1; char* pnt = dst + 4; for ( int y = 0; y < d; y++ ) { for ( int x = 0; x < d; x++ ) { int dx = x - d/2 ; int dy = d/2 - y; float nx, ny; if ( organgle != 0 && organgle != -180 && organgle != 180) { float wnk ; if ( dx ) wnk = atan2 ( double(dy), double(dx) ); else if ( dy > 0 ) wnk = pi/2; else wnk = -pi/2; wnk -= angle; float radius = sqrt ( double(dx * dx + dy * dy )); nx = radius * cos ( wnk ); ny = radius * sin ( wnk ); } else if ( organgle == 0 ) { nx = -dx; ny = -dy; } else if ( organgle == 180 || organgle == -180) { nx = dx; ny = dy; } int newpix = getimagepixel ( image, (int)-nx, (int)ny ); if ( newpix == -1 ) *pnt = 255; else *pnt = newpix; pnt++; } } return dst; } void flippict ( void* s, void* d, int dir ) { Uint16* sw = (Uint16*) s; char* sc = (char*) s + 4; Uint16* dw = (Uint16*) d; char* dc = (char*) d + 4; dw[1] = sw[1]; dw[0] = sw[0]; int sl = sw[0]+1; int sh = sw[1]+1; if ( dir == 1 ) { for (int y = 0; y <= dw[1]; y++) for (int x = 0; x <= dw[0]; x++) dc[ y * sl + x] = sc[ y * sl + ( sl - 1 - x ) ]; } else { for (int y = 0; y <= dw[1]; y++) for (int x = 0; x <= dw[0]; x++) dc[ y * sl + x] = sc[ ( sh - 1 - y) * sl + x ]; } } void putpixel8 ( int x1, int y1, int color ) { collategraphicoperations cgo ( x1, y1, x1, y1 ); char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); *buf = color; } int getpixel8 ( int x1, int y1 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); return *buf; } void putpixel(int x1, int y1, int color) { collategraphicoperations cgo ( x1, y1, x1, y1 ); if ( agmp->byteperpix == 1 ) putpixel8 ( x1, y1, color ); else { if ( agmp->windowstatus == 100 ) { char* pc = (char*) ( agmp->linearaddress + x1 * agmp->byteperpix + y1 * agmp->scanlinelength ); int alpha = color >> 24; if ( alpha == 0 ) { pc[ agmp->redfieldposition/8 ] = color & 0xff; pc[ agmp->greenfieldposition/8 ] = (color >> 8) & 0xff; pc[ agmp->bluefieldposition/8 ] = (color >> 16) & 0xff; } else { pc[ agmp->redfieldposition/8 ] = pc[ agmp->redfieldposition/8 ] * alpha / alphabase + (color & 0xff) * (alphabase - alpha ) / alphabase; pc[ agmp->greenfieldposition/8 ] = pc[ agmp->greenfieldposition/8 ] * alpha / alphabase + ((color >> 8 ) & 0xff) * (alphabase - alpha ) / alphabase; pc[ agmp->bluefieldposition/8 ] = pc[ agmp->bluefieldposition/8 ] * alpha / alphabase + ((color >> 16) & 0xff) * (alphabase - alpha ) / alphabase; } } else { /* int pos = x1 * agmp->byteperpix + y1 * agmp->scanlinelength; int page = pos >> 16; if ( hgmp->actsetpage != page ) setvirtualpagepos ( page ); char* pc = (char*) ( agmp->linearaddress + (pos & 0xffff) ); int alpha = color >> 24; if ( alpha == 0 ) { pc[ agmp->redfieldposition/8 ] = color & 0xff; pc[ agmp->greenfieldposition/8 ] = (color >> 8) & 0xff; pc[ agmp->bluefieldposition/8 ] = (color >> 16) & 0xff; } else { pc[ agmp->redfieldposition/8 ] = pc[ agmp->redfieldposition/8 ] * alpha / alphabase + (color & 0xff) * (alphabase - alpha ) / alphabase; pc[ agmp->greenfieldposition/8 ] = pc[ agmp->greenfieldposition/8 ] * alpha / alphabase + ((color >> 8 ) & 0xff) * (alphabase - alpha ) / alphabase; pc[ agmp->bluefieldposition/8 ] = pc[ agmp->bluefieldposition/8 ] * alpha / alphabase + ((color >> 16) & 0xff) * (alphabase - alpha ) / alphabase; } */ } } } int getpixel(int x1, int y1) { if ( agmp->byteperpix == 1 ) return getpixel8( x1, y1 ); else { if ( agmp->windowstatus == 100 ) { char* pc = (char*) ( agmp->linearaddress + x1 * agmp->byteperpix + y1 * agmp->scanlinelength ); trgbpixel pix; pix.channel.r = pc[ agmp->redfieldposition/8 ]; pix.channel.g = pc[ agmp->greenfieldposition/8 ]; pix.channel.b = pc[ agmp->bluefieldposition/8 ]; pix.channel.a = 0; return pix.rgb; } else { return -1; } } } TrueColorImage :: TrueColorImage ( int x, int y ) { pix = new trgbpixel[x*y]; xsize = x; ysize = y; } TrueColorImage :: ~TrueColorImage ( ) { if ( pix ) { delete[] pix; pix = NULL; } } int getpixelfromimage ( void* buf, int x, int y ) { Uint16* wp = (Uint16*) buf; if ( x > wp[0] || y > wp[1] || x < 0 || y < 0 ) return -1; char* pc = (char*) buf; return pc[4 + x + y * (wp[0]+1) ]; } void TrueColorImage :: setpix ( int x, int y, int r, int g, int b, int alpha ) { trgbpixel* p = & pix[ x + y * xsize ]; p->channel.r = r; p->channel.g = g; p->channel.b = b; p->channel.a = alpha; } void TrueColorImage :: setpix ( int x, int y, const trgbpixel& _pix ) { pix[ x + y * xsize ] = _pix; } trgbpixel TrueColorImage :: getpix ( int x, int y ) { return pix[ x + y * xsize ]; } int TrueColorImage :: getxsize( void ) { return xsize; } int TrueColorImage :: getysize( void ) { return ysize; } #define f2i(x) (int(x)) #define f2i2(x) (int(x+0.5)) int newpalgenerated = 0; dacpalette256 ppal; TrueColorImage* zoomimage ( void* buf, int xsize, int ysize, dacpalette256 pal, int interpolate, int proportional ) { if ( !newpalgenerated ) for ( int i = 0; i < 256; i++ ) for ( int j = 0; j<3; j++ ) ppal[i][j] = pal[i][j] << 2; int orgx; int orgy; getpicsize ( buf, orgx, orgy ); { float ratiox = (float)xsize / (float)orgx; float ratioy = (float)ysize / (float)orgy; if ( proportional ) { if ( ratiox > ratioy ) xsize = (int) (ratioy * orgx); else ysize = (int) (ratiox * orgy); } } TrueColorImage* img = new TrueColorImage ( xsize, ysize ); float dx = (float)orgx / (float)xsize; float dy = (float)orgy / (float)ysize; float oy = 0; for ( int y = 0; y < ysize; y++, oy+=dy ) { int oyi = f2i ( oy ); float oyif = oyi; float ox = 0; for ( int x = 0; x < xsize; x++,ox+=dx ) { float r = 0; float g = 0; float b = 0; float alpha = 0; if ( interpolate ) { float d; int oxi = f2i ( ox ); float oxif = oxi; float dist = 0; int alphanum = 0; // pixel links oben int px1 = getpixelfromimage ( buf, oxi, oyi ); int px2 = getpixelfromimage ( buf, oxi+1, oyi ); int px3 = getpixelfromimage ( buf, oxi, oyi+1 ); int px4 = getpixelfromimage ( buf, oxi+1, oyi+1 ); if ( px1 == 255 && px2 == 255 && px3 == 255 && px4 == 255 ) { r = 0; g = 0; b = 0; alpha = alphabase; } else { if ( px1 >= 0 ) { d = ( 1-(ox - oxif)) * ( 1-( oy - oyif )); if ( px1 == 255 ) { alpha += ((float)alphabase) * d; alphanum++; } else { dist += d; r += ppal[px1][0] * d ; g += ppal[px1][1] * d ; b += ppal[px1][2] * d ; } } // pixel rechts oben if ( px2 >= 0 ) { d = (ox - oxif) * ( 1 - ( oy - oyif )); if ( px2 == 255 ) { alpha += ((float)alphabase) * d; alphanum++; } else { dist += d; r += ppal[px2][0] * d ; g += ppal[px2][1] * d ; b += ppal[px2][2] * d ; } } // pixel links unten if ( px3 >= 0 ) { d = ( 1- (ox - oxif)) * (oy - oyif); if ( px3 == 255 ) { alpha += ((float)alphabase) * d; alphanum++; } else { dist += d; r += ppal[px3][0] * d ; g += ppal[px3][1] * d ; b += ppal[px3][2] * d ; } } // pixel rechts unten if ( px4 >= 0 ) { d = (ox - oxif) * (oy - oyif); if ( px4 == 255 ) { alpha += ((float)alphabase) * d; alphanum++; } else { dist += d; r += ppal[px4][0] * d ; g += ppal[px4][1] * d ; b += ppal[px4][2] * d ; } } if ( alphanum <= 2 ) alpha = 0; if ( dist ) { r /= dist; g /= dist; b /= dist; alpha /= dist; } else { r = 0; g = 0; b = 0; alpha = alphabase; } } } else { int px = getpixelfromimage ( buf, f2i2(ox-0.01), f2i2(oy-0.01) ); if ( px == 255 ) alpha += alphabase ; else { r += ppal[px][0] ; g += ppal[px][1] ; b += ppal[px][2] ; } } img->setpix ( x, y, f2i(r), f2i(g), f2i(b), f2i(alpha) ); } } return img; } TrueColorImage* smoothimage ( TrueColorImage* src ) { TrueColorImage* dst = new TrueColorImage ( src->getxsize(), src->getysize() ); for ( int y = 0; y < src->getysize(); y++ ) for ( int x = 0; x < src->getxsize(); x++ ) { if ( src->getpix ( x, y ).channel.a < alphabase / 2 ) { int cnt = 0; int r = 0; int g = 0; int b = 0; for ( int a = -1; a <= 1; a++ ) for ( int bb = -1; bb <= 1; bb++ ) { int nx = x+a; int ny = y+bb; if ( nx >= 0 && ny >= 0 && nx < src->getxsize() && ny < src->getysize()) { trgbpixel p = src->getpix( nx, ny ); if ( p.channel.a < alphabase/2 ) { cnt++; r += p.channel.r; g += p.channel.g; b += p.channel.b; } } } dst->setpix ( x, y, r/cnt, g/cnt, b/cnt, 0 ); } else { dst->setpix ( x, y, 0, 0, 0, alphabase ); } } return dst; } #define sqr(a) (a)*(a) #define cub(a) abs ((a)*(a)*(a)) #ifndef minimal #include "basestrm.h" #endif TrueColorImage* convertimage2tc ( void* buf, dacpalette256 pal ) { if ( !buf ) return NULL; int x, y; getpicsize ( buf, x, y ); return zoomimage ( buf, x,y , pal, 0, 0 ); } int imagesize(int x1, int y1, int x2, int y2) { return ((x2 - x1 + 1) * (y2 - y1 + 1) + 4); } char* convertimage ( TrueColorImage* img, dacpalette256 pal ) { #ifndef minimal if ( truecolor2pal_table[0] == 255 ) { tfindfile ff ( "tc2pal.dat" ); if ( !ff.getnextname().empty() ) { tnfilestream stream ( "tc2pal.dat", tnstream::reading ); stream.readdata ( truecolor2pal_table, sizeof ( truecolor2pal_table )); } else { for ( int r = 0; r < 64; r++ ) for ( int g = 0; g < 64; g++ ) for ( int b = 0; b < 64; b++ ) { int sml = r + ( g << 6) + ( b << 12 ); int diff = 0xFFFFFFF; int pix1; for ( int k=0;k<256 ;k++ ) { int actdif = sqr( pal[k][0] - r ) + sqr( pal[k][1] - g ) + sqr( pal[k][2] - b ); if (actdif < diff) { diff = actdif; pix1 = k; } } truecolor2pal_table[sml] = pix1; } /* tnfilestream stream ( "tc2pal.dat", 2 ); stream.writedata ( truecolor2pal_table, sizeof ( truecolor2pal_table )); */ } } #endif int size = imagesize ( 1, 1, img->getxsize(), img->getysize() ); char* newimg = new char[ size ] ; char* start = newimg; Uint16* wp = (Uint16*) newimg; wp[0] = img->getxsize()-1; wp[1] = img->getysize()-1; newimg+= 4; for ( int y = 0; y <= wp[1]; y++ ) for ( int x = 0; x <= wp[0]; x++ ) { trgbpixel p = img->getpix ( x, y ); if ( p.channel.a <= alphabase*2/3 ) { int sml = ( p.channel.r >> 2) + (( p.channel.g >> 2) << 6) + (( p.channel.b >> 2) << 12); *newimg = truecolor2pal_table[sml]; } else { *newimg = 255; } newimg++; } if ( newimg - start > size ) printf("\a"); return (char*)wp; } fatalgraphicserror :: fatalgraphicserror ( char* strng ) { strcpy ( st, strng ); } fatalgraphicserror :: fatalgraphicserror ( void ) { st[0] = 0; } void putmask ( int x1, int y1, void* vbuf, int newtransparence ) { // int linecount = 0; // int rowcount = 0; Uint16* wp = (Uint16*) vbuf; char* basemembuf = (char*) (agmp->linearaddress + y1 * agmp->bytesperscanline + x1 * agmp->byteperpix ); char* img = (char*) vbuf + 4; for ( int y = 0; y <= wp[1]; y++ ) { char* membuf = basemembuf + y * agmp->bytesperscanline; for ( int x = 0; x <= wp[0]; x++ ) { if ( *img != newtransparence ) *membuf = *img; membuf += agmp->byteperpix; img++; } } } int graphicinitialized = 0; void* uncompress_rlepict ( void* pict ) { trleheader* hd = (trleheader*) pict; if (hd->id == 16973) { int w, h; getpicsize( pict, w, h ); w++; h++; void* newbuf = asc_malloc ( w * h + 4 ); Uint16* wp = (Uint16*) newbuf; char* dest = (char*) newbuf; wp[0] = w-1; wp[1] = h-1; dest +=4; char* buf = (char*) pict; buf += sizeof ( *hd ); for ( int c = 0; c < hd->size; c++ ) { if ( *buf == hd->rle ) { for ( int i = buf[1]; i > 0; i-- ) { *dest = buf[2]; dest++; } buf += 3; c += 2; } else { *dest = *buf; dest++; buf++; } } return newbuf; } else return NULL; } void setvgapalette256 ( dacpalette256 pal ) { if ( graphicinitialized ) set_vgapalette256( pal ); else memcpy ( activepalette256, pal, sizeof ( *activepalette256 )); } void ellipse ( int x1, int y1, int x2, int y2, int color, float tolerance ) { collategraphicoperations cgs ( x1, y1, x2, y2 ); int midx = (x1 + x2) / 2; int midy = (y1 + y2) / 2; float xr = x2 - x1; float yr = y2 - y1; tolerance = tolerance / (xr+yr) * 80; xr= (xr/2)*(xr/2); yr= (yr/2)*(yr/2); for ( int y = y1; y <= y2; y++ ) for ( int x = x1; x <= x2; x++ ) { float dx = x - midx; float dy = y - midy; float tmp = dx*dx/xr + dy*dy/yr; // float tmp = dx*dx*yr + dy*dy*xr; if ( tmp <= 1 + tolerance && tmp >= 1 - tolerance ) putpixel ( x, y, color ); } } char truecolor2pal_table[262144]; dacpalette256* activepalette256; class tinitgfxengine { public: tinitgfxengine ( void ); } initgfx; tinitgfxengine::tinitgfxengine ( void ) { memset ( truecolor2pal_table, 255, sizeof ( truecolor2pal_table )); hgmp = (tgraphmodeparameters *) & hardwaregraphmodeparameters; agmp = (tgraphmodeparameters *) & activegraphmodeparameters; activepalette256 = (dacpalette256*) &activepalette; xlatbuffer = asc_malloc ( xlatbuffersize ); } void tvirtualdisplay :: init ( int x, int y, int color, int depth ) { agmp = (tgraphmodeparameters *) & activegraphmodeparameters; oldparams = *agmp ; char* cbuf = (char*) asc_malloc ( x * y * depth/8 ); if ( !cbuf ) throw fatalgraphicserror ( "could not allocate memory !"); buf = cbuf; for ( int i = 0; i < (x*y*depth/8); i++ ) cbuf[i] = color; agmp->resolutionx = x ; agmp->resolutiony = y ; agmp->windowstatus = 100 ; agmp->scanlinelength = x*depth/8 ; agmp->scanlinenumber = y ; agmp->bytesperscanline = x * depth/8; agmp->byteperpix = depth/8 ; agmp->linearaddress = (PointerSizedInt) buf ; agmp->bitperpix = depth; agmp->directscreenaccess = 1; if ( depth ==24 || depth==32 ) { agmp->redmasksize = 8; agmp->greenmasksize = 8; agmp->bluemasksize = 8; agmp->redfieldposition = 0; agmp->greenfieldposition = 8; agmp->bluefieldposition = 16; } } tvirtualdisplay :: tvirtualdisplay ( int x, int y ) { init ( x, y, 0, 8 ); } tvirtualdisplay :: tvirtualdisplay ( int x, int y, int color, int depth ) { init ( x, y, color, depth ); } tvirtualdisplay :: ~tvirtualdisplay ( ) { asc_free ( buf ) ; *agmp = oldparams; } collategraphicoperations :: collategraphicoperations ( void ) { #ifndef _DOS_ status = 1; x1 = -1; y1 = -1; x2 = -1; y2 = -1; olddirectscreenaccess = agmp->directscreenaccess; agmp->directscreenaccess = 1; #endif } collategraphicoperations :: collategraphicoperations ( int _x1, int _y1, int _x2, int _y2 ) { #ifndef _DOS_ status = 1; x1 = _x1; y1 = _y1; x2 = _x2; y2 = _y2; olddirectscreenaccess = agmp->directscreenaccess; agmp->directscreenaccess = 1; #endif } void collategraphicoperations :: on ( void ) { #ifndef _DOS_ agmp->directscreenaccess = 1; status = 1; #endif } void collategraphicoperations :: off ( void ) { #ifndef _DOS_ status = 0; agmp->directscreenaccess = 0; if (agmp->directscreenaccess == 0) copy2screen( x1, y1, x2, y2 ); #endif } collategraphicoperations :: ~collategraphicoperations ( ) { #ifndef _DOS_ if ( status ) { agmp->directscreenaccess = olddirectscreenaccess; if (agmp->directscreenaccess == 0) copy2screen( x1, y1, x2, y2 ); } #endif } void copySurface2screen( void ) { if (agmp->directscreenaccess == 0) copy2screen( -1, -1, -1, -1 ); } void copySurface2screen( int x1, int y1, int x2, int y2 ) { if (agmp->directscreenaccess == 0) copy2screen( x1, y1, x2, y2 ); } tgraphmodeparameters activegraphmodeparameters; tgraphmodeparameters hardwaregraphmodeparameters; int dpmscapabilities; int actdpmsmode; dacpalette256 activepalette; int palette16[256][4]; void* xlatbuffer; // dacpalette256 *activepalette256; void bar(int x1, int y1, int x2, int y2, char color) { collategraphicoperations cgo ( x1, y1, x2, y2 ); if ( agmp->windowstatus == 100 ) { int spacelength = agmp->scanlinelength - (x2-x1) - 1; char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); for ( int y = y1; y <= y2; y++ ) { for ( int x = x1; x <= x2; x++ ) *(buf++) = color; buf+=spacelength; } } } void getimage(int x1, int y1, int x2, int y2, void *buffer) { if ( agmp->windowstatus == 100 ) { int spacelength = agmp->scanlinelength - (x2-x1) - 1; char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); char* cb = (char*) buffer; Uint16* wb = (Uint16*) buffer; wb[0] = x2 - x1; wb[1] = y2 - y1; cb += 4; for ( int y = y1; y <= y2; y++ ) { for ( int x = x1; x <= x2; x++ ) *(cb++) = *(buf++); buf+=spacelength; } } } void putimage ( int x1, int y1, void* img ) { char* src = (char*) img; if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); trleheader* hd = (trleheader*) img; if ( hd->id == 16973 ) { collategraphicoperations cgo ( x1, y1, x1+hd->x, y1+hd->y ); int spacelength = agmp->scanlinelength - hd->x - 1; src += sizeof ( *hd ); int x = 0; for ( int c = 0; c < hd->size; c++ ) { if ( *src == hd->rle ) { x += src[1]; for ( int i = src[1]; i > 0; i-- ) *(buf++) = src[2]; src += 3; c+=2; } else { *(buf++) = *(src++); x++; } if ( x > hd->x ) { buf += spacelength; x = 0; } } } else { Uint16* w = (Uint16*) img; collategraphicoperations cgo ( x1, y1, x1+w[0], y1+w[1] ); int spacelength = agmp->scanlinelength - *w - 1; src += 4; for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) *(buf++) = *(src++); buf+=spacelength; } } } } void putimage ( int x1, int y1, TrueColorImage* tci ) { for ( int y = 0; y < tci->getysize(); y++ ) for ( int x = 0; x < tci->getxsize(); x++ ) { trgbpixel t = tci->getpix ( x,y ); putpixel ( x1 + x, y1 + y, t.channel.r + 256*t.channel.g + 256*256*t.channel.b ); } } void putimage_noalpha ( int x1, int y1, TrueColorImage* tci ) { for ( int y = 0; y < tci->getysize(); y++ ) for ( int x = 0; x < tci->getxsize(); x++ ) { trgbpixel t = tci->getpix ( x,y ); if (t.channel.a > alphabase * 2 / 3 ) putpixel ( x1 + x, y1 + y, TCalpha ); else putpixel ( x1 + x, y1 + y, t.channel.r + 256*t.channel.g + 256*256*t.channel.b ); } } bool trgbpixel::isTransparent() { return ( channel.r == 0xfe && channel.g == 0xfe && channel.b == 0xfe ) ; } TrueColorImage* getimage ( int x1, int y1, int x2, int y2 ) { TrueColorImage* tci = new TrueColorImage ( x2-x1+1, y2-y1+1 ); for ( int y = 0; y < tci->getysize(); y++ ) for ( int x = 0; x < tci->getxsize(); x++ ) { trgbpixel t; t.rgb = getpixel ( x1 + x, y1 + y ); if ( t.isTransparent() ) t.channel.a = alphabase; tci->setpix ( x, y, t ); } return tci; } void putxlatfilter ( int x1, int y1, void* pic, char* xlattables ) { char* src = (char*) pic; if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); trleheader* hd = (trleheader*) pic; if ( hd->id == 16973 ) { collategraphicoperations cgo ( x1, y1, x1+hd->x, y1+hd->y ); int spacelength = agmp->scanlinelength - hd->x - 1; src += sizeof ( *hd ); int x = 0; for ( int c = 0; c < hd->size; c++ ) { if ( *src == hd->rle ) { x += src[1]; for ( int i = src[1]; i > 0; i-- ) { if ( src[2] != 255 ) *buf = xlattables[ src[2] * 256 + *buf ]; buf++; } src += 3; c+=2; } else { if ( *src != 255 ) *buf = xlattables[ *(src++) * 256 + *buf ]; else src++; buf++; x++; } if ( x > hd->x ) { buf += spacelength; x = 0; } } } else { Uint16* w = (Uint16*) pic; collategraphicoperations cgo ( x1, y1, x1+w[0], y1+w[1] ); int spacelength = agmp->scanlinelength - *w - 1; src += 4; for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) { if ( *src != 255 ) *buf = xlattables[ *(src++) * 256 + *buf ]; else src++; buf++; } buf+=spacelength; } } } } void putspriteimage ( int x1, int y1, void* pic ) { char* src = (char*) pic; if ( agmp->windowstatus == 100 ) { trleheader* hd = (trleheader*) pic; char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); if ( hd->id == 16973 ) { collategraphicoperations cgo ( x1, y1, x1+hd->x, y1+hd->y ); int spacelength = agmp->scanlinelength - hd->x - 1; src += sizeof ( *hd ); int x = 0; for ( int c = 0; c < hd->size; c++ ) { if ( *src == hd->rle ) { x += src[1]; if ( src[2] != 255 ) { for ( int i = src[1]; i > 0; i-- ) *(buf++) = src[2]; } else buf += src[1]; src += 3; c+=2; } else { if ( *src != 255 ) *buf = *src; buf++; src++; x++; } if ( x > hd->x ) { buf += spacelength; x = 0; } } } else { Uint16* w = (Uint16*) pic; collategraphicoperations cgo ( x1, y1, x1+w[0], y1+w[1] ); int spacelength = agmp->scanlinelength - *w - 1; src += 4; for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) { char d = *(src++); if ( d != 255 ) *buf = d; buf++; } buf+=spacelength; } } } } void putrotspriteimage(int x1, int y1, void *pic, int rotationvalue) { char* src = (char*) pic; if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); trleheader* hd = (trleheader*) pic; if ( hd->id == 16973 ) { collategraphicoperations cgo ( x1, y1, x1+hd->x, y1+hd->y ); int spacelength = agmp->scanlinelength - hd->x - 1; src += sizeof ( *hd ); int x = 0; for ( int c = 0; c < hd->size; c++ ) { if ( *src == hd->rle ) { x += src[1]; char d = src[2]; if ( d != 255 ) { if ( d >= 16 && d < 24 ) d += rotationvalue; for ( int i = src[1]; i > 0; i-- ) *(buf++) = d; } else buf += src[1]; src += 3; c+=2; } else { char d = *(src++); if ( d != 255 ) { if ( d >= 16 && d < 24 ) d += rotationvalue; *(buf++) = d; } else buf++; x++; } if ( x > hd->x ) { buf += spacelength; x = 0; } } } else { Uint16* w = (Uint16*) pic; collategraphicoperations cgo ( x1, y1, x1+w[0], y1+w[1] ); int spacelength = agmp->scanlinelength - *w - 1; src += 4; for ( int y = w[1] + 1; y > 0; y-- ) { for ( int x = w[0]+1; x > 0; x-- ) { char d = *(src++); if ( d != 255 ) { if ( d >= 16 && d < 24 ) d += rotationvalue; *buf = d; } buf++; } buf+=spacelength; } } } } void putrotspriteimage90(int x1, int y1, void *pic, int rotationvalue) { Uint16* w = (Uint16*) pic; // char* c = (char*) pic + 4; int spacelength = agmp->scanlinelength - w[1] - 1; collategraphicoperations cgo ( x1, y1, x1+w[1], y1+w[0] ); if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); for ( int y = 0; y <= w[0] ; y++ ) { for ( int x = 0; x <= w[1]; x++ ) { int d = getpixelfromimage ( pic, y, w[1] - x ); if ( d != 255 && d != -1) { if ( d >= 16 && d < 24 ) d += rotationvalue; *buf = d; } buf++; } buf+=spacelength; } } } void putrotspriteimage180(int x1, int y1, void *pic, int rotationvalue) { Uint16* w = (Uint16*) pic; collategraphicoperations cgo ( x1, y1, x1+w[0], y1+w[1] ); // char* c = (char*) pic + 4; int spacelength = agmp->scanlinelength - *w - 1; if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); for ( int y = 0; y <= w[1] ; y++ ) { for ( int x = 0; x <= w[0]; x++ ) { int d = getpixelfromimage ( pic, w[0] - x, w[1] - y ); if ( d != 255 && d != -1) { if ( d >= 16 && d < 24 ) d += rotationvalue; *buf = d; } buf++; } buf+=spacelength; } } } void putrotspriteimage270(int x1, int y1, void *pic, int rotationvalue) { Uint16* w = (Uint16*) pic; collategraphicoperations cgo ( x1, y1, x1+w[0], y1+w[1] ); // char* c = (char*) pic + 4; int spacelength = agmp->scanlinelength - *w - 1; if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); for ( int y = 0; y <= w[1] ; y++ ) { for ( int x = 0; x <= w[0]; x++ ) { int d = getpixelfromimage ( pic, w[1] - y, x ); if ( d != 255 && d != -1) { if ( d >= 16 && d < 24 ) d += rotationvalue; *buf = d; } buf++; } buf+=spacelength; } } } void puttexture ( int x1, int y1, int x2, int y2, void *texture ) { collategraphicoperations cgo ( x1, y1, x2, y2 ); char* c = (char*) texture; int spacelength = agmp->scanlinelength - (x2 - x1) - 1; if ( agmp->windowstatus == 100 ) { int offset = agmp->scanlinelength * y1 + x1; char* buf = (char*) agmp->linearaddress; for ( int y = y1 ; y <= y2; y++ ) { for ( int x = x1; x <= x2 ; x++ ) { buf[offset] = c[offset]; offset++; } offset+=spacelength; } } } void putspritetexture ( int x1, int y1, int x2, int y2, void *texture ) { collategraphicoperations cgo ( x1, y1, x2, y2 ); char* c = (char*) texture; int spacelength = agmp->scanlinelength - (x2 - x1) - 1; if ( agmp->windowstatus == 100 ) { int offset = agmp->scanlinelength * y1 + x1; char* buf = (char*) agmp->linearaddress; for ( int y = y1 ; y <= y2; y++ ) { for ( int x = x1; x <= x2 ; x++ ) { char d = c[offset]; if ( d != 255 ) buf[offset] = d; offset++; } offset+=spacelength; } } } void putimageprt ( int x1, int y1, int x2, int y2, void *texture, int dx, int dy ) { collategraphicoperations cgo ( x1, y1, x2, y2 ); int spacelength = agmp->scanlinelength - (x2-x1) - 1; if ( agmp->windowstatus == 100 ) { char* buf = (char*) (agmp->scanlinelength * y1 + x1 * agmp->byteperpix + agmp->linearaddress); for ( int y = y1; y <= y2 ; y++ ) { for ( int x = x1; x <= x2; x++ ) { int p = getpixelfromimage ( texture, x - x1 + dx, y - y1 + dy ); if ( p != -1 ) *buf = p; buf++; } buf+=spacelength; } /* for ( int y = 0; y <= w[1] ; y++ ) { for ( int x = 0; x <= w[0]; x++ ) { int p = getpixelfromimage ( texture, x + dx, y + dy ); if ( p != -1 ) *buf = p; buf++; } buf+=spacelength; } */ } } void copybuf2displaymemory(int size, void *buf) { collategraphicoperations cgo ; memcpy ( (void*) agmp->linearaddress, buf, size ); } void* xlatpict ( ppixelxlattable xl, void* vbuf ) { char* buf = (char*) vbuf; Uint16* wp = (Uint16*) xlatbuffer; char* dest = (char*) xlatbuffer; trleheader* hd = (trleheader*) vbuf; if ( hd->id == 16973 ) { memcpy ( xlatbuffer, vbuf, sizeof ( *hd )); trleheader* desthead = (trleheader*) xlatbuffer; dest += sizeof ( *hd ); buf += sizeof ( *hd ); for ( int c = 0; c < hd->size; c++ ) if ( *buf == hd->rle ) { *(dest++) = *(buf++); *(dest++) = *(buf++); *(dest++) = (*xl)[ *(buf++) ]; c += 2; } else { int newpix = (*xl)[ *(buf++) ]; if ( newpix == hd->rle ) { *(dest++) = hd->rle; *(dest++) = 1; *(dest++) = hd->rle; desthead->size += 2; } else *(dest++) = newpix; } } else { Uint16* wp2 = (Uint16*) vbuf; wp[0] = wp2[0]; wp[1] = wp2[1]; /* if ( ( wp[0] + 1 ) * ( wp[1] + 1 ) + 4 >= xlatbuffersize ) throw fatalgraphicserror ( "halfpict : picture larger than buffer ! " ); */ dest += 4; buf += 4; for ( int c = (wp2[0] + 1) * (wp2[1] + 1); c > 0; c-- ) { *dest = (*xl)[ *buf ]; dest++; buf++; } } return xlatbuffer; } int loga2 ( int a ) { int l = 0; if ( a ) while ( ! (a & 1)) { a >>= 1; l++; } return l; } void showtext ( const char* text, int x, int y, int textcol ) { if ( !activefontsettings.font ) return; if ( !text ) return; char* fb = (char*)(x * agmp->byteperpix + y * agmp->scanlinelength + agmp->linearaddress); int fontheight; int extraheight = 0; if ( activefontsettings.height == 0 ) fontheight = activefontsettings.font->height; else if ( activefontsettings.height > activefontsettings.font->height ) { fontheight = activefontsettings.font->height; extraheight = activefontsettings.height - activefontsettings.font->height; } else fontheight = activefontsettings.height; const char* t = text; int length = 0; char* characterpointer[1024]; int characterwidth[1024]; int characterdist[1024]; int ps = 0; while ( *t ) { if ( activefontsettings.font->character[*t].width ) { characterwidth[ps] = activefontsettings.font->character[*t].width; characterpointer[ps] = activefontsettings.font->character[*t].memposition + 2; if ( t[1] ) characterdist[ps] = activefontsettings.font->kerning[t[1]][t[0]] + 2; else characterdist[ps] = 0; length +=activefontsettings.font->character[*t].width; length += characterdist[ps]; ps++; } t++; } int leftextralength; int rightextralength; if ( !activefontsettings.length ) leftextralength = rightextralength = 0; else { if ( activefontsettings.justify == 0 ) { leftextralength = 0; if ( activefontsettings.length > length ) rightextralength = activefontsettings.length - length; else { rightextralength = 0; length = activefontsettings.length; } } else if ( activefontsettings.justify == 1 ) { if ( activefontsettings.length > length ) { leftextralength = (activefontsettings.length - length+2)/2; rightextralength = activefontsettings.length - length - leftextralength; } else { rightextralength = 0; leftextralength = 0; length = activefontsettings.length; } } else if ( activefontsettings.justify == 2 ) { rightextralength = 0; if ( activefontsettings.length > length ) leftextralength = activefontsettings.length - length; else { leftextralength = 0; length = activefontsettings.length; } } } collategraphicoperations cgo ( x, y, x +length + leftextralength + rightextralength, y + fontheight + extraheight ); int suppressbkgr = 0; int spacelength = agmp->scanlinelength - (length + leftextralength + rightextralength); if ( activefontsettings.background == 255 ) { spacelength += leftextralength + rightextralength; fb += leftextralength; leftextralength = rightextralength = 0; extraheight = 0; } for ( int yl = 0; yl < fontheight; yl++ ) { if ( leftextralength ) for ( int i = 0; i < leftextralength; i++ ) *(fb++) = activefontsettings.background; int x = 0; ps = 0; while ( x < length ) { int cx; for ( cx = characterwidth[ps]; cx > 0 && x < length; cx--) { int pix = *(characterpointer[ps]++); if ( pix ) if ( textcol != -1 ) *fb = textcol; else *fb = pix; else if ( activefontsettings.background != 255 ) if ( suppressbkgr ) suppressbkgr--; else *fb = activefontsettings.background; fb++; x++; } /* endfor */ if ( x < length ) { if ( characterdist[ps] > 0 ) { for (int i = characterdist[ps]; i && x < length; i-- ) { if ( activefontsettings.background != 255 ) *fb = activefontsettings.background; fb++; x++; } /* endfor */ } else { fb += characterdist[ps]; x += characterdist[ps]; suppressbkgr = -characterdist[ps]; } } else { characterpointer[ps] += cx; } ps++; } if ( rightextralength ) for ( int i = 0; i < rightextralength; i++ ) *(fb++) = activefontsettings.background; fb += spacelength; } if ( extraheight ) for ( int yl = extraheight; yl > 0; yl-- ) { for ( int x = length + leftextralength + rightextralength; x > 0; x-- ) *(fb++) = activefontsettings.background; fb += spacelength; } } void showtext2 ( const ASCString& text, int x, int y ) { showtext ( text.c_str(), x, y, activefontsettings.color ); } void showtext2c ( const ASCString& text, int x, int y ) { showtext ( text.c_str(), x, y, -1 ); } void* convertSurface ( SDLmm::Surface& s, bool paletteTranslation ) { s.Lock(); char* buf = new char[ imagesize ( 1, 1, s.w(), s.h())]; Uint16* wp = (Uint16*) buf; wp[0] = s.w()-1; wp[1] = s.h()-1; SDLmm::PixelFormat fmt = s.GetPixelFormat(); if ( fmt.BytesPerPixel() == 1 && !paletteTranslation ) { for ( int y = 0; y < s.h(); y++ ) for ( int x = 0; x < s.w(); x++ ) buf[4 + s.w()*y+x] = s.GetPixel ( x, y ); } else { for ( int y = 0; y < s.h(); y++ ) for ( int x = 0; x < s.w(); x++ ) { Uint8 red, green, blue, alpha; fmt.GetRGBA ( s.GetPixel ( x, y ), red, green, blue, alpha); if ( alpha < 128 ) buf[4 + s.w()*y+x] = 255; else buf[4 + s.w()*y+x] = truecolor2pal_table[ (red >> 2) + (( green >> 2) << 6) + (( blue >> 2) << 12) ]; } } s.Unlock(); return buf; }