Files
2026-02-02 04:50:13 +01:00

1249 lines
42 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "bagel/hodjnpodj/hnplibs/stdafx.h"
#include "bagel/hodjnpodj/hnplibs/dibapi.h"
#include "bagel/hodjnpodj/hnplibs/bitmaps.h"
namespace Bagel {
namespace HodjNPodj {
CBitmap *FetchScreenBitmap(CDC *pDC, CPalette *pPalette, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CDC *pWorkDC = nullptr;
CPalette *pPalOld = nullptr,
*pPalOldWork = nullptr;
CBitmap *pWork = nullptr,
*pWorkOld = nullptr;
if (pPalette != nullptr) { // map in color palette to be used
pPalOld = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pWorkDC = new CDC(); // create the context and bitmap objects
pWork = new CBitmap();
if ((pWorkDC != nullptr) && // construct an offscreen bitmap that we
(pWork != nullptr) && // ... can use as a work area, and then
(*pWorkDC).CreateCompatibleDC(pDC) && // ... use as a return value to the caller
(*pWork).CreateCompatibleBitmap(pDC, dx, dy)) { // create a bitmap of the appropriate size
if (pPalette != nullptr) { // map the palette into the work area
pPalOldWork = (*pWorkDC).SelectPalette(pPalette, false);
(*pWorkDC).RealizePalette();
}
pWorkOld = (*pWorkDC).SelectObject(pWork); // now map in the work area's bitmap
if (pWorkOld != nullptr) // capture the desired pixels
bSuccess = (*pWorkDC).BitBlt(0, 0, dx, dy, pDC, x, y, SRCCOPY);
}
if (pPalOld != nullptr) // relinquish the resources we built
(*pDC).SelectPalette(pPalOld, false);
if (pWorkOld != nullptr)
(*pWorkDC).SelectObject(pWorkOld);
if (pPalOldWork != nullptr)
(*pWorkDC).SelectPalette(pPalOldWork, false);
if (!bSuccess && // release the bitmap result we built
(pWork != nullptr)) { // ... if something failed
(*pWork).DeleteObject();
delete pWork;
pWork = nullptr;
}
if (pWorkDC != nullptr) {
(*pWorkDC).DeleteDC();
delete pWorkDC;
}
return pWork;
}
CBitmap *FetchBitmap(CDC *pDC, CPalette **pPalette, const char *pszPathName) {
CDibDoc *pDIB; // Pointer to our loaded DIB file
HDIB hDIB = nullptr;
CBitmap *pBitmap = nullptr;
CPalette *pThisPalette = nullptr;
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenDocument(pszPathName)) { // .... bitmap file
pThisPalette = (*pDIB).GetDocPalette();
hDIB = (*pDIB).GetHDIB();
pBitmap = ConvertDIB(pDC, hDIB, pThisPalette);
if (pPalette != nullptr)
*pPalette = (*pDIB).DetachPalette();
}
delete pDIB;
return pBitmap;
}
CBitmap *FetchBitmap(CDC *pDC, CPalette *pPalette, const char *pszPathName) {
CDibDoc *pDIB = nullptr; // pointer to our loaded DIB file
HDIB hDIB = nullptr;
CBitmap *pBitmap = nullptr;
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenDocument(pszPathName)) { // .... bitmap file
hDIB = (*pDIB).GetHDIB();
pBitmap = ConvertDIB(pDC, hDIB, pPalette);
}
if (pDIB != nullptr)
delete pDIB;
return pBitmap;
}
CBitmap *FetchResourceBitmap(CDC *pDC, CPalette **pPalette, const char *pszName) {
CDibDoc *pDIB = nullptr; // pointer to our loaded DIB file
HDIB hDIB = nullptr;
CBitmap *pBitmap = nullptr;
CPalette *pThisPalette = nullptr;
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenResourceDocument(pszName)) { // .... bitmap file
pThisPalette = (*pDIB).GetDocPalette();
hDIB = (*pDIB).GetHDIB();
pBitmap = ConvertDIB(pDC, hDIB, pThisPalette);
if (pPalette != nullptr)
*pPalette = (*pDIB).DetachPalette();
}
if (pDIB != nullptr)
delete pDIB;
return pBitmap;
}
CBitmap *FetchResourceBitmap(CDC *pDC, CPalette **pPalette, const int nResID) {
CDibDoc *pDIB = nullptr; // pointer to our loaded DIB file
HDIB hDIB = nullptr;
CBitmap *pBitmap = nullptr;
char chResName[16];
CPalette *pThisPalette = nullptr;
Common::sprintf_s(chResName, "#%d", nResID);
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenResourceDocument(chResName)) { // .... bitmap file
pThisPalette = (*pDIB).GetDocPalette();
hDIB = (*pDIB).GetHDIB();
pBitmap = ConvertDIB(pDC, hDIB, pThisPalette);
if (pPalette != nullptr)
*pPalette = (*pDIB).DetachPalette();
}
if (pDIB != nullptr)
delete pDIB;
return pBitmap;
}
CBitmap *ExtractBitmap(CDC *pDC, CBitmap *pBitmap, CPalette *pPalette, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CDC *pWorkDC = nullptr,
*pBaseDC = nullptr;
CPalette *pPalOld = nullptr,
*pPalOldWork = nullptr,
*pPalOldBase = nullptr;
CBitmap *pWork = nullptr,
*pWorkOld = nullptr,
*pBaseOld = nullptr;
if (pPalette != nullptr) { // map in color palette to be used
pPalOld = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pWorkDC = new CDC(); // create the context and bitmap objects
pWork = new CBitmap();
pBaseDC = new CDC();
if ((pWorkDC != nullptr) && // construct an offscreen bitmap that we
(pWork != nullptr) && // ... can use as a work area, and then
(pBaseDC != nullptr) && // ... use as a return value to the caller
(*pWorkDC).CreateCompatibleDC(pDC) && // setup a context for the source bitmap
(*pBaseDC).CreateCompatibleDC(pDC) &&
(*pWork).CreateCompatibleBitmap(pDC, dx, dy)) { // create a bitmap of the appropriate size
if (pPalette != nullptr) { // map the palette into the contexts
pPalOldWork = (*pWorkDC).SelectPalette(pPalette, false);
(*pWorkDC).RealizePalette();
pPalOldBase = (*pBaseDC).SelectPalette(pPalette, false);
(*pBaseDC).RealizePalette();
}
pWorkOld = (*pWorkDC).SelectObject(pWork); // now map in the work area's bitmap
pBaseOld = (*pBaseDC).SelectObject(pBitmap); // ... as well as the source bitmap
if ((pWorkOld != nullptr) &&
(pBaseOld != nullptr)) // grab the bitmap section if all is well
bSuccess = (*pWorkDC).BitBlt(0, 0, dx, dy, pBaseDC, x, y, SRCCOPY);
}
if (pPalOld != nullptr) // relinquish the resources we built
(*pDC).SelectPalette(pPalOld, false);
if (pWorkOld != nullptr)
(*pWorkDC).SelectObject(pWorkOld);
if (pBaseOld != nullptr)
(*pBaseDC).SelectObject(pBaseOld);
if (pPalOldWork != nullptr)
(*pWorkDC).SelectPalette(pPalOldWork, false);
if (pPalOldBase != nullptr)
(*pBaseDC).SelectPalette(pPalOldBase, false);
if (!bSuccess && // release the bitmap result we built
(pWork != nullptr)) { // ... if something failed
(*pWork).DeleteObject();
delete pWork;
pWork = nullptr;
}
if (pWorkDC != nullptr) {
(*pWorkDC).DeleteDC();
delete pWorkDC;
}
if (pBaseDC != nullptr) {
(*pBaseDC).DeleteDC();
delete pBaseDC;
}
return pWork;
}
/*************************************************************************
*
* BltBitmap()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* CBitmap *pBitmap pointer to bitmap to be painted
* CRect *pSrcRect source rectange in bitmap
* CRect *pDstRect destination rectange in context
* int nMode blt mode for transfer
*
* Return Value:
* bool success / failure return
*
* Description: paint a rectangular area of the screen from a CBitmap object.
*
************************************************************************/
bool BltBitmap(CDC *pDC, CPalette *pPalette, CBitmap *pBitmap, CRect *pSrcRect, CRect *pDstRect, uint32 dwMode) {
bool bSuccess = false;
CDC *pWorkDC = nullptr;
CPalette *pPalOld = nullptr,
*pPalOldWork = nullptr;
CBitmap *pWorkOld = nullptr;
if (pPalette != nullptr) { // map in color palette to be used
pPalOld = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pWorkDC = new CDC(); // create the context and bitmap objects
if ((pWorkDC != nullptr) && // verify we got what we asked for
(pBitmap != nullptr) &&
(*pWorkDC).CreateCompatibleDC(pDC)) { // create a context for our bitmap
if (pPalette != nullptr) { // map the palette into the context
pPalOldWork = (*pWorkDC).SelectPalette(pPalette, false);
(*pWorkDC).RealizePalette();
}
pWorkOld = (*pWorkDC).SelectObject(pBitmap); // now map in our bitmap
if (pWorkOld != nullptr) { // paint back the saved pixels
if ((((*pSrcRect).right - (*pSrcRect).left) != ((*pDstRect).right - (*pDstRect).left)) ||
(((*pSrcRect).bottom - (*pSrcRect).top) != ((*pDstRect).bottom - (*pDstRect).top))) {
(*pDC).SetStretchBltMode(STRETCH_DELETESCANS);
assert(GetDeviceCaps((*pDC).m_hDC, RASTERCAPS) & RC_STRETCHBLT);
bSuccess = (*pDC).StretchBlt((*pDstRect).left,
(*pDstRect).top,
(*pDstRect).right - (*pDstRect).left,
(*pDstRect).bottom - (*pDstRect).top,
pWorkDC,
(*pSrcRect).left,
(*pSrcRect).top,
(*pSrcRect).right - (*pSrcRect).left,
(*pSrcRect).bottom - (*pSrcRect).top,
dwMode);
} else {
bSuccess = (*pDC).BitBlt((*pDstRect).left,
(*pDstRect).top,
(*pSrcRect).right - (*pSrcRect).left,
(*pSrcRect).bottom - (*pSrcRect).top,
pWorkDC,
(*pSrcRect).left,
(*pSrcRect).top,
dwMode);
}
}
}
if (pPalOld != nullptr) // relinquish the resources we built
(*pDC).SelectPalette(pPalOld, false);
if (pWorkOld != nullptr)
(*pWorkDC).SelectObject(pWorkOld);
if (pPalOldWork != nullptr)
(*pWorkDC).SelectPalette(pPalOldWork, false);
if (pWorkDC != nullptr) {
(*pWorkDC).DeleteDC();
delete pWorkDC;
}
return bSuccess;
}
/*************************************************************************
*
* BltMaskedBitmap()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* CBitmap *pBitmap pointer to bitmap to be displayed
* int x, y upper lefthand corner of the destination rectangle
* CRect *pSrcRect source rectange in bitmap
*
* Return Value:
* bool success/failure condition
*
* Description: "mask" paint a bitmap to the specified display context. White
* pixels are assumed to be transparent, allowing the background
* artwork to show through.
*
************************************************************************/
bool BltMaskedBitmap(CDC *pDC, CPalette *pPalette, CBitmap *pBitmap, CRect *pSrcRect, const int x, const int y) {
CDC *pImageDC = nullptr, // context for the bitmap image
*pWorkDC = nullptr, // context for the bitmap work area
*pMaskDC = nullptr; // context for the image's mask
CBitmap *pImage = nullptr, // bitmap that has our image
*pImageOld = nullptr, // bitmap previously mapped to image context
*pWork = nullptr, // work area bitmap
*pWorkOld = nullptr, // bitmap previously mapped to work context
*pMask = nullptr, // image mask bitmap
*pMaskOld = nullptr; // bitmap previously mapped to mask context
CPalette *pPalOldImage = nullptr, // palette previously mapped to image context
*pPalOldWork = nullptr; // palette previously mapped to work context
bool bSuccess = false;
CPalette *pPalOld = nullptr;
CSize cSize;
int dx, dy;
CRect dstRect;
if (pPalette != nullptr) {
pPalOld = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pImageDC = new CDC(); // create the necessary objects
pMaskDC = new CDC();
pWorkDC = new CDC();
pImage = new CBitmap();
pMask = new CBitmap();
pWork = new CBitmap();
if ((pImageDC != nullptr) && // verify we got the requested objects
(pMaskDC != nullptr) &&
(pWorkDC != nullptr) &&
(pImage != nullptr) &&
(pMask != nullptr) &&
(pWork != nullptr) &&
(*pImageDC).CreateCompatibleDC(pDC) && // now create all the compatible contexts
(*pMaskDC).CreateCompatibleDC(pDC) && // ... that we need to hold our bitmaps
(*pWorkDC).CreateCompatibleDC(pDC)) {
dx = (*pSrcRect).right - (*pSrcRect).left;
dy = (*pSrcRect).bottom - (*pSrcRect).top;
if (pPalette != nullptr) { // map in the color palette if specified
pPalOldImage = (*pImageDC).SelectPalette(pPalette, false);
(*pImageDC).RealizePalette();
pPalOldWork = (*pWorkDC).SelectPalette(pPalette, false);
(*pWorkDC).RealizePalette();
}
if ((*pImage).CreateCompatibleBitmap(pDC, dx, dy) &&
(*pWork).CreateCompatibleBitmap(pDC, dx, dy) &&
(*pMask).CreateBitmap(dx, dy, 1, 1, nullptr)) {
pImageOld = (*pImageDC).SelectObject(pImage);
pMaskOld = (*pMaskDC).SelectObject(pMask); // map the work and mask bitmaps into
pWorkOld = (*pWorkDC).SelectObject(pWork); // ... their contexts
dstRect.SetRect(0, 0, dx, dy);
BltBitmap(pImageDC, pPalette, pBitmap, pSrcRect, &dstRect, (uint32) SRCCOPY);
if ((pMaskOld != nullptr) && // verify so far so good
(pWorkOld != nullptr)) {
(*pWorkDC).BitBlt( // grab what the background looks like
0, // ... putting it in the work area
0,
dx,
dy,
pDC,
x,
y,
SRCCOPY);
(*pMaskDC).BitBlt( // create the mask by inverting the image
0, 0, // ... i.e. the pixels occupied by the image
dx,
dy,
pImageDC,
0, 0,
NOTSRCCOPY);
(*pImageDC).BitBlt( // remove the image's "transparent" white area
0, 0, // ... i.e. its background becomes black
dx,
dy,
pMaskDC,
0, 0,
SRCAND);
(*pMaskDC).BitBlt( // invert the mask
0, 0,
dx,
dy,
pMaskDC,
0, 0,
DSTINVERT);
(*pWorkDC).BitBlt( // remove the image's space from the work area
0, 0, // ... i.e. the pixels where the image will go
dx,
dy,
pMaskDC,
0, 0
, SRCAND);
(*pWorkDC).BitBlt( // paint the image into the cleared (black) space
0, 0, // ... we made in the work area
dx,
dy,
pImageDC,
0, 0,
SRCPAINT);
bSuccess = (*pDC).BitBlt( // now splat the result to the destination context
x,
y,
dx,
dy,
pWorkDC,
0,
0,
SRCCOPY);
}
}
}
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
if (pImageOld != nullptr) // select out bitmaps out of their contexts
(*pImageDC).SelectObject(pImageOld);
if (pWorkOld != nullptr)
(*pWorkDC).SelectObject(pWorkOld);
if (pMaskOld != nullptr)
(*pMaskDC).SelectObject(pMaskOld);
if (pPalOldImage != nullptr) // map out the palettes we used
(*pImageDC).SelectPalette(pPalOldImage, false);
if (pPalOldWork != nullptr)
(*pWorkDC).SelectPalette(pPalOldWork, false);
if (pImage != nullptr) { // delete the bitmaps we created
(*pImage).DeleteObject();
delete pImage;
}
if (pWork != nullptr) {
(*pWork).DeleteObject();
delete pWork;
}
if (pMask != nullptr) {
(*pMask).DeleteObject();
delete pMask;
}
if (pImageDC != nullptr) { // delete the contexts we created
(*pImageDC).DeleteDC();
delete pImageDC;
}
if (pWorkDC != nullptr) {
(*pWorkDC).DeleteDC();
delete pWorkDC;
}
if (pMaskDC != nullptr) {
(*pMaskDC).DeleteDC();
delete pMaskDC;
}
return bSuccess; // return success or failure
}
/*************************************************************************
*
* PaintBitmap()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* CBitmap *pBitmap pointer to bitmap to be painted
* int x, y upper left hand corner where bitmap is to be painted
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success / failure return
*
* Description: paint a rectangular area of the screen from a CBitmap object.
*
************************************************************************/
bool PaintBitmap(CDC *pDC, CPalette *pPalette, CBitmap *pBitmap, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CDC *pWorkDC = nullptr;
CPalette *pPalOld = nullptr,
*pPalOldWork = nullptr;
CBitmap *pWorkOld = nullptr;
BITMAP cBitmapData;
CRect SrcRect, DstRect;
(*pBitmap).GetObject(sizeof(BITMAP), &cBitmapData);
if (pPalette != nullptr) { // map in color palette to be used
pPalOld = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pWorkDC = new CDC(); // create the context and bitmap objects
if ((*pWorkDC).CreateCompatibleDC(pDC)) { // create a context for our bitmap
if (pPalette != nullptr) { // map the palette into the context
pPalOldWork = (*pWorkDC).SelectPalette(pPalette, false);
(*pWorkDC).RealizePalette();
}
pWorkOld = (*pWorkDC).SelectObject(pBitmap); // now map in our bitmap
if (pWorkOld != nullptr) { // paint back the saved pixels
if ((dx != 0) && (dy != 0) &&
((dx != cBitmapData.bmWidth) || (dy != cBitmapData.bmHeight))) {
(*pDC).SetStretchBltMode(STRETCH_DELETESCANS);
assert(GetDeviceCaps((*pDC).m_hDC, RASTERCAPS) & RC_STRETCHBLT);
bSuccess = (*pDC).StretchBlt(x, y, dx, dy, pWorkDC, 0, 0, cBitmapData.bmWidth, cBitmapData.bmHeight, SRCCOPY);
} else {
bSuccess = (*pDC).BitBlt(x, y, cBitmapData.bmWidth, cBitmapData.bmHeight, pWorkDC, 0, 0, SRCCOPY);
}
}
}
if (pPalOld != nullptr) // relinquish the resources we built
(*pDC).SelectPalette(pPalOld, false);
if (pWorkOld != nullptr)
(*pWorkDC).SelectObject(pWorkOld);
if (pPalOldWork != nullptr)
(*pWorkDC).SelectPalette(pPalOldWork, false);
if (pWorkDC != nullptr) {
(*pWorkDC).DeleteDC();
delete pWorkDC;
}
return bSuccess;
}
/*************************************************************************
*
* PaintBitmap()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* char *pszPathName pointer to path string for disk based DIB file
* int x, y upper left hand corner where bitmap is to be painted
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success / failure return
*
* Description: paint a rectangular area of the screen from a disk based DIB.
*
************************************************************************/
bool PaintBitmap(CDC *pDC, CPalette *pPalette, const char *pszPathName, const int x, const int y, const int dx, const int dy) {
CDibDoc myDoc;
HDIB hDIB;
CRect rcDest;
CRect rcDIB;
int cxDIB;
int cyDIB;
bool bSuccess;
bSuccess = myDoc.OpenDocument(pszPathName);
if ((pDC != nullptr) && bSuccess) {
hDIB = myDoc.GetHDIB();
if (hDIB == nullptr)
bSuccess = false;
else {
cxDIB = (int) DIBWidth(hDIB);
cyDIB = (int) DIBHeight(hDIB);
rcDIB.top = rcDIB.left = 0;
rcDIB.right = cxDIB;
rcDIB.bottom = cyDIB;
if ((dx == 0) || (dy == 0))
rcDest.SetRect(x, y, x + cxDIB, y + cyDIB);
else
rcDest.SetRect(x, y, x + dx, y + dy);
bSuccess = PaintDIB((*pDC).m_hDC, &rcDest, hDIB, &rcDIB, pPalette);
}
}
return bSuccess;
}
/*************************************************************************
*
* PaintMaskedDIB()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* char *pszPathName pointer to path string for disk based DIB file
* int x, y upper lefthand corner of the destination rectangle
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success/failure condition
*
* Description: Read in a DDB bitmap from disk and "mask" paint it to the
* specified display context. White pixels are assumed to be
* transparent, allowing the background artwork to show through.
*
************************************************************************/
bool PaintMaskedDIB(CDC *pDC, CPalette *pPalette, const char *pszPathName, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CDibDoc *pDIB = nullptr; // pointer to our loaded DIB file
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenDocument(pszPathName)) // .... bitmap file
bSuccess = PaintMaskedDIB(pDC, pPalette, pDIB, x, y, dx, dy) ;
if (pDIB != nullptr)
delete pDIB;
return bSuccess; // return success or failure
}
/*************************************************************************
*
* PaintMaskedResource()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* int resId resource number for the bitmap in the .RC file
* int x, y upper lefthand corner of the destination rectangle
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success/failure condition
*
* Description: Read in a DDB bitmap resource and "mask" paint it to the
* specified display context. White pixels are assumed to be
* transparent, allowing the background artwork to show through.
*
************************************************************************/
bool PaintMaskedResource(CDC *pDC, CPalette *pPalette, const int nResID, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CDibDoc *pDIB = nullptr; // pointer to our loaded DIB file
char chResName[16];
Common::sprintf_s(chResName, "#%d", nResID);
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenResourceDocument(chResName)) // .... bitmap file
bSuccess = PaintMaskedDIB(pDC, pPalette, pDIB, x, y, dx, dy) ;
if (pDIB != nullptr)
delete pDIB;
return bSuccess; // return success or failure
}
/*************************************************************************
*
* PaintMaskedResource()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* char *pszName resource name for the bitmap in the .RC file
* int x, y upper lefthand corner of the destination rectangle
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success/failure condition
*
* Description: Read in a DDB bitmap resource and "mask" paint it to the
* specified display context. White pixels are assumed to be
* transparent, allowing the background artwork to show through.
*
************************************************************************/
bool PaintMaskedResource(CDC *pDC, CPalette *pPalette, const char *pszName, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CDibDoc *pDIB = nullptr; // pointer to our loaded DIB file
pDIB = new CDibDoc(); // create an object for our DIB
if ((pDIB != nullptr) && // verify we have the objects we just created
(*pDIB).OpenResourceDocument(pszName)) // .... bitmap file
bSuccess = PaintMaskedDIB(pDC, pPalette, pDIB, x, y, dx, dy) ;
if (pDIB != nullptr)
delete pDIB;
return bSuccess; // return success or failure
}
/*************************************************************************
*
* PaintMaskedDIB()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* CDibDoc *pDIB pointer to DIB to be displayed
* int x, y upper lefthand corner of the destination rectangle
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success/failure condition
*
* Description: "mask" paint a DIB to the specified display context. White
* pixels are assumed to be transparent, allowing the background
* artwork to show through.
*
************************************************************************/
bool PaintMaskedDIB(CDC *pDC, CPalette *pPalette, CDibDoc *pDIB, const int x, const int y, const int dx, const int dy) {
bool bSuccess = false;
CBitmap *pBitmap = nullptr;
CPalette *pMyPalette = nullptr;
HDIB hDIB = nullptr;
if (pPalette == nullptr)
pMyPalette = (*pDIB).GetDocPalette();
else
pMyPalette = pPalette;
hDIB = (*pDIB).GetHDIB();
pBitmap = ConvertDIB(pDC, hDIB, pMyPalette);
if (pBitmap != nullptr) {
bSuccess = PaintMaskedBitmap(pDC, pMyPalette, pBitmap, x, y, dx, dy);
(*pBitmap).DeleteObject();
delete pBitmap;
}
return bSuccess;
}
/*************************************************************************
*
* PaintMaskedBitmap()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CPalette *pPalette pointer to color palette to be used for the bitmap
* CBitmap *pBitmap pointer to bitmap to be displayed
* int x, y upper lefthand corner of the destination rectangle
* int dx, dy optional sizing info to force a stretch blt
*
* Return Value:
* bool success/failure condition
*
* Description: "mask" paint a bitmap to the specified display context. White
* pixels are assumed to be transparent, allowing the background
* artwork to show through.
*
************************************************************************/
bool PaintMaskedBitmap(CDC *pDC, CPalette *pPalette, CBitmap *pBitmap, const int x, const int y, const int dx, const int dy) {
BITMAP myBitmap; // area for bitmap info
CDC *pImageDC = nullptr, // context for the bitmap image
*pWorkDC = nullptr, // context for the bitmap work area
*pMaskDC = nullptr; // context for the image's mask
CBitmap *pImage = nullptr, // bitmap that has our image
*pImageOld = nullptr, // bitmap previously mapped to image context
*pWork = nullptr, // work area bitmap
*pWorkOld = nullptr, // bitmap previously mapped to work context
*pMask = nullptr, // image mask bitmap
*pMaskOld = nullptr; // bitmap previously mapped to mask context
CPalette *pPalOldImage = nullptr, // palette previously mapped to image context
*pPalOldWork = nullptr; // palette previously mapped to work context
bool bSuccess = false;
CPalette *pPalOld = nullptr;
CSize cSize;
if (pPalette != nullptr) {
pPalOld = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pImageDC = new CDC(); // create the necessary objects
pMaskDC = new CDC();
pWorkDC = new CDC();
pImage = new CBitmap();
pMask = new CBitmap();
pWork = new CBitmap();
if ((pImageDC != nullptr) && // verify we got the requested objects
(pMaskDC != nullptr) &&
(pWorkDC != nullptr) &&
(pImage != nullptr) &&
(pMask != nullptr) &&
(pWork != nullptr) &&
(*pImageDC).CreateCompatibleDC(pDC) && // now create all the compatible contexts
(*pMaskDC).CreateCompatibleDC(pDC) && // ... that we need to hold our bitmaps
(*pWorkDC).CreateCompatibleDC(pDC)) {
(*pBitmap).GetObject(sizeof(BITMAP), &myBitmap); // get the image's sizing info
cSize.cx = myBitmap.bmWidth;
cSize.cy = myBitmap.bmHeight;
if ((dx != 0) && (dy != 0) &&
((dx != cSize.cx) || (dy != cSize.cy))) {
cSize.cx = dx;
cSize.cy = dy;
}
if (pPalette != nullptr) { // map in the color palette if specified
pPalOldImage = (*pImageDC).SelectPalette(pPalette, false);
(*pImageDC).RealizePalette();
pPalOldWork = (*pWorkDC).SelectPalette(pPalette, false);
(*pWorkDC).RealizePalette();
}
if ((*pImage).CreateCompatibleBitmap(pDC, cSize.cx, cSize.cy) &&
(*pWork).CreateCompatibleBitmap(pDC, cSize.cx, cSize.cy) &&
(*pMask).CreateBitmap(cSize.cx, cSize.cy, 1, 1, nullptr)) {
pImageOld = (*pImageDC).SelectObject(pImage);
pMaskOld = (*pMaskDC).SelectObject(pMask); // map the work and mask bitmaps into
pWorkOld = (*pWorkDC).SelectObject(pWork); // ... their contexts
PaintBitmap(pImageDC, pPalette, pBitmap, 0, 0, dx, dy);
if ((pMaskOld != nullptr) && // verify so far so good
(pWorkOld != nullptr)) {
(*pWorkDC).BitBlt( // grab what the background looks like
0, // ... putting it in the work area
0,
cSize.cx,
cSize.cy,
pDC,
x,
y,
SRCCOPY);
(*pMaskDC).BitBlt( // create the mask by inverting the image
0, 0, // ... i.e. the pixels occupied by the image
cSize.cx,
cSize.cy,
pImageDC,
0, 0,
NOTSRCCOPY);
(*pImageDC).BitBlt( // remove the image's "transparent" white area
0, 0, // ... i.e. its background becomes black
cSize.cx,
cSize.cy,
pMaskDC,
0, 0,
SRCAND);
(*pMaskDC).BitBlt( // invert the mask
0, 0,
cSize.cx,
cSize.cy,
pMaskDC,
0, 0,
DSTINVERT);
(*pWorkDC).BitBlt( // remove the image's space from the work area
0, 0, // ... i.e. the pixels where the image will go
cSize.cx,
cSize.cy,
pMaskDC,
0, 0
, SRCAND);
(*pWorkDC).BitBlt( // paint the image into the cleared (black) space
0, 0, // ... we made in the work area
cSize.cx,
cSize.cy,
pImageDC,
0, 0,
SRCPAINT);
bSuccess = (*pDC).BitBlt( // now splat the result to the destination context
x,
y,
cSize.cx,
cSize.cy,
pWorkDC,
0,
0,
SRCCOPY);
}
}
}
if (pPalOld != nullptr)
(*pDC).SelectPalette(pPalOld, false);
if (pImageOld != nullptr) // select out bitmaps out of their contexts
(*pImageDC).SelectObject(pImageOld);
if (pWorkOld != nullptr)
(*pWorkDC).SelectObject(pWorkOld);
if (pMaskOld != nullptr)
(*pMaskDC).SelectObject(pMaskOld);
if (pPalOldImage != nullptr) // map out the palettes we used
(*pImageDC).SelectPalette(pPalOldImage, false);
if (pPalOldWork != nullptr)
(*pWorkDC).SelectPalette(pPalOldWork, false);
if (pImage != nullptr) { // delete the bitmaps we created
(*pImage).DeleteObject();
delete pImage;
}
if (pWork != nullptr) {
(*pWork).DeleteObject();
delete pWork;
}
if (pMask != nullptr) {
(*pMask).DeleteObject();
delete pMask;
}
if (pImageDC != nullptr) { // delete the contexts we created
(*pImageDC).DeleteDC();
delete pImageDC;
}
if (pWorkDC != nullptr) {
(*pWorkDC).DeleteDC();
delete pWorkDC;
}
if (pMaskDC != nullptr) {
(*pMaskDC).DeleteDC();
delete pMaskDC;
}
return bSuccess; // return success or failure
}
/*************************************************************************
*
* PaintBlockEffect()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CBitmap *pBitmap pointer to the DIB to be displayed
* CPalette *pPalette pointer to color palette to be used for the DIB
* int nBlockSize size of block to be painted at each step
*
* Return Value:
* bool success/failure condition
*
* Description: randomly paint a DIB to the specified display context
* a section/block at a time, without repeating any blocks;
* the DIB is converted to a bitmap and then a companion
* routine is called.
*
************************************************************************/
#define BIT0 0x00000001
#define BIT2 0x00000004
#define BIT15 0x00008000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define SEQ (BIT17)
#define BLOCK 4
bool PaintBlockEffect(CDC *pDC, CDibDoc *pDIB, CPalette* pPalette, int nBlockSize) {
HDIB hDIB = nullptr;
CBitmap *pBitmap = nullptr;
bool bSuccess = false;
if ((pDC == nullptr) ||
(pDIB == nullptr))
return false;
hDIB = (*pDIB).GetHDIB();
pBitmap = ConvertDIB(pDC, hDIB, pPalette);
bSuccess = PaintBlockEffect(pDC, pBitmap, pPalette, nBlockSize);
if (pBitmap != nullptr)
delete pBitmap;
return bSuccess;
}
/*************************************************************************
*
* PaintBlockEffect()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* CBitmap *pBitmap pointer to bitmap to be displayed
* CPalette *pPalette pointer to color palette to be used for the bitmap
* int nBlockSize size of block to be painted at each step
*
* Return Value:
* bool success/failure condition
*
* Description: randomly paint a bitmap to the specified display context
* a section/block at a time, without repeating blocks.
*
************************************************************************/
bool PaintBlockEffect(CDC *pDC, CBitmap *pBitmap, CPalette* pPalette, int nBlockSize) {
CPalette *pOldPal = nullptr;
CPalette *pOldPal2 = nullptr;
CBitmap *pBitmapOld = nullptr;
CDC *pMemDC = nullptr;
BITMAP myBitmap;
bool bSuccess = false;
unsigned long seed;
unsigned long value, maxvalue;
unsigned long x, y;
unsigned long fill,
mask = (BIT16 | BIT15 | BIT2 | BIT0);
unsigned long tmp, cnt, shft;
unsigned long width, height;
if ((pDC == nullptr) ||
(pBitmap == nullptr))
return false;
if (pPalette != nullptr) {
pOldPal = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
pMemDC = new CDC();
if ((pMemDC == nullptr) ||
((*pMemDC).CreateCompatibleDC(pDC) == false))
goto clean_up;
pOldPal2 = (*pMemDC).SelectPalette(pPalette, false);
(*pMemDC).RealizePalette();
pBitmapOld = (*pMemDC).SelectObject(pBitmap);
(*pBitmap).GetObject(sizeof(BITMAP), &myBitmap);
width = myBitmap.bmWidth / nBlockSize;
height = myBitmap.bmHeight;
maxvalue = height / nBlockSize * width;
seed = SEQ - 1;
for (value = seed; ;) {
fill = 0L;
tmp = (value & mask);
shft = BIT0;
cnt = 0;
while (shft < SEQ) {
if (tmp & shft)
cnt++;
shft <<= 1;
}
if (cnt & BIT0)
fill = BIT0;
value <<= 1;
value |= fill;
value &= (SEQ - 1);
if (value == seed)
break;
if (value > maxvalue)
continue;
y = (value / width) * nBlockSize;
x = (value % width) * nBlockSize;
(*pDC).BitBlt((uint16) x,
(uint16) y,
nBlockSize,
nBlockSize,
pMemDC,
(uint16) x,
(uint16) y,
SRCCOPY);
}
(*pDC).BitBlt(0,
0,
nBlockSize,
nBlockSize,
pMemDC,
0,
0,
SRCCOPY);
bSuccess = true;
clean_up:
if (pBitmapOld != nullptr)
(*pMemDC).SelectObject(pBitmapOld);
if (pOldPal2 != nullptr)
(*pMemDC).SelectPalette(pOldPal2, false);
if (pMemDC != nullptr)
delete pMemDC;
if (pOldPal != nullptr)
(*pDC).SelectPalette(pOldPal, false);
return bSuccess;
}
/*************************************************************************
*
* PaintBlockEffect()
*
* Parameters:
* CDC *pDC pointer to device context to be used for display
* COLORREF color to be displayed
* CPalette *pPalette pointer to color palette to be used for the bitmap
* int nBlockSize size of block to be painted at each step
*
* Return Value:
* bool success/failure condition
*
* Description: randomly paint a solid background color to the specified
* display context a section/block at a time, without repeating blocks.
*
************************************************************************/
bool PaintBlockEffect(CDC *pDC, COLORREF rgbColor, CPalette* pPalette, int nBlockSize, int nX, int nY, int nWidth, int nHeight) {
CBrush myBrush;
CRect thisRect, fillRect;
CPalette *pOldPal = nullptr;
bool bSuccess = false;
unsigned long seed;
unsigned long value, maxvalue;
unsigned long x, y;
unsigned long fill,
mask = (BIT16 | BIT15 | BIT2 | BIT0);
unsigned long tmp, cnt, shft;
unsigned long width, height;
if (pDC == nullptr)
return false;
if (pPalette != nullptr) {
pOldPal = (*pDC).SelectPalette(pPalette, false);
(*pDC).RealizePalette();
}
myBrush.CreateSolidBrush(rgbColor);
width = nWidth / nBlockSize;
height = nHeight;
maxvalue = height / nBlockSize * width;
seed = SEQ - 1;
for (value = seed; ;) {
fill = 0L;
tmp = (value & mask);
shft = BIT0;
cnt = 0;
while (shft < SEQ) {
if (tmp & shft)
cnt++;
shft <<= 1;
}
if (cnt & BIT0)
fill = BIT0;
value <<= 1;
value |= fill;
value &= (SEQ - 1);
if (value == seed)
break;
if (value > maxvalue)
continue;
y = (value / width) * nBlockSize;
x = (value % width) * nBlockSize;
fillRect.SetRect(nX + x, nY + y, nX + x + nBlockSize, nY + y + nBlockSize);
(*pDC).FillRect(&fillRect, &myBrush);
}
fillRect.SetRect(nX, nY, nX + nBlockSize, nY + nBlockSize);
(*pDC).FillRect(&fillRect, &myBrush);
bSuccess = true;
if (pOldPal != nullptr)
(*pDC).SelectPalette(pOldPal, false);
return bSuccess;
}
/*************************************************************************
*
* GetBitmapSize()
*
* Parameters:
* CBitmap *pBitmap pointer to bitmap
*
* Return Value:
* CSize size of the bitmap
*
* Description: get sizing information for a bitmap objext.
*
************************************************************************/
CSize GetBitmapSize(CBitmap *pBitmap) {
CSize mySize;
BITMAP cBitmapData;
(*pBitmap).GetObject(sizeof(BITMAP), &cBitmapData);
mySize.cx = cBitmapData.bmWidth;
mySize.cy = cBitmapData.bmHeight;
return mySize;
}
} // namespace HodjNPodj
} // namespace Bagel