Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
12 KiB

  1. /***************************************************************************/
  2. /** Microsoft Windows **/
  3. /** Copyright(c) Microsoft Corp., 1991, 1992 **/
  4. /***************************************************************************/
  5. /****************************************************************************
  6. card.cpp
  7. Nov 91, JimH
  8. Methods for card objects
  9. ****************************************************************************/
  10. #include "hearts.h"
  11. #include <stdlib.h> // for labs() prototype
  12. #include "card.h"
  13. // Declare (and initialize) static members
  14. HINSTANCE card::hCardsDLL;
  15. INITPROC card::lpcdtInit;
  16. DRAWPROC card::lpcdtDraw;
  17. FARPROC card::lpcdtTerm;
  18. CBitmap card::m_bmFgnd;
  19. CBitmap card::m_bmBgnd2;
  20. CDC card::m_MemB;
  21. CDC card::m_MemB2;
  22. CRgn card::m_Rgn1;
  23. CRgn card::m_Rgn2;
  24. CRgn card::m_Rgn;
  25. DWORD card::dwPixel[12];
  26. BOOL card::bConstructed;
  27. int card::dxCrd;
  28. int card::dyCrd;
  29. CBitmap card::m_bmBgnd;
  30. int card::count = 0;
  31. int card::stepsize = 15; // bigger stepsize -> faster glide
  32. /****************************************************************************
  33. card::card
  34. If this is the first card being constructed, links to cards.dll are
  35. set up, along with the bitmaps and regions required for glide()
  36. ****************************************************************************/
  37. card::card(int n) : id(n), state(NORMAL)
  38. {
  39. loc.x = 0;
  40. loc.y = 0;
  41. if (count == 0)
  42. {
  43. bConstructed = FALSE;
  44. hCardsDLL = LoadLibrary(TEXT("CARDS.DLL"));
  45. if (hCardsDLL < (HINSTANCE)HINSTANCE_ERROR)
  46. return;
  47. lpcdtInit = (INITPROC) GetProcAddress(hCardsDLL, "cdtInit");
  48. lpcdtDraw = (DRAWPROC) GetProcAddress(hCardsDLL, "cdtDraw");
  49. lpcdtTerm = (FARPROC) GetProcAddress(hCardsDLL, "cdtTerm");
  50. BOOL bResult = FALSE;
  51. if(lpcdtInit)
  52. {
  53. bResult = (*lpcdtInit)(&dxCrd, &dyCrd);
  54. }
  55. if (!bResult)
  56. return;
  57. bConstructed = TRUE;
  58. CDC ic;
  59. ic.CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
  60. if (!m_bmBgnd.CreateCompatibleBitmap(&ic, dxCrd, dyCrd) ||
  61. !m_bmFgnd.CreateCompatibleBitmap(&ic, dxCrd, dyCrd) ||
  62. !m_bmBgnd2.CreateCompatibleBitmap(&ic, dxCrd, dyCrd))
  63. bConstructed = FALSE;
  64. ic.DeleteDC();
  65. if (!m_Rgn1.CreateRectRgn(1, 1, 2, 2) || // dummy sizes
  66. !m_Rgn2.CreateRectRgn(1, 1, 2, 2) ||
  67. !m_Rgn.CreateRectRgn(1, 1, 2, 2))
  68. bConstructed = FALSE;
  69. }
  70. count++;
  71. }
  72. /****************************************************************************
  73. card::~card
  74. If this is the last card being destroyed, cards.dll is freed and the
  75. bitmaps and regions created for glide() are deleted.
  76. ****************************************************************************/
  77. card::~card()
  78. {
  79. count--;
  80. if (count == 0)
  81. {
  82. (*lpcdtTerm)();
  83. FreeLibrary(hCardsDLL);
  84. m_bmBgnd.DeleteObject();
  85. m_bmFgnd.DeleteObject();
  86. m_bmBgnd2.DeleteObject();
  87. m_Rgn.DeleteObject();
  88. m_Rgn1.DeleteObject();
  89. m_Rgn2.DeleteObject();
  90. }
  91. }
  92. /****************************************************************************
  93. card::Draw
  94. wrapper for cards.cdtDraw()
  95. EMPTY cards are not passed through
  96. ****************************************************************************/
  97. BOOL card::Draw(CDC &dc, int x, int y, int mode, BOOL bUpdateLoc)
  98. {
  99. if (bUpdateLoc)
  100. {
  101. loc.x = x; // update current location
  102. loc.y = y;
  103. }
  104. if (id == EMPTY)
  105. return FALSE;
  106. return (*lpcdtDraw)(dc.m_hDC, x, y,
  107. mode == FACEDOWN ? CARDBACK : id, mode, 255);
  108. }
  109. /****************************************************************************
  110. card::CleanDraw
  111. Same as Draw except corners are cleaned up before bitmap is blted.
  112. It's slower than normal draw, but there won't be a white flash in the
  113. corners.
  114. ****************************************************************************/
  115. BOOL card::CleanDraw(CDC &dc)
  116. {
  117. if (id == EMPTY)
  118. return FALSE;
  119. SaveCorners(dc, loc.x, loc.y);
  120. CDC memDC;
  121. memDC.CreateCompatibleDC(&dc);
  122. CBitmap bitmap;
  123. if (!bitmap.CreateCompatibleBitmap(&dc, dxCrd, dyCrd))
  124. return FALSE;
  125. CBitmap *oldbitmap = memDC.SelectObject(&bitmap);
  126. BOOL bResult = (*lpcdtDraw)(memDC.m_hDC, 0, 0, id, FACEUP, 0);
  127. if (!bResult)
  128. return FALSE;
  129. RestoreCorners(memDC, 0, 0);
  130. dc.BitBlt(loc.x, loc.y, dxCrd, dyCrd, &memDC, 0, 0, SRCCOPY);
  131. memDC.SelectObject(oldbitmap);
  132. bitmap.DeleteObject();
  133. return TRUE;
  134. }
  135. /****************************************************************************
  136. card::PopDraw
  137. Version of Draw intended for local humans. Selected cards are popped up.
  138. ****************************************************************************/
  139. BOOL card::PopDraw(CDC &dc)
  140. {
  141. if (id == EMPTY)
  142. return FALSE;
  143. int y = loc.y;
  144. if (state == SELECTED)
  145. y -= POPSPACING;
  146. return (*lpcdtDraw)(dc.m_hDC, loc.x, y, id, FACEUP, 0);
  147. }
  148. /****************************************************************************
  149. card::Draw
  150. This routine glides a card from its current position to the specified
  151. end position.
  152. NOTE: before Glide() is called, the client must load card::m_bmBgnd with
  153. a bitmap of what should be displayed as being underneath the original
  154. card location. card::m_bmBgnd is created when the first card is
  155. constructed, and destroyed when the last card is destructed. Note also
  156. that card::m_bmBgnd must NOT be selected in any DC when Glide() is called.
  157. ****************************************************************************/
  158. VOID card::Glide(CDC &dc, int xEnd, int yEnd)
  159. {
  160. int x1, y1, x2, y2; // each step is x1,y1 to x2,y2
  161. if (!m_MemB.CreateCompatibleDC(&dc) || // memory DCs
  162. !m_MemB2.CreateCompatibleDC(&dc))
  163. return;
  164. m_MemB2.SelectObject(&m_bmBgnd2);
  165. m_MemB.SelectObject(&m_bmFgnd);
  166. // draw card into fgnd bitmap
  167. (*lpcdtDraw)(m_MemB.m_hDC, 0, 0, id, FACEUP, 0);
  168. m_MemB.SelectObject(&m_bmBgnd); // associate memDCs with bitmaps
  169. SaveCorners(dc, loc.x, loc.y);
  170. RestoreCorners(m_MemB, 0, 0);
  171. long dx = xEnd - loc.x;
  172. long dy = yEnd - loc.y;
  173. int distance = IntSqrt(dx*dx + dy*dy); // int approx. of dist. to travel
  174. int steps = distance / stepsize; // determine # of intermediate steps
  175. // Ensure that GlideStep gets called an even number of times so
  176. // the background bitmap will get set properly for multi-glide moves
  177. if ((steps % 2) == 1)
  178. steps++;
  179. x1 = loc.x;
  180. y1 = loc.y;
  181. for (int i = 1; i < steps; i++)
  182. {
  183. x2 = loc.x + (int) (((long)i * dx) / (long)steps);
  184. y2 = loc.y + (int) (((long)i * dy) / (long)steps);
  185. GlideStep(dc, x1, y1, x2, y2);
  186. x1 = x2;
  187. y1 = y2;
  188. }
  189. // do last step manually so it lands exactly on xEnd, yEnd
  190. GlideStep(dc, x1, y1, xEnd, yEnd);
  191. // reset clip region for entire screen
  192. m_Rgn.SetRectRgn(0, 0, 30000, 30000); // really big region
  193. dc.SelectObject(&m_Rgn);
  194. loc.x = xEnd;
  195. loc.y = yEnd;
  196. m_MemB.DeleteDC(); // clean up memory DCs
  197. m_MemB2.DeleteDC();
  198. }
  199. /******************************************************************************
  200. GlideStep
  201. This routine gets called once for each step in the glide animation. On
  202. input, it needs the screen under the source in m_MemB, and the card to be
  203. moved in m_bmFgnd. It calculates the screen under the destination itself
  204. and blts it into m_MemB2. At the end of the animation, it moves m_MemB2 into
  205. m_MemB so it can be called again immediately with new coordinates.
  206. ******************************************************************************/
  207. VOID card::GlideStep(CDC &dc, int x1, int y1, int x2, int y2)
  208. {
  209. m_Rgn1.SetRectRgn(x1, y1, x1+dxCrd, y1+dyCrd);
  210. m_Rgn2.SetRectRgn(x2, y2, x2+dxCrd, y2+dyCrd);
  211. /* create background of new location by combing screen background
  212. plus overlap from old background */
  213. m_MemB2.BitBlt(0, 0, dxCrd, dyCrd, &dc, x2, y2, SRCCOPY);
  214. m_MemB2.BitBlt(x1-x2, y1-y2, dxCrd, dyCrd, &m_MemB, 0, 0, SRCCOPY);
  215. SaveCorners(m_MemB2, 0, 0);
  216. /* Draw old background and then draw card */
  217. m_Rgn.CombineRgn(&m_Rgn1, &m_Rgn2, RGN_DIFF); // part of hRgn1 not in hRgn2
  218. dc.SelectObject(&m_Rgn);
  219. dc.BitBlt(x1, y1, dxCrd, dyCrd, &m_MemB, 0, 0, SRCCOPY);
  220. dc.SelectObject(&m_Rgn2);
  221. CBitmap *oldbitmap = m_MemB.SelectObject(&m_bmFgnd); // temp
  222. RestoreCorners(m_MemB, 0, 0);
  223. dc.BitBlt(x2, y2, dxCrd, dyCrd, &m_MemB, 0, 0, SRCCOPY);
  224. m_MemB.SelectObject(oldbitmap); // restore
  225. /* copy new background to old background, or rather, accomplish the
  226. same effect by swapping the associated memory device contexts. */
  227. HDC temp = m_MemB.Detach(); // detach the hDC from the CDC
  228. m_MemB.Attach(m_MemB2.Detach()); // move the hDC from B2 to B
  229. m_MemB2.Attach(temp); // finish the swap
  230. }
  231. /******************************************************************************
  232. IntSqrt
  233. Newton's method to find a quick close-enough square root without pulling
  234. in the floating point libraries.
  235. f(x) = x*x - square = 0
  236. f'(x) = 2x
  237. ******************************************************************************/
  238. int card::IntSqrt(long square)
  239. {
  240. long lastguess = square;
  241. long guess = min(square / 2L, 1024L);
  242. while (labs(guess-lastguess) > 3L) // 3 is close enough
  243. {
  244. lastguess = guess;
  245. guess -= ((guess * guess) - square) / (2L * guess);
  246. }
  247. return (int) guess;
  248. }
  249. /******************************************************************************
  250. SaveCorners
  251. RestoreCorners
  252. based on similar routines in cards.dll
  253. ******************************************************************************/
  254. VOID card::SaveCorners(CDC &dc, int x, int y)
  255. {
  256. // Upper Left
  257. dwPixel[0] = dc.GetPixel(x, y);
  258. dwPixel[1] = dc.GetPixel(x+1, y);
  259. dwPixel[2] = dc.GetPixel(x, y+1);
  260. // Upper Right
  261. x += dxCrd -1;
  262. dwPixel[3] = dc.GetPixel(x, y);
  263. dwPixel[4] = dc.GetPixel(x-1, y);
  264. dwPixel[5] = dc.GetPixel(x, y+1);
  265. // Lower Right
  266. y += dyCrd-1;
  267. dwPixel[6] = dc.GetPixel(x, y);
  268. dwPixel[7] = dc.GetPixel(x, y-1);
  269. dwPixel[8] = dc.GetPixel(x-1, y);
  270. // Lower Left
  271. x -= dxCrd-1;
  272. dwPixel[9] = dc.GetPixel(x, y);
  273. dwPixel[10] = dc.GetPixel(x+1, y);
  274. dwPixel[11] = dc.GetPixel(x, y-1);
  275. }
  276. VOID card::RestoreCorners(CDC &dc, int x, int y)
  277. {
  278. // Upper Left
  279. dc.SetPixel(x, y, dwPixel[0]);
  280. dc.SetPixel(x+1, y, dwPixel[1]);
  281. dc.SetPixel(x, y+1, dwPixel[2]);
  282. // Upper Right
  283. x += dxCrd-1;
  284. dc.SetPixel(x, y, dwPixel[3]);
  285. dc.SetPixel(x-1, y, dwPixel[4]);
  286. dc.SetPixel(x, y+1, dwPixel[5]);
  287. // Lower Right
  288. y += dyCrd-1;
  289. dc.SetPixel(x, y, dwPixel[6]);
  290. dc.SetPixel(x, y-1, dwPixel[7]);
  291. dc.SetPixel(x-1, y, dwPixel[8]);
  292. // Lower Left
  293. x -= dxCrd-1;
  294. dc.SetPixel(x, y, dwPixel[9]);
  295. dc.SetPixel(x+1, y, dwPixel[10]);
  296. dc.SetPixel(x, y-1, dwPixel[11]);
  297. }
  298. /******************************************************************************
  299. GetRect()
  300. sets and returns a rect that covers the card
  301. ******************************************************************************/
  302. CRect &card::GetRect(CRect &rect)
  303. {
  304. rect.SetRect(loc.x, loc.y, loc.x+dxCrd, loc.y+dyCrd);
  305. return(rect);
  306. }