wined3d: Use the FBO cache in stretch_rect_fbo().
[wine/hramrach.git] / dlls / cards / cards.c
blob6a5a95f9a46bbb829e7665d692ec6bc892ded3f1
1 /*
2 * Cards dll implementation
4 * Copyright (C) 2004 Sami Nopanen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "wingdi.h"
30 #include "cards.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(cards);
36 void WINAPI cdtTerm(void);
39 static HINSTANCE hInst;
40 static int cardWidth;
41 static int cardHeight;
42 static HBITMAP cardBitmaps[CARD_MAX + 1];
45 /***********************************************************************
46 * Initializes the cards.dll library. Loads the card bitmaps from the
47 * resources, and initializes the card size variables.
49 BOOL WINAPI cdtInit(int *width, int *height)
51 BITMAP bm;
52 int i;
54 TRACE("(%p, %p)\n", width, height);
56 for(i = 0; i <= CARD_MAX; i++)
57 cardBitmaps[i] = 0;
59 for(i = 0; i <= CARD_MAX; i++)
61 cardBitmaps[i] = LoadBitmapA(hInst, MAKEINTRESOURCEA(i));
62 if(cardBitmaps[i] == 0)
64 cdtTerm();
65 return FALSE;
69 GetObjectA(cardBitmaps[0], sizeof(BITMAP), &bm);
70 *width = cardWidth = bm.bmWidth;
71 *height = cardHeight = bm.bmHeight;
72 return TRUE;
75 static DWORD do_blt(HDC hdc, int x, int y, int dx, int dy, HDC hMemoryDC, DWORD rasterOp )
77 if((cardWidth == dx) && (cardHeight == dy))
78 return BitBlt(hdc, x, y, cardWidth, cardHeight, hMemoryDC, 0, 0, rasterOp);
79 return StretchBlt(hdc, x, y, dx, dy, hMemoryDC, 0, 0, cardWidth, cardHeight, rasterOp);
82 /***********************************************************************
83 * Draw a card. Unlike cdtDrawCard, this version allows you to stretch
84 * card bitmaps to the size you specify (dx, dy). See cdtDraw for info
85 * on card, mode and color parameters.
87 BOOL WINAPI cdtDrawExt(HDC hdc, int x, int y, int dx, int dy, int card, int mode, DWORD color)
89 HDC hMemoryDC;
90 HBITMAP hCardBitmap;
91 HGDIOBJ result;
92 DWORD rasterOp = SRCCOPY;
93 BOOL roundCornersFlag;
94 BOOL eraseFlag = FALSE;
95 BOOL drawFlag = TRUE;
97 TRACE("(%p, %d, %d, %d, %d, %d, %d, %d)\n", hdc, x, y, dx, dy, card, mode, color);
99 roundCornersFlag = !(mode & MODEFLAG_DONT_ROUND_CORNERS) &&
100 (dx == cardWidth) && (dy == cardHeight);
101 mode &= ~MODEFLAG_DONT_ROUND_CORNERS;
103 if((card < 0) || (card > CARD_MAX))
105 FIXME("Unexpected card: %d\n", card);
106 return FALSE;
109 if((mode < MODE_FACEUP) || (mode > MODE_DECKO))
111 FIXME("Unexpected mode: %d\n", mode);
112 return FALSE;
115 switch(mode)
117 case MODE_FACEUP:
118 break;
119 case MODE_FACEDOWN:
120 break;
121 case MODE_HILITE:
122 rasterOp = NOTSRCCOPY;
123 break;
124 case MODE_GHOST:
125 card = CARD_FREE_MASK;
126 eraseFlag = TRUE;
127 rasterOp = SRCAND;
128 break;
129 case MODE_REMOVE:
130 eraseFlag = TRUE;
131 drawFlag = FALSE;
132 break;
133 case MODE_INVISIBLEGHOST:
134 card = CARD_FREE_MASK;
135 rasterOp = SRCAND;
136 break;
137 case MODE_DECKX:
138 card = CARD_BACK_THE_X;
139 break;
140 case MODE_DECKO:
141 card = CARD_BACK_THE_O;
142 break;
145 hMemoryDC = CreateCompatibleDC(hdc);
146 if(hMemoryDC == 0)
147 return FALSE;
149 if(eraseFlag)
151 HBRUSH hBrush;
152 RECT rect;
153 hBrush = CreateSolidBrush(color);
154 rect.left = x;
155 rect.top = y;
156 rect.right = x + cardWidth - 1;
157 rect.bottom = y + cardHeight - 1;
158 FillRect(hdc, &rect, hBrush);
161 if(drawFlag)
163 hCardBitmap = cardBitmaps[card];
164 if(hCardBitmap == 0)
165 return FALSE;
167 result = SelectObject(hMemoryDC, hCardBitmap);
168 if((result == 0) || (result == HGDI_ERROR))
170 DeleteDC(hMemoryDC);
171 return FALSE;
174 SetBkColor(hdc, color);
176 if(roundCornersFlag)
178 /* NOTE: native uses Get/SetPixel for corners, but that really
179 * hurts on X11 since it needs a server round-trip for each pixel.
180 * So we use a clip region instead. */
181 HRGN saved = CreateRectRgn( 0, 0, 0, 0 );
182 HRGN line = CreateRectRgn( x + 2, y, x + dx - 2, y + 1 );
183 HRGN clip = CreateRectRgn( x, y + 2, x + dx, y + dy - 2 );
185 CombineRgn( clip, clip, line, RGN_OR );
186 SetRectRgn( line, x + 1, y + 1, x + dx - 1, y + 2 );
187 CombineRgn( clip, clip, line, RGN_OR );
188 SetRectRgn( line, x + 1, y + dy - 2, x + dx - 1, y + dy - 1 );
189 CombineRgn( clip, clip, line, RGN_OR );
190 SetRectRgn( line, x + 2, y + dy - 1, x + dx - 2, y + dy );
191 CombineRgn( clip, clip, line, RGN_OR );
192 DeleteObject( line );
194 if (!GetClipRgn( hdc, saved ))
196 DeleteObject( saved );
197 saved = 0;
199 ExtSelectClipRgn( hdc, clip, RGN_AND );
200 DeleteObject( clip );
202 do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp);
204 SelectClipRgn( hdc, saved );
205 if (saved) DeleteObject( saved );
207 else
208 do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp);
211 DeleteDC(hMemoryDC);
213 return TRUE;
217 /***********************************************************************
218 * Draws a card at position x, y in its default size (as returned by
219 * cdtInit.
221 * Mode controls how the card gets drawn:
222 * MODE_FACEUP ; draw card facing up
223 * MODE_FACEDOWN ; draw card facing down
224 * MODE_HILITE ; draw face up, with NOTSRCCOPY
225 * MODE_GHOST ; draw 'ghost' card
226 * MODE_REMOVE ; draw with background color
227 * MODE_INVISIBLEGHOST ; draw 'ghost' card, without clearing background
228 * MODE_DECKX ; draw X
229 * MODE_DECKO ; draw O
231 * The card parameter defines the card graphic to be drawn. If we are
232 * drawing fronts of cards, card should have a value from 0 through 51
233 * to represent the card face. If we are drawing card backs, 53 through
234 * 68 represent different card backs.
236 * When drawing card faces, two lowest bits represent the card suit
237 * (clubs, diamonds, hearts, spades), and the bits above that define the
238 * card value (ace, 2, ..., king). That is,
239 * card = face * 4 + suit.
241 * Color parameter defines the background color, used when drawing some
242 * card backs.
244 BOOL WINAPI cdtDraw(HDC hdc, int x, int y, int card, int mode, DWORD color)
246 TRACE("(%p, %d, %d, %d, %d, %d)\n", hdc, x, y, card, mode, color);
248 return cdtDrawExt(hdc, x, y, cardWidth, cardHeight, card, mode, color);
252 /***********************************************************************
253 * Animates the card backs, e.g. blinking lights on the robot, the sun
254 * donning sunglasses, bats flying across the caste, etc.. Works only
255 * for cards of normal size (as drawn with cdtDraw). To draw frames of
256 * the card back animation, start with frame = 0, and increment the
257 * frame by one, until cdtAnimate returns FALSE (to indicate that we
258 * have gone through all frames of animation).
260 BOOL WINAPI cdtAnimate(HDC hdc, int cardback, int x, int y, int frame)
262 TRACE("(%p, %d, %d, %d, %d)\n", hdc, cardback, x, y, frame);
263 FIXME("Implement me.\n");
265 return FALSE;
269 /***********************************************************************
270 * Frees resources reserved by cdtInitialize.
272 void WINAPI cdtTerm(void)
274 int i;
276 TRACE("()\n");
278 for(i = 0; i <= CARD_MAX; i++)
280 if(cardBitmaps[i] != 0)
281 DeleteObject(cardBitmaps[i]);
282 cardBitmaps[i] = 0;
287 /***********************************************************************
288 * DllMain.
290 BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
292 switch (reason)
294 case DLL_PROCESS_ATTACH:
295 hInst = inst;
296 DisableThreadLibraryCalls( inst );
297 break;
298 case DLL_PROCESS_DETACH:
299 break;
301 return TRUE;