2 // CardLib - CardRegion drawing support
5 // Copyright J Brown 2001
9 #include "cardregion.h"
10 #include "cardcolor.h"
12 HPALETTE
UseNicePalette(HDC hdc
, HPALETTE hPalette
);
13 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
14 void CardBlt(HDC hdc
, int x
, int y
, int nCardNum
);
15 void DrawCard(HDC hdc
, int x
, int y
, HDC hdcSource
, int width
, int height
);
18 // Draw specified card at position x, y
19 // xoff - source offset from left of card
20 // yoff - source offset from top of card
21 // width - width to draw
22 // height - height to draw
24 void CardBlt(HDC hdc
, int x
, int y
, int nCardNum
)//, int xoff, int yoff, int width, int height)
26 int sx
= nCardNum
* __cardwidth
;
28 int width
= __cardwidth
;
29 int height
= __cardheight
;
31 //draw main center band
32 BitBlt(hdc
, x
+2, y
, width
- 4, height
, __hdcCardBitmaps
, sx
+2, sy
+0, SRCCOPY
);
34 //draw the two bits to the left
35 BitBlt(hdc
, x
, y
+2, 1, height
- 4, __hdcCardBitmaps
, sx
+0, sy
+2, SRCCOPY
);
36 BitBlt(hdc
, x
+1, y
+1, 1, height
- 2, __hdcCardBitmaps
, sx
+1, sy
+1, SRCCOPY
);
38 //draw the two bits to the right
39 BitBlt(hdc
, x
+width
-2, y
+1, 1, height
- 2, __hdcCardBitmaps
, sx
+width
-2, sy
+1, SRCCOPY
);
40 BitBlt(hdc
, x
+width
-1, y
+2, 1, height
- 4, __hdcCardBitmaps
, sx
+width
-1, sy
+2, SRCCOPY
);
44 // Draw a shape this this:
50 void DrawHorzCardStrip(HDC hdc
, int x
, int y
, int nCardNum
, int height
, BOOL fDrawTips
)
52 int sx
= nCardNum
* __cardwidth
;
56 BOOL tips
= fDrawTips
? FALSE
: TRUE
;
58 if(height
== 0) return;
62 sy
= sy
+ __cardheight
;
68 // draw the main vertical band
70 BitBlt(hdc
, x
+ 2, y
, __cardwidth
- 4, height
, __hdcCardBitmaps
, sx
+2, sy
, SRCCOPY
);
72 //if(height <= 1) return;
74 // draw the "lips" at the left and right
75 BitBlt(hdc
, x
+1, y
+one
, 1, height
-one
*tips
, __hdcCardBitmaps
, sx
+1, sy
+one
, SRCCOPY
);
76 BitBlt(hdc
, x
+__cardwidth
-2, y
+one
, 1, height
-one
*tips
, __hdcCardBitmaps
, sx
+__cardwidth
-2, sy
+one
, SRCCOPY
);
78 //if(height <= 2) return;
80 // draw the outer-most lips
81 BitBlt(hdc
, x
, y
+two
, 1, height
-two
*tips
, __hdcCardBitmaps
, sx
, sy
+two
, SRCCOPY
);
82 BitBlt(hdc
, x
+__cardwidth
-1, y
+two
, 1, height
-two
*tips
, __hdcCardBitmaps
, sx
+__cardwidth
-1, sy
+two
, SRCCOPY
);
86 // Draw a shape like this:
100 void DrawVertCardStrip(HDC hdc
, int x
, int y
, int nCardNum
, int width
, BOOL fDrawTips
)
102 int sx
= nCardNum
* __cardwidth
;
106 BOOL tips
= fDrawTips
? FALSE
: TRUE
;
108 if(width
== 0) return;
113 sx
= sx
+ __cardwidth
;
119 // draw the main vertical band
121 BitBlt(hdc
, x
, y
+ 2, width
, __cardheight
- 4, __hdcCardBitmaps
, sx
, sy
+2, SRCCOPY
);
123 //if(width <= 1) return;
125 // draw the "lips" at the top and bottom
126 BitBlt(hdc
, x
+one
, y
+1, width
-one
*tips
, 1, __hdcCardBitmaps
, sx
+one
, sy
+ 1, SRCCOPY
);
127 BitBlt(hdc
, x
+one
, y
+__cardheight
-2, width
-one
*tips
, 1, __hdcCardBitmaps
, sx
+one
, sy
+ __cardheight
-2, SRCCOPY
);
129 //if(width <= 2) return;
131 // draw the outer-most lips
132 BitBlt(hdc
, x
+two
, y
, width
-two
*tips
, 1, __hdcCardBitmaps
, sx
+two
, sy
, SRCCOPY
);
133 BitBlt(hdc
, x
+two
, y
+__cardheight
-1, width
-two
*tips
, 1, __hdcCardBitmaps
, sx
+two
, sy
+ __cardheight
-1, SRCCOPY
);
140 void DrawCardCorner(HDC hdc
, int x
, int y
, int cardval
, int xdir
, int ydir
)
142 int sx
= cardval
* __cardwidth
;
145 HDC hdcSource
= __hdcCardBitmaps
;
149 x
+= __cardwidth
+ xdir
- 1;
150 sx
+= __cardwidth
+ xdir
- 1;
160 y
+= __cardheight
+ ydir
- 1;
161 sy
+= __cardheight
+ ydir
- 1;
169 //convert x,y directions to -1, +1
170 xdir
= xdir
< 0 ? -1 : 1;
171 ydir
= ydir
< 0 ? -1 : 1;
173 SetPixel(hdc
, x
+xdir
, y
, GetPixel(hdcSource
, sx
+xdir
, sy
));
174 SetPixel(hdc
, x
, y
, GetPixel(hdcSource
, sx
, sy
));
175 SetPixel(hdc
, x
, y
+ydir
, GetPixel(hdcSource
, sx
, sy
+ydir
));
180 // Draw a card (i.e. miss out the corners)
182 void DrawCard(HDC hdc
, int x
, int y
, HDC hdcDragCard
, int width
, int height
)
184 //draw main center band
185 BitBlt(hdc
, x
+2, y
, width
- 4, height
, hdcDragCard
, 2, 0, SRCCOPY
);
187 //draw the two bits to the left
188 BitBlt(hdc
, x
, y
+2, 1, height
- 4, hdcDragCard
, 0, 2, SRCCOPY
);
189 BitBlt(hdc
, x
+1, y
+1, 1, height
- 2, hdcDragCard
, 1, 1, SRCCOPY
);
191 //draw the two bits to the right
192 BitBlt(hdc
, x
+width
-2, y
+1, 1, height
- 2, hdcDragCard
, width
-2, 1, SRCCOPY
);
193 BitBlt(hdc
, x
+width
-1, y
+2, 1, height
- 4, hdcDragCard
, width
-1, 2, SRCCOPY
);
197 // Clip a card SHAPE - basically any rectangle
198 // with rounded corners
200 int ClipCard(HDC hdc
, int x
, int y
, int width
, int height
)
202 ExcludeClipRect(hdc
, x
+2, y
, x
+2+width
-4, y
+ height
);
203 ExcludeClipRect(hdc
, x
, y
+2, x
+1, y
+2+height
-4);
204 ExcludeClipRect(hdc
, x
+1, y
+1, x
+2, y
+1+height
-2);
205 ExcludeClipRect(hdc
, x
+width
-2, y
+1, x
+width
-2+1, y
+1+height
-2);
206 ExcludeClipRect(hdc
, x
+width
-1, y
+2, x
+width
-1+1, y
+2+height
-4);
210 void CardRegion::Clip(HDC hdc
)
214 if(fVisible
== false)
217 Update(); //Update this stack's size+card count
218 numtoclip
= nNumApparentCards
;
220 //if we are making this stack flash on/off, then only
221 //clip the stack for drawing if the flash is in its ON state
224 if(fFlashVisible
== FALSE
)
228 //if offset along a diagonal
229 if(xoffset
!= 0 && yoffset
!= 0 && cardstack
.NumCards() != 0)
231 for(int j
= 0; j
< numtoclip
; j
++)
233 ClipCard(hdc
, xpos
+ xoffset
* j
, ypos
+ yoffset
* j
, __cardwidth
, __cardheight
);
236 //otherwise if just offset along a horizontal/vertical axis
239 if(yoffset
< 0 && numtoclip
> 0)
241 ClipCard(hdc
, xpos
, ypos
-((numtoclip
-1)*-yoffset
), width
, height
);
243 else if(xoffset
< 0 && numtoclip
> 0)
245 ClipCard(hdc
, xpos
-((numtoclip
-1)*-xoffset
), ypos
, width
, height
);
249 ClipCard(hdc
, xpos
, ypos
, width
, height
);
255 void CardRegion::Render(HDC hdc
)
261 Update(); //Update this stack's card count + size
263 numtodraw
= nNumApparentCards
;
267 if(fFlashVisible
== false)
271 if(fVisible
== 0) return;
273 cardnum
= cardstack
.NumCards() - numtodraw
;
276 for(counter
= 0; counter
< numtodraw
; counter
++)
280 int x
= xoffset
* counter
+ xpos
;
281 int y
= yoffset
* counter
+ ypos
;
283 //if about to draw last card, then actually draw the top card
284 if(counter
== numtodraw
- 1) cardnum
= cardstack
.NumCards() - 1;
286 Card card
= cardstack
.cardlist
[cardnum
];
287 cardval
= card
.Idx();
290 cardval
= nBackCardIdx
; //card-back
292 //only draw the visible part of the card
293 if(counter
< numtodraw
- 1)
295 if(yoffset
!= 0 && xoffset
!= 0)
300 if(yoffset
!= 0 && abs(xoffset
) == 1 || xoffset
!= 0 && abs(yoffset
) == 1)
303 //draw horizontal strips
306 DrawHorzCardStrip(hdc
, x
, y
, cardval
, yoffset
, fDrawTips
);
310 DrawHorzCardStrip(hdc
, x
, y
+__cardheight
+yoffset
, cardval
, yoffset
, fDrawTips
);
313 //draw some vertical bars
316 DrawVertCardStrip(hdc
, x
, y
, cardval
, xoffset
, fDrawTips
);
320 DrawVertCardStrip(hdc
, x
+__cardwidth
+xoffset
, y
, cardval
, xoffset
, fDrawTips
);
323 if(yoffset
!= 0 && xoffset
!= 0)//fDrawTips == FALSE)
325 //if we didn't draw any tips, then this is a 2-dim stack
326 //(i.e, it goes at a diagonal).
327 //in this case, we need to fill in the small triangle in
329 DrawCardCorner(hdc
, x
, y
, cardval
, xoffset
, yoffset
);
332 //if the top card, draw the whole thing
335 CardBlt(hdc
, x
, y
, cardval
);
342 if(counter
== 0) //if the cardstack is empty, then draw it that way
349 default: case CS_EI_NONE
:
350 //this wipes the RECT variable, so watch out!
351 //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);
352 //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
353 parentWnd
.PaintCardRgn(hdc
, x
, y
, __cardwidth
, __cardheight
, x
, y
);
356 case CS_EI_SUNK
: //case CS_EI_CIRC: case CS_EI_X:
357 DrawCard(hdc
, x
, y
, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
366 int calc_offset(int offset
, int numcards
, int numtodrag
, int realvisible
)
369 return -offset
* numcards
;
371 return -offset
* (numtodrag
) +
372 -offset
* (realvisible
- 1);
375 void CardRegion::PrepareDragBitmaps(int numtodrag
)
380 int numcards
= cardstack
.NumCards();
385 PrepareDragBitmapsThreed(numtodrag
);
389 //work out how big the bitmaps need to be
390 nDragCardWidth
= (numtodrag
- 1) * abs(xoffset
) + __cardwidth
;
391 nDragCardHeight
= (numtodrag
- 1) * abs(yoffset
) + __cardheight
;
393 //Create bitmap for the back-buffer
395 hdcBackGnd
= CreateCompatibleDC(hdc
);
396 hbmBackGnd
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
397 SelectObject(hdcBackGnd
, hbmBackGnd
);
399 //Create bitmap for the drag-image
400 hdcDragCard
= CreateCompatibleDC(hdc
);
401 hbmDragCard
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
402 SelectObject(hdcDragCard
, hbmDragCard
);
403 ReleaseDC(NULL
, hdc
);
405 UseNicePalette(hdcBackGnd
, __hPalette
);
406 UseNicePalette(hdcDragCard
, __hPalette
);
408 int realvisible
= numcards
/ nThreedCount
;
410 //if(numcards > 0 && realvisible == 0) realvisible = 1;
411 int iwhichcard
= numcards
- 1;
412 if(nThreedCount
== 1) iwhichcard
= 0;
414 //grab the first bit of background so we can prep the back buffer; do this by
415 //rendering the card stack (minus the card we are dragging) to the temporary
416 //background buffer, so it appears if we have lifted the card from the stack
417 //PaintRect(hdcBackGnd, &rect, crBackgnd);
418 SetRect(&rect
, 0, 0, nDragCardWidth
, nDragCardHeight
);
420 xoff
= calc_offset(xoffset
, numcards
, numtodrag
, realvisible
);
421 yoff
= calc_offset(yoffset
, numcards
, numtodrag
, realvisible
);
423 parentWnd
.PaintCardRgn(hdcBackGnd
, 0, 0, nDragCardWidth
, nDragCardHeight
, xpos
- xoff
, ypos
- yoff
);
426 // Render the cardstack into the back-buffer. The stack
427 // has already had the dragcards removed, so just draw
430 for(icard
= 0; icard
< realvisible
; icard
++)
432 Card card
= cardstack
.cardlist
[iwhichcard
];
435 nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
437 xoff
= xoffset
* icard
+ calc_offset(xoffset
, numcards
, numtodrag
, realvisible
);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
438 yoff
= yoffset
* icard
+ calc_offset(yoffset
, numcards
, numtodrag
, realvisible
);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
440 CardBlt(hdcBackGnd
, xoff
, yoff
, nCardVal
);
445 // If there are no cards under this one, just draw the place holder
449 int xoff
= 0, yoff
= 0;
451 if(xoffset
< 0) xoff
= nDragCardWidth
- __cardwidth
;
452 if(yoffset
< 0) yoff
= nDragCardHeight
- __cardheight
;
457 //No need to draw anything: We already cleared the
458 //back-buffer before the main loop..
460 //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);
461 //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));
462 //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);
466 DrawCard(hdcBackGnd
, xoff
, yoff
, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
472 // now render the drag-cards into the dragcard image
474 PaintRect(hdcDragCard
, &rect
, crBackgnd
);
476 for(icard
= 0; icard
< numtodrag
; icard
++)
480 if(xoffset
>= 0) xoff
= xoffset
* icard
;
481 else xoff
= -xoffset
* (numtodrag
- icard
- 1);
483 if(yoffset
>= 0) yoff
= yoffset
* icard
;
484 else yoff
= -yoffset
* (numtodrag
- icard
- 1);
486 Card card
= dragstack
.cardlist
[icard
];
488 nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
490 CardBlt(hdcDragCard
, xoff
, yoff
, nCardVal
);
494 void CardRegion::PrepareDragBitmapsThreed(int numtodrag
)
502 int numcards
= cardstack
.NumCards();
504 //work out how big the bitmaps need to be
505 nDragCardWidth
= (numtodrag
- 1) * abs(xoffset
) + __cardwidth
;
506 nDragCardHeight
= (numtodrag
- 1) * abs(yoffset
) + __cardheight
;
508 //Create bitmap for the back-buffer
510 hdcBackGnd
= CreateCompatibleDC(hdc
);
511 hbmBackGnd
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
512 SelectObject(hdcBackGnd
, hbmBackGnd
);
514 //create bitmap for the drag-image
515 hdcDragCard
= CreateCompatibleDC(hdc
);
516 hbmDragCard
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
517 SelectObject(hdcDragCard
, hbmDragCard
);
518 ReleaseDC(NULL
, hdc
);
520 UseNicePalette(hdcBackGnd
, __hPalette
);
521 UseNicePalette(hdcDragCard
, __hPalette
);
523 //grab the first bit of background so we can prep the back buffer; do this by
524 //rendering the card stack (minus the card we are dragging) to the temporary
525 //background buffer, so it appears if we have lifted the card from the stack
526 //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
527 //--PaintRect(hdcBackGnd, &rect, crBackgnd);
529 int threedadjust
= numcards
% nThreedCount
== 0;
531 numunder
= CalcApparentCards(numcards
);
532 iwhichcard
= (numcards
+numtodrag
) - numunder
- 1;
533 if(nThreedCount
== 1) iwhichcard
= 0;
535 int xoff
= calc_offset(xoffset
, numunder
, numtodrag
, numunder
);
536 int yoff
= calc_offset(yoffset
, numunder
, numtodrag
, numunder
);
538 parentWnd
.PaintCardRgn(hdcBackGnd
, 0,0, nDragCardWidth
,nDragCardHeight
, xpos
- xoff
,ypos
- yoff
);
541 // Render the cardstack into the back-buffer. The stack
542 // has already had the dragcards removed, so just draw
545 for(icard
= 0; icard
< numunder
; icard
++)
547 Card card
= cardstack
.cardlist
[iwhichcard
];
548 int nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
551 xoffset
* icard
- xoffset
*(numunder
-numtodrag
+threedadjust
),
552 yoffset
* icard
- yoffset
*(numunder
-numtodrag
+threedadjust
),
559 // If there are no cards under this one, just draw the place holder
566 //no need! we've already cleared the whole
567 //back-buffer before the main loop!
568 //SetRect(&rect, 0, 0, __cardwidth, __cardheight);
569 //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));
573 DrawCard(hdcBackGnd
, 0, 0, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
580 // now render the drag-cards into the dragcard image
582 PaintRect(hdcDragCard
, &rect
, crBackgnd
);
584 for(icard
= 0; icard
< numtodrag
; icard
++)
586 Card card
= dragstack
.cardlist
[icard
];
587 int nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
589 CardBlt(hdcDragCard
, xoffset
* icard
, yoffset
* icard
, nCardVal
);
593 void CardRegion::ReleaseDragBitmaps(void)
595 //SelectObject(hdcBackGnd, hOld1);
596 DeleteObject(hbmBackGnd
);
597 DeleteDC(hdcBackGnd
);
599 //SelectObject(hdcDragCard, hOld2);
600 DeleteObject(hbmDragCard
);
601 DeleteDC(hdcDragCard
);
605 void CardRegion::Redraw()
607 HDC hdc
= GetDC((HWND
)parentWnd
);
612 ReleaseDC((HWND
)parentWnd
, hdc
);