[MSPAINT_NEW] refactoring: move selection management to a dedicated SelectionModel...
authorBenedikt Freisen <b.freisen@gmx.net>
Thu, 9 Jul 2015 09:48:01 +0000 (09:48 +0000)
committerBenedikt Freisen <b.freisen@gmx.net>
Thu, 9 Jul 2015 09:48:01 +0000 (09:48 +0000)
svn path=/trunk/; revision=68382

reactos/base/applications/mspaint_new/CMakeLists.txt
reactos/base/applications/mspaint_new/globalvar.h
reactos/base/applications/mspaint_new/main.cpp
reactos/base/applications/mspaint_new/mouse.cpp
reactos/base/applications/mspaint_new/precomp.h
reactos/base/applications/mspaint_new/selection.cpp
reactos/base/applications/mspaint_new/selection.h
reactos/base/applications/mspaint_new/selectionmodel.cpp [new file with mode: 0644]
reactos/base/applications/mspaint_new/selectionmodel.h [new file with mode: 0644]
reactos/base/applications/mspaint_new/winproc.cpp

index 377f70d..6322943 100644 (file)
@@ -18,6 +18,7 @@ list(APPEND SOURCE
     registry.cpp
     scrollbox.cpp
     selection.cpp
+    selectionmodel.cpp
     sizebox.cpp
     textedit.cpp
     toolbox.cpp
index 270a3e5..7fcc211 100644 (file)
@@ -21,7 +21,6 @@ typedef struct tagSTRETCHSKEW {
 /* VARIABLES declared in main.c *************************************/
 
 extern HDC hDrawingDC;
-extern HDC hSelDC;
 extern int *bmAddress;
 extern BITMAPINFO bitmapinfo;
 
@@ -39,10 +38,9 @@ extern POINT last;
 class ToolsModel;
 extern ToolsModel toolsModel;
 
-extern RECT rectSel_src;
-extern RECT rectSel_dest;
-extern HBITMAP hSelBm;
-extern HBITMAP hSelMask;
+class SelectionModel;
+extern SelectionModel selectionModel;
+
 extern HWND hwndEditCtl;
 extern LOGFONT lfTextFont;
 extern HFONT hfontTextFont;
@@ -114,5 +112,3 @@ extern CTextEditWindow textEditWindow;
 
 extern POINT pointStack[256];
 extern short pointSP;
-extern POINT *ptStack;
-extern int ptSP;
index 363c635..abdfb6b 100644 (file)
@@ -13,7 +13,6 @@
 /* FUNCTIONS ********************************************************/
 
 HDC hDrawingDC;
-HDC hSelDC;
 int *bmAddress;
 BITMAPINFO bitmapinfo;
 int imgXRes = 400;
@@ -31,10 +30,8 @@ POINT last;
 
 ToolsModel toolsModel;
 
-RECT rectSel_src;
-RECT rectSel_dest;
-HBITMAP hSelBm;
-HBITMAP hSelMask;
+SelectionModel selectionModel;
+
 LOGFONT lfTextFont;
 HFONT hfontTextFont;
 HWND hwndEditCtl;
@@ -205,7 +202,7 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument
 
     hDC = imageArea.GetDC();
     hDrawingDC = CreateCompatibleDC(hDC);
-    hSelDC     = CreateCompatibleDC(hDC);
+    selectionModel.SetDC(CreateCompatibleDC(hDC));
     imageArea.ReleaseDC(hDC);
     SelectObject(hDrawingDC, CreatePen(PS_SOLID, 0, paletteModel.GetFgColor()));
     SelectObject(hDrawingDC, CreateSolidBrush(paletteModel.GetBgColor()));
index 10f446e..a4eaf6b 100644 (file)
 void
 placeSelWin()
 {
-    selectionWindow.MoveWindow(rectSel_dest.left * toolsModel.GetZoom() / 1000, rectSel_dest.top * toolsModel.GetZoom() / 1000,
-        RECT_WIDTH(rectSel_dest) * toolsModel.GetZoom() / 1000 + 6, RECT_HEIGHT(rectSel_dest) * toolsModel.GetZoom() / 1000 + 6, TRUE);
+    selectionWindow.MoveWindow(selectionModel.GetDestRectLeft() * toolsModel.GetZoom() / 1000, selectionModel.GetDestRectTop() * toolsModel.GetZoom() / 1000,
+        selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 6, selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
     selectionWindow.BringWindowToTop();
     imageArea.InvalidateRect(NULL, FALSE);
 }
 
 void
-regularize(LONG x0, LONG y0, LONG *x1, LONG *y1)
+regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
 {
-    if (abs(*x1 - x0) >= abs(*y1 - y0))
-        *y1 = y0 + (*y1 > y0 ? abs(*x1 - x0) : -abs(*x1 - x0));
+    if (abs(x1 - x0) >= abs(y1 - y0))
+        y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
     else
-        *x1 = x0 + (*x1 > x0 ? abs(*y1 - y0) : -abs(*y1 - y0));
+        x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
 }
 
 void
-roundTo8Directions(LONG x0, LONG y0, LONG *x1, LONG *y1)
+roundTo8Directions(LONG x0, LONG y0, LONG& x1, LONG& y1)
 {
-    if (abs(*x1 - x0) >= abs(*y1 - y0))
+    if (abs(x1 - x0) >= abs(y1 - y0))
     {
-        if (abs(*y1 - y0) * 5 < abs(*x1 - x0) * 2)
-            *y1 = y0;
+        if (abs(y1 - y0) * 5 < abs(x1 - x0) * 2)
+            y1 = y0;
         else
-            *y1 = y0 + (*y1 > y0 ? abs(*x1 - x0) : -abs(*x1 - x0));
+            y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
     }
     else
     {
-        if (abs(*x1 - x0) * 5 < abs(*y1 - y0) * 2)
-            *x1 = x0;
+        if (abs(x1 - x0) * 5 < abs(y1 - y0) * 2)
+            x1 = x0;
         else
-            *x1 = x0 + (*x1 > x0 ? abs(*y1 - y0) : -abs(*y1 - y0));
+            x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
     }
 }
 
 POINT pointStack[256];
 short pointSP;
-POINT *ptStack = NULL;
-int ptSP = 0;
 
 void
 startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
@@ -65,12 +63,8 @@ startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
     {
         case TOOL_FREESEL:
             selectionWindow.ShowWindow(SW_HIDE);
-            if (ptStack != NULL)
-                HeapFree(GetProcessHeap(), 0, ptStack);
-            ptStack = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
-            ptSP = 0;
-            ptStack[0].x = x;
-            ptStack[0].y = y;
+            selectionModel.ResetPtStack();
+            selectionModel.PushToPtStack(x, y);
             break;
         case TOOL_LINE:
         case TOOL_RECT:
@@ -82,8 +76,7 @@ startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_TEXT:
             imageModel.CopyPrevious();
             selectionWindow.ShowWindow(SW_HIDE);
-            rectSel_src.right = rectSel_src.left;
-            rectSel_src.bottom = rectSel_src.top;
+            selectionModel.SetSrcRectSizeToZero();
             break;
         case TOOL_RUBBER:
             imageModel.CopyPrevious();
@@ -134,15 +127,11 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
     switch (toolsModel.GetActiveTool())
     {
         case TOOL_FREESEL:
-            if (ptSP == 0)
+            if (selectionModel.PtStackSize() == 1)
                 imageModel.CopyPrevious();
-            ptSP++;
-            if (ptSP % 1024 == 0)
-                ptStack = (POINT*) HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, ptStack, sizeof(POINT) * (ptSP + 1024));
-            ptStack[ptSP].x = max(0, min(x, imageModel.GetWidth()));
-            ptStack[ptSP].y = max(0, min(y, imageModel.GetHeight()));
+            selectionModel.PushToPtStack(max(0, min(x, imageModel.GetWidth())), max(0, min(y, imageModel.GetHeight())));
             imageModel.ResetToPrevious();
-            Poly(hdc, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE, TRUE); /* draw the freehand selection inverted/xored */
+            selectionModel.DrawFramePoly(hdc);
             break;
         case TOOL_RECTSEL:
         case TOOL_TEXT:
@@ -151,10 +140,7 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             imageModel.ResetToPrevious();
             temp.x = max(0, min(x, imageModel.GetWidth()));
             temp.y = max(0, min(y, imageModel.GetHeight()));
-            rectSel_dest.left = rectSel_src.left = min(start.x, temp.x);
-            rectSel_dest.top = rectSel_src.top = min(start.y, temp.y);
-            rectSel_dest.right = rectSel_src.right = max(start.x, temp.x);
-            rectSel_dest.bottom = rectSel_src.bottom = max(start.y, temp.y);
+            selectionModel.SetSrcAndDestRectFromPoints(start, temp);
             RectSel(hdc, start.x, start.y, temp.x, temp.y);
             break;
         }
@@ -173,7 +159,7 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_LINE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                roundTo8Directions(start.x, start.y, &x, &y);
+                roundTo8Directions(start.x, start.y, x, y);
             Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
             break;
         case TOOL_BEZIER:
@@ -197,7 +183,7 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_RECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
@@ -206,20 +192,20 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
-                                   &pointStack[pointSP].x, &pointStack[pointSP].y);
+                                   pointStack[pointSP].x, pointStack[pointSP].y);
             if (pointSP + 1 >= 2)
                 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
             break;
         case TOOL_ELLIPSE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
     }
@@ -235,79 +221,30 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
     {
         case TOOL_FREESEL:
         {
-            POINT *ptStackCopy;
-            int i;
-            rectSel_src.left = rectSel_src.top = MAXLONG;
-            rectSel_src.right = rectSel_src.bottom = 0;
-            for (i = 0; i <= ptSP; i++)
+            selectionModel.CalculateBoundingBoxAndContents(hdc);
+            if (selectionModel.PtStackSize() > 1)
             {
-                if (ptStack[i].x < rectSel_src.left)
-                    rectSel_src.left = ptStack[i].x;
-                if (ptStack[i].y < rectSel_src.top)
-                    rectSel_src.top = ptStack[i].y;
-                if (ptStack[i].x > rectSel_src.right)
-                    rectSel_src.right = ptStack[i].x;
-                if (ptStack[i].y > rectSel_src.bottom)
-                    rectSel_src.bottom = ptStack[i].y;
-            }
-            rectSel_src.right  += 1;
-            rectSel_src.bottom += 1;
-            rectSel_dest.left   = rectSel_src.left;
-            rectSel_dest.top    = rectSel_src.top;
-            rectSel_dest.right  = rectSel_src.right;
-            rectSel_dest.bottom = rectSel_src.bottom;
-            if (ptSP != 0)
-            {
-                DeleteObject(hSelMask);
-                hSelMask = CreateBitmap(RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), 1, 1, NULL);
-                DeleteObject(SelectObject(hSelDC, hSelMask));
-                ptStackCopy = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * (ptSP + 1));
-                for (i = 0; i <= ptSP; i++)
-                {
-                    ptStackCopy[i].x = ptStack[i].x - rectSel_src.left;
-                    ptStackCopy[i].y = ptStack[i].y - rectSel_src.top;
-                }
-                Poly(hSelDC, ptStackCopy, ptSP + 1, 0x00ffffff, 0x00ffffff, 1, 2, TRUE, FALSE);
-                HeapFree(GetProcessHeap(), 0, ptStackCopy);
-                SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src)));
-                imageModel.ResetToPrevious();
-                MaskBlt(hSelDC, 0, 0, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hDrawingDC, rectSel_src.left,
-                        rectSel_src.top, hSelMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
-                Poly(hdc, ptStack, ptSP + 1, bg, bg, 1, 2, TRUE, FALSE);
+                selectionModel.DrawBackgroundPoly(hdc, bg);
                 imageModel.CopyPrevious();
 
-                MaskBlt(hDrawingDC, rectSel_src.left, rectSel_src.top, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hSelDC, 0,
-                        0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
+                selectionModel.DrawSelection(hdc);
 
                 placeSelWin();
                 selectionWindow.ShowWindow(SW_SHOW);
-                /* force refresh of selection contents */
-                selectionWindow.SendMessage(WM_LBUTTONDOWN, 0, 0);
-                selectionWindow.SendMessage(WM_MOUSEMOVE, 0, 0);
-                selectionWindow.SendMessage(WM_LBUTTONUP, 0, 0);
+                ForceRefreshSelectionContents();
             }
-            HeapFree(GetProcessHeap(), 0, ptStack);
-            ptStack = NULL;
+            selectionModel.ResetPtStack();
             break;
         }
         case TOOL_RECTSEL:
             imageModel.ResetToPrevious();
-            if ((RECT_WIDTH(rectSel_src) != 0) && (RECT_HEIGHT(rectSel_src) != 0))
+            if (selectionModel.IsSrcRectSizeNonzero())
             {
-                DeleteObject(hSelMask);
-                hSelMask = CreateBitmap(RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), 1, 1, NULL);
-                DeleteObject(SelectObject(hSelDC, hSelMask));
-                Rect(hSelDC, 0, 0, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), 0x00ffffff, 0x00ffffff, 1, 2);
-                SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src)));
-                imageModel.ResetToPrevious();
-                BitBlt(hSelDC, 0, 0, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hDrawingDC, rectSel_src.left,
-                       rectSel_src.top, SRCCOPY);
-                Rect(hdc, rectSel_src.left, rectSel_src.top, rectSel_src.right,
-                     rectSel_src.bottom, bg, bg, 0, TRUE);
+                selectionModel.CalculateContents(hdc);
+                selectionModel.DrawBackgroundRect(hdc, bg);
                 imageModel.CopyPrevious();
 
-                BitBlt(hDrawingDC, rectSel_src.left, rectSel_src.top, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hSelDC, 0,
-                       0, SRCCOPY);
+                selectionModel.DrawSelection(hdc);
 
                 placeSelWin();
                 selectionWindow.ShowWindow(SW_SHOW);
@@ -316,7 +253,7 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             break;
         case TOOL_TEXT:
             imageModel.ResetToPrevious();
-            if ((RECT_WIDTH(rectSel_src) != 0) && (RECT_HEIGHT(rectSel_src) != 0))
+            if (selectionModel.IsSrcRectSizeNonzero())
             {
                 imageModel.CopyPrevious();
 
@@ -335,7 +272,7 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_LINE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                roundTo8Directions(start.x, start.y, &x, &y);
+                roundTo8Directions(start.x, start.y, x, y);
             Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
             break;
         case TOOL_BEZIER:
@@ -346,7 +283,7 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_RECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
@@ -355,7 +292,7 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
-                                   &pointStack[pointSP].x, &pointStack[pointSP].y);
+                                   pointStack[pointSP].x, pointStack[pointSP].y);
             pointSP++;
             if (pointSP >= 2)
             {
@@ -376,13 +313,13 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_ELLIPSE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
     }
@@ -468,7 +405,7 @@ whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_LINE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                roundTo8Directions(start.x, start.y, &x, &y);
+                roundTo8Directions(start.x, start.y, x, y);
             Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
             break;
         case TOOL_BEZIER:
@@ -492,7 +429,7 @@ whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_RECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
@@ -501,20 +438,20 @@ whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
-                                   &pointStack[pointSP].x, &pointStack[pointSP].y);
+                                   pointStack[pointSP].x, pointStack[pointSP].y);
             if (pointSP + 1 >= 2)
                 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
             break;
         case TOOL_ELLIPSE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
     }
@@ -538,7 +475,7 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_LINE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                roundTo8Directions(start.x, start.y, &x, &y);
+                roundTo8Directions(start.x, start.y, x, y);
             Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
             break;
         case TOOL_BEZIER:
@@ -549,7 +486,7 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_RECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
@@ -558,7 +495,7 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
-                                   &pointStack[pointSP].x, &pointStack[pointSP].y);
+                                   pointStack[pointSP].x, pointStack[pointSP].y);
             pointSP++;
             if (pointSP >= 2)
             {
@@ -579,13 +516,13 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_ELLIPSE:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
             imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
-                regularize(start.x, start.y, &x, &y);
+                regularize(start.x, start.y, x, y);
             RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
     }
index 123ee89..960dfab 100644 (file)
@@ -30,6 +30,7 @@
 #include "palettemodel.h"
 #include "scrollbox.h"
 #include "selection.h"
+#include "selectionmodel.h"
 #include "sizebox.h"
 #include "textedit.h"
 #include "toolbox.h"
index 3016dca..cd3df62 100644 (file)
 
 #include "precomp.h"
 
-/* DEFINES **********************************************************/
-
-#define ACTION_MOVE                 0
-#define ACTION_RESIZE_TOP_LEFT      1
-#define ACTION_RESIZE_TOP           2
-#define ACTION_RESIZE_TOP_RIGHT     3
-#define ACTION_RESIZE_LEFT          4
-#define ACTION_RESIZE_RIGHT         5
-#define ACTION_RESIZE_BOTTOM_LEFT   6
-#define ACTION_RESIZE_BOTTOM        7
-#define ACTION_RESIZE_BOTTOM_RIGHT  8
-
 /* FUNCTIONS ********************************************************/
 
-LPCTSTR cursors[9] = { /* action to mouse cursor lookup table */
+const LPCTSTR CSelectionWindow::m_lpszCursorLUT[9] = { /* action to mouse cursor lookup table */
     IDC_SIZEALL,
 
     IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
@@ -32,13 +20,6 @@ LPCTSTR cursors[9] = { /* action to mouse cursor lookup table */
     IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE
 };
 
-BOOL moving = FALSE;
-int action = ACTION_MOVE;
-POINTS pos;
-POINTS frac;
-POINT delta;
-DWORD system_selection_color;
-
 BOOL
 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask, DWORD dwRop, COLORREF keyColor)
 {
@@ -81,32 +62,31 @@ ForceRefreshSelectionContents()
     }
 }
 
-int
-identifyCorner(short x, short y, short w, short h)
+int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight)
 {
-    if (y < 3)
+    if (iYPos < 3)
     {
-        if (x < 3)
+        if (iXPos < 3)
             return ACTION_RESIZE_TOP_LEFT;
-        if ((x < w / 2 + 2) && (x >= w / 2 - 1))
+        if ((iXPos < iWidth / 2 + 2) && (iXPos >= iWidth / 2 - 1))
             return ACTION_RESIZE_TOP;
-        if (x >= w - 3)
+        if (iXPos >= iWidth - 3)
             return ACTION_RESIZE_TOP_RIGHT;
     }
-    if ((y < h / 2 + 2) && (y >= h / 2 - 1))
+    if ((iYPos < iHeight / 2 + 2) && (iYPos >= iHeight / 2 - 1))
     {
-        if (x < 3)
+        if (iXPos < 3)
             return ACTION_RESIZE_LEFT;
-        if (x >= w - 3)
+        if (iXPos >= iWidth - 3)
             return ACTION_RESIZE_RIGHT;
     }
-    if (y >= h - 3)
+    if (iYPos >= iHeight - 3)
     {
-        if (x < 3)
+        if (iXPos < 3)
             return ACTION_RESIZE_BOTTOM_LEFT;
-        if ((x < w / 2 + 2) && (x >= w / 2 - 1))
+        if ((iXPos < iWidth / 2 + 2) && (iXPos >= iWidth / 2 - 1))
             return ACTION_RESIZE_BOTTOM;
-        if (x >= w - 3)
+        if (iXPos >= iWidth - 3)
             return ACTION_RESIZE_BOTTOM_RIGHT;
     }
     return 0;
@@ -114,13 +94,13 @@ identifyCorner(short x, short y, short w, short h)
 
 LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    if (!moving)
+    if (!m_bMoving)
     {
         HDC hDC = GetDC();
         DefWindowProc(WM_PAINT, wParam, lParam);
-        SelectionFrame(hDC, 1, 1, RECT_WIDTH(rectSel_dest) * toolsModel.GetZoom() / 1000 + 5,
-                       RECT_HEIGHT(rectSel_dest) * toolsModel.GetZoom() / 1000 + 5,
-                       system_selection_color);
+        SelectionFrame(hDC, 1, 1, selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 5,
+                       selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 5,
+                       m_dwSystemSelectionColor);
         ReleaseDC(hDC);
     }
     return 0;
@@ -134,8 +114,10 @@ LRESULT CSelectionWindow::OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam,
 
 LRESULT CSelectionWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
+    m_bMoving = FALSE;
+    m_iAction = ACTION_MOVE;
     /* update the system selection color */
-    system_selection_color = GetSysColor(COLOR_HIGHLIGHT);
+    m_dwSystemSelectionColor = GetSysColor(COLOR_HIGHLIGHT);
     SendMessage(WM_PAINT, 0, MAKELPARAM(0, 0));
     return 0;
 }
@@ -143,7 +125,7 @@ LRESULT CSelectionWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL
 LRESULT CSelectionWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
     /* update the system selection color */
-    system_selection_color = GetSysColor(COLOR_HIGHLIGHT);
+    m_dwSystemSelectionColor = GetSysColor(COLOR_HIGHLIGHT);
     SendMessage(WM_PAINT, 0, MAKELPARAM(0, 0));
     return 0;
 }
@@ -156,14 +138,14 @@ LRESULT CSelectionWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, B
 
 LRESULT CSelectionWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    pos.x = GET_X_LPARAM(lParam);
-    pos.y = GET_Y_LPARAM(lParam);
-    delta.x = 0;
-    delta.y = 0;
+    m_ptPos.x = GET_X_LPARAM(lParam);
+    m_ptPos.y = GET_Y_LPARAM(lParam);
+    m_ptDelta.x = 0;
+    m_ptDelta.y = 0;
     SetCapture();
-    if (action != ACTION_MOVE)
-        SetCursor(LoadCursor(NULL, cursors[action]));
-    moving = TRUE;
+    if (m_iAction != ACTION_MOVE)
+        SetCursor(LoadCursor(NULL, m_lpszCursorLUT[m_iAction]));
+    m_bMoving = TRUE;
     scrlClientWindow.InvalidateRect(NULL, TRUE);
     imageArea.SendMessage(WM_PAINT, 0, 0);
     return 0;
@@ -171,127 +153,66 @@ LRESULT CSelectionWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam,
 
 LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    if (moving)
+    if (m_bMoving)
     {
         TCHAR sizeStr[100];
-        POINT deltaUsed;
         imageModel.ResetToPrevious();
-        frac.x += GET_X_LPARAM(lParam) - pos.x;
-        frac.y += GET_Y_LPARAM(lParam) - pos.y;
-        delta.x += frac.x * 1000 / toolsModel.GetZoom();
-        delta.y += frac.y * 1000 / toolsModel.GetZoom();
+        m_ptFrac.x += GET_X_LPARAM(lParam) - m_ptPos.x;
+        m_ptFrac.y += GET_Y_LPARAM(lParam) - m_ptPos.y;
+        m_ptDelta.x += m_ptFrac.x * 1000 / toolsModel.GetZoom();
+        m_ptDelta.y += m_ptFrac.y * 1000 / toolsModel.GetZoom();
         if (toolsModel.GetZoom() < 1000)
         {
-            frac.x = 0;
-            frac.y = 0;
+            m_ptFrac.x = 0;
+            m_ptFrac.y = 0;
         }
         else
         {
-            frac.x -= (frac.x * 1000 / toolsModel.GetZoom()) * toolsModel.GetZoom() / 1000;
-            frac.y -= (frac.y * 1000 / toolsModel.GetZoom()) * toolsModel.GetZoom() / 1000;
-        }
-        switch (action)
-        {
-            case ACTION_MOVE:                /* move selection */
-                deltaUsed.x = delta.x;
-                deltaUsed.y = delta.y;
-                OffsetRect(&rectSel_dest, deltaUsed.x, deltaUsed.y);
-                break;
-            case ACTION_RESIZE_TOP_LEFT:     /* resize at upper left corner */
-                deltaUsed.x = min(delta.x, RECT_WIDTH(rectSel_dest) - 1);
-                deltaUsed.y = min(delta.y, RECT_HEIGHT(rectSel_dest) - 1);
-                rectSel_dest.left += deltaUsed.x;
-                rectSel_dest.top  += deltaUsed.y;
-                break;
-            case ACTION_RESIZE_TOP:          /* resize at top edge */
-                deltaUsed.x = delta.x;
-                deltaUsed.y = min(delta.y, RECT_HEIGHT(rectSel_dest) - 1);
-                rectSel_dest.top += deltaUsed.y;
-                break;
-            case ACTION_RESIZE_TOP_RIGHT:    /* resize at upper right corner */
-                deltaUsed.x = max(delta.x, -(RECT_WIDTH(rectSel_dest) - 1));
-                deltaUsed.y = min(delta.y, RECT_HEIGHT(rectSel_dest) - 1);
-                rectSel_dest.top   += deltaUsed.y;
-                rectSel_dest.right += deltaUsed.x;
-                break;
-            case ACTION_RESIZE_LEFT:         /* resize at left edge */
-                deltaUsed.x = min(delta.x, RECT_WIDTH(rectSel_dest) - 1);
-                deltaUsed.y = delta.y;
-                rectSel_dest.left += deltaUsed.x;
-                break;
-            case ACTION_RESIZE_RIGHT:        /* resize at right edge */
-                deltaUsed.x = max(delta.x, -(RECT_WIDTH(rectSel_dest) - 1));
-                deltaUsed.y = delta.y;
-                rectSel_dest.right += deltaUsed.x;
-                break;
-            case ACTION_RESIZE_BOTTOM_LEFT:  /* resize at lower left corner */
-                deltaUsed.x = min(delta.x, RECT_WIDTH(rectSel_dest) - 1);
-                deltaUsed.y = max(delta.y, -(RECT_HEIGHT(rectSel_dest) - 1));
-                rectSel_dest.left   += deltaUsed.x;
-                rectSel_dest.bottom += deltaUsed.y;
-                break;
-            case ACTION_RESIZE_BOTTOM:       /* resize at bottom edge */
-                deltaUsed.x = delta.x;
-                deltaUsed.y = max(delta.y, -(RECT_HEIGHT(rectSel_dest) - 1));
-                rectSel_dest.bottom += deltaUsed.y;
-                break;
-            case ACTION_RESIZE_BOTTOM_RIGHT: /* resize at lower right corner */
-                deltaUsed.x = max(delta.x, -(RECT_WIDTH(rectSel_dest) - 1));
-                deltaUsed.y = max(delta.y, -(RECT_HEIGHT(rectSel_dest) - 1));
-                rectSel_dest.right  += deltaUsed.x;
-                rectSel_dest.bottom += deltaUsed.y;
-                break;
+            m_ptFrac.x -= (m_ptFrac.x * 1000 / toolsModel.GetZoom()) * toolsModel.GetZoom() / 1000;
+            m_ptFrac.y -= (m_ptFrac.y * 1000 / toolsModel.GetZoom()) * toolsModel.GetZoom() / 1000;
         }
-        delta.x -= deltaUsed.x;
-        delta.y -= deltaUsed.y;
+        selectionModel.ModifyDestRect(m_ptDelta, m_iAction);
 
-        _stprintf(sizeStr, _T("%d x %d"), RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest));
+        _stprintf(sizeStr, _T("%d x %d"), selectionModel.GetDestRectWidth(), selectionModel.GetDestRectHeight());
         SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) sizeStr);
 
         if (toolsModel.GetActiveTool() == TOOL_TEXT)
         {
-            Text(hDrawingDC, rectSel_dest.left, rectSel_dest.top, rectSel_dest.right, rectSel_dest.bottom, paletteModel.GetFgColor(), paletteModel.GetBgColor(), textToolText, hfontTextFont, toolsModel.IsBackgroundTransparent());
+            selectionModel.DrawTextToolText(hDrawingDC, paletteModel.GetFgColor(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
         }
         else
         {
-            if (action != ACTION_MOVE)
-                StretchBlt(hDrawingDC, rectSel_dest.left, rectSel_dest.top, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC, 0, 0, GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY);
-            else
-            if (toolsModel.IsBackgroundTransparent() == 0)
-                MaskBlt(hDrawingDC, rectSel_dest.left, rectSel_dest.top, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest),
-                        hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
+            if (m_iAction != ACTION_MOVE)
+                selectionModel.DrawSelectionStretched(hDrawingDC);
             else
-            {
-                ColorKeyedMaskBlt(hDrawingDC, rectSel_dest.left, rectSel_dest.top, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest),
-                                  hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND), paletteModel.GetBgColor());
-            }
+                selectionModel.DrawSelection(hDrawingDC, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
         }
         imageArea.InvalidateRect(NULL, FALSE);
         imageArea.SendMessage(WM_PAINT, 0, 0);
-        pos.x = GET_X_LPARAM(lParam);
-        pos.y = GET_Y_LPARAM(lParam);
+        m_ptPos.x = GET_X_LPARAM(lParam);
+        m_ptPos.y = GET_Y_LPARAM(lParam);
     }
     else
     {
-        int w = RECT_WIDTH(rectSel_dest) * toolsModel.GetZoom() / 1000 + 6;
-        int h = RECT_HEIGHT(rectSel_dest) * toolsModel.GetZoom() / 1000 + 6;
-        pos.x = GET_X_LPARAM(lParam);
-        pos.y = GET_Y_LPARAM(lParam);
+        int w = selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 6;
+        int h = selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 6;
+        m_ptPos.x = GET_X_LPARAM(lParam);
+        m_ptPos.y = GET_Y_LPARAM(lParam);
         SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) NULL);
-        action = identifyCorner(pos.x, pos.y, w, h);
-        if (action != ACTION_MOVE)
-            SetCursor(LoadCursor(NULL, cursors[action]));
+        m_iAction = IdentifyCorner(m_ptPos.x, m_ptPos.y, w, h);
+        if (m_iAction != ACTION_MOVE)
+            SetCursor(LoadCursor(NULL, m_lpszCursorLUT[m_iAction]));
     }
     return 0;
 }
 
 LRESULT CSelectionWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    if (moving)
+    if (m_bMoving)
     {
-        moving = FALSE;
+        m_bMoving = FALSE;
         ReleaseCapture();
-        if (action != ACTION_MOVE)
+        if (m_iAction != ACTION_MOVE)
         {
             if (toolsModel.GetActiveTool() == TOOL_TEXT)
             {
@@ -299,25 +220,7 @@ LRESULT CSelectionWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, B
             }
             else
             {
-                HDC hTempDC;
-                HBITMAP hTempBm;
-                hTempDC = CreateCompatibleDC(hSelDC);
-                hTempBm = CreateDIBWithProperties(RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest));
-                SelectObject(hTempDC, hTempBm);
-                SelectObject(hSelDC, hSelBm);
-                StretchBlt(hTempDC, 0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC, 0, 0,
-                           GetDIBWidth(hSelBm), GetDIBHeight(hSelBm), SRCCOPY);
-                DeleteObject(hSelBm);
-                hSelBm = hTempBm;
-                hTempBm = CreateBitmap(RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), 1, 1, NULL);
-                SelectObject(hTempDC, hTempBm);
-                SelectObject(hSelDC, hSelMask);
-                StretchBlt(hTempDC, 0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC, 0, 0,
-                           GetDIBWidth(hSelMask), GetDIBHeight(hSelMask), SRCCOPY);
-                DeleteObject(hSelMask);
-                hSelMask = hTempBm;
-                SelectObject(hSelDC, hSelBm);
-                DeleteDC(hTempDC);
+                selectionModel.ScaleContentsToFit();
             }
         }
         placeSelWin();
index 916a20a..bf42c0c 100644 (file)
@@ -30,6 +30,17 @@ public:
     LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+private:
+    static const LPCTSTR m_lpszCursorLUT[9];
+    BOOL m_bMoving;
+    int m_iAction;
+    POINT m_ptPos;
+    POINT m_ptFrac;
+    POINT m_ptDelta;
+    DWORD m_dwSystemSelectionColor;
+
+    int IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight);
 };
 
 void ForceRefreshSelectionContents();
diff --git a/reactos/base/applications/mspaint_new/selectionmodel.cpp b/reactos/base/applications/mspaint_new/selectionmodel.cpp
new file mode 100644 (file)
index 0000000..4ed7b07
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * PROJECT:     PAINT for ReactOS
+ * LICENSE:     LGPL
+ * FILE:        base/applications/mspaint_new/selectionmodel.cpp
+ * PURPOSE:     Keep track of selection parameters, notify listeners
+ * PROGRAMMERS: Benedikt Freisen
+ */
+
+/* INCLUDES *********************************************************/
+
+#include "precomp.h"
+
+/* FUNCTIONS ********************************************************/
+
+SelectionModel::SelectionModel()
+{
+    m_ptStack = NULL;
+    m_iPtSP = 0;
+}
+
+void SelectionModel::SetDC(HDC hDC)
+{
+    m_hDC = hDC;
+}
+
+void SelectionModel::ResetPtStack()
+{
+    if (m_ptStack != NULL)
+        HeapFree(GetProcessHeap(), 0, m_ptStack);
+    m_ptStack = NULL;
+    m_iPtSP = 0;
+}
+
+void SelectionModel::PushToPtStack(LONG x, LONG y)
+{
+    if (m_iPtSP % 1024 == 0)
+    {
+        if (m_ptStack)
+            m_ptStack = (POINT*) HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, m_ptStack, sizeof(POINT) * (m_iPtSP + 1024));
+        else
+            m_ptStack = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
+    }
+    m_ptStack[m_iPtSP].x = x;
+    m_ptStack[m_iPtSP].y = y;
+    m_iPtSP++;
+}
+
+void SelectionModel::CalculateBoundingBoxAndContents(HDC hDCImage)
+{
+    int i;
+    m_rcSrc.left = m_rcSrc.top = MAXLONG;
+    m_rcSrc.right = m_rcSrc.bottom = 0;
+    for (i = 0; i < m_iPtSP; i++)
+    {
+        if (m_ptStack[i].x < m_rcSrc.left)
+            m_rcSrc.left = m_ptStack[i].x;
+        if (m_ptStack[i].y < m_rcSrc.top)
+            m_rcSrc.top = m_ptStack[i].y;
+        if (m_ptStack[i].x > m_rcSrc.right)
+            m_rcSrc.right = m_ptStack[i].x;
+        if (m_ptStack[i].y > m_rcSrc.bottom)
+            m_rcSrc.bottom = m_ptStack[i].y;
+    }
+    m_rcSrc.right  += 1;
+    m_rcSrc.bottom += 1;
+    m_rcDest.left   = m_rcSrc.left;
+    m_rcDest.top    = m_rcSrc.top;
+    m_rcDest.right  = m_rcSrc.right;
+    m_rcDest.bottom = m_rcSrc.bottom;
+
+    if (m_iPtSP > 1)
+    {
+        DeleteObject(m_hMask);
+        m_hMask = CreateBitmap(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 1, 1, NULL);
+        DeleteObject(SelectObject(m_hDC, m_hMask));
+        POINT *m_ptStackCopy = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * m_iPtSP);
+        for (i = 0; i < m_iPtSP; i++)
+        {
+            m_ptStackCopy[i].x = m_ptStack[i].x - m_rcSrc.left;
+            m_ptStackCopy[i].y = m_ptStack[i].y - m_rcSrc.top;
+        }
+        Poly(m_hDC, m_ptStackCopy, m_iPtSP, 0x00ffffff, 0x00ffffff, 1, 2, TRUE, FALSE);
+        HeapFree(GetProcessHeap(), 0, m_ptStackCopy);
+        SelectObject(m_hDC, m_hBm = CreateDIBWithProperties(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc)));
+        imageModel.ResetToPrevious();
+        MaskBlt(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), hDCImage, m_rcSrc.left,
+                m_rcSrc.top, m_hMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
+    }
+}
+
+void SelectionModel::CalculateContents(HDC hDCImage)
+{
+    DeleteObject(m_hMask);
+    m_hMask = CreateBitmap(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 1, 1, NULL);
+    DeleteObject(SelectObject(m_hDC, m_hMask));
+    Rect(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 0x00ffffff, 0x00ffffff, 1, 2);
+    SelectObject(m_hDC, m_hBm = CreateDIBWithProperties(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc)));
+    BitBlt(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), hDCImage, m_rcSrc.left,
+           m_rcSrc.top, SRCCOPY);
+}
+
+void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
+{
+    Poly(hDCImage, m_ptStack, m_iPtSP, crBg, crBg, 1, 2, TRUE, FALSE);
+}
+
+void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
+{
+    Rect(hDCImage, m_rcSrc.left, m_rcSrc.top, m_rcSrc.right, m_rcSrc.bottom, crBg, crBg, 0, TRUE);
+}
+
+extern BOOL
+ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask, DWORD dwRop, COLORREF keyColor);
+
+void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
+{
+    MaskBlt(hDCImage, m_rcSrc.left, m_rcSrc.top, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), m_hDC, 0,
+            0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
+    if (!bBgTransparent)
+        MaskBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest),
+                m_hDC, 0, 0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
+    else
+        ColorKeyedMaskBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest),
+                          m_hDC, 0, 0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND), crBg);
+}
+
+void SelectionModel::DrawSelectionStretched(HDC hDCImage)
+{
+    StretchBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0, GetDIBWidth(m_hBm), GetDIBHeight(m_hBm), SRCCOPY);
+}
+
+void SelectionModel::ScaleContentsToFit()
+{
+    HDC hTempDC;
+    HBITMAP hTempBm;
+    hTempDC = CreateCompatibleDC(m_hDC);
+    hTempBm = CreateDIBWithProperties(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest));
+    SelectObject(hTempDC, hTempBm);
+    SelectObject(m_hDC, m_hBm);
+    StretchBlt(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0,
+               GetDIBWidth(m_hBm), GetDIBHeight(m_hBm), SRCCOPY);
+    DeleteObject(m_hBm);
+    m_hBm = hTempBm;
+    hTempBm = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
+    SelectObject(hTempDC, hTempBm);
+    SelectObject(m_hDC, m_hMask);
+    StretchBlt(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0,
+               GetDIBWidth(m_hMask), GetDIBHeight(m_hMask), SRCCOPY);
+    DeleteObject(m_hMask);
+    m_hMask = hTempBm;
+    SelectObject(m_hDC, m_hBm);
+    DeleteDC(hTempDC);
+}
+
+void SelectionModel::InsertFromHBITMAP(HBITMAP hBm)
+{
+    HDC hTempDC;
+    HBITMAP hTempMask;
+
+    DeleteObject(SelectObject(m_hDC, m_hBm = (HBITMAP) CopyImage(hBm,
+                                                                 IMAGE_BITMAP, 0, 0,
+                                                                 LR_COPYRETURNORG)));
+
+    SetRectEmpty(&m_rcSrc);
+    m_rcDest.left = m_rcDest.top = 0;
+    m_rcDest.right = m_rcDest.left + GetDIBWidth(m_hBm);
+    m_rcDest.bottom = m_rcDest.top + GetDIBHeight(m_hBm);
+
+    hTempDC = CreateCompatibleDC(m_hDC);
+    hTempMask = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
+    SelectObject(hTempDC, hTempMask);
+    Rect(hTempDC, m_rcDest.left, m_rcDest.top, m_rcDest.right, m_rcDest.bottom, 0x00ffffff, 0x00ffffff, 1, 1);
+    DeleteObject(m_hMask);
+    m_hMask = hTempMask;
+    DeleteDC(hTempDC);
+}
+
+void SelectionModel::FlipHorizontally()
+{
+    SelectObject(m_hDC, m_hMask);
+    StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, 0, -RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC,
+               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+    SelectObject(m_hDC, m_hBm);
+    StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, 0, -RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC,
+               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+}
+
+void SelectionModel::FlipVertically()
+{
+    SelectObject(m_hDC, m_hMask);
+    StretchBlt(m_hDC, 0, RECT_HEIGHT(m_rcDest) - 1, RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
+               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+    SelectObject(m_hDC, m_hBm);
+    StretchBlt(m_hDC, 0, RECT_HEIGHT(m_rcDest) - 1, RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
+               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+}
+
+void SelectionModel::RotateNTimes90Degrees(int iN)
+{
+    if (iN == 2)
+    {
+        SelectObject(m_hDC, m_hMask);
+        StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
+                   0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+        SelectObject(m_hDC, m_hBm);
+        StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
+                   0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+    }
+}
+
+HBITMAP SelectionModel::GetBitmap()
+{
+    return m_hBm;
+}
+
+int SelectionModel::PtStackSize()
+{
+    return m_iPtSP;
+}
+
+void SelectionModel::DrawFramePoly(HDC hDCImage)
+{
+    Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE); /* draw the freehand selection inverted/xored */
+}
+
+void SelectionModel::SetSrcAndDestRectFromPoints(POINT& ptFrom, POINT& ptTo)
+{
+    m_rcDest.left = m_rcSrc.left = min(ptFrom.x, ptTo.x);
+    m_rcDest.top = m_rcSrc.top = min(ptFrom.y, ptTo.y);
+    m_rcDest.right = m_rcSrc.right = max(ptFrom.x, ptTo.x);
+    m_rcDest.bottom = m_rcSrc.bottom = max(ptFrom.y, ptTo.y);
+}
+
+void SelectionModel::SetSrcRectSizeToZero()
+{
+    m_rcSrc.right = m_rcSrc.left;
+    m_rcSrc.bottom = m_rcSrc.top;
+}
+
+BOOL SelectionModel::IsSrcRectSizeNonzero()
+{
+    return (RECT_WIDTH(m_rcSrc) != 0) && (RECT_HEIGHT(m_rcSrc) != 0);
+}
+
+void SelectionModel::ModifyDestRect(POINT& ptDelta, int iAction)
+{
+    POINT ptDeltaUsed;
+
+    switch (iAction)
+    {
+        case ACTION_MOVE:                /* move selection */
+            ptDeltaUsed.x = ptDelta.x;
+            ptDeltaUsed.y = ptDelta.y;
+            OffsetRect(&m_rcDest, ptDeltaUsed.x, ptDeltaUsed.y);
+            break;
+        case ACTION_RESIZE_TOP_LEFT:     /* resize at upper left corner */
+            ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
+            ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
+            m_rcDest.left += ptDeltaUsed.x;
+            m_rcDest.top  += ptDeltaUsed.y;
+            break;
+        case ACTION_RESIZE_TOP:          /* resize at top edge */
+            ptDeltaUsed.x = ptDelta.x;
+            ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
+            m_rcDest.top += ptDeltaUsed.y;
+            break;
+        case ACTION_RESIZE_TOP_RIGHT:    /* resize at upper right corner */
+            ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
+            ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
+            m_rcDest.top   += ptDeltaUsed.y;
+            m_rcDest.right += ptDeltaUsed.x;
+            break;
+        case ACTION_RESIZE_LEFT:         /* resize at left edge */
+            ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
+            ptDeltaUsed.y = ptDelta.y;
+            m_rcDest.left += ptDeltaUsed.x;
+            break;
+        case ACTION_RESIZE_RIGHT:        /* resize at right edge */
+            ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
+            ptDeltaUsed.y = ptDelta.y;
+            m_rcDest.right += ptDeltaUsed.x;
+            break;
+        case ACTION_RESIZE_BOTTOM_LEFT:  /* resize at lower left corner */
+            ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
+            ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
+            m_rcDest.left   += ptDeltaUsed.x;
+            m_rcDest.bottom += ptDeltaUsed.y;
+            break;
+        case ACTION_RESIZE_BOTTOM:       /* resize at bottom edge */
+            ptDeltaUsed.x = ptDelta.x;
+            ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
+            m_rcDest.bottom += ptDeltaUsed.y;
+            break;
+        case ACTION_RESIZE_BOTTOM_RIGHT: /* resize at lower right corner */
+            ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
+            ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
+            m_rcDest.right  += ptDeltaUsed.x;
+            m_rcDest.bottom += ptDeltaUsed.y;
+            break;
+    }
+    ptDelta.x -= ptDeltaUsed.x;
+    ptDelta.y -= ptDeltaUsed.y;
+}
+
+LONG SelectionModel::GetDestRectWidth()
+{
+    return m_rcDest.right - m_rcDest.left;
+}
+
+LONG SelectionModel::GetDestRectHeight()
+{
+    return m_rcDest.bottom - m_rcDest.top;
+}
+
+LONG SelectionModel::GetDestRectLeft()
+{
+    return m_rcDest.left;
+}
+
+LONG SelectionModel::GetDestRectTop()
+{
+    return m_rcDest.top;
+}
+
+void SelectionModel::DrawTextToolText(HDC hDCImage, COLORREF crFg, COLORREF crBg, BOOL bBgTransparent)
+{
+    Text(hDCImage, m_rcDest.left, m_rcDest.top, m_rcDest.right, m_rcDest.bottom, crFg, crBg, textToolText, hfontTextFont, bBgTransparent);
+}
diff --git a/reactos/base/applications/mspaint_new/selectionmodel.h b/reactos/base/applications/mspaint_new/selectionmodel.h
new file mode 100644 (file)
index 0000000..a3de6dc
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * PROJECT:     PAINT for ReactOS
+ * LICENSE:     LGPL
+ * FILE:        base/applications/mspaint_new/selectionmodel.h
+ * PURPOSE:     Keep track of selection parameters, notify listeners
+ * PROGRAMMERS: Benedikt Freisen
+ */
+
+/* DEFINES **********************************************************/
+
+#define ACTION_MOVE                 0
+#define ACTION_RESIZE_TOP_LEFT      1
+#define ACTION_RESIZE_TOP           2
+#define ACTION_RESIZE_TOP_RIGHT     3
+#define ACTION_RESIZE_LEFT          4
+#define ACTION_RESIZE_RIGHT         5
+#define ACTION_RESIZE_BOTTOM_LEFT   6
+#define ACTION_RESIZE_BOTTOM        7
+#define ACTION_RESIZE_BOTTOM_RIGHT  8
+
+/* CLASSES **********************************************************/
+
+class SelectionModel
+{
+private:
+    HDC m_hDC;
+    RECT m_rcSrc;
+    RECT m_rcDest;
+    HBITMAP m_hBm;
+    HBITMAP m_hMask;
+    POINT *m_ptStack;
+    int m_iPtSP;
+
+//     void NotifySelectionChanging();
+//     void NotifySelectionChanged();
+
+public:
+    SelectionModel();
+    void SetDC(HDC hDC);
+    void ResetPtStack();
+    void PushToPtStack(LONG x, LONG y);
+    void CalculateBoundingBoxAndContents(HDC hDCImage);
+    void CalculateContents(HDC hDCImage);
+    void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
+    void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
+    void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
+    void DrawSelectionStretched(HDC hDCImage);
+    void ScaleContentsToFit();
+    void InsertFromHBITMAP(HBITMAP hBm);
+    void FlipHorizontally();
+    void FlipVertically();
+    void RotateNTimes90Degrees(int iN);
+    HBITMAP GetBitmap();
+    int PtStackSize();
+    void DrawFramePoly(HDC hDCImage);
+    void SetSrcAndDestRectFromPoints(POINT& ptFrom, POINT& ptTo);
+    void SetSrcRectSizeToZero();
+    BOOL IsSrcRectSizeNonzero();
+    void ModifyDestRect(POINT& ptDelta, int iAction);
+    LONG GetDestRectWidth();
+    LONG GetDestRectHeight();
+    LONG GetDestRectLeft();
+    LONG GetDestRectTop();
+    void DrawTextToolText(HDC hDCImage, COLORREF crFg, COLORREF crBg, BOOL bBgTransparent = FALSE);
+};
index 109296d..6757174 100644 (file)
@@ -107,29 +107,12 @@ void CMainWindow::UpdateApplicationProperties(HBITMAP bitmap, LPTSTR newfilename
 
 void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
 {
-    HDC hTempDC;
-    HBITMAP hTempMask;
-
     HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, TOOLBARCLASSNAME, NULL);
     SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 0));
     toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
 
-    DeleteObject(SelectObject(hSelDC, hSelBm = (HBITMAP) CopyImage(bitmap,
-                                                                   IMAGE_BITMAP, 0, 0,
-                                                                   LR_COPYRETURNORG)));
     imageModel.CopyPrevious();
-    SetRectEmpty(&rectSel_src);
-    rectSel_dest.left = rectSel_dest.top = 0;
-    rectSel_dest.right = rectSel_dest.left + GetDIBWidth(hSelBm);
-    rectSel_dest.bottom = rectSel_dest.top + GetDIBHeight(hSelBm);
-
-    hTempDC = CreateCompatibleDC(hSelDC);
-    hTempMask = CreateBitmap(RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), 1, 1, NULL);
-    SelectObject(hTempDC, hTempMask);
-    Rect(hTempDC, rectSel_dest.left, rectSel_dest.top, rectSel_dest.right, rectSel_dest.bottom, 0x00ffffff, 0x00ffffff, 1, 1);
-    DeleteObject(hSelMask);
-    hSelMask = hTempMask;
-    DeleteDC(hTempDC);
+    selectionModel.InsertFromHBITMAP(bitmap);
 
     placeSelWin();
     selectionWindow.ShowWindow(SW_SHOW);
@@ -159,8 +142,6 @@ LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa
 {
     SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
     SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
-    ptStack = NULL;
-    ptSP = 0;
     return 0;
 }
 
@@ -392,7 +373,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         case IDM_EDITCOPY:
             OpenClipboard();
             EmptyClipboard();
-            SetClipboardData(CF_BITMAP, CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
+            SetClipboardData(CF_BITMAP, CopyImage(selectionModel.GetBitmap(), IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
             CloseClipboard();
             break;
         case IDM_EDITCUT:
@@ -411,20 +392,8 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             break;
         case IDM_EDITDELETESELECTION:
         {
-            /* remove selection window and already painted content using undo(),
-            paint Rect for rectangular selections and Poly for freeform selections */
+            /* remove selection window and already painted content using undo */
             imageModel.Undo();
-            if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
-            {
-                imageModel.CopyPrevious();
-                Rect(hDrawingDC, rectSel_dest.left, rectSel_dest.top, rectSel_dest.right,
-                     rectSel_dest.bottom, paletteModel.GetBgColor(), paletteModel.GetBgColor(), 0, TRUE);
-            }
-            if (toolsModel.GetActiveTool() == TOOL_FREESEL)
-            {
-                imageModel.CopyPrevious();
-                Poly(hDrawingDC, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE, TRUE);
-            }
             break;
         }
         case IDM_EDITSELECTALL:
@@ -440,7 +409,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         }
         case IDM_EDITCOPYTO:
             if (GetSaveFileName(&ofn) != 0)
-                SaveDIBToFile(hSelBm, ofn.lpstrFile, hDrawingDC, NULL, NULL, fileHPPM, fileVPPM);
+                SaveDIBToFile(selectionModel.GetBitmap(), ofn.lpstrFile, hDrawingDC, NULL, NULL, fileHPPM, fileVPPM);
             break;
         case IDM_EDITPASTEFROM:
             if (GetOpenFileName(&ofn) != 0)
@@ -480,12 +449,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                 case 1: /* flip horizontally */
                     if (selectionWindow.IsWindowVisible())
                     {
-                        SelectObject(hSelDC, hSelMask);
-                        StretchBlt(hSelDC, RECT_WIDTH(rectSel_dest) - 1, 0, -RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC,
-                                   0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), SRCCOPY);
-                        SelectObject(hSelDC, hSelBm);
-                        StretchBlt(hSelDC, RECT_WIDTH(rectSel_dest) - 1, 0, -RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), hSelDC,
-                                   0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), SRCCOPY);
+                        selectionModel.FlipHorizontally();
                         ForceRefreshSelectionContents();
                     }
                     else
@@ -499,12 +463,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                 case 2: /* flip vertically */
                     if (selectionWindow.IsWindowVisible())
                     {
-                        SelectObject(hSelDC, hSelMask);
-                        StretchBlt(hSelDC, 0, RECT_HEIGHT(rectSel_dest) - 1, RECT_WIDTH(rectSel_dest), -RECT_HEIGHT(rectSel_dest), hSelDC,
-                                   0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), SRCCOPY);
-                        SelectObject(hSelDC, hSelBm);
-                        StretchBlt(hSelDC, 0, RECT_HEIGHT(rectSel_dest) - 1, RECT_WIDTH(rectSel_dest), -RECT_HEIGHT(rectSel_dest), hSelDC,
-                                   0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), SRCCOPY);
+                        selectionModel.FlipVertically();
                         ForceRefreshSelectionContents();
                     }
                     else
@@ -520,12 +479,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                 case 4: /* rotate 180 degrees */
                     if (selectionWindow.IsWindowVisible())
                     {
-                        SelectObject(hSelDC, hSelMask);
-                        StretchBlt(hSelDC, RECT_WIDTH(rectSel_dest) - 1, RECT_HEIGHT(rectSel_dest) - 1, -RECT_WIDTH(rectSel_dest), -RECT_HEIGHT(rectSel_dest), hSelDC,
-                                   0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), SRCCOPY);
-                        SelectObject(hSelDC, hSelBm);
-                        StretchBlt(hSelDC, RECT_WIDTH(rectSel_dest) - 1, RECT_HEIGHT(rectSel_dest) - 1, -RECT_WIDTH(rectSel_dest), -RECT_HEIGHT(rectSel_dest), hSelDC,
-                                   0, 0, RECT_WIDTH(rectSel_dest), RECT_HEIGHT(rectSel_dest), SRCCOPY);
+                        selectionModel.RotateNTimes90Degrees(2);
                         ForceRefreshSelectionContents();
                     }
                     else
@@ -561,7 +515,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             toolsModel.SetBackgroundTransparent(!toolsModel.IsBackgroundTransparent());
             break;
         case IDM_IMAGECROP:
-            imageModel.Insert((HBITMAP) CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
+            imageModel.Insert((HBITMAP) CopyImage(selectionModel.GetBitmap(), IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
             break;
 
         case IDM_VIEWTOOLBOX: