| /* |
| * Cards dll implementation |
| * |
| * Copyright (C) 2004 Sami Nopanen |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library 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 |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #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]; |
| |
| |
| /*********************************************************************** |
| * Initializes the cards.dll library. Loads the card bitmaps from the |
| * resources, and initializes the card size variables. |
| */ |
| 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); |
| } |
| |
| /*********************************************************************** |
| * Draw a card. Unlike cdtDrawCard, this version allows you to stretch |
| * card bitmaps to the size you specify (dx, dy). See cdtDraw for info |
| * on card, mode and color parameters. |
| */ |
| 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, %d)\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); |
| rect.left = x; |
| rect.top = y; |
| rect.right = x + cardWidth - 1; |
| rect.bottom = 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) |
| { |
| /* NOTE: native uses Get/SetPixel for corners, but that really |
| * hurts on X11 since it needs a server round-trip for each pixel. |
| * So we use a clip region instead. */ |
| 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; |
| } |
| |
| |
| /*********************************************************************** |
| * Draws a card at position x, y in its default size (as returned by |
| * cdtInit. |
| * |
| * Mode controls how the card gets drawn: |
| * MODE_FACEUP ; draw card facing up |
| * MODE_FACEDOWN ; draw card facing down |
| * MODE_HILITE ; draw face up, with NOTSRCCOPY |
| * MODE_GHOST ; draw 'ghost' card |
| * MODE_REMOVE ; draw with background color |
| * MODE_INVISIBLEGHOST ; draw 'ghost' card, without clearing background |
| * MODE_DECKX ; draw X |
| * MODE_DECKO ; draw O |
| * |
| * The card parameter defines the card graphic to be drawn. If we are |
| * drawing fronts of cards, card should have a value from 0 through 51 |
| * to represent the card face. If we are drawing card backs, 53 through |
| * 68 represent different card backs. |
| * |
| * When drawing card faces, two lowest bits represent the card suit |
| * (clubs, diamonds, hearts, spades), and the bits above that define the |
| * card value (ace, 2, ..., king). That is, |
| * card = face * 4 + suit. |
| * |
| * Color parameter defines the background color, used when drawing some |
| * card backs. |
| */ |
| BOOL WINAPI cdtDraw(HDC hdc, int x, int y, int card, int mode, DWORD color) |
| { |
| TRACE("(%p, %d, %d, %d, %d, %d)\n", hdc, x, y, card, mode, color); |
| |
| return cdtDrawExt(hdc, x, y, cardWidth, cardHeight, card, mode, color); |
| } |
| |
| |
| /*********************************************************************** |
| * Animates the card backs, e.g. blinking lights on the robot, the sun |
| * donning sunglasses, bats flying across the caste, etc.. Works only |
| * for cards of normal size (as drawn with cdtDraw). To draw frames of |
| * the card back animation, start with frame = 0, and increment the |
| * frame by one, until cdtAnimate returns FALSE (to indicate that we |
| * have gone through all frames of animation). |
| */ |
| 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; |
| } |
| |
| |
| /*********************************************************************** |
| * Frees resources reserved by cdtInit. |
| */ |
| 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; |
| } |
| } |
| |
| |
| /*********************************************************************** |
| * DllMain. |
| */ |
| BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) |
| { |
| switch (reason) |
| { |
| case DLL_PROCESS_ATTACH: |
| hInst = inst; |
| DisableThreadLibraryCalls( inst ); |
| break; |
| } |
| return TRUE; |
| } |