From d84c76f347f6175bf290166aba37461bb1aa366f Mon Sep 17 00:00:00 2001 From: Benedikt Freisen Date: Sat, 16 Jan 2010 23:21:45 +0000 Subject: [PATCH] [Paint] Initial support for free selections, resizing selections and experimental selection transparency svn path=/trunk/; revision=45113 --- reactos/base/applications/paint/globalvar.h | 1 + reactos/base/applications/paint/main.c | 1 + reactos/base/applications/paint/mouse.c | 78 ++++++++++ reactos/base/applications/paint/selection.c | 163 ++++++++++++++++++-- reactos/base/applications/paint/winproc.c | 21 ++- 5 files changed, 242 insertions(+), 22 deletions(-) diff --git a/reactos/base/applications/paint/globalvar.h b/reactos/base/applications/paint/globalvar.h index 821e814be27..ed73d4113de 100644 --- a/reactos/base/applications/paint/globalvar.h +++ b/reactos/base/applications/paint/globalvar.h @@ -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]; diff --git a/reactos/base/applications/paint/main.c b/reactos/base/applications/paint/main.c index c83554a80ed..98565f4b36c 100644 --- a/reactos/base/applications/paint/main.c +++ b/reactos/base/applications/paint/main.c @@ -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, diff --git a/reactos/base/applications/paint/mouse.c b/reactos/base/applications/paint/mouse.c index 87cee6c027a..383d5d9016e 100644 --- a/reactos/base/applications/paint/mouse.c +++ b/reactos/base/applications/paint/mouse.c @@ -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); diff --git a/reactos/base/applications/paint/selection.c b/reactos/base/applications/paint/selection.c index f08b3b112f9..5028f9e66cf 100644 --- a/reactos/base/applications/paint/selection.c +++ b/reactos/base/applications/paint/selection.c @@ -13,12 +13,51 @@ #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); diff --git a/reactos/base/applications/paint/winproc.c b/reactos/base/applications/paint/winproc.c index 9d269d3f046..464b62c9842 100644 --- a/reactos/base/applications/paint/winproc.c +++ b/reactos/base/applications/paint/winproc.c @@ -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: -- 2.17.1