[Paint] Initial support for free selections, resizing selections and experimental...
authorBenedikt Freisen <b.freisen@gmx.net>
Sat, 16 Jan 2010 23:21:45 +0000 (23:21 +0000)
committerBenedikt Freisen <b.freisen@gmx.net>
Sat, 16 Jan 2010 23:21:45 +0000 (23:21 +0000)
svn path=/trunk/; revision=45113

reactos/base/applications/paint/globalvar.h
reactos/base/applications/paint/main.c
reactos/base/applications/paint/mouse.c
reactos/base/applications/paint/selection.c
reactos/base/applications/paint/winproc.c

index 821e814..ed73d41 100644 (file)
@@ -43,6 +43,7 @@ extern int rectSel_dest[4];
 extern HWND hSelection;
 extern HWND hImageArea;
 extern HBITMAP hSelBm;
+extern HBITMAP hSelMask;
 
 extern int palColors[28];
 
index c83554a..98565f4 100644 (file)
@@ -60,6 +60,7 @@ int rectSel_dest[4];
 HWND hSelection;
 HWND hImageArea;
 HBITMAP hSelBm;
+HBITMAP hSelMask;
 
 /* initial palette colors; may be changed by the user during execution */
 int palColors[28] = { 0x000000, 0x464646, 0x787878, 0x300099, 0x241ced, 0x0078ff, 0x0ec2ff,
index 87cee6c..383d5d9 100644 (file)
@@ -27,6 +27,8 @@ placeSelWin()
 
 POINT pointStack[256];
 short pointSP;
+POINT *ptStack = NULL;
+int ptSP = 0;
 
 void
 startPaintingL(HDC hdc, short x, short y, int fg, int bg)
@@ -38,15 +40,25 @@ startPaintingL(HDC hdc, short x, short y, int fg, int bg)
     switch (activeTool)
     {
         case 1:
+            ShowWindow(hSelection, SW_HIDE);
+            if (ptStack != NULL)
+                HeapFree(GetProcessHeap(), 0, ptStack);
+            ptStack = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
+            ptSP = 0;
+            ptStack[0].x = x;
+            ptStack[0].y = y;
+            break;
         case 10:
         case 11:
         case 13:
         case 15:
         case 16:
             newReversible();
+            break;
         case 2:
             newReversible();
             ShowWindow(hSelection, SW_HIDE);
+            rectSel_src[2] = rectSel_src[3] = 0;
             break;
         case 3:
             newReversible();
@@ -96,6 +108,17 @@ whilePaintingL(HDC hdc, short x, short y, int fg, int bg)
 {
     switch (activeTool)
     {
+        case 1:
+            if (ptSP == 0)
+                newReversible();
+            ptSP++;
+            if (ptSP % 1024 == 0)
+                ptStack = HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, ptStack, sizeof(POINT) * (ptSP + 1024));
+            ptStack[ptSP].x = max(0, min(x, imgXRes));
+            ptStack[ptSP].y = max(0, min(y, imgYRes));
+            resetToU1();
+            Poly(hdc, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE);
+            break;
         case 2:
         {
             short tempX;
@@ -174,6 +197,56 @@ endPaintingL(HDC hdc, short x, short y, int fg, int bg)
 {
     switch (activeTool)
     {
+        case 1:
+        {
+            POINT *ptStackCopy;
+            int i;
+            rectSel_src[0] = rectSel_src[1] = 0x7fffffff;
+            rectSel_src[2] = rectSel_src[3] = 0;
+            for (i = 0; i <= ptSP; i++)
+            {
+                if (ptStack[i].x < rectSel_src[0])
+                    rectSel_src[0] = ptStack[i].x;
+                if (ptStack[i].y < rectSel_src[1])
+                    rectSel_src[1] = ptStack[i].y;
+                if (ptStack[i].x > rectSel_src[2])
+                    rectSel_src[2] = ptStack[i].x;
+                if (ptStack[i].y > rectSel_src[3])
+                    rectSel_src[3] = ptStack[i].y;
+            }
+            rectSel_src[2] += 1 - rectSel_src[0];
+            rectSel_src[3] += 1 - rectSel_src[1];
+            rectSel_dest[0] = rectSel_src[0];
+            rectSel_dest[1] = rectSel_src[1];
+            rectSel_dest[2] = rectSel_src[2];
+            rectSel_dest[3] = rectSel_src[3];
+            if (ptSP != 0)
+            {
+                DeleteObject(hSelMask);
+                hSelMask = CreateBitmap(rectSel_src[2], rectSel_src[3], 1, 1, NULL);
+                DeleteObject(SelectObject(hSelDC, hSelMask));
+                ptStackCopy = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * (ptSP + 1));
+                for (i = 0; i <= ptSP; i++)
+                {
+                    ptStackCopy[i].x = ptStack[i].x - rectSel_src[0];
+                    ptStackCopy[i].y = ptStack[i].y - rectSel_src[1];
+                }
+                Poly(hSelDC, ptStackCopy, ptSP + 1, 0x00ffffff, 0x00ffffff, 1, 2, TRUE);
+                HeapFree(GetProcessHeap(), 0, ptStackCopy);
+                SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(rectSel_src[2], rectSel_src[3]));
+                resetToU1();
+                MaskBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0],
+                        rectSel_src[1], hSelMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
+                Poly(hdc, ptStack, ptSP + 1, bg, bg, 1, 2, TRUE);
+                newReversible();
+
+                placeSelWin();
+                ShowWindow(hSelection, SW_SHOW);
+            }
+            HeapFree(GetProcessHeap(), 0, ptStack);
+            ptStack = NULL;
+            break;
+        }
         case 2:
             resetToU1();
             if ((rectSel_src[2] != 0) && (rectSel_src[3] != 0))
@@ -181,8 +254,12 @@ endPaintingL(HDC hdc, short x, short y, int fg, int bg)
                 DeleteObject(SelectObject
                              (hSelDC, hSelBm =
                               (HBITMAP) CreateDIBWithProperties(rectSel_src[2], rectSel_src[3])));
+                DeleteObject(hSelMask);
                 BitBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0],
                        rectSel_src[1], SRCCOPY);
+                Rect(hdc, rectSel_src[0], rectSel_src[1], rectSel_src[0] + rectSel_src[2],
+                     rectSel_src[1] + rectSel_src[3], bgColor, bgColor, 0, TRUE);
+                newReversible();
                 placeSelWin();
                 ShowWindow(hSelection, SW_SHOW);
             }
@@ -255,6 +332,7 @@ startPaintingR(HDC hdc, short x, short y, int fg, int bg)
         case 15:
         case 16:
             newReversible();
+            break;
         case 3:
             newReversible();
             Replace(hdc, x, y, x, y, fg, bg, rubberRadius);
index f08b3b1..5028f9e 100644 (file)
 #include "drawing.h"
 #include "history.h"
 #include "mouse.h"
+#include "dib.h"
 
 /* FUNCTIONS ********************************************************/
 
+LPCTSTR cursors[9] = { IDC_SIZEALL, IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
+    IDC_SIZEWE, IDC_SIZEWE, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE
+};
+
 BOOL moving = FALSE;
+int action = 0;
 short xPos;
 short yPos;
+short xFrac;
+short yFrac;
+
+int
+identifyCorner(short x, short y, short w, short h)
+{
+    if (y < 3)
+    {
+        if (x < 3)
+            return 1;
+        if ((x < w / 2 + 2) && (x >= w / 2 - 1))
+            return 2;
+        if (x >= w - 3)
+            return 3;
+    }
+    if ((y < h / 2 + 2) && (y >= h / 2 - 1))
+    {
+        if (x < 3)
+            return 4;
+        if (x >= w - 3)
+            return 5;
+    }
+    if (y >= h - 3)
+    {
+        if (x < 3)
+            return 6;
+        if ((x < w / 2 + 2) && (x >= w / 2 - 1))
+            return 7;
+        if (x >= w - 3)
+            return 8;
+    }
+    return 0;
+}
 
 LRESULT CALLBACK
 SelectionWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -41,36 +80,140 @@ SelectionWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             xPos = LOWORD(lParam);
             yPos = HIWORD(lParam);
             SetCapture(hwnd);
+            if (action != 0)
+                SetCursor(LoadCursor(NULL, cursors[action]));
             moving = TRUE;
             break;
         case WM_MOUSEMOVE:
             if (moving)
             {
+                int xDelta;
+                int yDelta;
                 resetToU1();
-                rectSel_dest[0] += (short)LOWORD(lParam) - xPos;
-                rectSel_dest[1] += (short)HIWORD(lParam) - yPos;
+                xFrac += (short)LOWORD(lParam) - xPos;
+                yFrac += (short)HIWORD(lParam) - yPos;
+                if (zoom < 1000)
+                {
+                    xDelta = xFrac * 1000 / zoom;
+                    xFrac = 0;
+                    yDelta = yFrac * 1000 / zoom;
+                    yFrac = 0;
+                }
+                else
+                {
+                    xDelta = xFrac * 1000 / zoom;
+                    xFrac -= (xFrac * 1000 / zoom) * zoom / 1000;
+                    yDelta = yFrac * 1000 / zoom;
+                    yFrac -= (yFrac * 1000 / zoom) * zoom / 1000;
+                }
+                switch (action)
+                {
+                    case 0:
+                        rectSel_dest[0] += xDelta;
+                        rectSel_dest[1] += yDelta;
+                        break;
+                    case 1:
+                        rectSel_dest[0] += xDelta;
+                        rectSel_dest[1] += yDelta;
+                        rectSel_dest[2] -= xDelta;
+                        rectSel_dest[3] -= yDelta;
+                        break;
+                    case 2:
+                        rectSel_dest[1] += yDelta;
+                        rectSel_dest[3] -= yDelta;
+                        break;
+                    case 3:
+                        rectSel_dest[2] += xDelta;
+                        rectSel_dest[1] += yDelta;
+                        break;
+                    case 4:
+                        rectSel_dest[0] += xDelta;
+                        rectSel_dest[2] -= xDelta;
+                        break;
+                    case 5:
+                        rectSel_dest[2] += xDelta;
+                        break;
+                    case 6:
+                        rectSel_dest[0] += xDelta;
+                        rectSel_dest[2] -= xDelta;
+                        rectSel_dest[3] += yDelta;
+                        break;
+                    case 7:
+                        rectSel_dest[3] += yDelta;
+                        break;
+                    case 8:
+                        rectSel_dest[2] += xDelta;
+                        rectSel_dest[3] += yDelta;
+                        break;
+                }
 
-                Rect(hDrawingDC, rectSel_src[0], rectSel_src[1], rectSel_src[0] + rectSel_src[2],
-                     rectSel_src[1] + rectSel_src[3], bgColor, bgColor, 0, TRUE);
+                if (action != 0)
+                    StretchBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY);
+                else
                 if (transpBg == 0)
-                    BitBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
-                           hSelDC, 0, 0, SRCCOPY);
+                    MaskBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
+                            hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
                 else
-                    BitBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
-                           hSelDC, 0, 0, SRCAND);
-                    //TransparentBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3], 
-                    //               hSelDC, 0, 0, rectSel_dest[2], rectSel_dest[3], bgColor);
+                {
+                    HBITMAP tempMask;
+                    HBRUSH oldBrush;
+                    HDC tempDC;
+                    tempMask = CreateBitmap(rectSel_dest[2], rectSel_dest[3], 1, 1, NULL);
+                    oldBrush = SelectObject(hSelDC, CreateSolidBrush(bgColor));
+                    tempDC = CreateCompatibleDC(hSelDC);
+                    SelectObject(tempDC, tempMask);
+                    MaskBlt(tempDC, 0, 0, rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0, hSelMask, 0, 0,
+                            MAKEROP4(NOTSRCCOPY, BLACKNESS));
+                    DeleteDC(tempDC);
+                    DeleteObject(SelectObject(hSelDC, oldBrush));
+
+                    MaskBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
+                            hSelDC, 0, 0, tempMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
+                    DeleteObject(tempMask);
+                }
                 SendMessage(hImageArea, WM_PAINT, 0, 0);
                 xPos = LOWORD(lParam);
                 yPos = HIWORD(lParam);
                 //SendMessage(hwnd, WM_PAINT, 0, 0);
             }
+            else
+            {
+                int w = rectSel_dest[2] * zoom / 1000 + 6;
+                int h = rectSel_dest[3] * zoom / 1000 + 6;
+                xPos = LOWORD(lParam);
+                yPos = HIWORD(lParam);
+                action = identifyCorner(xPos, yPos, w, h);
+                if (action != 0)
+                    SetCursor(LoadCursor(NULL, cursors[action]));
+            }
             break;
         case WM_LBUTTONUP:
             if (moving)
             {
                 moving = FALSE;
                 ReleaseCapture();
+                if (action != 0)
+                {
+                    HDC hTempDC;
+                    HBITMAP hTempBm;
+                    hTempDC = CreateCompatibleDC(hSelDC);
+                    hTempBm = CreateDIBWithProperties(rectSel_dest[2], rectSel_dest[3]);
+                    SelectObject(hTempDC, hTempBm);
+                    SelectObject(hSelDC, hSelBm);
+                    StretchBlt(hTempDC, 0, 0, rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0,
+                               GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY);
+                    DeleteObject(hSelBm);
+                    hSelBm = hTempBm;
+                    hTempBm = CreateBitmap(rectSel_dest[2], rectSel_dest[3], 1, 1, NULL);
+                    SelectObject(hTempDC, hTempBm);
+                    SelectObject(hSelDC, hSelMask);
+                    StretchBlt(hTempDC, 0, 0, rectSel_dest[2], rectSel_dest[3], hSelDC, 0, 0,
+                               GetDIBWidth(hSelMask), GetDIBHeight(hSelMask), SRCCOPY);
+                    DeleteObject(hSelMask);
+                    hSelMask = hTempBm;
+                    SelectObject(hSelDC, hSelBm);
+                    DeleteDC(hTempDC);
+                }
                 placeSelWin();
                 ShowWindow(hSelection, SW_HIDE);
                 ShowWindow(hSelection, SW_SHOW);
index 9d269d3..464b62c 100644 (file)
@@ -744,18 +744,15 @@ WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                     break;
                 case IDM_EDITDELETESELECTION:
                 {
-                    /* FIXME: deleting freeform selections unsupported */
-                    RECT selectionRect, areaRect;
-                    long x1, x2, y1, y2;
-
-                    GetWindowRect(hSelection, &selectionRect);
-                    GetWindowRect(hImageArea, &areaRect);
-                    x1 = ((selectionRect.left - areaRect.left) / (zoom / 1000)) + 1;
-                    y1 = ((selectionRect.top - areaRect.top) / (zoom / 1000)) + 1;
-                    x2 = (selectionRect.right - areaRect.left) / (zoom / 1000);
-                    y2 = (selectionRect.bottom - areaRect.top) / (zoom / 1000);
-                    Rect(hDrawingDC, x1, y1, x2, y2, bgColor, bgColor, 0, TRUE);
-                    ShowWindow(hSelection, SW_HIDE);
+                    /* remove selection window and already painted content using undo(),
+                    paint Rect for rectangular selections and nothing for freeform selections */
+                    undo();
+                    if (activeTool == 2)
+                    {
+                        newReversible();
+                        Rect(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2] + rectSel_dest[0],
+                             rectSel_dest[3] + rectSel_dest[1], bgColor, bgColor, 0, TRUE);
+                    }
                     break;
                 }
                 case IDM_EDITSELECTALL: