Files
scummvm-cursorfix/engines/bagel/hodjnpodj/hnplibs/dibapi.cpp
2026-02-02 04:50:13 +01:00

420 lines
11 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 "graphics/palette.h"
#include "bagel/hodjnpodj/hnplibs/dibapi.h"
#include "bagel/hodjnpodj/hnplibs/stdafx.h"
namespace Bagel {
namespace HodjNPodj {
static BITMAPINFOHEADER getDIBInfoHeader(HDIB hDib) {
BITMAPINFOHEADER h;
h.biSize = 40;
h.biWidth = hDib->w;
h.biHeight = hDib->h;
h.biPlanes = 1;
h.biBitCount = 8;
h.biCompression = BI_RGB;
h.biSizeImage = 0;
h.biXPelsPerMeter = 0;
h.biYPelsPerMeter = 0;
h.biClrUsed = !hDib->hasPalette() ? 0 :
hDib->grabPalette()->size();
h.biClrImportant = 0;
return h;
}
static BITMAPINFO *getDIBInfo(HDIB hDib) {
BITMAPINFO *h = (BITMAPINFO *)malloc(
sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
h->bmiHeader = getDIBInfoHeader(hDib);
const Graphics::Palette *pal = hDib->grabPalette();
for (uint i = 0; i < h->bmiHeader.biClrUsed; ++i) {
auto &col = h->bmiColors[i];
pal->get(i, col.rgbRed, col.rgbGreen, col.rgbBlue);
col.rgbReserved = 0;
}
return h;
}
/*************************************************************************
*
* PaintDIB()
*
* Parameters:
*
* HDC hDC - DC to do output to
*
* LPRECT lpDCRect - rectangle on DC to do output to
*
* HDIB hDIB - handle to global memory with a DIB spec
* in it followed by the DIB bits
*
* LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
*
* CPalette* pPal - pointer to CPalette containing DIB's palette
*
* Return Value:
*
* bool - true if DIB was drawn, false otherwise
*
* Description:
* Painting routine for a DIB. Calls StretchDIBits() or
* SetDIBitsToDevice() to paint the DIB. The DIB is
* output to the specified DC, at the coordinates given
* in lpDCRect. The area of the DIB to be output is
* given by lpDIBRect.
*
************************************************************************/
bool PaintDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB,
LPRECT lpDIBRect, CPalette *pPal) {
bool bSuccess = false; // Success/fail flag
HPALETTE hPal = nullptr; // Our DIB's palette
HPALETTE hOldPal = nullptr; // Previous palette
HPALETTE hOldPal2 = nullptr; // Previous palette
HBITMAP hBitmap, hBitmapOld;
HDC hdcMem; // memory device context
int nDevCaps;
// Check for valid DIB handle
if (hDIB == nullptr)
return false;
// Get the palette, then select it into DC
if (pPal != nullptr) {
hPal = (HPALETTE)pPal->m_hObject;
// Select as foreground and realize it
hOldPal = SelectPalette(hDC, hPal, false);
RealizePalette(hDC);
}
nDevCaps = GetDeviceCaps(hDC, RASTERCAPS);
if (!(nDevCaps & RC_STRETCHDIB)) {
hBitmap = DIBtoBitmap(hDC, nullptr, hDIB);
if (hBitmap) {
hdcMem = CreateCompatibleDC(hDC);
if (hdcMem) {
hOldPal2 = SelectPalette(hdcMem, hPal, false);
RealizePalette(hdcMem);
hBitmapOld = SelectBitmap(hdcMem, hBitmap);
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
bSuccess = BitBlt(hDC, lpDCRect->left, lpDCRect->top,
RECTWIDTH(lpDIBRect),
RECTHEIGHT(lpDIBRect),
hdcMem, lpDIBRect->left, lpDIBRect->top, SRCCOPY);
else if (nDevCaps & RC_STRETCHBLT)
bSuccess = StretchBlt(hDC, lpDCRect->left, lpDCRect->top, RECTWIDTH(lpDCRect), RECTHEIGHT(lpDCRect),
hdcMem, lpDIBRect->left, lpDIBRect->top, RECTWIDTH(lpDIBRect), RECTHEIGHT(lpDIBRect),
SRCCOPY);
else
bSuccess = false;
SelectBitmap(hdcMem, hBitmapOld);
SelectPalette(hdcMem, hOldPal2, false);
DeleteDC(hdcMem);
}
}
if (hBitmap != nullptr)
DeleteBitmap(hBitmap);
if (pPal != nullptr)
SelectPalette(hDC, hOldPal, false);
return bSuccess;
}
error("TODO: Populate binfo and enable below if this is ever needed");
#if 0
BITMAPINFO bInfo;
// Lock down the DIB, and get a pointer to it
Graphics::ManagedSurface *surf = (Graphics::ManagedSurface *)hDIB;
void *lpDIBBits = surf->getPixels();
// Make sure to use the stretching mode best for color pictures
SetStretchBltMode(hDC, COLORONCOLOR);
bSuccess = StretchDIBits(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
lpDIBRect->top, // SrcY
RECTWIDTH(lpDIBRect), // wSrcWidth
RECTHEIGHT(lpDIBRect), // wSrcHeight
lpDIBBits, // lpBits
&bInfo, // lpBitsInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
if (pPal != nullptr)
SelectPalette(hDC, hOldPal, false);
return bSuccess;
#endif
}
bool CreateDIBPalette(HDIB hDIB, CPalette *pPal) {
uint16 wNumColors;
bool bResult = false;
// If handle to DIB is invalid, return false
if (hDIB == nullptr)
return false;
// Get the number of colors in the DIB
wNumColors = DIBNumColors(hDIB);
if (wNumColors != 0) {
const Graphics::Palette *pal = hDIB->grabPalette();
bResult = pPal->SetPaletteEntries(*pal);
}
return bResult;
}
CPalette *DuplicatePalette(CPalette *pOrigPal) {
CPalette *pPal;
LPLOGPALETTE lpPal; // pointer to a logical palette
HANDLE hLogPal; // handle to a logical palette
uint16 wNumColors; // number of colors in color table
bool bResult;
wNumColors = pOrigPal->GetPaletteEntries(0, 0, nullptr);
if (wNumColors == 0)
return nullptr;
/* allocate memory block for logical palette */
hLogPal = GlobalAlloc(GPTR, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors);
assert(hLogPal);
lpPal = (LPLOGPALETTE) GlobalLock((HGLOBAL)hLogPal);
/* set version and number of palette entries */
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (uint16)wNumColors;
(*pOrigPal).GetPaletteEntries(0, wNumColors - 1, &lpPal->palPalEntry[0]);
/* create the palette and get handle to it */
pPal = new CPalette();
bResult = pPal->CreatePalette(lpPal);
if (!bResult) {
delete pPal;
pPal = nullptr;
}
GlobalUnlock((HGLOBAL)hLogPal);
GlobalFree((HGLOBAL)hLogPal);
return pPal;
}
char *FindDIBBits(HDIB hDIB) {
return (char *)hDIB->getPixels();
}
uint32 DIBWidth(HDIB hDIB) {
return hDIB->w;
}
uint32 DIBHeight(HDIB hDIB) {
return hDIB->h;
}
uint16 PaletteSize(HDIB hDIB) {
const Graphics::Palette *pal = hDIB->grabPalette();
return pal->size() * 3;
}
uint16 DIBNumColors(HDIB lpDIB) {
const Graphics::Palette *pal = lpDIB->grabPalette();
return pal->size();
}
CBitmap *ConvertDIB(CDC *pDC, HDIB hDIB, CPalette *pPal) {
HPALETTE hPal = nullptr; // Our DIB's palette
HPALETTE hOldPal = nullptr; // Previous palette
HDC hDC;
HBITMAP hBitmap = nullptr;
CBitmap *pBitmap = nullptr;
hDC = (*pDC).m_hDC;
// Get the palette, then select it into DC
if (pPal != nullptr) {
hPal = (HPALETTE)pPal->m_hObject;
// Select as foreground and realize it
hOldPal = SelectPalette(hDC, hPal, false);
RealizePalette(hDC);
}
// Convert the bit buffer to a bitmap
hBitmap = DIBtoBitmap(hDC, nullptr, hDIB);
if (hBitmap != nullptr) {
pBitmap = new CBitmap();
if (pBitmap != nullptr)
(*pBitmap).Attach(hBitmap);
}
/* Reselect old palette */
if (pPal != nullptr)
SelectPalette(hDC, hOldPal, false);
return pBitmap;
}
HBITMAP DIBtoBitmap(HDC hDC, HPALETTE hPalette, HDIB hDib) {
BITMAPINFO *info = getDIBInfo(hDib);
void *lpbihBits = FindDIBBits(hDib);
HBITMAP hBitmap = CreateDIBitmap(hDC,
&info->bmiHeader,
CBM_INIT,
lpbihBits,
info,
DIB_RGB_COLORS);
assert(hBitmap);
free(info);
return hBitmap;
}
//---------------------------------------------------------------------
//
// Function: InitBitmapInfoHeader
//
// Purpose: Does a "standard" initialization of a BITMAPINFOHEADER,
// given the Width, Height, and Bits per Pixel for the
// DIB.
//
// By standard, I mean that all the relevant fields are set
// to the specified values. biSizeImage is computed, the
// biCompression field is set to "no compression," and all
// other fields are 0.
//
// Note that DIBs only allow BitsPixel values of 1, 4, 8, or
// 24. This routine makes sure that one of these values is
// used (whichever is most appropriate for the specified
// nBPP).
//
// Parms: lpBmInfoHdr == Far pointer to a BITMAPINFOHEADER structure
// to be filled in.
// dwWidth == Width of DIB (not in Win 3.0 & 3.1, high
// word MUST be 0).
// dwHeight == Height of DIB (not in Win 3.0 & 3.1, high
// word MUST be 0).
// nBPP == Bits per Pixel for the DIB.
//
// History: Date Reason
// 11/07/91 Created
//
//---------------------------------------------------------------------
void WINAPI InitBitmapInfoHeader(LPBITMAPINFOHEADER lpBmInfoHdr,
uint32 dwWidth,
uint32 dwHeight,
int nBPP) {
memset(lpBmInfoHdr, 0, sizeof(BITMAPINFOHEADER));
lpBmInfoHdr->biSize = sizeof(BITMAPINFOHEADER);
lpBmInfoHdr->biWidth = dwWidth;
lpBmInfoHdr->biHeight = dwHeight;
lpBmInfoHdr->biPlanes = 1;
if (nBPP <= 1)
nBPP = 1;
else if (nBPP <= 4)
nBPP = 4;
else if (nBPP <= 8)
nBPP = 8;
else
nBPP = 24;
lpBmInfoHdr->biBitCount = nBPP;
lpBmInfoHdr->biSizeImage = WIDTHBYTES(dwWidth * nBPP) * dwHeight;
}
//////////////////////////////////////////////////////////////////////////
//// Clipboard support
//---------------------------------------------------------------------
//
// Function: CopyHandle (from SDK DibView sample clipbrd.c)
//
// Purpose: Makes a copy of the given global memory block. Returns
// a handle to the new memory block (nullptr on error).
//
// Routine stolen verbatim out of ShowDIB.
//
// Parms: h == Handle to global memory to duplicate.
//
// Returns: Handle to new global memory block.
//
//---------------------------------------------------------------------
HANDLE WINAPI CopyHandle(HANDLE h) {
byte *lpCopy;
byte *lp;
HANDLE hCopy;
uint32 dwLen;
if (h == nullptr)
return nullptr;
dwLen = GlobalSize((HGLOBAL)h);
if ((hCopy = (HANDLE) GlobalAlloc(GHND, dwLen)) != nullptr) {
lpCopy = (byte *) GlobalLock((HGLOBAL)hCopy);
lp = (byte *) GlobalLock((HGLOBAL)h);
while (dwLen--)
*lpCopy++ = *lp++;
GlobalUnlock((HGLOBAL)hCopy);
GlobalUnlock((HGLOBAL)h);
}
return hCopy;
}
void WINAPI ShowMemoryInfo(const char *chMessage, const char *chTitle) {
// No implementation
}
} // namespace HodjNPodj
} // namespace Bagel