/* 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 . * */ #include "common/system.h" #include "common/textconsole.h" #include "bagel/mfc/wingdi.h" #include "bagel/mfc/global_functions.h" #include "bagel/mfc/afxwin.h" #include "bagel/mfc/gfx/blitter.h" #include "bagel/mfc/gfx/palette_map.h" namespace Bagel { namespace MFC { int GetDeviceCaps(HDC hdc, int index) { CDC::Impl *dc = (CDC::Impl *)hdc; const CBitmap::Impl *bitmap = (CBitmap::Impl *)dc->_bitmap; switch (index) { case HORZRES: return bitmap->w; case VERTRES: return bitmap->h; case BITSPIXEL: return bitmap->format.bytesPerPixel * 8; case RASTERCAPS: return (bitmap->format.bytesPerPixel == 1 ? RC_PALETTE : 0) | RC_BITBLT | RC_BITMAP64 | RC_DI_BITMAP | RC_DIBTODEV | RC_STRETCHBLT; default: break; } error("TODO: CDC::GetDeviceCaps"); return 0; } HDC CreateCompatibleDC(HDC hdc) { return new CDC::Impl(hdc); } HDC GetDC(HWND hWnd) { if (hWnd) { CWnd *wnd = CWnd::FromHandle(hWnd); CDC *dc = wnd->GetDC(); return dc->m_hDC; } else { // Screen DC, so set the screen rect CDC::Impl *dc = new CDC::Impl(); dc->setScreenRect(); return dc; } } int ReleaseDC(HWND hWnd, HDC hDC) { if (hWnd) { // Window based DC CWnd *wnd = CWnd::FromHandle(hWnd); CDC *dc = CDC::FromHandle(hDC); return wnd->ReleaseDC(dc); } else { // System screen DC delete (CDC::Impl *)hDC; return 1; } } bool DeleteDC(HDC hDC) { delete (CDC::Impl *)hDC; return true; } bool DeleteObject(HGDIOBJ ho) { delete (CGdiObjectImpl *)ho; return true; } int GetObject(HANDLE h, int c, void *pv) { error("TODO: GetObject"); } HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) { CWnd *wnd = static_cast(hWnd); return wnd->BeginPaint(lpPaint); } bool EndPaint(HWND hWnd, const PAINTSTRUCT *lpPaint) { CWnd *wnd = static_cast(hWnd); return wnd->EndPaint(lpPaint); } intptr DialogBoxParam(HINSTANCE hInstance, const char *lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { error("TODO: DialogBoxParam"); } bool IsWindow(HWND hWnd) { error("TODO: IsWindow"); } bool SetWindowText(HWND hWnd, const char *lpszString) { CWnd *wnd = CWnd::FromHandle(hWnd); wnd->SetWindowText(lpszString); return true; } int GetWindowText(HWND hWnd, char *lpszStringBuf, int nMaxCount) { CWnd *wnd = CWnd::FromHandle(hWnd); return wnd->GetWindowText(lpszStringBuf, nMaxCount); } bool ScreenToClient(HWND hWnd, LPPOINT lpPoint) { CWnd *wnd = CWnd::FromHandle(hWnd); wnd->ScreenToClient(lpPoint); return true; } HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h) { CDC::Impl *dc = (CDC::Impl *)hdc; return dc->Attach(h); } HGDIOBJ GetStockObject(int i) { switch (i) { case SYSTEM_FONT: return AfxGetApp()->getDefaultFont(); default: break; } error("TODO: GetStockObject value"); } HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, bool bForceBkgd) { auto *surf = static_cast(hdc); return surf->selectPalette(hPal, bForceBkgd); } unsigned int RealizePalette(HDC hdc) { auto *surf = static_cast(hdc); surf->realizePalette(); return 256; } HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER *pbmih, uint32 flInit, CONST void *pjBits, CONST BITMAPINFO *pbmi, unsigned int iUsage) { CBitmap::Impl *bitmap = new CBitmap::Impl(); // Figure out the pixel format assert(pbmih->biSize == 40 && pbmih->biPlanes == 1); Graphics::PixelFormat format; switch (pbmih->biBitCount) { case 1: // Monochrome. Since ScummVM doesn't support it directly, // I use a standard 8bpp surface, but in the format's // aLoss field, I use a value of 255 as a flag. // This should be okay, as loss & shift aren't used for 8bpp. format = Graphics::PixelFormat::createFormatCLUT8(); format.aLoss = 255; break; case 8: format = Graphics::PixelFormat::createFormatCLUT8(); break; case 16: format = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); break; case 32: format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); break; default: error("Unknown biBitCount"); break; } // Create the bitmap bitmap->create(pbmih->biWidth, pbmih->biHeight, format); // Set the palette Graphics::Palette pal((pbmi && pbmih->biClrUsed) ? pbmih->biClrUsed : 0); if (pbmi && pbmih->biClrUsed) { for (uint i = 0; i < pbmih->biClrUsed; ++i) { const RGBQUAD &col = pbmi->bmiColors[i]; pal.set(i, col.rgbRed, col.rgbGreen, col.rgbBlue); } // bitmap->setPalette(pal.data(), 0, pal.size()); } // If pixels are provided, copy them over if (flInit & CBM_INIT) { assert(pjBits); if (bitmap->format.bytesPerPixel == 1 && !pal.empty()) { const CDC::Impl *destDC = (const CDC::Impl *)hdc; const CPalette::Impl *destPal = (const CPalette::Impl * )destDC->_palette; Gfx::PaletteMap palMap(pal, *destPal); palMap.map((const byte *)pjBits, (byte *)bitmap->getPixels(), bitmap->w * bitmap->h); } else { size_t size = bitmap->w * bitmap->h * bitmap->format.bytesPerPixel; Common::copy((const byte *)pjBits, (const byte *)pjBits + size, (byte *)bitmap->getPixels()); } } return bitmap; } int GetDIBits(HDC hdc, HBITMAP hbm, unsigned int start, unsigned int cLines, void *lpvBits, LPBITMAPINFO lpbmi, unsigned int usage) { error("TODO: GetDIBits"); } bool BitBlt(HDC hdc, int xDest, int yDest, int width, int height, HDC hdcSrc, int xSrc, int ySrc, uint32 rop) { CDC::Impl *srcDc = (CDC::Impl *)hdcSrc; CDC::Impl *destDc = (CDC::Impl *)hdc; CBitmap::Impl *src = (CBitmap::Impl *)srcDc->_bitmap; CBitmap::Impl *dest = (CBitmap::Impl *)destDc->_bitmap; uint bgColor = destDc->getBkColor(); Gfx::blit(src, dest, Common::Rect(xSrc, ySrc, xSrc + width, ySrc + height), Common::Point(xDest, yDest), bgColor, rop, nullptr); return true; } bool StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, uint32 rop) { CDC *srcDC = CDC::FromHandle(hdcSrc); CDC *destDC = CDC::FromHandle(hdcDest); return destDC->StretchBlt(xDest, yDest, wDest, hDest, srcDC, xSrc, ySrc, wSrc, hSrc, rop); } int SetStretchBltMode(HDC hdc, int mode) { CDC *dc = CDC::FromHandle(hdc); return dc->SetStretchBltMode(mode); } int StretchDIBits(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, CONST void *lpBits, CONST BITMAPINFO *lpbmi, unsigned int iUsage, uint32 rop) { error("TODO: StretchDIBits"); } int GetTextExtent(HDC hdc, const char *text, size_t len) { CDC *dc = CDC::FromHandle(hdc); CSize size = dc->GetTextExtent(CString(text, len)); return size.cx; } bool GetTextMetrics(HDC hdc, LPTEXTMETRIC lptm) { CDC *dc = CDC::FromHandle(hdc); return dc->GetTextMetrics(lptm); } intptr GetWindowWord(HWND hWnd, int nIndex) { assert(nIndex == GWW_HINSTANCE); return 0; } int AddFontResource(const char *fontName) { return AfxGetApp()->addFontResource(fontName); } bool RemoveFontResource(const char *fontName) { return AfxGetApp()->removeFontResource(fontName); } int SetScrollPos(HWND hWnd, int /*nBar*/, int nPos, bool bRedraw) { CWnd *wnd = CWnd::FromHandle(hWnd); return wnd->SetScrollPos(nPos, bRedraw); } void SetScrollRange(HWND hWnd, int /*nBar*/, int nMinPos, int nMaxPos, bool bRedraw) { CWnd *wnd = CWnd::FromHandle(hWnd); wnd->SetScrollRange(nMinPos, nMaxPos, bRedraw); } bool ClipCursor(const RECT *lpRect) { // Ignored in ScummVM return false; } bool GetCursorPos(LPPOINT lpPoint) { Common::Point mousePos = AfxGetApp()->getMousePos(); lpPoint->x = mousePos.x; lpPoint->y = mousePos.y; return true; } bool SetCursorPos(int x, int y) { AfxGetApp()->setMousePos(Common::Point(x, y)); return true; } bool SetCapture(HWND hWnd) { AfxGetApp()->SetCapture(hWnd); return true; } bool ReleaseCapture() { AfxGetApp()->ReleaseCapture(); return true; } HWND GetCapture() { return AfxGetApp()->GetCapture(); } HCURSOR LoadCursor(HINSTANCE hInstance, const char *lpCursorName) { return AfxGetApp()->LoadCursor(lpCursorName); } HCURSOR SetCursor(HCURSOR hCursor) { return AfxGetApp()->SetCursor(hCursor); } int ShowCursor(bool bShow) { g_system->showMouse(bShow); return 0; } bool LineDDA(int x0, int y0, int x1, int y1, LINEDDAPROC lpProc, CDC *cdc) { if (!lpProc) return false; int dx = ABS(x1 - x0); int dy = ABS(y1 - y0); int sx = (x0 < x1) ? 1 : -1; int sy = (y0 < y1) ? 1 : -1; int err = dx - dy; for (;;) { lpProc(x0, y0, cdc); // Call the callback for this pixel if (x0 == x1 && y0 == y1) break; int e2 = 2 * err; if (e2 > -dy) { err -= dy; x0 += sx; } if (e2 < dx) { err += dx; y0 += sy; } } return true; } byte GetRValue(COLORREF color) { return ((byte)(color & 0xFF)); } byte GetGValue(COLORREF color) { return ((byte)((color >> 8) & 0xFF)); } byte GetBValue(COLORREF color) { return ((byte)((color >> 16) & 0xFF)); } HWND GetDlgItem(HWND hDlg, int nIDDlgItem) { error("TODO: GetDlgItem"); } bool EndDialog(HWND hDlg, intptr nResult) { error("TODO: EndDialog"); } bool SetDlgItemInt(HWND hDlg, int nIDDlgItem, unsigned int uValue, bool bSigned) { error("TODO: SetDlgItemInt"); } bool CheckRadioButton(HWND hDlg, int nIDFirstButton, int nIDLastButton, int nIDCheckButton) { error("TODO: CheckRadioButton"); } uint32 GetSysColor(int nIndex) { switch (nIndex) { case COLOR_3DHIGHLIGHT: return RGB(255, 255, 255); case COLOR_BTNSHADOW: return RGB(128, 128, 128); case COLOR_BTNFACE: return RGB(192, 192, 192); case COLOR_BTNTEXT: case COLOR_WINDOWTEXT: return RGB(0, 0, 0); default: error("Unknown GetSysColor value"); break; } } HBRUSH GetSysColorBrush(int nIndex) { switch (nIndex) { case COLOR_WINDOW: return new CBrush::Impl(RGB(255, 255, 255)); default: error("Unknown GetSysColorBrush value"); break; } } bool DestroyMenu(HMENU hMenu) { error("TODO: DestroyMenu"); } void SetActiveWindow(HWND hWnd) { error("TODO: SetActiveWindow"); } } // namespace MFC } // namespace Bagel