mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-16 12:08:36 +00:00
258 lines
5.4 KiB
C++
258 lines
5.4 KiB
C++
#include "ht.h"
|
|
|
|
namespace wi {
|
|
|
|
// This exists soley for the purpose of being overridden
|
|
|
|
HtBitmap::~HtBitmap()
|
|
{
|
|
}
|
|
|
|
RawBitmap *LoadRawBitmap(char *pszFn)
|
|
{
|
|
RawBitmap *prbm = new RawBitmap();
|
|
if (prbm == NULL)
|
|
return NULL;
|
|
if (!prbm->Init(pszFn)) {
|
|
delete prbm;
|
|
return NULL;
|
|
}
|
|
return prbm;
|
|
}
|
|
|
|
RawBitmap::RawBitmap()
|
|
{
|
|
m_pfil = NULL;
|
|
m_cx = 0;
|
|
m_cy = 0;
|
|
}
|
|
|
|
RawBitmap::~RawBitmap()
|
|
{
|
|
if (m_pfil != NULL) {
|
|
gpakr.fclose(m_pfil);
|
|
m_pfil = NULL;
|
|
}
|
|
}
|
|
|
|
bool RawBitmap::Init(char *pszFn)
|
|
{
|
|
File *pfil = gpakr.fopen(pszFn, "rb");
|
|
if (pfil == NULL)
|
|
return false;
|
|
|
|
short cx;
|
|
if (gpakr.fread(&cx, sizeof(cx), 1, pfil) != 1) {
|
|
gpakr.fclose(pfil);
|
|
return false;
|
|
}
|
|
|
|
short cy;
|
|
if (gpakr.fread(&cy, sizeof(cy), 1, pfil) != 1) {
|
|
gpakr.fclose(pfil);
|
|
return false;
|
|
}
|
|
|
|
m_pfil = pfil;
|
|
m_cx = BigWord(cx);
|
|
m_cy = BigWord(cy);
|
|
return true;
|
|
}
|
|
|
|
void RawBitmap::GetSize(Size *psiz)
|
|
{
|
|
psiz->cx = m_cx;
|
|
psiz->cy = m_cy;
|
|
}
|
|
|
|
#if 0
|
|
// fread based blt
|
|
|
|
void RawBitmap::BltTo(DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc)
|
|
{
|
|
// Get dib dimensions
|
|
|
|
Size sizDib;
|
|
pbmDst->GetSize(&sizDib);
|
|
|
|
// Src rect to blt from
|
|
|
|
if (prcSrc == NULL) {
|
|
Rect rcSrcT;
|
|
rcSrcT.Set(0, 0, sizDib.cx, sizDib.cy);
|
|
prcSrc = &rcSrcT;
|
|
}
|
|
|
|
// Right and bottom edge clipping
|
|
|
|
if (sizDib.cx - xDst < prcSrc->Width())
|
|
prcSrc->right = prcSrc->left + sizDib.cx - xDst;
|
|
if (sizDib.cy - yDst < prcSrc->Height())
|
|
prcSrc->bottom = prcSrc->top + sizDib.cy - yDst;
|
|
|
|
// Left and top edge clipping
|
|
|
|
int xDstT = xDst;
|
|
if (xDstT < 0) {
|
|
prcSrc->left -= xDstT;
|
|
xDstT = 0;
|
|
}
|
|
int yDstT = yDst;
|
|
if (yDstT < 0) {
|
|
prcSrc->top -= yDstT;
|
|
yDstT = 0;
|
|
}
|
|
|
|
// Anything to blt?
|
|
|
|
if (prcSrc->IsEmpty())
|
|
return;
|
|
|
|
// Get destination address and dest row bytes
|
|
|
|
int cbRow = pbmDst->GetRowBytes();
|
|
byte *pbDst = pbmDst->GetBits() + (long)yDstT * cbRow + xDstT;
|
|
|
|
// Seek to the start of bits
|
|
|
|
gpakr.fseek(m_pfil, sizeof(word) * 2 + (long)prcSrc->top * m_cx + prcSrc->left, SEEK_SET);
|
|
|
|
// Can't use the scratch buffer to chunk because the decompressor
|
|
// uses it! Use this lame approach for now.
|
|
|
|
int cbSrcReturn = m_cx - prcSrc->Width();
|
|
int cy = prcSrc->Height();
|
|
for (int y = 0; y < cy; y++) {
|
|
if (gpakr.fread(pbDst, prcSrc->Width(), 1, m_pfil) != 1)
|
|
return;
|
|
if (cbSrcReturn != 0)
|
|
gpakr.fseek(m_pfil, cbSrcReturn, SEEK_CUR);
|
|
pbDst += cbRow;
|
|
}
|
|
}
|
|
#else
|
|
// Record mapping based blt
|
|
|
|
void RawBitmap::BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect *prcSrc)
|
|
{
|
|
BltTo(pbmDst, xDst, yDst, prcSrc);
|
|
}
|
|
|
|
void RawBitmap::BltTo(DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc)
|
|
{
|
|
// Src rect to blt from
|
|
|
|
Rect rcSrcT;
|
|
if (prcSrc == NULL) {
|
|
rcSrcT.Set(0, 0, m_cx, m_cy);
|
|
prcSrc = &rcSrcT;
|
|
}
|
|
|
|
// Right and bottom edge clipping
|
|
|
|
Size sizDib;
|
|
pbmDst->GetSize(&sizDib);
|
|
if (sizDib.cx - xDst < prcSrc->Width())
|
|
prcSrc->right = prcSrc->left + sizDib.cx - xDst;
|
|
if (sizDib.cy - yDst < prcSrc->Height())
|
|
prcSrc->bottom = prcSrc->top + sizDib.cy - yDst;
|
|
|
|
// Left and top edge clipping
|
|
|
|
int xDstT = xDst;
|
|
if (xDstT < 0) {
|
|
prcSrc->left -= xDstT;
|
|
xDstT = 0;
|
|
}
|
|
int yDstT = yDst;
|
|
if (yDstT < 0) {
|
|
prcSrc->top -= yDstT;
|
|
yDstT = 0;
|
|
}
|
|
|
|
// Anything to blt?
|
|
|
|
if (prcSrc->IsEmpty())
|
|
return;
|
|
|
|
// Get destination address and dest row bytes
|
|
|
|
int cbRowDst = pbmDst->GetRowBytes();
|
|
byte *pbDst = pbmDst->GetBits() + (long)yDstT * cbRowDst + xDstT;
|
|
|
|
// Seek to the start of bits
|
|
|
|
dword offBits = sizeof(word) * 2 + prcSrc->top * m_cx + prcSrc->left;
|
|
gpakr.fseek(m_pfil, offBits, SEEK_SET);
|
|
int nRecCurrent = BigWord(m_pfil->nRecFirst) + m_pfil->nRecOffStream;
|
|
dword offRecCurrent = m_pfil->offRecStart;
|
|
|
|
// Try to blt chunks as large as possible. If a scan intersects a record boundary, handle it
|
|
// specially.
|
|
|
|
int cxBlt = prcSrc->Width();
|
|
int cyLeft = prcSrc->Height();
|
|
byte *pbRec = NULL;
|
|
word cbRec;
|
|
void *pvCookie;
|
|
while (cyLeft > 0) {
|
|
// See how much we can blt from the current record
|
|
|
|
if (pbRec == NULL) {
|
|
pbRec = m_pfil->prnfo->ppdbReader->MapRecord(nRecCurrent, &pvCookie, &cbRec);
|
|
if (pbRec == NULL)
|
|
break;
|
|
}
|
|
|
|
dword cbRecLeft = offRecCurrent + cbRec - offBits;
|
|
int cyRecWholeScans = cbRecLeft / m_cx;
|
|
|
|
// Blt as much as we can
|
|
|
|
int cyBlt = _min(cyLeft, cyRecWholeScans);
|
|
LeftToRightBltThunk(&pbRec[offBits - offRecCurrent], m_cx, pbDst, cbRowDst, cxBlt, cyBlt);
|
|
cyLeft -= cyBlt;
|
|
if (cyLeft == 0)
|
|
break;
|
|
offBits += (long)cyBlt * m_cx;
|
|
pbDst += (long)cyBlt * cbRowDst;
|
|
|
|
// Does the next scan intersect a record boundary?
|
|
|
|
if (offRecCurrent + cbRec - offBits < (word)cxBlt) {
|
|
// Blt left half, unlock current record, lock next record, blt right half
|
|
|
|
int cbLeftHalf = (int)(offRecCurrent + cbRec - offBits);
|
|
memcpy(pbDst, &pbRec[offBits - offRecCurrent], cbLeftHalf);
|
|
m_pfil->prnfo->ppdbReader->UnmapRecord(nRecCurrent, pvCookie);
|
|
offRecCurrent += cbRec;
|
|
nRecCurrent++;
|
|
pbRec = m_pfil->prnfo->ppdbReader->MapRecord(nRecCurrent, &pvCookie, &cbRec);
|
|
if (pbRec == NULL)
|
|
return;
|
|
memcpy(pbDst + cbLeftHalf, pbRec, cxBlt - cbLeftHalf);
|
|
pbDst += cbRowDst;
|
|
offBits += m_cx;
|
|
cyLeft--;
|
|
continue;
|
|
}
|
|
|
|
// Next scan doesn't intersect a record boundary
|
|
|
|
memcpy(pbDst, &pbRec[offBits - offRecCurrent], cxBlt);
|
|
m_pfil->prnfo->ppdbReader->UnmapRecord(nRecCurrent, pvCookie);
|
|
pbRec = NULL;
|
|
offRecCurrent += cbRec;
|
|
offBits += m_cx;
|
|
nRecCurrent++;
|
|
pbDst += cbRowDst;
|
|
cyLeft--;
|
|
}
|
|
|
|
if (pbRec != NULL)
|
|
m_pfil->prnfo->ppdbReader->UnmapRecord(nRecCurrent, pvCookie);
|
|
}
|
|
#endif
|
|
|
|
} // namespace wi
|