#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "cards.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(cards);
void WINAPI cdtTerm(void);
static HINSTANCE hInst;
static int cardWidth;
static int cardHeight;
static HBITMAP cardBitmaps[CARD_MAX + 1];
BOOL WINAPI cdtInit(int *width, int *height)
{
BITMAP bm;
int i;
TRACE("(%p, %p)\n", width, height);
for(i = 0; i <= CARD_MAX; i++)
cardBitmaps[i] = 0;
for(i = 0; i <= CARD_MAX; i++)
{
cardBitmaps[i] = LoadBitmapA(hInst, MAKEINTRESOURCEA(i));
if(cardBitmaps[i] == 0)
{
cdtTerm();
return FALSE;
}
}
GetObjectA(cardBitmaps[0], sizeof(BITMAP), &bm);
*width = cardWidth = bm.bmWidth;
*height = cardHeight = bm.bmHeight;
return TRUE;
}
static DWORD do_blt(HDC hdc, int x, int y, int dx, int dy, HDC hMemoryDC, DWORD rasterOp )
{
if((cardWidth == dx) && (cardHeight == dy))
return BitBlt(hdc, x, y, cardWidth, cardHeight, hMemoryDC, 0, 0, rasterOp);
return StretchBlt(hdc, x, y, dx, dy, hMemoryDC, 0, 0, cardWidth, cardHeight, rasterOp);
}
BOOL WINAPI cdtDrawExt(HDC hdc, int x, int y, int dx, int dy, int card, int mode, DWORD color)
{
HDC hMemoryDC;
HBITMAP hCardBitmap;
HGDIOBJ result;
DWORD rasterOp = SRCCOPY;
BOOL roundCornersFlag;
BOOL eraseFlag = FALSE;
BOOL drawFlag = TRUE;
TRACE("(%p, %d, %d, %d, %d, %d, %d, %ld)\n", hdc, x, y, dx, dy, card, mode, color);
roundCornersFlag = !(mode & MODEFLAG_DONT_ROUND_CORNERS) &&
(dx == cardWidth) && (dy == cardHeight);
mode &= ~MODEFLAG_DONT_ROUND_CORNERS;
if((card < 0) || (card > CARD_MAX))
{
FIXME("Unexpected card: %d\n", card);
return FALSE;
}
if((mode < MODE_FACEUP) || (mode > MODE_DECKO))
{
FIXME("Unexpected mode: %d\n", mode);
return FALSE;
}
switch(mode)
{
case MODE_FACEUP:
break;
case MODE_FACEDOWN:
break;
case MODE_HILITE:
rasterOp = NOTSRCCOPY;
break;
case MODE_GHOST:
card = CARD_FREE_MASK;
eraseFlag = TRUE;
rasterOp = SRCAND;
break;
case MODE_REMOVE:
eraseFlag = TRUE;
drawFlag = FALSE;
break;
case MODE_INVISIBLEGHOST:
card = CARD_FREE_MASK;
rasterOp = SRCAND;
break;
case MODE_DECKX:
card = CARD_BACK_THE_X;
break;
case MODE_DECKO:
card = CARD_BACK_THE_O;
break;
}
hMemoryDC = CreateCompatibleDC(hdc);
if(hMemoryDC == 0)
return FALSE;
if(eraseFlag)
{
HBRUSH hBrush;
RECT rect;
hBrush = CreateSolidBrush(color);
SetRect(&rect, x, y, x + cardWidth - 1, y + cardHeight - 1);
FillRect(hdc, &rect, hBrush);
}
if(drawFlag)
{
hCardBitmap = cardBitmaps[card];
if(hCardBitmap == 0)
return FALSE;
result = SelectObject(hMemoryDC, hCardBitmap);
if((result == 0) || (result == HGDI_ERROR))
{
DeleteDC(hMemoryDC);
return FALSE;
}
SetBkColor(hdc, color);
if(roundCornersFlag)
{
HRGN saved = CreateRectRgn( 0, 0, 0, 0 );
HRGN line = CreateRectRgn( x + 2, y, x + dx - 2, y + 1 );
HRGN clip = CreateRectRgn( x, y + 2, x + dx, y + dy - 2 );
CombineRgn( clip, clip, line, RGN_OR );
SetRectRgn( line, x + 1, y + 1, x + dx - 1, y + 2 );
CombineRgn( clip, clip, line, RGN_OR );
SetRectRgn( line, x + 1, y + dy - 2, x + dx - 1, y + dy - 1 );
CombineRgn( clip, clip, line, RGN_OR );
SetRectRgn( line, x + 2, y + dy - 1, x + dx - 2, y + dy );
CombineRgn( clip, clip, line, RGN_OR );
DeleteObject( line );
if (!GetClipRgn( hdc, saved ))
{
DeleteObject( saved );
saved = 0;
}
ExtSelectClipRgn( hdc, clip, RGN_AND );
DeleteObject( clip );
do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp);
SelectClipRgn( hdc, saved );
if (saved) DeleteObject( saved );
}
else
do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp);
}
DeleteDC(hMemoryDC);
return TRUE;
}
BOOL WINAPI cdtDraw(HDC hdc, int x, int y, int card, int mode, DWORD color)
{
TRACE("(%p, %d, %d, %d, %d, %ld)\n", hdc, x, y, card, mode, color);
return cdtDrawExt(hdc, x, y, cardWidth, cardHeight, card, mode, color);
}
BOOL WINAPI cdtAnimate(HDC hdc, int cardback, int x, int y, int frame)
{
TRACE("(%p, %d, %d, %d, %d)\n", hdc, cardback, x, y, frame);
FIXME("Implement me.\n");
return FALSE;
}
void WINAPI cdtTerm(void)
{
int i;
TRACE("()\n");
for(i = 0; i <= CARD_MAX; i++)
{
if(cardBitmaps[i] != 0)
DeleteObject(cardBitmaps[i]);
cardBitmaps[i] = 0;
}
}
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
hInst = inst;
DisableThreadLibraryCalls( inst );
break;
}
return TRUE;
}