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.

710 lines
13 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * QuadTest.cpp
  8. *
  9. * Abstract:
  10. *
  11. * Test app for quad transform
  12. *
  13. * Usage:
  14. * QuadTest
  15. *
  16. *
  17. * Revision History:
  18. *
  19. * 03/18/1999 ikkof
  20. * Created it.
  21. *
  22. \**************************************************************************/
  23. #include "precomp.hpp"
  24. #include <stddef.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <math.h>
  28. #include <float.h>
  29. #include <windows.h>
  30. #include <objbase.h>
  31. #include <gdiplus.h>
  32. // Use the given namespace
  33. using namespace Gdiplus;
  34. CHAR* programName; // program name
  35. HINSTANCE appInstance; // handle to the application instance
  36. HWND hwndMain; // handle to application's main window
  37. SIZE srcSize; // source bitmap size
  38. SIZE dstSize; // destination bitmap size
  39. SIZE wndSizeExtra; // extra pixels for window decorations
  40. BOOL isDragging = FALSE; // used to handle mouse dragging
  41. INT knobSize = 6; // mesh control point knob size
  42. BOOL showMesh = TRUE;
  43. POINT pts[5];
  44. INT index = -1;
  45. Rect srcRect;
  46. Point ptsF[5];
  47. Point pt00, pt10, pt20, pt30;
  48. Point bPts[4];
  49. class QuadGraphics : public Graphics
  50. {
  51. public:
  52. QuadGraphics(HDC hdc) : Graphics(hdc)
  53. {
  54. }
  55. QuadGraphics(HWND hwnd) : Graphics(hwnd)
  56. {
  57. }
  58. Status DrawWarpedLine(
  59. const Pen* pen,
  60. Point& pt1,
  61. Point& pt2,
  62. Point* points,
  63. INT count,
  64. Rect srcRect
  65. )
  66. {
  67. return SetStatus(DllExports::GdipDrawWarpedLine(
  68. GetNativeGraphics(),
  69. GetNativePen(pen),
  70. pt1.X,
  71. pt1.Y,
  72. pt2.X,
  73. pt2.Y,
  74. points,
  75. count,
  76. &srcRect
  77. )
  78. );
  79. }
  80. Status DrawWarpedBezier(
  81. const Pen* pen,
  82. Point& pt1,
  83. Point& pt2,
  84. Point& pt3,
  85. Point& pt4,
  86. Point* points,
  87. INT count,
  88. Rect srcRect
  89. )
  90. {
  91. return SetStatus(DllExports::GdipDrawWarpedBezier(
  92. GetNativeGraphics(),
  93. GetNativePen(pen),
  94. pt1.X,
  95. pt1.Y,
  96. pt2.X,
  97. pt2.Y,
  98. pt3.X,
  99. pt3.Y,
  100. pt4.X,
  101. pt4.Y,
  102. points,
  103. count,
  104. &srcRect
  105. )
  106. );
  107. }
  108. };
  109. //
  110. // Display an error message dialog and quit
  111. //
  112. VOID
  113. Error(
  114. const CHAR* fmt,
  115. ...
  116. )
  117. {
  118. va_list arglist;
  119. va_start(arglist, fmt);
  120. vfprintf(stderr, fmt, arglist);
  121. va_end(arglist);
  122. exit(-1);
  123. }
  124. //
  125. // Create a new mesh object
  126. //
  127. VOID
  128. CreateMesh()
  129. {
  130. srcSize.cx = 300;
  131. srcSize.cy = 300;
  132. dstSize = srcSize;
  133. INT offset = 10;
  134. pts[0].x = offset;
  135. pts[0].y = offset;
  136. pts[1].x = srcSize.cx - offset;
  137. pts[1].y = offset;
  138. pts[2].x = srcSize.cx - offset;
  139. pts[2].y = srcSize.cy - offset;
  140. pts[3].x = offset;
  141. pts[3].y = srcSize.cy - offset;
  142. pts[4] = pts[0];
  143. srcRect.X = (REAL) pts[0].x;
  144. srcRect.Y = (REAL) pts[0].y;
  145. srcRect.Width = (REAL) pts[2].x - pts[0].x;
  146. srcRect.Height = (REAL) pts[2].y - pts[0].y;
  147. ptsF[0].X = (REAL) pts[0].x;
  148. ptsF[0].Y = (REAL) pts[0].y;
  149. ptsF[1].X = (REAL) pts[1].x;
  150. ptsF[1].Y = (REAL) pts[1].y;
  151. ptsF[2].X = (REAL) pts[3].x;
  152. ptsF[2].Y = (REAL) pts[3].y;
  153. ptsF[3].X = (REAL) pts[2].x;
  154. ptsF[3].Y = (REAL) pts[2].y;
  155. pt00 = ptsF[0];
  156. pt10 = ptsF[1];
  157. pt20 = ptsF[2];
  158. pt30 = ptsF[3];
  159. bPts[0].X = (REAL) 2*offset;
  160. bPts[0].Y = (REAL) srcSize.cy/2;
  161. bPts[1].X = (REAL) srcSize.cx/2;
  162. bPts[1].Y = 0;
  163. bPts[2].X = (REAL) srcSize.cx;
  164. bPts[2].Y = (REAL) srcSize.cy/2;
  165. bPts[3].X = (REAL) 3*srcSize.cx/4;
  166. bPts[3].Y = (REAL) 3*srcSize.cy/4;
  167. }
  168. //
  169. // Draw mesh
  170. //
  171. #define MESHCOLOR RGB(255, 0, 0)
  172. VOID
  173. DrawMesh(
  174. HDC hdc
  175. )
  176. {
  177. static HPEN meshPen = NULL;
  178. static HBRUSH meshBrush = NULL;
  179. if (meshPen == NULL)
  180. meshPen = CreatePen(PS_SOLID, 1, MESHCOLOR);
  181. SelectObject(hdc, meshPen);
  182. // Draw horizontal meshes
  183. INT i, j, rows, cols, pointCount;
  184. POINT* points;
  185. // Draw knobs
  186. // Create the brush to draw the mesh if necessary
  187. if (meshBrush == NULL)
  188. meshBrush = CreateSolidBrush(MESHCOLOR);
  189. Polyline(hdc, pts, 5);
  190. for (j=0; j < 4; j++)
  191. {
  192. RECT rect;
  193. rect.left = pts[j].x - knobSize/2;
  194. rect.top = pts[j].y - knobSize/2;
  195. rect.right = rect.left + knobSize;
  196. rect.bottom = rect.top + knobSize;
  197. FillRect(hdc, &rect, meshBrush);
  198. }
  199. }
  200. VOID
  201. DoGDIPlusDrawing(
  202. HWND hwnd,
  203. HDC hdc
  204. )
  205. {
  206. // QuadGraphics *g = Graphics::GetFromHwnd(hwnd);
  207. QuadGraphics *g = new QuadGraphics(hwnd);
  208. REAL width = 1;
  209. Color color(0, 0, 0);
  210. SolidBrush brush(color);
  211. Pen pen(&brush, width);
  212. ptsF[0].X = (REAL) pts[0].x;
  213. ptsF[0].Y = (REAL) pts[0].y;
  214. ptsF[1].X = (REAL) pts[1].x;
  215. ptsF[1].Y = (REAL) pts[1].y;
  216. ptsF[2].X = (REAL) pts[3].x;
  217. ptsF[2].Y = (REAL) pts[3].y;
  218. ptsF[3].X = (REAL) pts[2].x;
  219. ptsF[3].Y = (REAL) pts[2].y;
  220. g->DrawWarpedLine(&pen, pt00, pt30, ptsF, 4, srcRect);
  221. g->DrawWarpedLine(&pen, pt10, pt20, ptsF, 4, srcRect);
  222. g->DrawWarpedBezier(&pen, bPts[0], bPts[1], bPts[2], bPts[3],
  223. ptsF, 4, srcRect);
  224. delete g;
  225. }
  226. //
  227. // Handle window repaint event
  228. //
  229. VOID
  230. DoPaint(
  231. HWND hwnd
  232. )
  233. {
  234. HDC hdc;
  235. PAINTSTRUCT ps;
  236. RECT rect;
  237. INT width, height;
  238. // Determine if we need to perform warping operation
  239. GetClientRect(hwnd, &rect);
  240. width = rect.right;
  241. height = rect.bottom;
  242. hdc = BeginPaint(hwnd, &ps);
  243. HBRUSH brush = CreateSolidBrush(RGB(255, 255, 255));
  244. HBRUSH savedBrush = (HBRUSH) SelectObject(hdc, brush);
  245. Rectangle(hdc, 0, 0, width, height);
  246. DoGDIPlusDrawing(hwnd, hdc);
  247. // Draw to offscreen DC to reduce flashing
  248. DrawMesh(hdc);
  249. SelectObject(hdc, savedBrush);
  250. DeleteObject(brush);
  251. EndPaint(hwnd, &ps);
  252. }
  253. //
  254. // Handle WM_SIZING message
  255. //
  256. BOOL
  257. DoWindowSizing(
  258. HWND hwnd,
  259. RECT* rect,
  260. INT side
  261. )
  262. {
  263. INT w = rect->right - rect->left - wndSizeExtra.cx;
  264. INT h = rect->bottom - rect->top - wndSizeExtra.cy;
  265. if (w >= srcSize.cx && h >= srcSize.cy)
  266. return FALSE;
  267. // Window width is too small
  268. if (w < srcSize.cx)
  269. {
  270. INT dx = srcSize.cx + wndSizeExtra.cx;
  271. switch (side)
  272. {
  273. case WMSZ_LEFT:
  274. case WMSZ_TOPLEFT:
  275. case WMSZ_BOTTOMLEFT:
  276. rect->left = rect->right - dx;
  277. break;
  278. default:
  279. rect->right = rect->left + dx;
  280. break;
  281. }
  282. }
  283. // Window height is too small
  284. if (h < srcSize.cy)
  285. {
  286. INT dy = srcSize.cy + wndSizeExtra.cy;
  287. switch (side)
  288. {
  289. case WMSZ_TOP:
  290. case WMSZ_TOPLEFT:
  291. case WMSZ_TOPRIGHT:
  292. rect->top = rect->bottom - dy;
  293. break;
  294. default:
  295. rect->bottom = rect->top + dy;
  296. break;
  297. }
  298. }
  299. return TRUE;
  300. }
  301. //
  302. // Handle left mouse-down event
  303. //
  304. VOID
  305. DoMouseDown(
  306. HWND hwnd,
  307. INT x,
  308. INT y
  309. )
  310. {
  311. // Figure out if the click happened in a mesh control knob
  312. INT i, j, rows, cols;
  313. POINT pt;
  314. RECT rect;
  315. GetClientRect(hwnd, &rect);
  316. for(i = 0; i < 4; i++)
  317. {
  318. pt = pts[i];
  319. pt.x -= knobSize/2;
  320. pt.y -= knobSize/2;
  321. if (x >= pt.x && x < pt.x+knobSize &&
  322. y >= pt.y && y < pt.y+knobSize)
  323. {
  324. index = i;
  325. SetCapture(hwnd);
  326. isDragging = TRUE;
  327. return;
  328. }
  329. }
  330. index = -1;
  331. }
  332. //
  333. // Handle mouse-move event
  334. //
  335. VOID
  336. DoMouseMove(
  337. HWND hwnd,
  338. INT x,
  339. INT y
  340. )
  341. {
  342. // We assume isDragging is true here.
  343. RECT rect;
  344. INT w, h;
  345. GetClientRect(hwnd, &rect);
  346. w = rect.right;
  347. h = rect.bottom;
  348. if (x < 0 || x >= w || y < 0 || y >= h)
  349. return;
  350. pts[index].x = x;
  351. pts[index].y = y;
  352. if(index == 0)
  353. pts[4] = pts[0];
  354. InvalidateRect(hwnd, NULL, FALSE);
  355. }
  356. //
  357. // Handle menu command
  358. //
  359. VOID
  360. DoCommand(
  361. HWND hwnd,
  362. INT command
  363. )
  364. {
  365. InvalidateRect(hwnd, NULL, FALSE);
  366. }
  367. //
  368. // Handle popup menu
  369. //
  370. VOID
  371. DoPopupMenu(
  372. HWND hwnd,
  373. INT x,
  374. INT y
  375. )
  376. {
  377. HMENU menu;
  378. DWORD result;
  379. POINT pt;
  380. GetCursorPos(&pt);
  381. menu = LoadMenu(appInstance, MAKEINTRESOURCE(IDM_MAINMENU));
  382. result = TrackPopupMenu(
  383. GetSubMenu(menu, 0),
  384. TPM_CENTERALIGN | TPM_TOPALIGN |
  385. TPM_NONOTIFY | TPM_RETURNCMD |
  386. TPM_RIGHTBUTTON,
  387. pt.x,
  388. pt.y,
  389. 0,
  390. hwnd,
  391. NULL);
  392. if (result == 0)
  393. return;
  394. DoCommand(hwnd, LOWORD(result));
  395. }
  396. //
  397. // Window callback procedure
  398. //
  399. LRESULT CALLBACK
  400. MyWindowProc(
  401. HWND hwnd,
  402. UINT uMsg,
  403. WPARAM wParam,
  404. LPARAM lParam
  405. )
  406. {
  407. INT x, y;
  408. switch (uMsg)
  409. {
  410. case WM_PAINT:
  411. DoPaint(hwnd);
  412. break;
  413. case WM_LBUTTONDOWN:
  414. if (showMesh)
  415. {
  416. x = (SHORT) LOWORD(lParam);
  417. y = (SHORT) HIWORD(lParam);
  418. DoMouseDown(hwnd, x, y);
  419. }
  420. break;
  421. case WM_LBUTTONUP:
  422. if (isDragging)
  423. {
  424. ReleaseCapture();
  425. isDragging = FALSE;
  426. InvalidateRect(hwnd, NULL, FALSE);
  427. }
  428. break;
  429. case WM_MOUSEMOVE:
  430. if (isDragging)
  431. {
  432. x = (SHORT) LOWORD(lParam);
  433. y = (SHORT) HIWORD(lParam);
  434. DoMouseMove(hwnd, x, y);
  435. }
  436. break;
  437. case WM_SIZING:
  438. if (DoWindowSizing(hwnd, (RECT*) lParam, wParam))
  439. return TRUE;
  440. else
  441. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  442. case WM_SIZE:
  443. InvalidateRect(hwnd, NULL, FALSE);
  444. break;
  445. case WM_CHAR:
  446. switch ((CHAR) wParam)
  447. {
  448. case 'r': // reset
  449. DoCommand(hwnd, IDC_RESETMESH);
  450. break;
  451. case ' ': // show/hide mesh
  452. DoCommand(hwnd, IDC_TOGGLEMESH);
  453. break;
  454. case '1': // restore 1-to-1 scale
  455. DoCommand(hwnd, IDC_SHRINKTOFIT);
  456. break;
  457. case '<': // decrease mesh density
  458. DoCommand(hwnd, IDC_SPARSEMESH);
  459. break;
  460. case '>': // increase mesh density
  461. DoCommand(hwnd, IDC_DENSEMESH);
  462. break;
  463. case 'f': // toggle live feedback
  464. DoCommand(hwnd, IDC_LIVEFEEDBACK);
  465. break;
  466. }
  467. break;
  468. case WM_RBUTTONDOWN:
  469. x = (SHORT) LOWORD(lParam);
  470. y = (SHORT) HIWORD(lParam);
  471. DoPopupMenu(hwnd, x, y);
  472. break;
  473. case WM_DESTROY:
  474. PostQuitMessage(0);
  475. break;
  476. default:
  477. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  478. }
  479. return 0;
  480. }
  481. //
  482. // Create main application window
  483. //
  484. VOID
  485. CreateMainWindow(
  486. VOID
  487. )
  488. #define MYWNDCLASSNAME L"QuadTest"
  489. {
  490. //
  491. // Register window class if necessary
  492. //
  493. static BOOL wndclassRegistered = FALSE;
  494. if (!wndclassRegistered)
  495. {
  496. WNDCLASS wndClass =
  497. {
  498. 0,
  499. MyWindowProc,
  500. 0,
  501. 0,
  502. appInstance,
  503. LoadIcon(NULL, IDI_APPLICATION),
  504. LoadCursor(NULL, IDC_ARROW),
  505. NULL,
  506. NULL,
  507. MYWNDCLASSNAME
  508. };
  509. RegisterClass(&wndClass);
  510. wndclassRegistered = TRUE;
  511. }
  512. wndSizeExtra.cx = 2*GetSystemMetrics(SM_CXSIZEFRAME);
  513. wndSizeExtra.cy = 2*GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
  514. hwndMain = CreateWindow(
  515. MYWNDCLASSNAME,
  516. MYWNDCLASSNAME,
  517. WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  518. CW_USEDEFAULT,
  519. CW_USEDEFAULT,
  520. srcSize.cx + wndSizeExtra.cx,
  521. srcSize.cy + wndSizeExtra.cy,
  522. NULL,
  523. NULL,
  524. appInstance,
  525. NULL);
  526. }
  527. //
  528. // Main program entrypoint
  529. //
  530. INT _cdecl
  531. main(
  532. INT argc,
  533. CHAR **argv
  534. )
  535. {
  536. programName = *argv++;
  537. argc--;
  538. appInstance = GetModuleHandle(NULL);
  539. // Initialize mesh configuration
  540. CreateMesh();
  541. // Create the main application window
  542. CreateMainWindow();
  543. // Main message loop
  544. MSG msg;
  545. while (GetMessage(&msg, NULL, 0, 0))
  546. {
  547. TranslateMessage(&msg);
  548. DispatchMessage(&msg);
  549. }
  550. return msg.wParam;
  551. }