2004/01/18 01:27:16
[org.ibex.core.git] / src / org / xwt / plat / Win32.cc
index 25812a3..c278998 100644 (file)
@@ -5,6 +5,7 @@
 #define INT32 WIN32_INT32
 
 // this has to precede the others so we don't get collisions on min/max
+#include <org/xwt/js/JS.h>
 #include <org/xwt/Box.h>
 
 #include <stdint.h>
@@ -26,7 +27,6 @@
 #include <org/xwt/Surface.h>
 #include <org/xwt/PixelBuffer.h>
 #include <org/xwt/Picture.h>
-#include <org/xwt/ByteStream.h>
 #include <org/xwt/Platform.h>
 #include <org/xwt/plat/Win32.h>
 #include <org/xwt/plat/Win32$Win32Surface.h>
@@ -180,22 +180,31 @@ void org::xwt::plat::Win32::natInit() {
             sprintf(buf, "XWT_WINDOW_CLASS_%i", window_class_counter++);
 
             WNDCLASSEX wc;
-            wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+            wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
             wc.lpfnWndProc = WndProc;
             wc.cbClsExtra = 0;
             wc.cbSize = sizeof(WNDCLASSEX);
             wc.cbWndExtra = 0;
             wc.hInstance = GetModuleHandle(NULL);
-            wc.hIcon = NULL;
-            wc.hIconSm = NULL;
-            wc.hCursor = NULL;
-            wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR + 1);
-            wc.lpszMenuName = NULL;
+            wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+            wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL),
+                                          MAKEINTRESOURCE(5),
+                                          IMAGE_ICON,
+                                          GetSystemMetrics(SM_CXSMICON),
+                                          GetSystemMetrics(SM_CYSMICON),
+                                          LR_DEFAULTCOLOR);
+            wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+            wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+            wc.lpszMenuName = "menu";
             wc.lpszClassName = buf;
             RegisterClassEx(&wc);
+
+            surface->hwnd = (jint)CreateWindow(wc.lpszClassName, TEXT(""),
+                                               msg.wParam ? WS_NORMAL : WS_POPUP,
+                                               200, 200, 100, 100,
+                                               (HWND__*)NULL, (HMENU__*)NULL,
+                                               GetModuleHandle(NULL), (LPVOID)NULL);
             
-            surface->hwnd = (jint)CreateWindow(wc.lpszClassName, TEXT(""), msg.wParam ? WS_NORMAL : WS_POPUP, 200, 200, 100, 100,
-                                               (HWND__*)NULL, (HMENU__*)NULL, GetModuleHandle(NULL), (LPVOID)NULL);
             SetFocus((HWND)surface->hwnd);
             surface->hwndCreated->release();
             
@@ -354,24 +363,28 @@ static jint* scratch_bits = NULL;
 static jint scratch_w = 0;
 static jint scratch_h = 0;
 
-#define BLT(dest, dx1, dy1, dx2, dy2, src, sx1, sy1, sx2, sy2, op)                                   \
-    if ((dx2 - dx1 == sx2 - sx1) && (dy2 - dy1 == sy2 - sy1))                                        \
-        BitBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, op);                             \
-    else                                                                                             \
-        StretchBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, sx2 - sx1, sy2 - sy1, op);
-        
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
+
 void org::xwt::plat::Win32$Win32PixelBuffer::drawPicture(org::xwt::Picture* source0,
-                                                          jint dx1, jint dy1, jint dx2, jint dy2,
-                                                          jint sx1, jint sy1, jint sx2, jint sy2) {
+                                                         jint dx, jint dy,
+                                                         jint cx1, jint cy1, jint cx2, jint cy2,
+                                                         jint rgb, jboolean alphaOnly) {
     org::xwt::plat::Win32$Win32Picture* source = (org::xwt::plat::Win32$Win32Picture*)source0;
 
+    cx1 = max(dx, cx1);
+    cy1 = max(dy, cy1);
+    cx2 = min(dx + source->getWidth(), cx2);
+    cy2 = min(dy + source->getHeight(), cy2);
+    if (cx1 >= cx2 || cy1 >= cy2) return; 
+
     if (source->hasalpha) {
 
-        if (scratch == NULL || scratch_w < dx2 - dx1 || scratch_h < dy2 - dy1) {
+        if (scratch == NULL || scratch_w < cx2 - cx1 || scratch_h < cy2 - cy1) {
             if (scratch_dc != NULL) DeleteDC(scratch_dc);
             if (scratch != NULL) DeleteObject(scratch);
-            scratch_w = max(dx2 - dx1, scratch_w);
-            scratch_h = max(dy2 - dy1, scratch_h);
+            scratch_w = max(cx2 - cx1, scratch_w);
+            scratch_h = max(cy2 - cy1, scratch_h);
 
             BITMAPINFO bitmapinfo;
             memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
@@ -389,33 +402,35 @@ void org::xwt::plat::Win32$Win32PixelBuffer::drawPicture(org::xwt::Picture* sour
         }
 
         // copy from screen to scratch
-        BitBlt((HDC)scratch_dc, 0, 0, dx2 - dx1, dy2 - dy1, (HDC)hdc, dx1, dy1, SRCCOPY);
+        BitBlt((HDC)scratch_dc, 0, 0, cx2 - cx1, cy2 - cy1, (HDC)hdc, cx1, cy1, SRCCOPY);
 
         // apply alpha-blending to scratch
         jint* dat = elements(source->data);
 
-        for(int x = max(clipx1, dx1) - dx1; x < min(clipx2, dx2) - dx1; x++)
-            for(int y = max(clipy1, dy1) - dy1; y < min(clipy2, dy2) - dy1; y++) {
-                int sx = (x * (sx2 - sx1)) / (dx2 - dx1) + sx1;
-                int sy = (y * (sy2 - sy1)) / (dy2 - dy1) + sy1;
-                jint dst = scratch_bits[y * scratch_w + x];
-                jint src = dat[sy * source->getWidth() + sx];
-                jint alpha = (src & 0xFF000000) >> 24;
+        for(int x = cx1; x < cx2; x++)
+            for(int y = cy1; y < cy2; y++) {
+                jint dst = scratch_bits[(y - dy) * scratch_w + (x - dx)];
+
+                // FEATURE: see if we can leverage GDI to do something more clever here with alphaOnly
+                jint src = alphaOnly ? rgb : dat[(y - dy) * source->getWidth() + x - dx];
+                jint alpha = (dat[(y - dy) * source->getWidth() + x - dx] & 0xFF000000) >> 24;
                 jint r = (((src & 0x00FF0000) >> 16) * alpha + ((dst & 0x00FF0000) >> 16) * (0xFF - alpha)) / 0xFF;
                 jint g = (((src & 0x0000FF00) >> 8)  * alpha + ((dst & 0x0000FF00) >> 8)  * (0xFF - alpha)) / 0xFF;
                 jint b = (((src & 0x000000FF))       * alpha + ((dst & 0x000000FF))       * (0xFF - alpha)) / 0xFF;
-                scratch_bits[y * scratch_w + x] = (r << 16) | (g << 8) | b;
+                scratch_bits[(y - dy) * scratch_w + (x - dx)] = (r << 16) | (g << 8) | b;
             }
 
         // copy back from scratch to screen
-        BitBlt((HDC)hdc, dx1, dy1, dx2 - dx1, dy2 - dy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
+        BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
 
     } else {
+
+        // FIXME: support alphaOnly case here
         if (source->hasmask) {
-            BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->maskdc, sx1, sy1, sx2, sy2, SRCAND);
-            BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCPAINT);
+            BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)source->maskdc, cx1 - dx, cy1 - dy, SRCAND);
+            BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)source->hdc, cx1 - dx, cy1 - dy, SRCPAINT);
         } else {
-            BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCCOPY);
+            BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)source->hdc, cx1 - dx, cy1 - dy, SRCCOPY);
         }
 
     }
@@ -447,13 +462,6 @@ void org::xwt::plat::Win32$Win32PixelBuffer::natInit() {
     SelectObject((HDC)hdc, (HBITMAP)hbitmap);
 }
 
-void org::xwt::plat::Win32$Win32PixelBuffer::setClip(jint x, jint y, jint x2, jint y2) {
-    clipx1 = x; clipx2 = x2; clipy1 = y; clipy2 = y2;
-    HRGN hrgn = CreateRectRgn(x, y, x2, y2);
-    SelectClipRgn((HDC)hdc, hrgn);
-    DeleteObject(hrgn);
-}
-
 void org::xwt::plat::Win32$Win32PixelBuffer::finalize() {
     DeleteObject((void*)hdc);
     DeleteObject((void*)hbitmap);
@@ -468,18 +476,18 @@ void org::xwt::plat::Win32$Win32Picture::natInit() {
     BITMAPINFO bitmapinfo;
     memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
     bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
-    bitmapinfo.bmiHeader.biWidth = w;
-    bitmapinfo.bmiHeader.biHeight = -1 * h;
+    bitmapinfo.bmiHeader.biWidth = width;
+    bitmapinfo.bmiHeader.biHeight = -1 * height;
     bitmapinfo.bmiHeader.biPlanes = 1;
     bitmapinfo.bmiHeader.biBitCount = 32;
     bitmapinfo.bmiHeader.biCompression = BI_RGB;
 
-    hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
+    hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, width, height);
     hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
     SelectObject((HDC)hdc, (HBITMAP)hbitmap);
     uint32_t* dat = (uint32_t*)elements(data);
     for(int i=0; i<data->length; i++) if ((dat[i] & 0xFF000000) == 0x00000000) dat[i] = 0x00000000;
-    StretchDIBits((HDC)hdc, 0, 0, w, h, 0, 0, w, h, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
+    StretchDIBits((HDC)hdc, 0, 0, width, height, 0, 0, width, height, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
 
     jint _copy[min(1024, data->length)];
     jint* copy = data->length > 1024 ? (jint*)malloc(data->length * 4) : _copy;
@@ -504,10 +512,10 @@ void org::xwt::plat::Win32$Win32Picture::natInit() {
     }
 
     //    hmask = (jint)CreateBitmap(w, h, 1, 1, NULL);
-    hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
+    hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, width, height);
     maskdc = (jint)CreateCompatibleDC(NULL);
     SelectObject((HDC)maskdc, (HBITMAP)hmask);
-    StretchDIBits((HDC)maskdc, 0, 0, w, h, 0, 0, w, h, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
+    StretchDIBits((HDC)maskdc, 0, 0, width, height, 0, 0, width, height, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
     if (data->length > 1024) free(copy);
 }
 
@@ -547,7 +555,7 @@ void org::xwt::plat::Win32$Win32Surface::setLocation() {
     SetWindowPos((HWND)hwnd, NULL, root->x - (point.x - rect.left), root->y - (point.y - rect.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
 }
 
-void org::xwt::plat::Win32$Win32Surface::setSize(jint w, jint h) {
+void org::xwt::plat::Win32$Win32Surface::_setSize(jint w, jint h) {
     RECT client_rect, window_rect;
     GetClientRect((HWND)hwnd, &client_rect);
     GetWindowRect((HWND)hwnd, &window_rect);
@@ -577,7 +585,7 @@ void org::xwt::plat::Win32$Win32Surface::setIcon(org::xwt::Picture* p0) {
     HBITMAP bit = CreateCompatibleBitmap((HDC)hdc, icon_width, icon_height);
     HDC memdc = CreateCompatibleDC((HDC)hdc);
     SelectObject(memdc, bit);
-    BLT((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, p->getWidth(), p->getHeight(), SRCCOPY);
+    BitBlt((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, SRCCOPY);
 
     // create the mask
     jint* dat = elements(p->data);
@@ -610,6 +618,7 @@ jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _w
 
     int oldmousex, oldmousey;
     MINMAXINFO* mmi;
+    int resizable;
     POINT point;
     HWND hwnd2;
     RECT rect, rect2;
@@ -730,8 +739,9 @@ jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _w
         mmi = (MINMAXINFO*)lParam;
         mmi->ptMinTrackSize.x = ((uint32_t)root->minwidth) + addwidth;
         mmi->ptMinTrackSize.y = ((uint32_t)root->minheight) + addheight;
-        mmi->ptMaxTrackSize.x = min(org::xwt::plat::Win32::getScreenWidth(), ((uint32_t)root->maxwidth) + addwidth);
-        mmi->ptMaxTrackSize.y = min(org::xwt::plat::Win32::getScreenHeight(), ((uint32_t)root->maxheight) + addheight);
+        resizable = !((root->minwidth == root->maxwidth) && (root->minheight == root->maxheight));
+        mmi->ptMaxTrackSize.x = resizable ? org::xwt::plat::Win32::getScreenWidth() : mmi->ptMinTrackSize.x;
+        mmi->ptMaxTrackSize.y = resizable ? org::xwt::plat::Win32::getScreenHeight() : mmi->ptMinTrackSize.y;
         return 0;
         
     case WM_PAINT: