home *** CD-ROM | disk | FTP | other *** search
/ ftp.sunet.se/pub/OS2/ / 2014.11.ftp.sunet.se_pub_OS2.tar / ftp.sunet.se / pub / OS2 / hobbes / os2 / games / action / ow2inst.exe / from_me / GDIRotate.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  12KB  |  457 lines

  1. // GDIRotate.cpp : Defines the entry point for the application.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include <math.h>
  6. #include "resource.h"
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include "comdef.h"
  10.  
  11. #define MAX_LOADSTRING 100
  12.  
  13. // Global Variables:
  14. HINSTANCE hInst;                                // current instance
  15. TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
  16. TCHAR szWindowClass[MAX_LOADSTRING];            // The title bar text
  17. float g_angle = 0.2f;                            // The current Rotation angle
  18.  
  19. // Foward declarations of functions included in this code module:
  20. ATOM                MyRegisterClass(HINSTANCE hInstance);
  21. BOOL                InitInstance(HINSTANCE, int);
  22. LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
  23. LRESULT CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
  24.  
  25. int APIENTRY WinMain(HINSTANCE hInstance,
  26.                      HINSTANCE hPrevInstance,
  27.                      LPSTR     lpCmdLine,
  28.                      int       nCmdShow)
  29. {
  30.     MSG msg;
  31.     HACCEL hAccelTable;
  32.  
  33.     // Initialize global strings
  34.     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  35.     LoadString(hInstance, IDC_GDIROTATE, szWindowClass, MAX_LOADSTRING);
  36.     MyRegisterClass(hInstance);
  37.  
  38.     // Perform application initialization:
  39.     if (!InitInstance (hInstance, nCmdShow)) 
  40.     {
  41.         return FALSE;
  42.     }
  43.  
  44.     hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_GDIROTATE);
  45.  
  46.     // Main message loop:
  47.     while (GetMessage(&msg, NULL, 0, 0)) 
  48.     {
  49.         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
  50.         {
  51.             TranslateMessage(&msg);
  52.             DispatchMessage(&msg);
  53.         }
  54.     }
  55.  
  56.     return msg.wParam;
  57. }
  58.  
  59.  
  60.  
  61. //
  62. //  FUNCTION: MyRegisterClass()
  63. //
  64. //  PURPOSE: Registers the window class.
  65. //
  66. //  COMMENTS:
  67. //
  68. //    This function and its usage is only necessary if you want this code
  69. //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
  70. //    function that was added to Windows 95. It is important to call this function
  71. //    so that the application will get 'well formed' small icons associated
  72. //    with it.
  73. //
  74. ATOM MyRegisterClass(HINSTANCE hInstance)
  75. {
  76.     WNDCLASSEX wcex;
  77.  
  78.     wcex.cbSize = sizeof(WNDCLASSEX); 
  79.  
  80.     wcex.style            = CS_HREDRAW | CS_VREDRAW;
  81.     wcex.lpfnWndProc    = (WNDPROC)WndProc;
  82.     wcex.cbClsExtra        = 0;
  83.     wcex.cbWndExtra        = 0;
  84.     wcex.hInstance        = hInstance;
  85.     wcex.hIcon            = LoadIcon(hInstance, (LPCTSTR)IDI_GDIROTATE);
  86.     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
  87.     wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
  88.     wcex.lpszMenuName    = (LPCSTR)IDC_GDIROTATE;
  89.     wcex.lpszClassName    = szWindowClass;
  90.     wcex.hIconSm        = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
  91.  
  92.     return RegisterClassEx(&wcex);
  93. }
  94.  
  95. //
  96. //   FUNCTION: InitInstance(HANDLE, int)
  97. //
  98. //   PURPOSE: Saves instance handle and creates main window
  99. //
  100. //   COMMENTS:
  101. //
  102. //        In this function, we save the instance handle in a global variable and
  103. //        create and display the main program window.
  104. //
  105. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  106. {
  107.    HWND hWnd;
  108.  
  109.    hInst = hInstance; // Store instance handle in our global variable
  110.  
  111.    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  112.       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  113.  
  114.    if (!hWnd)
  115.    {
  116.       return FALSE;
  117.    }
  118.  
  119.    // Initialize the Timer to 100 ms delay between screen updates
  120.    SetTimer(hWnd, 10, 100, 0);
  121.    ShowWindow(hWnd, nCmdShow);
  122.    UpdateWindow(hWnd);
  123.  
  124.    return TRUE;
  125. }
  126.  
  127. // Helper function for getting the minimum of 4 floats
  128. float min4(float a, float b, float c, float d)
  129. {
  130.     if (a < b) {
  131.         if (c < a) {
  132.             if (d < c)
  133.                 return d;
  134.             else
  135.                 return c;
  136.         } else {
  137.             if (d < a)
  138.                 return d;
  139.             else
  140.                 return a;
  141.         }
  142.     } else {
  143.         if (c < b) {
  144.             if (d < c)
  145.                 return d;
  146.             else
  147.                 return c;
  148.         } else {
  149.             if (d < b)
  150.                 return d;
  151.             else
  152.                 return b;
  153.         }
  154.     }
  155. }
  156.  
  157. // Helper function for getting the maximum of 4 floats
  158. float max4(float a, float b, float c, float d)
  159. {
  160.     if (a > b) {
  161.         if (c > a) {
  162.             if (d > c)
  163.                 return d;
  164.             else
  165.                 return c;
  166.         } else {
  167.             if (d > a)
  168.                 return d;
  169.             else
  170.                 return a;
  171.         }
  172.     } else {
  173.         if (c > b) {
  174.             if (d > c)
  175.                 return d;
  176.             else
  177.                 return c;
  178.         } else {
  179.             if (d > b)
  180.                 return d;
  181.             else
  182.                 return b;
  183.         }
  184.     }
  185. }
  186.  
  187. // The Representation of a 32 bit color table entry
  188. #pragma pack(push)
  189. #pragma pack(1)
  190. typedef struct ssBGR {
  191.     unsigned char b;
  192.     unsigned char g;
  193.     unsigned char r;
  194.     unsigned char pad;
  195. } sBGR;
  196.  
  197. typedef sBGR *pBGR;
  198. #pragma pack(pop)
  199.  
  200.  
  201. // Returns the DI (Device Independent) bits of the Bitmap
  202. // Here I use 32 bit since it's easy to adress in memory and no
  203. // padding of the horizontal lines is required.
  204. pBGR MyGetDibBits(HDC hdcSrc, HBITMAP hBmpSrc, int nx, int ny)
  205. {
  206.     BITMAPINFO bi;
  207.     BOOL bRes;
  208.     pBGR buf;
  209.  
  210.     bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
  211.     bi.bmiHeader.biWidth = nx;
  212.     bi.bmiHeader.biHeight = - ny;
  213.     bi.bmiHeader.biPlanes = 1;
  214.     bi.bmiHeader.biBitCount = 32;
  215.     bi.bmiHeader.biCompression = BI_RGB;
  216.     bi.bmiHeader.biSizeImage = nx * 4 * ny;
  217.     bi.bmiHeader.biClrUsed = 0;
  218.     bi.bmiHeader.biClrImportant = 0;
  219.     
  220.     buf = (pBGR) malloc(nx * 4 * ny);
  221.     bRes = GetDIBits(hdcSrc, hBmpSrc, 0, ny, buf, &bi, DIB_RGB_COLORS);
  222.     if (!bRes) {
  223.         free(buf);
  224.         buf = 0;
  225.     }
  226.     return buf;
  227. }
  228.  
  229. // RotateMemoryDC rotates a memory DC and returns the rotated DC as well as its dimensions
  230. void RotateMemoryDC(HBITMAP hBmpSrc, HDC hdcSrc, int SrcX, int SrcY, float angle, HDC &hdcDst, int &dstX, int &dstY)
  231. {
  232.     HBITMAP hBmpDst;
  233.     float x1, x2, x3, x4, y1, y2, y3, y4, cA, sA;
  234.     float CtX, CtY, orgX, orgY, divisor;
  235.     int OfX, OfY;
  236.     int stepX, stepY;
  237.     int iorgX, iorgY;
  238.     RECT rt;
  239.     char s[40];
  240.     LARGE_INTEGER lStart, lEnd, lFreq;
  241.     pBGR src, dst, dstLine;
  242.     BITMAPINFO bi;
  243.  
  244.     // Rotate the bitmap around the center
  245.     CtX = ((float) SrcX) / 2;
  246.     CtY = ((float) SrcY) / 2;
  247.  
  248.     // First, calculate the destination positions for the four courners to get dstX and dstY
  249.     cA = (float) cos(angle);
  250.     sA = (float) sin(angle);
  251.  
  252.     x1 = CtX + (-CtX) * cA - (-CtY) * sA;
  253.     x2 = CtX + (SrcX - CtX) * cA - (-CtY) * sA;
  254.     x3 = CtX + (SrcX - CtX) * cA - (SrcY - CtY) * sA;
  255.     x4 = CtX + (-CtX) * cA - (SrcY - CtY) * sA;
  256.  
  257.     y1 = CtY + (-CtY) * cA + (-CtX) * sA;
  258.     y2 = CtY + (SrcY - CtY) * cA + (-CtX) * sA;
  259.     y3 = CtY + (SrcY - CtY) * cA + (SrcX - CtX) * sA;
  260.     y4 = CtY + (-CtY) * cA + (SrcX - CtX) * sA;
  261.  
  262.     OfX = ((int) floor(min4(x1, x2, x3, x4)));
  263.     OfY = ((int) floor(min4(y1, y2, y3, y4)));
  264.     
  265.     dstX = ((int) ceil(max4(x1, x2, x3, x4))) - OfX;
  266.     dstY = ((int) ceil(max4(y1, y2, y3, y4))) - OfY;
  267.  
  268.     // Create the new memory DC
  269.     hdcDst = CreateCompatibleDC(hdcSrc);
  270.     hBmpDst = CreateCompatibleBitmap(hdcSrc, dstX, dstY);
  271.     SelectObject(hdcDst, hBmpDst);
  272.  
  273.     // Fill the new memory DC with the current Window color
  274.     rt.left = 0;
  275.     rt.top = 0;
  276.     rt.right = dstX;
  277.     rt.bottom = dstY;
  278.     FillRect(hdcDst, &rt, GetSysColorBrush(COLOR_WINDOW));
  279.  
  280.     // Start timing
  281.     QueryPerformanceFrequency(&lFreq);
  282.     QueryPerformanceCounter(&lStart);
  283.  
  284.     // Get the bitmap bits for the source and destination
  285.     src = MyGetDibBits(hdcSrc, hBmpSrc, SrcX, SrcY);
  286.     dst = MyGetDibBits(hdcDst, hBmpDst, dstX, dstY);
  287.  
  288.     dstLine = dst;
  289.     divisor = cA*cA + sA*sA;
  290.     // Step through the destination bitmap
  291.     for (stepY = 0; stepY < dstY; stepY++) {
  292.         for (stepX = 0; stepX < dstX; stepX++) {
  293.             // Calculate the source coordinate
  294.             orgX = (cA * (((float) stepX + OfX) + CtX * (cA - 1)) + sA * (((float) stepY + OfY) + CtY * (sA - 1))) / divisor;
  295.             orgY = CtY + (CtX - ((float) stepX + OfX)) * sA + cA *(((float) stepY + OfY) - CtY + (CtY - CtX) * sA);
  296.             iorgX = (int) orgX;
  297.             iorgY = (int) orgY;
  298.             if ((iorgX >= 0) && (iorgY >= 0) && (iorgX < SrcX) && (iorgY < SrcY)) {
  299.                 // Inside the source bitmap -> copy the bits
  300.                 dstLine[dstX - stepX - 1] = src[iorgX + iorgY * SrcX];
  301.             } else {
  302.                 // Outside the source -> set the color to light grey
  303.                 dstLine[dstX - stepX - 1].b = 240;
  304.                 dstLine[dstX - stepX - 1].g = 240;
  305.                 dstLine[dstX - stepX - 1].r = 240;
  306.             }
  307.         }
  308.         dstLine = dstLine + dstX;
  309.     }
  310.  
  311.     // Set the new Bitmap
  312.     bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
  313.     bi.bmiHeader.biWidth = dstX;
  314.     bi.bmiHeader.biHeight = dstY;
  315.     bi.bmiHeader.biPlanes = 1;
  316.     bi.bmiHeader.biBitCount = 32;
  317.     bi.bmiHeader.biCompression = BI_RGB;
  318.     bi.bmiHeader.biSizeImage = dstX * 4 * dstY;
  319.     bi.bmiHeader.biClrUsed = 0;
  320.     bi.bmiHeader.biClrImportant = 0;
  321.     SetDIBits(hdcDst, hBmpDst, 0, dstY, dst, &bi, DIB_RGB_COLORS);
  322.     DeleteObject(hBmpDst);
  323.  
  324.     // End timing and show Time taken in milliseconds
  325.     QueryPerformanceCounter(&lEnd);
  326.     sprintf(s, "%d ms", ((lEnd.QuadPart - lStart.QuadPart) * 1000) / lFreq.QuadPart);
  327.     TextOut(hdcDst, 0, 0, s, strlen(s));
  328.  
  329.     // Free the color arrays
  330.     free(src);
  331.     free(dst);
  332. }
  333.  
  334. // Handler for drawing
  335. void OnDraw(HWND hWnd)
  336. {
  337.     PAINTSTRUCT ps;
  338.     HDC hdc, hdcMem, hdcNew;
  339.     HBITMAP hBmp;
  340.     HBRUSH hBr;
  341.     int dstX, dstY, i, offset;
  342.     RECT rt, rtmp;
  343.  
  344.     hdc = BeginPaint(hWnd, &ps);
  345.     GetClientRect(hWnd, &rt);
  346.  
  347.     // First draw the colored bars in the upper part of the window that serve as
  348.     // the starting bitmap to rotate
  349.     offset = (rt.right - rt.left - 200) / 2;
  350.     rtmp.left = offset;
  351.     rtmp.right = offset + 1;
  352.     rtmp.top = 0;
  353.     rtmp.bottom = 200;
  354.     for (i = 0; i < 200; i++) {
  355.         hBr = CreateSolidBrush(RGB(i * 8 % 255, i * 5 % 255, i * 2 % 255));
  356.         FillRect(hdc, &rtmp, hBr);
  357.         DeleteObject(hBr);
  358.         rtmp.left++;
  359.         rtmp.right++;
  360.     }
  361.  
  362.     // BitBlt the starting Bitmap into a memory HDC
  363.     hdcNew = CreateCompatibleDC(hdc);
  364.     hBmp = CreateCompatibleBitmap(hdc, 200,200);
  365.     SelectObject(hdcNew, hBmp);
  366.     BitBlt(hdcNew, 0, 0, 200, 200, hdc, (rt.right - rt.left - 200) / 2, 0, SRCCOPY);
  367.  
  368.     // Rotate that memory HDC
  369.     RotateMemoryDC(hBmp, hdcNew, 200, 200, g_angle, hdcMem, dstX, dstY);
  370.     DeleteObject(hBmp);
  371.     DeleteDC(hdcNew);
  372.  
  373.     // Create the output HDC
  374.     hdcNew = CreateCompatibleDC(hdc);
  375.     hBmp = CreateCompatibleBitmap(hdc, 400,400);
  376.     SelectObject(hdcNew, hBmp);
  377.     rtmp.left = rtmp.top = 0;
  378.     rtmp.right = rtmp.bottom = 400;
  379.  
  380.     // Fill the output HDC with the window background color and BitBlt the rotated bitmap into it
  381.     FillRect(hdcNew, &rtmp, GetSysColorBrush(COLOR_WINDOW));
  382.     BitBlt(hdcNew, (400 - dstX) / 2, (400-dstY) / 2, dstX, dstY, hdcMem, 0, 0, SRCCOPY);
  383.     DeleteDC(hdcMem);
  384.     BitBlt(hdc, (rt.left + rt.right - 400) / 2, rt.bottom - 400, 400, 400, hdcNew, 0, 0, SRCCOPY);
  385.     DeleteObject(hBmp);
  386.     DeleteDC(hdcNew);
  387.     EndPaint(hWnd, &ps);
  388. }
  389.  
  390. //
  391. //  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
  392. //
  393. //  PURPOSE:  Processes messages for the main window.
  394. //
  395. //  WM_COMMAND    - process the application menu
  396. //  WM_PAINT    - Paint the main window
  397. //  WM_DESTROY    - post a quit message and return
  398. //
  399. //
  400. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  401. {
  402.     int wmId, wmEvent;
  403.  
  404.     switch (message) 
  405.     {
  406.         case WM_TIMER:
  407.             // Handle the redraw with the timer
  408.             g_angle = g_angle + .05f;
  409.             RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  410.             break;
  411.         case WM_COMMAND:
  412.             wmId    = LOWORD(wParam); 
  413.             wmEvent = HIWORD(wParam); 
  414.             // Parse the menu selections:
  415.             switch (wmId)
  416.             {
  417.                 case IDM_ABOUT:
  418.                    DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
  419.                    break;
  420.                 case IDM_EXIT:
  421.                    DestroyWindow(hWnd);
  422.                    break;
  423.                 default:
  424.                    return DefWindowProc(hWnd, message, wParam, lParam);
  425.             }
  426.             break;
  427.         case WM_PAINT:
  428.             OnDraw(hWnd);
  429.             break;
  430.         case WM_DESTROY:
  431.             PostQuitMessage(0);
  432.             break;
  433.         default:
  434.             return DefWindowProc(hWnd, message, wParam, lParam);
  435.    }
  436.    return 0;
  437. }
  438.  
  439. // Mesage handler for about box.
  440. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  441. {
  442.     switch (message)
  443.     {
  444.         case WM_INITDIALOG:
  445.                 return TRUE;
  446.  
  447.         case WM_COMMAND:
  448.             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
  449.             {
  450.                 EndDialog(hDlg, LOWORD(wParam));
  451.                 return TRUE;
  452.             }
  453.             break;
  454.     }
  455.     return FALSE;
  456. }
  457.