[Paint] Initial support for free selections, resizing selections and experimental selection transparency

svn path=/trunk/; revision=45113
This commit is contained in:
Benedikt Freisen 2010-01-16 23:21:45 +00:00
parent d005d3aaa4
commit d84c76f347
5 changed files with 244 additions and 24 deletions

View 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];

View 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,

View 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);

View file

@ -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;
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 (transpBg == 0)
BitBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
hSelDC, 0, 0, SRCCOPY);
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
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);
{
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;
}
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)
MaskBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
hSelDC, 0, 0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
else
{
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);

View 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: