mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2026-04-16 02:51:26 -06:00
Implement new DibBitmap code
Implemented with SDL API
This commit is contained in:
parent
de281e5fd7
commit
bc8777e56e
283
game/bitmap.cpp
283
game/bitmap.cpp
@ -0,0 +1,283 @@
|
||||
#include "ht.h"
|
||||
|
||||
#if defined(SDL)
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
|
||||
#define SURFACE_FLAGS 0
|
||||
#define SURFACE_DEPTH 32
|
||||
#define SURFACE_PITCH(x) x*4 // row length in bytes: x*sizeof(byte)*sizeof(dword)
|
||||
#define SHADOW_ALPHA_MOD 100
|
||||
#endif // defined(SDL)
|
||||
|
||||
namespace wi {
|
||||
|
||||
#if defined(SDL)
|
||||
|
||||
DibBitmap::DibBitmap()
|
||||
{
|
||||
m_surface = NULL;
|
||||
m_wf = 0;
|
||||
m_pszFn = NULL;
|
||||
m_renderer = NULL;
|
||||
}
|
||||
|
||||
DibBitmap::~DibBitmap()
|
||||
{
|
||||
SDL_DestroyRenderer(m_renderer);
|
||||
SDL_FreeSurface(m_surface);
|
||||
if (m_wf & kfDibFreeMem)
|
||||
free(m_surface->pixels);
|
||||
m_surface = NULL;
|
||||
if (m_pszFn != NULL)
|
||||
delete[] m_pszFn;
|
||||
}
|
||||
|
||||
DibBitmap *LoadDibBitmap(char *pszFn)
|
||||
{
|
||||
DibBitmap *pbm = new DibBitmap();
|
||||
Assert(pbm != NULL, "out of memory!");
|
||||
if (pbm == NULL)
|
||||
return NULL;
|
||||
if (!pbm->Init(pszFn)) {
|
||||
delete pbm;
|
||||
return NULL;
|
||||
}
|
||||
return pbm;
|
||||
}
|
||||
|
||||
DibBitmap *CreateDibBitmap(dword *pb, int cx, int cy, bool alpha)
|
||||
{
|
||||
DibBitmap *pbm = new DibBitmap();
|
||||
Assert(pbm != NULL, "out of memory!");
|
||||
if (pbm == NULL)
|
||||
return NULL;
|
||||
if (!pbm->Init(pb, cx, cy, alpha, false)) {
|
||||
delete pbm;
|
||||
return NULL;
|
||||
}
|
||||
return pbm;
|
||||
}
|
||||
|
||||
DibBitmap *CreateBigDibBitmap(dword *pb, int cx, int cy, bool alpha)
|
||||
{
|
||||
DibBitmap *pbm = new DibBitmap();
|
||||
Assert(pbm != NULL, "out of memory!");
|
||||
if (pbm == NULL)
|
||||
return NULL;
|
||||
if (!pbm->Init(pb, cx, cy, alpha, true)) {
|
||||
delete pbm;
|
||||
return NULL;
|
||||
}
|
||||
return pbm;
|
||||
}
|
||||
|
||||
bool DibBitmap::Init(char *pszFn)
|
||||
{
|
||||
// Read the file
|
||||
|
||||
File *pfil = gpakr.fopen(pszFn, "rb");
|
||||
if (pfil == NULL)
|
||||
return false;
|
||||
byte *pb = new byte[pfil->cbTotal];
|
||||
|
||||
if (gpakr.fread(pb, pfil->cbTotal, 1, pfil) != 1)
|
||||
return false;
|
||||
|
||||
// Feed the bytes into an SDL surface
|
||||
|
||||
SDL_RWops *prwio = SDL_RWFromMem(pb, pfil->cbTotal);
|
||||
m_surface = IMG_Load_RW(prwio, 0);
|
||||
|
||||
// Cleanup
|
||||
|
||||
SDL_FreeRW(prwio);
|
||||
delete[] pb;
|
||||
gpakr.fclose(pfil);
|
||||
|
||||
// Keep the name around
|
||||
|
||||
m_pszFn = AllocString(pszFn);
|
||||
|
||||
return m_surface != NULL;
|
||||
}
|
||||
|
||||
bool DibBitmap::Init(dword *pb, int cx, int cy, bool alpha, bool bigendian)
|
||||
{
|
||||
Uint32 rmask, gmask, bmask, amask;
|
||||
if (bigendian) {
|
||||
rmask = 0x000000ff;
|
||||
gmask = 0x0000ff00;
|
||||
bmask = 0x00ff0000;
|
||||
amask = 0xff000000;
|
||||
} else {
|
||||
rmask = 0xff000000;
|
||||
gmask = 0x00ff0000;
|
||||
bmask = 0x0000ff00;
|
||||
amask = 0x000000ff;
|
||||
}
|
||||
if (!alpha)
|
||||
amask = 0;
|
||||
|
||||
if (pb == NULL) {
|
||||
m_surface = SDL_CreateRGBSurface(SURFACE_FLAGS, cx, cy, SURFACE_DEPTH,
|
||||
rmask, gmask, bmask, amask);
|
||||
} else {
|
||||
m_surface = SDL_CreateRGBSurfaceFrom(pb, cx, cy, SURFACE_DEPTH, SURFACE_PITCH(cx),
|
||||
rmask, gmask, bmask, amask);
|
||||
|
||||
// When using SDL_CreateRGBSurfaceFrom(), SDL does not manage the pixel data
|
||||
// so it will need to be freed manually
|
||||
|
||||
m_wf |= kfDibFreeMem;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This can be used to set the alpha color (only works if amask is 0)
|
||||
// SDL_SetColorKey(m_surface, 1, SDL_MapRGB(m_surface->format, 255, 0, 255));
|
||||
#endif
|
||||
|
||||
return m_surface != NULL;
|
||||
}
|
||||
|
||||
void DibBitmap::Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst)
|
||||
{
|
||||
if (prcSrc == NULL) {
|
||||
SDL_Rect rcDst = { xDst, yDst, pbmSrc->GetSurface()->w, pbmSrc->GetSurface()->h };
|
||||
SDL_BlitSurface(pbmSrc->GetSurface(), NULL, m_surface, &rcDst);
|
||||
} else {
|
||||
SDL_Rect rcSrc = { prcSrc->left, prcSrc->top, prcSrc->Width(), prcSrc->Height() };
|
||||
SDL_Rect rcDst = { xDst, yDst, prcSrc->Width(), prcSrc->Height() };
|
||||
SDL_BlitSurface(pbmSrc->GetSurface(), &rcSrc, m_surface, &rcDst);
|
||||
}
|
||||
}
|
||||
|
||||
void DibBitmap::BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc)
|
||||
{
|
||||
if (prcSrc == NULL) {
|
||||
SDL_Rect rcDst = { xDst, yDst, m_surface->w, m_surface->h };
|
||||
SDL_BlitSurface(m_surface, NULL, pbmDst->GetSurface(), &rcDst);
|
||||
} else {
|
||||
SDL_Rect rcSrc = { prcSrc->left, prcSrc->top, prcSrc->Width(), prcSrc->Height() };
|
||||
SDL_Rect rcDst = { xDst, yDst, prcSrc->Width(), prcSrc->Height() };
|
||||
SDL_BlitSurface(m_surface, &rcSrc, pbmDst->GetSurface(), &rcDst);
|
||||
}
|
||||
}
|
||||
|
||||
void DibBitmap::BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst)
|
||||
{
|
||||
bool fFirst = true;
|
||||
Rect rc;
|
||||
while (pupd->EnumUpdateRects(fFirst, NULL, &rc)) {
|
||||
fFirst = false;
|
||||
Blt(pbmSrc, &rc, rc.left, rc.top + yTopDst);
|
||||
}
|
||||
}
|
||||
|
||||
void DibBitmap::GetSize(Size *psiz)
|
||||
{
|
||||
psiz->cx = m_surface->w;
|
||||
psiz->cy = m_surface->h;
|
||||
}
|
||||
|
||||
dword *DibBitmap::GetBits()
|
||||
{
|
||||
return (dword *)m_surface->pixels;
|
||||
}
|
||||
|
||||
int DibBitmap::GetPitch()
|
||||
{
|
||||
return m_surface->pitch;
|
||||
}
|
||||
|
||||
void DibBitmap::Fill(int x, int y, int cx, int cy, Color clr)
|
||||
{
|
||||
SDL_Rect rc = { x, y, cx, cy };
|
||||
SDL_FillRect(m_surface, &rc, clr);
|
||||
}
|
||||
|
||||
void DibBitmap::FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
|
||||
int cxDst, int cyDst, int xOrigin, int yOrigin)
|
||||
{
|
||||
Rect rcclp;
|
||||
|
||||
// For every y point that is disivible by m_surface->h
|
||||
|
||||
for (int y = 0; y < cyDst; y++) {
|
||||
if (!(y % m_surface->h)) {
|
||||
|
||||
// For every x point that is disivible by m_surface->w
|
||||
|
||||
for (int x = 0; x < cxDst; x++) {
|
||||
if (!(x % m_surface->w)) {
|
||||
|
||||
// Blt and clip appropriately
|
||||
|
||||
rcclp.Set(xDst + x, yDst + y, cxDst, cyDst);
|
||||
pbmDst->Blt(this, NULL, xDst + x, yDst + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DibBitmap::Clear(Color clr)
|
||||
{
|
||||
Fill(0, 0, m_surface->w, m_surface->h, clr);
|
||||
}
|
||||
|
||||
void DibBitmap::Shadow(int x, int y, int cx, int cy)
|
||||
{
|
||||
DibBitmap *pbm = CreateDibBitmap(NULL, cx, cy);
|
||||
pbm->Clear(GetColor(kiclrBlack));
|
||||
|
||||
SDL_SetSurfaceBlendMode(pbm->GetSurface(), SDL_BLENDMODE_BLEND);
|
||||
SDL_SetSurfaceAlphaMod(pbm->GetSurface(), SHADOW_ALPHA_MOD);
|
||||
|
||||
pbm->BltTo(this, x, y);
|
||||
}
|
||||
|
||||
void DibBitmap::DrawLine(short x1, short y1, short x2, short y2, Color clr)
|
||||
{
|
||||
if (m_renderer == NULL)
|
||||
if ((m_renderer = SDL_CreateSoftwareRenderer(m_surface)) == NULL)
|
||||
return;
|
||||
|
||||
byte r, g, b;
|
||||
SDL_GetRGB(clr, m_surface->format, &r, &g, &b);
|
||||
|
||||
SDL_SetRenderDrawColor(m_renderer, r, g, b, 255);
|
||||
SDL_RenderDrawLine(m_renderer, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void DibBitmap::Scroll(Rect *prcSrc, int xDst, int yDst)
|
||||
{
|
||||
// Some implementations do blts differently (such as rotated dibs).
|
||||
// That is why this method - essentially a blt from and to the
|
||||
// destination - exists.
|
||||
Blt(this, prcSrc, xDst, yDst);
|
||||
}
|
||||
|
||||
|
||||
DibBitmap *DibBitmap::Suballoc(int yTop, int cy)
|
||||
{
|
||||
Assert(yTop < m_surface->h && yTop + cy <= m_surface->h);
|
||||
dword *pb = (dword *)m_surface->pixels + (long)m_surface->w * yTop;
|
||||
DibBitmap *pbm = CreateDibBitmap(pb, m_surface->w, cy);
|
||||
|
||||
// We don't want it to free memory since that will be taken care
|
||||
// of by 'this'
|
||||
if (pbm != NULL)
|
||||
pbm->SetFlags(pbm->GetFlags() & ~kfDibFreeMem);
|
||||
|
||||
return pbm;
|
||||
}
|
||||
|
||||
dword DibBitmap::MapRGB(byte r, byte g, byte b)
|
||||
{
|
||||
return SDL_MapRGB(m_surface->format, r, g, b);
|
||||
}
|
||||
|
||||
#endif // defined(SDL)
|
||||
|
||||
} // namespace wi
|
||||
65
game/ht.h
65
game/ht.h
@ -1055,6 +1055,71 @@ struct TBitmapHeader // tbh
|
||||
TBitmapEntry atbe[1];
|
||||
};
|
||||
|
||||
// DibBitmap
|
||||
|
||||
#define kfDibFreeMem 0x0001
|
||||
#define kfDibBackWindow 0x0002
|
||||
#define kfDibWantScrolls 0x0004
|
||||
|
||||
class DibBitmap
|
||||
{
|
||||
public:
|
||||
DibBitmap() secDibBitmap;
|
||||
~DibBitmap() secDibBitmap;
|
||||
|
||||
bool Init(char *pszFn) secDibBitmap;
|
||||
bool Init(dword *pb, int cx, int cy, bool alpha, bool bigendian) secDibBitmap;
|
||||
|
||||
void Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst) secDibBitmap;
|
||||
void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc = NULL) secDibBitmap;
|
||||
void BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst) secDibBitmap;
|
||||
|
||||
void GetSize(Size *psiz) secDibBitmap;
|
||||
dword *GetBits() secDibBitmap;
|
||||
int GetPitch() secDibBitmap;
|
||||
|
||||
void Fill(int x, int y, int cx, int cy, Color clr) secDibBitmap;
|
||||
void FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
|
||||
int cxDst, int cyDst, int xOrigin = 0, int yOrigin = 0) secDibBitmap;
|
||||
void Clear(Color clr) secDibBitmap;
|
||||
void Shadow(int x, int y, int cx, int cy) secDibBitmap;
|
||||
void DrawLine(short x1, short y1, short x2, short y2, Color clr) secDibBitmap;
|
||||
void Scroll(Rect *prcSrc, int xDst, int yDst) secDibBitmap;
|
||||
|
||||
DibBitmap *Suballoc(int yTop, int cy) secDibBitmap;
|
||||
|
||||
word GetFlags() {
|
||||
return m_wf;
|
||||
}
|
||||
void SetFlags(word wf) {
|
||||
m_wf = wf;
|
||||
}
|
||||
int GetBaseline() {
|
||||
return 0;
|
||||
}
|
||||
char *GetFileName() {
|
||||
return m_pszFn;
|
||||
}
|
||||
|
||||
#if defined(SDL)
|
||||
int GetWidth() { return m_surface->w; }
|
||||
int GetHeight() { return m_surface->h; }
|
||||
dword MapRGB(byte r, byte g, byte b);
|
||||
SDL_Surface *GetSurface() { return m_surface; }
|
||||
#endif
|
||||
char *m_pszFn;
|
||||
|
||||
private:
|
||||
#if defined(SDL)
|
||||
SDL_Surface *m_surface;
|
||||
SDL_Renderer *m_renderer;
|
||||
#endif
|
||||
word m_wf;
|
||||
};
|
||||
DibBitmap *LoadDibBitmap(char *pszFn) secDibBitmap;
|
||||
DibBitmap *CreateDibBitmap(dword *pb, int cx, int cy, bool alpha = false) secDibBitmap;
|
||||
DibBitmap *CreateBigDibBitmap(dword *pb, int cx, int cy, bool alpha = false) secDibBitmap;
|
||||
|
||||
struct FontHeader // fnth
|
||||
{
|
||||
word cy;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user