home *** CD-ROM | disk | FTP | other *** search
- //---------------------------------------------------------------------------
- //
- // File: BITMAP.CPP
- // Path: ...\REHACK\graphics
- // Version: 1.1
- // Author: Dave Boynton
- // CIS Id: 71043,317
- // Created On: 6/26/93
- // Modified On: 7/25/93
- // Description: Bitmap class methods, requires pcx256 & display
- // classes.
- // Tabs: 4
- //
- //---------------------------------------------------------------------------
- // copyright (c) 1993 by the GAMERS Forum, Rehack project team.
- // All rights reserved.
- #include <alloc.h>
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <mem.h>
- #include "..\general\types.hpp"
- #include "..\general\misc.hpp"
- #include "..\graphics\pcx.hpp"
- #include "..\graphics\bitmap.hpp"
- #include "..\graphics\display.hpp"
-
- // -------------------------- Bitmap --------------------------------
- Bitmap::Bitmap(word width, word height, bool Direct)
- {
- memset(this, 0, sizeof(Bitmap));
- validFlag=true;
- if ( Direct )
- {
- directFlag=true;
- BitmapSetup(width,height);
- // bits must be set externally
- } else {
- directFlag=false;
- BitmapSetup(width, height);
- bits=new byte[(word)(width * height)];
- if ( bits )
- memset(bits,0,width*height);
- else
- validFlag=false;
- }
- }
-
- Bitmap::Bitmap(const OwnerRect &theBounds)
- {
- memset(this, 0, sizeof(Bitmap));
- word sizeX, sizeY;
- sizeX=(theBounds.bottomRight.x - theBounds.topLeft.x);
- sizeY=(theBounds.bottomRight.y - theBounds.topLeft.y);
-
- directFlag=false;
- BitmapSetup(sizeX, sizeY);
- bits=new byte[sizeX * sizeY];
- if ( bits )
- {
- ownerBounds=theBounds;
- } else
- validFlag=false;
- }
-
- Bitmap::Bitmap(char *filename, BitmapFileType fileType)
- {
- memset(this, 0, sizeof(Bitmap));
- validFlag=false;
- if ( ( fileType == detect ) &&
- ( (fileType=detectFileType(filename)) == 0 ) )
- return;
-
- FILE *fp;
- if ( (fp=fopen(filename,"rb")) != NULL )
- {
- BitmapLoad(fp, fileType);
- fclose(fp);
- } // end fopen's else
- }
-
- Bitmap::Bitmap(FILE *fp, BitmapFileType fileType)
- { // presumably within a resource file
- memset(this, 0, sizeof(Bitmap));
- validFlag=false;
- BitmapLoad(fp, fileType); // takes care of everything
- }
-
- BitmapFileType Bitmap::detectFileType(char *filename)
- {
- switch ( *(filename+strlen(filename)-1) )
- {
- case 'x':
- case 'X':
- return pcx;
- case 'g':
- case 'G':
- return img;
- case 'a':
- case 'A':
- return vga;
- default:
- return detect;
- }
- }
-
- // if bitmap.validFlag=false, this does a BitmapSetup with the file's
- // attributes and allocates memory for the bitmap
- void Bitmap::BitmapLoad(FILE *fp, BitmapFileType fileType)
- {
- switch (fileType)
- {
- case vga: // BGI graphics file, .VGA, as used by MVP Paint
- // struct vgaFile {
- // word widthMinusOne, heightMinusOne;
- // byte pixels[(widthMinusOne+1) * (heightMinusOne+1)];
- // byte padding[]; // this is useless, but the
- // // filesize must be correct
- // // or MVP won't read it
- // byte palette[768]; // (optional)
- // };
-
- case img: // ACK-3d file, .IMG
- // struct imgFile {
- // word width, height; // img_ed & ack assume 64x64
- // byte pixels[width*height];
- // };
-
- word fsizeX, fsizeY;
- if ( ( fread(&fsizeX,sizeof(fsizeX),1,fp) == 1 ) &&
- ( fread(&fsizeY,sizeof(fsizeY),1,fp) == 1 ) )
- {
- word sizeX, sizeY;
- if ( validFlag == false )
- {
- sizeX=fsizeX; sizeY=fsizeY;
- if ( fileType == img )
- {
- directFlag=false;
- BitmapSetup(sizeX, sizeY);
- bits=new byte[sizeX * sizeY];
- } else {// == vga
- BitmapSetup(sizeX+1, sizeY+1);
- bits=new byte[(sizeX+1) * (sizeY+1)];
- }
- if ( bits == NULL )
- validFlag=false;
- if ( validFlag == false )
- return;
- } else {
- // the bitmap is already established, and may be
- // a different size than the file
- sizeX=localBounds.bottomRight.x;
- sizeY=localBounds.bottomRight.y;
- if ( sizeY > fsizeY )
- sizeY=fsizeY;
- }
- word row;
- if ( fsizeX > sizeX )
- {
- word colSkip=fsizeX - sizeX;
- for (row=0; row<sizeY; row++)
- {
- if ( (fread(bits+(row*sizeX), sizeX, 1, fp) != 1) ||
- (fseek(fp, colSkip, SEEK_CUR) != 0 ) )
- {
- invalidate();
- return;
- }
- }
- } else {
- for (row=0; row<sizeY; row++)
- {
- if ( fread(bits+(row*sizeX), fsizeX, 1, fp) != 1 )
- {
- invalidate();
- return;
- }
- }
- }
- } // end fread sizes
- break; // end cases: img vga
-
- case pcx: // ZSoft PC-Paintbrush file, widely supported
- // for format details, download pcxref.txt
- PcxFile256 pcx(fp); //opens and reads header
- if ( pcx.validFlag == false )
- validFlag=false;
- else {
- if ( validFlag == false )
- {
- directFlag=false;
- BitmapSetup(pcx.hPixels, pcx.vPixels);
- if ( validFlag )
- {
- bits=new byte[pcx.hPixels * pcx.vPixels];
- if ( bits )
- memset(bits,0,pcx.hPixels*pcx.vPixels);
- else {
- validFlag=false;
- return;
- }
- }
- }
- if ( validFlag )
- {
- word row;
- word sizeX, sizeY, cSizeX;
-
- sizeX=localBounds.bottomRight.x;
- sizeY=localBounds.bottomRight.y;
- if ( pcx.vPixels < sizeY )
- sizeY=pcx.vPixels;
- if ( pcx.hPixels > sizeX )
- cSizeX=sizeX;
- else
- cSizeX=pcx.hPixels;
-
- assert( cSizeX <= sizeX );
- assert( (sizeY<201) && (sizeX<321) );
-
- for(row=0; row<sizeY; row++)
- {
- pcx.readLine( bits + (row * sizeX), 0, cSizeX-1);
- } // end for()
- } // end if ( type != 0 )
- }
- break; // end case: pcx
-
- default:
- validFlag=false; // just to make sure nothing gets by
- break;
-
- } // end switch (fileType)
- }
-
- bool Bitmap::BitmapSetup(word width, word height)
- {
- if ( ( width > 320 ) || ( height > 200 ) ||
- ( ((long)width * (long)height) > 0x0000ffffL ) )
- validFlag=false;
- else {
- if ( (validFlag) && (directFlag == false) && (bits != NULL) )
- invalidate();
- validFlag=true; dropoutColor=-1;
- localBounds.topLeft.x=0; localBounds.topLeft.y=0;
- localBounds.bottomRight.x=width;
- localBounds.bottomRight.y=height;
- viewPort=localBounds;
- ownerBounds=localBounds;
- }
- return validFlag;
- }
-
- void Bitmap::invalidate(void)
- {
- if ( (validFlag) && (directFlag == false) && (bits != NULL) )
- delete [] bits;
- validFlag=false; bits=NULL;
- }
-
- long Bitmap::getBitSize(Rect &bounds)
- {
- return (bounds.bottomRight.x - bounds.topLeft.x) *
- (bounds.bottomRight.y - bounds.topLeft.y);
- }
-
- // copy this' viewPort onto dest's viewPort, offset by Point &at (which
- // is relative to the bitmap's viewPort.
- void Bitmap::paint(Bitmap *dest, const Point &at)
- {
- Rect srcSize, destSize, srcRect, destRect; // destRect is local to dest
-
- destRect= (dest->viewPort + at) & dest->viewPort;
- destSize=destRect - destRect.topLeft; // shift to topLeft={ 0,0 },
- // bottomRight becomes size
-
- srcSize= (viewPort - viewPort.topLeft) & destSize;
- srcRect= (srcSize + viewPort.topLeft);
- destRect &= (srcSize + destRect.topLeft);
- // srcRect and destRect are now the same size, but local to their own
- // bitmap.
-
- if ( srcRect.isEmpty() || destRect.isEmpty() )
- return;
-
- byte * srcPtr;
- byte * destPtr;
- word srcWidth, destWidth, copyWidth;
-
- srcWidth=localBounds.bottomRight.x - localBounds.topLeft.x;
- destWidth=dest->localBounds.bottomRight.x - dest->localBounds.topLeft.x;
- copyWidth=srcRect.bottomRight.x - srcRect.topLeft.x;
-
- srcPtr=(srcRect.topLeft.y * srcWidth) + srcRect.topLeft.x + bits;
- destPtr=(destRect.topLeft.y * destWidth) + destRect.topLeft.x + dest->bits;
-
- if ( directFlag )
- {
- // VESA modes and Mode X will have to do something different.
- // If waiting for retraces or page flipping is necessary, then
- // it should be done here as well.
- }
- if ( dropoutColor == -1 )
- {
- word i;
- for (i=srcRect.topLeft.y; i<srcRect.bottomRight.y; i++)
- {
- memcpy(destPtr, srcPtr, copyWidth);
- destPtr+=destWidth;
- srcPtr+=srcWidth;
- }
- } else {
- word i;
- register word j;
- register byte c;
- // this needs heavy optimization!
- // an assembly routine using SCASB or SCASW I'd guess.
- for (i=srcRect.topLeft.y; i<srcRect.bottomRight.y; i++)
- for (j=0; j<copyWidth; j++)
- {
- c=*(srcPtr+j);
- if ( c != dropoutColor )
- *(destPtr+j)=c;
- }
- } // end if (dropoutColor == -1) {} else
- }
-
- // -------------------------- BitmapArray --------------------------------
- BitmapArray::BitmapArray(char *filename, Point TileSize,
- word XTiles, word YTiles, BitmapFileType FileType)
- : Bitmap(TileSize.x * XTiles, TileSize.y * YTiles)
- {
- if ( ( FileType == detect ) &&
- ( (FileType=detectFileType(filename)) == 0 ) )
- {
- validFlag=false;
- return;
- }
-
- FILE *fp;
- if ( (fp=fopen(filename,"rb")) == NULL )
- {
- invalidate();
- return;
- }
- BitmapLoad(fp,FileType);
- fclose(fp);
-
- tileSize=TileSize;
- xTiles=XTiles; yTiles=YTiles;
- setIndex(0,0);
- }
-
- BitmapArray::BitmapArray(FILE *fp, Point TileSize, word XTiles, word YTiles,
- BitmapFileType FileType)
- : Bitmap(TileSize.x * XTiles, TileSize.y * YTiles)
- {
- BitmapLoad(fp, FileType);
- tileSize=TileSize;
- xTiles=XTiles; yTiles=YTiles;
- setIndex( 0, 0 ); // sets viewPort to tile 0,0
- }
-
- void BitmapArray::setIndex(word xIndex, word yIndex)
- {
- if ( yIndex > yTiles )
- yIndex=yTiles;
- if ( yIndex > 0 )
- {
- if ( xIndex >= xTiles )
- xIndex=xTiles;
- } else {
- // allow access as a singly dimensioned array
- if ( xIndex >= xTiles )
- {
- yIndex= (xIndex / xTiles);
- xIndex= (xIndex % xTiles);
- }
- }
- viewPort.topLeft.x= tileSize.x * xIndex;
- viewPort.topLeft.y= tileSize.y * yIndex;
- viewPort.bottomRight.x= tileSize.x * (xIndex+1);
- viewPort.bottomRight.y= tileSize.y * (yIndex+1);
- viewPort &= localBounds; // just in case;
- index.x=xIndex; index.y=yIndex;
- }
-