2 // CardLib - CardRegion drawing support
5 // Copyright J Brown 2001
10 #include "cardregion.h"
11 #include "cardcolor.h"
13 HPALETTE
UseNicePalette(HDC hdc
, HPALETTE hPalette
);
14 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
15 void CardBlt(HDC hdc
, int x
, int y
, int nCardNum
);
16 void DrawCard(HDC hdc
, int x
, int y
, HDC hdcSource
, int width
, int height
);
19 // Draw specified card at position x, y
20 // xoff - source offset from left of card
21 // yoff - source offset from top of card
22 // width - width to draw
23 // height - height to draw
25 void CardBlt(HDC hdc
, int x
, int y
, int nCardNum
)//, int xoff, int yoff, int width, int height)
27 int sx
= nCardNum
* __cardwidth
;
29 int width
= __cardwidth
;
30 int height
= __cardheight
;
32 //draw main center band
33 BitBlt(hdc
, x
+2, y
, width
- 4, height
, __hdcCardBitmaps
, sx
+2, sy
+0, SRCCOPY
);
35 //draw the two bits to the left
36 BitBlt(hdc
, x
, y
+2, 1, height
- 4, __hdcCardBitmaps
, sx
+0, sy
+2, SRCCOPY
);
37 BitBlt(hdc
, x
+1, y
+1, 1, height
- 2, __hdcCardBitmaps
, sx
+1, sy
+1, SRCCOPY
);
39 //draw the two bits to the right
40 BitBlt(hdc
, x
+width
-2, y
+1, 1, height
- 2, __hdcCardBitmaps
, sx
+width
-2, sy
+1, SRCCOPY
);
41 BitBlt(hdc
, x
+width
-1, y
+2, 1, height
- 4, __hdcCardBitmaps
, sx
+width
-1, sy
+2, SRCCOPY
);
45 // Draw a shape this this:
51 void DrawHorzCardStrip(HDC hdc
, int x
, int y
, int nCardNum
, int height
, BOOL fDrawTips
)
53 int sx
= nCardNum
* __cardwidth
;
57 BOOL tips
= fDrawTips
? FALSE
: TRUE
;
59 if(height
== 0) return;
63 sy
= sy
+ __cardheight
;
69 // draw the main vertical band
71 BitBlt(hdc
, x
+ 2, y
, __cardwidth
- 4, height
, __hdcCardBitmaps
, sx
+2, sy
, SRCCOPY
);
73 //if(height <= 1) return;
75 // draw the "lips" at the left and right
76 BitBlt(hdc
, x
+1, y
+one
, 1, height
-one
*tips
, __hdcCardBitmaps
, sx
+1, sy
+one
, SRCCOPY
);
77 BitBlt(hdc
, x
+__cardwidth
-2, y
+one
, 1, height
-one
*tips
, __hdcCardBitmaps
, sx
+__cardwidth
-2, sy
+one
, SRCCOPY
);
79 //if(height <= 2) return;
81 // draw the outer-most lips
82 BitBlt(hdc
, x
, y
+two
, 1, height
-two
*tips
, __hdcCardBitmaps
, sx
, sy
+two
, SRCCOPY
);
83 BitBlt(hdc
, x
+__cardwidth
-1, y
+two
, 1, height
-two
*tips
, __hdcCardBitmaps
, sx
+__cardwidth
-1, sy
+two
, SRCCOPY
);
87 // Draw a shape like this:
101 void DrawVertCardStrip(HDC hdc
, int x
, int y
, int nCardNum
, int width
, BOOL fDrawTips
)
103 int sx
= nCardNum
* __cardwidth
;
107 BOOL tips
= fDrawTips
? FALSE
: TRUE
;
109 if(width
== 0) return;
114 sx
= sx
+ __cardwidth
;
120 // draw the main vertical band
122 BitBlt(hdc
, x
, y
+ 2, width
, __cardheight
- 4, __hdcCardBitmaps
, sx
, sy
+2, SRCCOPY
);
124 //if(width <= 1) return;
126 // draw the "lips" at the top and bottom
127 BitBlt(hdc
, x
+one
, y
+1, width
-one
*tips
, 1, __hdcCardBitmaps
, sx
+one
, sy
+ 1, SRCCOPY
);
128 BitBlt(hdc
, x
+one
, y
+__cardheight
-2, width
-one
*tips
, 1, __hdcCardBitmaps
, sx
+one
, sy
+ __cardheight
-2, SRCCOPY
);
130 //if(width <= 2) return;
132 // draw the outer-most lips
133 BitBlt(hdc
, x
+two
, y
, width
-two
*tips
, 1, __hdcCardBitmaps
, sx
+two
, sy
, SRCCOPY
);
134 BitBlt(hdc
, x
+two
, y
+__cardheight
-1, width
-two
*tips
, 1, __hdcCardBitmaps
, sx
+two
, sy
+ __cardheight
-1, SRCCOPY
);
141 void DrawCardCorner(HDC hdc
, int x
, int y
, int cardval
, int xdir
, int ydir
)
143 int sx
= cardval
* __cardwidth
;
146 HDC hdcSource
= __hdcCardBitmaps
;
150 x
+= __cardwidth
+ xdir
- 1;
151 sx
+= __cardwidth
+ xdir
- 1;
161 y
+= __cardheight
+ ydir
- 1;
162 sy
+= __cardheight
+ ydir
- 1;
170 //convert x,y directions to -1, +1
171 xdir
= xdir
< 0 ? -1 : 1;
172 ydir
= ydir
< 0 ? -1 : 1;
174 SetPixel(hdc
, x
+xdir
, y
, GetPixel(hdcSource
, sx
+xdir
, sy
));
175 SetPixel(hdc
, x
, y
, GetPixel(hdcSource
, sx
, sy
));
176 SetPixel(hdc
, x
, y
+ydir
, GetPixel(hdcSource
, sx
, sy
+ydir
));
181 // Draw a card (i.e. miss out the corners)
183 void DrawCard(HDC hdc
, int x
, int y
, HDC hdcDragCard
, int width
, int height
)
185 //draw main center band
186 BitBlt(hdc
, x
+2, y
, width
- 4, height
, hdcDragCard
, 2, 0, SRCCOPY
);
188 //draw the two bits to the left
189 BitBlt(hdc
, x
, y
+2, 1, height
- 4, hdcDragCard
, 0, 2, SRCCOPY
);
190 BitBlt(hdc
, x
+1, y
+1, 1, height
- 2, hdcDragCard
, 1, 1, SRCCOPY
);
192 //draw the two bits to the right
193 BitBlt(hdc
, x
+width
-2, y
+1, 1, height
- 2, hdcDragCard
, width
-2, 1, SRCCOPY
);
194 BitBlt(hdc
, x
+width
-1, y
+2, 1, height
- 4, hdcDragCard
, width
-1, 2, SRCCOPY
);
198 // Clip a card SHAPE - basically any rectangle
199 // with rounded corners
201 int ClipCard(HDC hdc
, int x
, int y
, int width
, int height
)
203 ExcludeClipRect(hdc
, x
+2, y
, x
+2+width
-4, y
+ height
);
204 ExcludeClipRect(hdc
, x
, y
+2, x
+1, y
+2+height
-4);
205 ExcludeClipRect(hdc
, x
+1, y
+1, x
+2, y
+1+height
-2);
206 ExcludeClipRect(hdc
, x
+width
-2, y
+1, x
+width
-2+1, y
+1+height
-2);
207 ExcludeClipRect(hdc
, x
+width
-1, y
+2, x
+width
-1+1, y
+2+height
-4);
211 void CardRegion::Clip(HDC hdc
)
215 if(fVisible
== false)
218 Update(); //Update this stack's size+card count
219 numtoclip
= nNumApparentCards
;
221 //if we are making this stack flash on/off, then only
222 //clip the stack for drawing if the flash is in its ON state
225 if(fFlashVisible
== FALSE
)
229 //if offset along a diagonal
230 if(xoffset
!= 0 && yoffset
!= 0 && cardstack
.NumCards() != 0)
232 for(int j
= 0; j
< numtoclip
; j
++)
234 ClipCard(hdc
, xpos
+ xoffset
* j
, ypos
+ yoffset
* j
, __cardwidth
, __cardheight
);
237 //otherwise if just offset along a horizontal/vertical axis
240 if(yoffset
< 0 && numtoclip
> 0)
242 ClipCard(hdc
, xpos
, ypos
-((numtoclip
-1)*-yoffset
), width
, height
);
244 else if(xoffset
< 0 && numtoclip
> 0)
246 ClipCard(hdc
, xpos
-((numtoclip
-1)*-xoffset
), ypos
, width
, height
);
250 ClipCard(hdc
, xpos
, ypos
, width
, height
);
256 void CardRegion::Render(HDC hdc
)
262 Update(); //Update this stack's card count + size
264 numtodraw
= nNumApparentCards
;
268 if(fFlashVisible
== false)
272 if(fVisible
== 0) return;
274 cardnum
= cardstack
.NumCards() - numtodraw
;
277 for(counter
= 0; counter
< numtodraw
; counter
++)
281 int x
= xoffset
* counter
+ xpos
;
282 int y
= yoffset
* counter
+ ypos
;
284 //if about to draw last card, then actually draw the top card
285 if(counter
== numtodraw
- 1) cardnum
= cardstack
.NumCards() - 1;
287 Card card
= cardstack
.cardlist
[cardnum
];
288 cardval
= card
.Idx();
291 cardval
= nBackCardIdx
; //card-back
293 //only draw the visible part of the card
294 if(counter
< numtodraw
- 1)
296 if(yoffset
!= 0 && xoffset
!= 0)
301 if((yoffset
!= 0 && abs(xoffset
) == 1) || (xoffset
!= 0 && abs(yoffset
) == 1))
304 //draw horizontal strips
307 DrawHorzCardStrip(hdc
, x
, y
, cardval
, yoffset
, fDrawTips
);
311 DrawHorzCardStrip(hdc
, x
, y
+__cardheight
+yoffset
, cardval
, yoffset
, fDrawTips
);
314 //draw some vertical bars
317 DrawVertCardStrip(hdc
, x
, y
, cardval
, xoffset
, fDrawTips
);
321 DrawVertCardStrip(hdc
, x
+__cardwidth
+xoffset
, y
, cardval
, xoffset
, fDrawTips
);
324 if(yoffset
!= 0 && xoffset
!= 0)//fDrawTips == FALSE)
326 //if we didn't draw any tips, then this is a 2-dim stack
327 //(i.e, it goes at a diagonal).
328 //in this case, we need to fill in the small triangle in
330 DrawCardCorner(hdc
, x
, y
, cardval
, xoffset
, yoffset
);
333 //if the top card, draw the whole thing
336 CardBlt(hdc
, x
, y
, cardval
);
343 if(counter
== 0) //if the cardstack is empty, then draw it that way
352 //this wipes the RECT variable, so watch out!
353 //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);
354 //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
355 parentWnd
.PaintCardRgn(hdc
, x
, y
, __cardwidth
, __cardheight
, x
, y
);
359 DrawCard(hdc
, x
, y
, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
364 CardBlt(hdc
, x
, y
, uEmptyImage
);
373 int calc_offset(int offset
, int numcards
, int numtodrag
, int realvisible
)
376 return -offset
* numcards
;
378 return -offset
* (numtodrag
) +
379 -offset
* (realvisible
- 1);
382 void CardRegion::PrepareDragBitmaps(int numtodrag
)
387 int numcards
= cardstack
.NumCards();
392 PrepareDragBitmapsThreed(numtodrag
);
396 //work out how big the bitmaps need to be
397 nDragCardWidth
= (numtodrag
- 1) * abs(xoffset
) + __cardwidth
;
398 nDragCardHeight
= (numtodrag
- 1) * abs(yoffset
) + __cardheight
;
400 //Create bitmap for the back-buffer
402 hdcBackGnd
= CreateCompatibleDC(hdc
);
403 hbmBackGnd
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
404 SelectObject(hdcBackGnd
, hbmBackGnd
);
406 //Create bitmap for the drag-image
407 hdcDragCard
= CreateCompatibleDC(hdc
);
408 hbmDragCard
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
409 SelectObject(hdcDragCard
, hbmDragCard
);
410 ReleaseDC(NULL
, hdc
);
412 UseNicePalette(hdcBackGnd
, __hPalette
);
413 UseNicePalette(hdcDragCard
, __hPalette
);
415 int realvisible
= numcards
/ nThreedCount
;
417 //if(numcards > 0 && realvisible == 0) realvisible = 1;
418 int iwhichcard
= numcards
- 1;
419 if(nThreedCount
== 1) iwhichcard
= 0;
421 //grab the first bit of background so we can prep the back buffer; do this by
422 //rendering the card stack (minus the card we are dragging) to the temporary
423 //background buffer, so it appears if we have lifted the card from the stack
424 //PaintRect(hdcBackGnd, &rect, crBackgnd);
425 SetRect(&rect
, 0, 0, nDragCardWidth
, nDragCardHeight
);
427 xoff
= calc_offset(xoffset
, numcards
, numtodrag
, realvisible
);
428 yoff
= calc_offset(yoffset
, numcards
, numtodrag
, realvisible
);
430 parentWnd
.PaintCardRgn(hdcBackGnd
, 0, 0, nDragCardWidth
, nDragCardHeight
, xpos
- xoff
, ypos
- yoff
);
433 // Render the cardstack into the back-buffer. The stack
434 // has already had the dragcards removed, so just draw
437 for(icard
= 0; icard
< realvisible
; icard
++)
439 Card card
= cardstack
.cardlist
[iwhichcard
];
442 nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
444 xoff
= xoffset
* icard
+ calc_offset(xoffset
, numcards
, numtodrag
, realvisible
);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
445 yoff
= yoffset
* icard
+ calc_offset(yoffset
, numcards
, numtodrag
, realvisible
);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
447 CardBlt(hdcBackGnd
, xoff
, yoff
, nCardVal
);
452 // If there are no cards under this one, just draw the place holder
456 int xoff
= 0, yoff
= 0;
458 if(xoffset
< 0) xoff
= nDragCardWidth
- __cardwidth
;
459 if(yoffset
< 0) yoff
= nDragCardHeight
- __cardheight
;
464 //No need to draw anything: We already cleared the
465 //back-buffer before the main loop..
467 //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);
468 //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));
469 //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);
473 DrawCard(hdcBackGnd
, xoff
, yoff
, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
478 CardBlt(hdc
, xoff
, yoff
, uEmptyImage
);
484 // now render the drag-cards into the dragcard image
486 PaintRect(hdcDragCard
, &rect
, crBackgnd
);
488 for(icard
= 0; icard
< numtodrag
; icard
++)
492 if(xoffset
>= 0) xoff
= xoffset
* icard
;
493 else xoff
= -xoffset
* (numtodrag
- icard
- 1);
495 if(yoffset
>= 0) yoff
= yoffset
* icard
;
496 else yoff
= -yoffset
* (numtodrag
- icard
- 1);
498 Card card
= dragstack
.cardlist
[icard
];
500 nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
502 CardBlt(hdcDragCard
, xoff
, yoff
, nCardVal
);
506 void CardRegion::PrepareDragBitmapsThreed(int numtodrag
)
514 int numcards
= cardstack
.NumCards();
516 //work out how big the bitmaps need to be
517 nDragCardWidth
= (numtodrag
- 1) * abs(xoffset
) + __cardwidth
;
518 nDragCardHeight
= (numtodrag
- 1) * abs(yoffset
) + __cardheight
;
520 //Create bitmap for the back-buffer
522 hdcBackGnd
= CreateCompatibleDC(hdc
);
523 hbmBackGnd
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
524 SelectObject(hdcBackGnd
, hbmBackGnd
);
526 //create bitmap for the drag-image
527 hdcDragCard
= CreateCompatibleDC(hdc
);
528 hbmDragCard
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
529 SelectObject(hdcDragCard
, hbmDragCard
);
530 ReleaseDC(NULL
, hdc
);
532 UseNicePalette(hdcBackGnd
, __hPalette
);
533 UseNicePalette(hdcDragCard
, __hPalette
);
535 //grab the first bit of background so we can prep the back buffer; do this by
536 //rendering the card stack (minus the card we are dragging) to the temporary
537 //background buffer, so it appears if we have lifted the card from the stack
538 //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
539 //--PaintRect(hdcBackGnd, &rect, crBackgnd);
541 int threedadjust
= numcards
% nThreedCount
== 0;
543 numunder
= CalcApparentCards(numcards
);
544 iwhichcard
= (numcards
+numtodrag
) - numunder
- 1;
545 if(nThreedCount
== 1) iwhichcard
= 0;
547 int xoff
= calc_offset(xoffset
, numunder
, numtodrag
, numunder
);
548 int yoff
= calc_offset(yoffset
, numunder
, numtodrag
, numunder
);
550 parentWnd
.PaintCardRgn(hdcBackGnd
, 0,0, nDragCardWidth
,nDragCardHeight
, xpos
- xoff
,ypos
- yoff
);
553 // Render the cardstack into the back-buffer. The stack
554 // has already had the dragcards removed, so just draw
557 for(icard
= 0; icard
< numunder
; icard
++)
559 Card card
= cardstack
.cardlist
[iwhichcard
];
560 int nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
563 xoffset
* icard
- xoffset
*(numunder
-numtodrag
+threedadjust
),
564 yoffset
* icard
- yoffset
*(numunder
-numtodrag
+threedadjust
),
571 // If there are no cards under this one, just draw the place holder
578 //no need! we've already cleared the whole
579 //back-buffer before the main loop!
580 //SetRect(&rect, 0, 0, __cardwidth, __cardheight);
581 //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));
585 DrawCard(hdcBackGnd
, 0, 0, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
590 CardBlt(hdc
, 0, 0, uEmptyImage
);
596 // now render the drag-cards into the dragcard image
598 PaintRect(hdcDragCard
, &rect
, crBackgnd
);
600 for(icard
= 0; icard
< numtodrag
; icard
++)
602 Card card
= dragstack
.cardlist
[icard
];
603 int nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
605 CardBlt(hdcDragCard
, xoffset
* icard
, yoffset
* icard
, nCardVal
);
609 void CardRegion::ReleaseDragBitmaps(void)
611 //SelectObject(hdcBackGnd, hOld1);
612 DeleteObject(hbmBackGnd
);
613 DeleteDC(hdcBackGnd
);
615 //SelectObject(hdcDragCard, hOld2);
616 DeleteObject(hbmDragCard
);
617 DeleteDC(hdcDragCard
);
621 void CardRegion::Redraw()
623 HDC hdc
= GetDC((HWND
)parentWnd
);
628 ReleaseDC((HWND
)parentWnd
, hdc
);