2 // CardLib - CardRegion drawing support
5 // Copyright J Brown 2001
10 HPALETTE
UseNicePalette(HDC hdc
, HPALETTE hPalette
);
11 void PaintRect(HDC hdc
, RECT
*rect
, COLORREF colour
);
12 void CardBlt(HDC hdc
, int x
, int y
, int nCardNum
);
13 void DrawCard(HDC hdc
, int x
, int y
, HDC hdcSource
, int width
, int height
);
16 // Draw specified card at position x, y
17 // xoff - source offset from left of card
18 // yoff - source offset from top of card
19 // width - width to draw
20 // height - height to draw
22 void CardBlt(HDC hdc
, int x
, int y
, int nCardNum
)//, int xoff, int yoff, int width, int height)
24 int sx
= nCardNum
* __cardwidth
;
26 int width
= __cardwidth
;
27 int height
= __cardheight
;
29 //draw main center band
30 BitBlt(hdc
, x
+2, y
, width
- 4, height
, __hdcCardBitmaps
, sx
+2, sy
+0, SRCCOPY
);
32 //draw the two bits to the left
33 BitBlt(hdc
, x
, y
+2, 1, height
- 4, __hdcCardBitmaps
, sx
+0, sy
+2, SRCCOPY
);
34 BitBlt(hdc
, x
+1, y
+1, 1, height
- 2, __hdcCardBitmaps
, sx
+1, sy
+1, SRCCOPY
);
36 //draw the two bits to the right
37 BitBlt(hdc
, x
+width
-2, y
+1, 1, height
- 2, __hdcCardBitmaps
, sx
+width
-2, sy
+1, SRCCOPY
);
38 BitBlt(hdc
, x
+width
-1, y
+2, 1, height
- 4, __hdcCardBitmaps
, sx
+width
-1, sy
+2, SRCCOPY
);
42 // Draw a shape this this:
48 void DrawHorzCardStrip(HDC hdc
, int x
, int y
, int nCardNum
, int height
, BOOL fDrawTips
)
50 int sx
= nCardNum
* __cardwidth
;
54 BOOL tips
= fDrawTips
? FALSE
: TRUE
;
56 if(height
== 0) return;
60 sy
= sy
+ __cardheight
;
66 // draw the main vertical band
68 BitBlt(hdc
, x
+ 2, y
, __cardwidth
- 4, height
, __hdcCardBitmaps
, sx
+2, sy
, SRCCOPY
);
70 //if(height <= 1) return;
72 // draw the "lips" at the left and right
73 BitBlt(hdc
, x
+1, y
+one
, 1, height
-one
*tips
, __hdcCardBitmaps
, sx
+1, sy
+one
, SRCCOPY
);
74 BitBlt(hdc
, x
+__cardwidth
-2, y
+one
, 1, height
-one
*tips
, __hdcCardBitmaps
, sx
+__cardwidth
-2, sy
+one
, SRCCOPY
);
76 //if(height <= 2) return;
78 // draw the outer-most lips
79 BitBlt(hdc
, x
, y
+two
, 1, height
-two
*tips
, __hdcCardBitmaps
, sx
, sy
+two
, SRCCOPY
);
80 BitBlt(hdc
, x
+__cardwidth
-1, y
+two
, 1, height
-two
*tips
, __hdcCardBitmaps
, sx
+__cardwidth
-1, sy
+two
, SRCCOPY
);
84 // Draw a shape like this:
98 void DrawVertCardStrip(HDC hdc
, int x
, int y
, int nCardNum
, int width
, BOOL fDrawTips
)
100 int sx
= nCardNum
* __cardwidth
;
104 BOOL tips
= fDrawTips
? FALSE
: TRUE
;
106 if(width
== 0) return;
111 sx
= sx
+ __cardwidth
;
117 // draw the main vertical band
119 BitBlt(hdc
, x
, y
+ 2, width
, __cardheight
- 4, __hdcCardBitmaps
, sx
, sy
+2, SRCCOPY
);
121 //if(width <= 1) return;
123 // draw the "lips" at the top and bottom
124 BitBlt(hdc
, x
+one
, y
+1, width
-one
*tips
, 1, __hdcCardBitmaps
, sx
+one
, sy
+ 1, SRCCOPY
);
125 BitBlt(hdc
, x
+one
, y
+__cardheight
-2, width
-one
*tips
, 1, __hdcCardBitmaps
, sx
+one
, sy
+ __cardheight
-2, SRCCOPY
);
127 //if(width <= 2) return;
129 // draw the outer-most lips
130 BitBlt(hdc
, x
+two
, y
, width
-two
*tips
, 1, __hdcCardBitmaps
, sx
+two
, sy
, SRCCOPY
);
131 BitBlt(hdc
, x
+two
, y
+__cardheight
-1, width
-two
*tips
, 1, __hdcCardBitmaps
, sx
+two
, sy
+ __cardheight
-1, SRCCOPY
);
138 void DrawCardCorner(HDC hdc
, int x
, int y
, int cardval
, int xdir
, int ydir
)
140 int sx
= cardval
* __cardwidth
;
143 HDC hdcSource
= __hdcCardBitmaps
;
147 x
+= __cardwidth
+ xdir
- 1;
148 sx
+= __cardwidth
+ xdir
- 1;
158 y
+= __cardheight
+ ydir
- 1;
159 sy
+= __cardheight
+ ydir
- 1;
167 //convert x,y directions to -1, +1
168 xdir
= xdir
< 0 ? -1 : 1;
169 ydir
= ydir
< 0 ? -1 : 1;
171 SetPixel(hdc
, x
+xdir
, y
, GetPixel(hdcSource
, sx
+xdir
, sy
));
172 SetPixel(hdc
, x
, y
, GetPixel(hdcSource
, sx
, sy
));
173 SetPixel(hdc
, x
, y
+ydir
, GetPixel(hdcSource
, sx
, sy
+ydir
));
178 // Draw a card (i.e. miss out the corners)
180 void DrawCard(HDC hdc
, int x
, int y
, HDC hdcDragCard
, int width
, int height
)
182 //draw main center band
183 BitBlt(hdc
, x
+2, y
, width
- 4, height
, hdcDragCard
, 2, 0, SRCCOPY
);
185 //draw the two bits to the left
186 BitBlt(hdc
, x
, y
+2, 1, height
- 4, hdcDragCard
, 0, 2, SRCCOPY
);
187 BitBlt(hdc
, x
+1, y
+1, 1, height
- 2, hdcDragCard
, 1, 1, SRCCOPY
);
189 //draw the two bits to the right
190 BitBlt(hdc
, x
+width
-2, y
+1, 1, height
- 2, hdcDragCard
, width
-2, 1, SRCCOPY
);
191 BitBlt(hdc
, x
+width
-1, y
+2, 1, height
- 4, hdcDragCard
, width
-1, 2, SRCCOPY
);
195 // Clip a card SHAPE - basically any rectangle
196 // with rounded corners
198 int ClipCard(HDC hdc
, int x
, int y
, int width
, int height
)
200 ExcludeClipRect(hdc
, x
+2, y
, x
+2+width
-4, y
+ height
);
201 ExcludeClipRect(hdc
, x
, y
+2, x
+1, y
+2+height
-4);
202 ExcludeClipRect(hdc
, x
+1, y
+1, x
+2, y
+1+height
-2);
203 ExcludeClipRect(hdc
, x
+width
-2, y
+1, x
+width
-2+1, y
+1+height
-2);
204 ExcludeClipRect(hdc
, x
+width
-1, y
+2, x
+width
-1+1, y
+2+height
-4);
208 void CardRegion::Clip(HDC hdc
)
212 if(fVisible
== false)
215 Update(); //Update this stack's size+card count
216 numtoclip
= nNumApparentCards
;
218 //if we are making this stack flash on/off, then only
219 //clip the stack for drawing if the flash is in its ON state
222 if(fFlashVisible
== FALSE
)
226 //if offset along a diagonal
227 if(xoffset
!= 0 && yoffset
!= 0 && cardstack
.NumCards() != 0)
229 for(int j
= 0; j
< numtoclip
; j
++)
231 ClipCard(hdc
, xpos
+ xoffset
* j
, ypos
+ yoffset
* j
, __cardwidth
, __cardheight
);
234 //otherwise if just offset along a horizontal/vertical axis
237 if(yoffset
< 0 && numtoclip
> 0)
239 ClipCard(hdc
, xpos
, ypos
-((numtoclip
-1)*-yoffset
), width
, height
);
241 else if(xoffset
< 0 && numtoclip
> 0)
243 ClipCard(hdc
, xpos
-((numtoclip
-1)*-xoffset
), ypos
, width
, height
);
247 ClipCard(hdc
, xpos
, ypos
, width
, height
);
253 void CardRegion::Render(HDC hdc
)
259 Update(); //Update this stack's card count + size
261 numtodraw
= nNumApparentCards
;
265 if(fFlashVisible
== false)
269 if(fVisible
== 0) return;
271 cardnum
= cardstack
.NumCards() - numtodraw
;
274 for(counter
= 0; counter
< numtodraw
; counter
++)
278 int x
= xoffset
* counter
+ xpos
;
279 int y
= yoffset
* counter
+ ypos
;
281 //if about to draw last card, then actually draw the top card
282 if(counter
== numtodraw
- 1) cardnum
= cardstack
.NumCards() - 1;
284 Card card
= cardstack
.cardlist
[cardnum
];
285 cardval
= card
.Idx();
288 cardval
= nBackCardIdx
; //card-back
290 //only draw the visible part of the card
291 if(counter
< numtodraw
- 1)
293 if(yoffset
!= 0 && xoffset
!= 0)
298 if((yoffset
!= 0 && abs(xoffset
) == 1) || (xoffset
!= 0 && abs(yoffset
) == 1))
301 //draw horizontal strips
304 DrawHorzCardStrip(hdc
, x
, y
, cardval
, yoffset
, fDrawTips
);
308 DrawHorzCardStrip(hdc
, x
, y
+__cardheight
+yoffset
, cardval
, yoffset
, fDrawTips
);
311 //draw some vertical bars
314 DrawVertCardStrip(hdc
, x
, y
, cardval
, xoffset
, fDrawTips
);
318 DrawVertCardStrip(hdc
, x
+__cardwidth
+xoffset
, y
, cardval
, xoffset
, fDrawTips
);
321 if(yoffset
!= 0 && xoffset
!= 0)//fDrawTips == FALSE)
323 //if we didn't draw any tips, then this is a 2-dim stack
324 //(i.e, it goes at a diagonal).
325 //in this case, we need to fill in the small triangle in
327 DrawCardCorner(hdc
, x
, y
, cardval
, xoffset
, yoffset
);
330 //if the top card, draw the whole thing
333 CardBlt(hdc
, x
, y
, cardval
);
340 if(counter
== 0) //if the cardstack is empty, then draw it that way
349 //this wipes the RECT variable, so watch out!
350 //SetRect(&rect, x, y, x+__cardwidth, y+__cardheight);
351 //PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd));
352 parentWnd
.PaintCardRgn(hdc
, x
, y
, __cardwidth
, __cardheight
, x
, y
);
356 DrawCard(hdc
, x
, y
, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
361 CardBlt(hdc
, x
, y
, uEmptyImage
);
370 int calc_offset(int offset
, int numcards
, int numtodrag
, int realvisible
)
373 return -offset
* numcards
;
375 return -offset
* (numtodrag
) +
376 -offset
* (realvisible
- 1);
379 void CardRegion::PrepareDragBitmaps(int numtodrag
)
384 int numcards
= cardstack
.NumCards();
389 PrepareDragBitmapsThreed(numtodrag
);
393 //work out how big the bitmaps need to be
394 nDragCardWidth
= (numtodrag
- 1) * abs(xoffset
) + __cardwidth
;
395 nDragCardHeight
= (numtodrag
- 1) * abs(yoffset
) + __cardheight
;
397 //Create bitmap for the back-buffer
399 hdcBackGnd
= CreateCompatibleDC(hdc
);
400 hbmBackGnd
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
401 SelectObject(hdcBackGnd
, hbmBackGnd
);
403 //Create bitmap for the drag-image
404 hdcDragCard
= CreateCompatibleDC(hdc
);
405 hbmDragCard
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
406 SelectObject(hdcDragCard
, hbmDragCard
);
407 ReleaseDC(NULL
, hdc
);
409 UseNicePalette(hdcBackGnd
, __hPalette
);
410 UseNicePalette(hdcDragCard
, __hPalette
);
412 int realvisible
= numcards
/ nThreedCount
;
414 //if(numcards > 0 && realvisible == 0) realvisible = 1;
415 int iwhichcard
= numcards
- 1;
416 if(nThreedCount
== 1) iwhichcard
= 0;
418 //grab the first bit of background so we can prep the back buffer; do this by
419 //rendering the card stack (minus the card we are dragging) to the temporary
420 //background buffer, so it appears if we have lifted the card from the stack
421 //PaintRect(hdcBackGnd, &rect, crBackgnd);
422 SetRect(&rect
, 0, 0, nDragCardWidth
, nDragCardHeight
);
424 xoff
= calc_offset(xoffset
, numcards
, numtodrag
, realvisible
);
425 yoff
= calc_offset(yoffset
, numcards
, numtodrag
, realvisible
);
427 parentWnd
.PaintCardRgn(hdcBackGnd
, 0, 0, nDragCardWidth
, nDragCardHeight
, xpos
- xoff
, ypos
- yoff
);
430 // Render the cardstack into the back-buffer. The stack
431 // has already had the dragcards removed, so just draw
434 for(icard
= 0; icard
< realvisible
; icard
++)
436 Card card
= cardstack
.cardlist
[iwhichcard
];
439 nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
441 xoff
= xoffset
* icard
+ calc_offset(xoffset
, numcards
, numtodrag
, realvisible
);//- xoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
442 yoff
= yoffset
* icard
+ calc_offset(yoffset
, numcards
, numtodrag
, realvisible
);//- yoffset * ((numcards+numtodrag) / nThreedCount - numtodrag);
444 CardBlt(hdcBackGnd
, xoff
, yoff
, nCardVal
);
449 // If there are no cards under this one, just draw the place holder
453 int xoff
= 0, yoff
= 0;
455 if(xoffset
< 0) xoff
= nDragCardWidth
- __cardwidth
;
456 if(yoffset
< 0) yoff
= nDragCardHeight
- __cardheight
;
461 //No need to draw anything: We already cleared the
462 //back-buffer before the main loop..
464 //SetRect(&rc, xoff, yoff, xoff+ __cardwidth, yoff + __cardheight);
465 //PaintRect(hdcBackGnd, &rc, MAKE_PALETTERGB(crBackgnd));
466 //parentWnd.PaintCardRgn(hdcBackGnd, xoff, yoff, __cardwidth, __cardheight, xpos, ypos);// + xoff, ypos + yoff);
470 DrawCard(hdcBackGnd
, xoff
, yoff
, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
475 CardBlt(hdc
, xoff
, yoff
, uEmptyImage
);
481 // now render the drag-cards into the dragcard image
483 PaintRect(hdcDragCard
, &rect
, crBackgnd
);
485 for(icard
= 0; icard
< numtodrag
; icard
++)
489 if(xoffset
>= 0) xoff
= xoffset
* icard
;
490 else xoff
= -xoffset
* (numtodrag
- icard
- 1);
492 if(yoffset
>= 0) yoff
= yoffset
* icard
;
493 else yoff
= -yoffset
* (numtodrag
- icard
- 1);
495 Card card
= dragstack
.cardlist
[icard
];
497 nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
499 CardBlt(hdcDragCard
, xoff
, yoff
, nCardVal
);
503 void CardRegion::PrepareDragBitmapsThreed(int numtodrag
)
511 int numcards
= cardstack
.NumCards();
513 //work out how big the bitmaps need to be
514 nDragCardWidth
= (numtodrag
- 1) * abs(xoffset
) + __cardwidth
;
515 nDragCardHeight
= (numtodrag
- 1) * abs(yoffset
) + __cardheight
;
517 //Create bitmap for the back-buffer
519 hdcBackGnd
= CreateCompatibleDC(hdc
);
520 hbmBackGnd
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
521 SelectObject(hdcBackGnd
, hbmBackGnd
);
523 //create bitmap for the drag-image
524 hdcDragCard
= CreateCompatibleDC(hdc
);
525 hbmDragCard
= CreateCompatibleBitmap(hdc
, nDragCardWidth
, nDragCardHeight
);
526 SelectObject(hdcDragCard
, hbmDragCard
);
527 ReleaseDC(NULL
, hdc
);
529 UseNicePalette(hdcBackGnd
, __hPalette
);
530 UseNicePalette(hdcDragCard
, __hPalette
);
532 //grab the first bit of background so we can prep the back buffer; do this by
533 //rendering the card stack (minus the card we are dragging) to the temporary
534 //background buffer, so it appears if we have lifted the card from the stack
535 //--SetRect(&rect, 0, 0, nDragCardWidth, nDragCardHeight);
536 //--PaintRect(hdcBackGnd, &rect, crBackgnd);
538 int threedadjust
= numcards
% nThreedCount
== 0;
540 numunder
= CalcApparentCards(numcards
);
541 iwhichcard
= (numcards
+numtodrag
) - numunder
- 1;
542 if(nThreedCount
== 1) iwhichcard
= 0;
544 int xoff
= calc_offset(xoffset
, numunder
, numtodrag
, numunder
);
545 int yoff
= calc_offset(yoffset
, numunder
, numtodrag
, numunder
);
547 parentWnd
.PaintCardRgn(hdcBackGnd
, 0,0, nDragCardWidth
,nDragCardHeight
, xpos
- xoff
,ypos
- yoff
);
550 // Render the cardstack into the back-buffer. The stack
551 // has already had the dragcards removed, so just draw
554 for(icard
= 0; icard
< numunder
; icard
++)
556 Card card
= cardstack
.cardlist
[iwhichcard
];
557 int nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
560 xoffset
* icard
- xoffset
*(numunder
-numtodrag
+threedadjust
),
561 yoffset
* icard
- yoffset
*(numunder
-numtodrag
+threedadjust
),
568 // If there are no cards under this one, just draw the place holder
575 //no need! we've already cleared the whole
576 //back-buffer before the main loop!
577 //SetRect(&rect, 0, 0, __cardwidth, __cardheight);
578 //PaintRect(hdcBackGnd, &rect, MAKE_PALETTERGB(crBackgnd));
582 DrawCard(hdcBackGnd
, 0, 0, __hdcPlaceHolder
, __cardwidth
, __cardheight
);
587 CardBlt(hdc
, 0, 0, uEmptyImage
);
593 // now render the drag-cards into the dragcard image
595 PaintRect(hdcDragCard
, &rect
, crBackgnd
);
597 for(icard
= 0; icard
< numtodrag
; icard
++)
599 Card card
= dragstack
.cardlist
[icard
];
600 int nCardVal
= card
.FaceUp() ? card
.Idx() : nBackCardIdx
;
602 CardBlt(hdcDragCard
, xoffset
* icard
, yoffset
* icard
, nCardVal
);
606 void CardRegion::ReleaseDragBitmaps(void)
608 //SelectObject(hdcBackGnd, hOld1);
609 DeleteObject(hbmBackGnd
);
610 DeleteDC(hdcBackGnd
);
612 //SelectObject(hdcDragCard, hOld2);
613 DeleteObject(hbmDragCard
);
614 DeleteDC(hdcDragCard
);
618 void CardRegion::Redraw()
620 HDC hdc
= GetDC((HWND
)parentWnd
);
625 ReleaseDC((HWND
)parentWnd
, hdc
);