Merge trunk HEAD (r46369)
[reactos.git] / reactos / base / applications / paint / mouse.c
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/paint/mouse.c
5 * PURPOSE: Things which should not be in the mouse event handler itself
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include "globalvar.h"
12 #include "dib.h"
13 #include "drawing.h"
14 #include "history.h"
15
16 /* FUNCTIONS ********************************************************/
17
18 void
19 placeSelWin()
20 {
21 MoveWindow(hSelection, rectSel_dest[0] * zoom / 1000, rectSel_dest[1] * zoom / 1000,
22 rectSel_dest[2] * zoom / 1000 + 6, rectSel_dest[3] * zoom / 1000 + 6, TRUE);
23 BringWindowToTop(hSelection);
24 SendMessage(hImageArea, WM_PAINT, 0, 0);
25 //SendMessage(hSelection, WM_PAINT, 0, 0);
26 }
27
28 POINT pointStack[256];
29 short pointSP;
30 POINT *ptStack = NULL;
31 int ptSP = 0;
32
33 void
34 startPaintingL(HDC hdc, short x, short y, int fg, int bg)
35 {
36 startX = x;
37 startY = y;
38 lastX = x;
39 lastY = y;
40 switch (activeTool)
41 {
42 case 1:
43 ShowWindow(hSelection, SW_HIDE);
44 if (ptStack != NULL)
45 HeapFree(GetProcessHeap(), 0, ptStack);
46 ptStack = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
47 ptSP = 0;
48 ptStack[0].x = x;
49 ptStack[0].y = y;
50 break;
51 case 10:
52 case 11:
53 case 13:
54 case 15:
55 case 16:
56 newReversible();
57 break;
58 case 2:
59 newReversible();
60 ShowWindow(hSelection, SW_HIDE);
61 rectSel_src[2] = rectSel_src[3] = 0;
62 break;
63 case 3:
64 newReversible();
65 Erase(hdc, x, y, x, y, bg, rubberRadius);
66 break;
67 case 4:
68 newReversible();
69 Fill(hdc, x, y, fg);
70 break;
71 case 7:
72 newReversible();
73 SetPixel(hdc, x, y, fg);
74 break;
75 case 8:
76 newReversible();
77 Brush(hdc, x, y, x, y, fg, brushStyle);
78 break;
79 case 9:
80 newReversible();
81 Airbrush(hdc, x, y, fg, airBrushWidth);
82 break;
83 case 12:
84 pointStack[pointSP].x = x;
85 pointStack[pointSP].y = y;
86 if (pointSP == 0)
87 {
88 newReversible();
89 pointSP++;
90 }
91 break;
92 case 14:
93 pointStack[pointSP].x = x;
94 pointStack[pointSP].y = y;
95 if (pointSP + 1 >= 2)
96 Poly(hdc, pointStack, pointSP + 1, fg, bg, lineWidth, shapeStyle, FALSE);
97 if (pointSP == 0)
98 {
99 newReversible();
100 pointSP++;
101 }
102 break;
103 }
104 }
105
106 void
107 whilePaintingL(HDC hdc, short x, short y, int fg, int bg)
108 {
109 switch (activeTool)
110 {
111 case 1:
112 if (ptSP == 0)
113 newReversible();
114 ptSP++;
115 if (ptSP % 1024 == 0)
116 ptStack = HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, ptStack, sizeof(POINT) * (ptSP + 1024));
117 ptStack[ptSP].x = max(0, min(x, imgXRes));
118 ptStack[ptSP].y = max(0, min(y, imgYRes));
119 resetToU1();
120 Poly(hdc, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE);
121 break;
122 case 2:
123 {
124 short tempX;
125 short tempY;
126 resetToU1();
127 tempX = max(0, min(x, imgXRes));
128 tempY = max(0, min(y, imgYRes));
129 rectSel_dest[0] = rectSel_src[0] = min(startX, tempX);
130 rectSel_dest[1] = rectSel_src[1] = min(startY, tempY);
131 rectSel_dest[2] = rectSel_src[2] = max(startX, tempX) - min(startX, tempX);
132 rectSel_dest[3] = rectSel_src[3] = max(startY, tempY) - min(startY, tempY);
133 RectSel(hdc, startX, startY, tempX, tempY);
134 break;
135 }
136 case 3:
137 Erase(hdc, lastX, lastY, x, y, bg, rubberRadius);
138 break;
139 case 7:
140 Line(hdc, lastX, lastY, x, y, fg, 1);
141 break;
142 case 8:
143 Brush(hdc, lastX, lastY, x, y, fg, brushStyle);
144 break;
145 case 9:
146 Airbrush(hdc, x, y, fg, airBrushWidth);
147 break;
148 case 11:
149 resetToU1();
150 Line(hdc, startX, startY, x, y, fg, lineWidth);
151 break;
152 case 12:
153 resetToU1();
154 pointStack[pointSP].x = x;
155 pointStack[pointSP].y = y;
156 switch (pointSP)
157 {
158 case 1:
159 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, fg,
160 lineWidth);
161 break;
162 case 2:
163 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], fg, lineWidth);
164 break;
165 case 3:
166 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], fg, lineWidth);
167 break;
168 }
169 break;
170 case 13:
171 resetToU1();
172 Rect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
173 break;
174 case 14:
175 resetToU1();
176 pointStack[pointSP].x = x;
177 pointStack[pointSP].y = y;
178 if (pointSP + 1 >= 2)
179 Poly(hdc, pointStack, pointSP + 1, fg, bg, lineWidth, shapeStyle, FALSE);
180 break;
181 case 15:
182 resetToU1();
183 Ellp(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
184 break;
185 case 16:
186 resetToU1();
187 RRect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
188 break;
189 }
190
191 lastX = x;
192 lastY = y;
193 }
194
195 void
196 endPaintingL(HDC hdc, short x, short y, int fg, int bg)
197 {
198 switch (activeTool)
199 {
200 case 1:
201 {
202 POINT *ptStackCopy;
203 int i;
204 rectSel_src[0] = rectSel_src[1] = 0x7fffffff;
205 rectSel_src[2] = rectSel_src[3] = 0;
206 for (i = 0; i <= ptSP; i++)
207 {
208 if (ptStack[i].x < rectSel_src[0])
209 rectSel_src[0] = ptStack[i].x;
210 if (ptStack[i].y < rectSel_src[1])
211 rectSel_src[1] = ptStack[i].y;
212 if (ptStack[i].x > rectSel_src[2])
213 rectSel_src[2] = ptStack[i].x;
214 if (ptStack[i].y > rectSel_src[3])
215 rectSel_src[3] = ptStack[i].y;
216 }
217 rectSel_src[2] += 1 - rectSel_src[0];
218 rectSel_src[3] += 1 - rectSel_src[1];
219 rectSel_dest[0] = rectSel_src[0];
220 rectSel_dest[1] = rectSel_src[1];
221 rectSel_dest[2] = rectSel_src[2];
222 rectSel_dest[3] = rectSel_src[3];
223 if (ptSP != 0)
224 {
225 DeleteObject(hSelMask);
226 hSelMask = CreateBitmap(rectSel_src[2], rectSel_src[3], 1, 1, NULL);
227 DeleteObject(SelectObject(hSelDC, hSelMask));
228 ptStackCopy = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * (ptSP + 1));
229 for (i = 0; i <= ptSP; i++)
230 {
231 ptStackCopy[i].x = ptStack[i].x - rectSel_src[0];
232 ptStackCopy[i].y = ptStack[i].y - rectSel_src[1];
233 }
234 Poly(hSelDC, ptStackCopy, ptSP + 1, 0x00ffffff, 0x00ffffff, 1, 2, TRUE);
235 HeapFree(GetProcessHeap(), 0, ptStackCopy);
236 SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(rectSel_src[2], rectSel_src[3]));
237 resetToU1();
238 MaskBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0],
239 rectSel_src[1], hSelMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
240 Poly(hdc, ptStack, ptSP + 1, bg, bg, 1, 2, TRUE);
241 newReversible();
242
243 placeSelWin();
244 ShowWindow(hSelection, SW_SHOW);
245 }
246 HeapFree(GetProcessHeap(), 0, ptStack);
247 ptStack = NULL;
248 break;
249 }
250 case 2:
251 resetToU1();
252 if ((rectSel_src[2] != 0) && (rectSel_src[3] != 0))
253 {
254 DeleteObject(SelectObject
255 (hSelDC, hSelBm =
256 (HBITMAP) CreateDIBWithProperties(rectSel_src[2], rectSel_src[3])));
257 DeleteObject(hSelMask);
258 BitBlt(hSelDC, 0, 0, rectSel_src[2], rectSel_src[3], hDrawingDC, rectSel_src[0],
259 rectSel_src[1], SRCCOPY);
260 Rect(hdc, rectSel_src[0], rectSel_src[1], rectSel_src[0] + rectSel_src[2],
261 rectSel_src[1] + rectSel_src[3], bgColor, bgColor, 0, TRUE);
262 newReversible();
263 placeSelWin();
264 ShowWindow(hSelection, SW_SHOW);
265 }
266 break;
267 case 3:
268 Erase(hdc, lastX, lastY, x, y, bg, rubberRadius);
269 break;
270 case 7:
271 Line(hdc, lastX, lastY, x, y, fg, 1);
272 SetPixel(hdc, x, y, fg);
273 break;
274 case 11:
275 resetToU1();
276 Line(hdc, startX, startY, x, y, fg, lineWidth);
277 break;
278 case 12:
279 pointSP++;
280 if (pointSP == 4)
281 pointSP = 0;
282 break;
283 case 13:
284 resetToU1();
285 Rect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
286 break;
287 case 14:
288 resetToU1();
289 pointStack[pointSP].x = x;
290 pointStack[pointSP].y = y;
291 pointSP++;
292 if (pointSP >= 2)
293 {
294 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
295 (pointStack[0].y - y) * (pointStack[0].y - y) <= lineWidth * lineWidth + 1)
296 {
297 Poly(hdc, pointStack, pointSP, fg, bg, lineWidth, shapeStyle, TRUE);
298 pointSP = 0;
299 }
300 else
301 {
302 Poly(hdc, pointStack, pointSP, fg, bg, lineWidth, shapeStyle, FALSE);
303 }
304 }
305 if (pointSP == 255)
306 pointSP--;
307 break;
308 case 15:
309 resetToU1();
310 Ellp(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
311 break;
312 case 16:
313 resetToU1();
314 RRect(hdc, startX, startY, x, y, fg, bg, lineWidth, shapeStyle);
315 break;
316 }
317 }
318
319 void
320 startPaintingR(HDC hdc, short x, short y, int fg, int bg)
321 {
322 startX = x;
323 startY = y;
324 lastX = x;
325 lastY = y;
326 switch (activeTool)
327 {
328 case 1:
329 case 10:
330 case 11:
331 case 13:
332 case 15:
333 case 16:
334 newReversible();
335 break;
336 case 3:
337 newReversible();
338 Replace(hdc, x, y, x, y, fg, bg, rubberRadius);
339 break;
340 case 4:
341 newReversible();
342 Fill(hdc, x, y, bg);
343 break;
344 case 7:
345 newReversible();
346 SetPixel(hdc, x, y, bg);
347 break;
348 case 8:
349 newReversible();
350 Brush(hdc, x, y, x, y, bg, brushStyle);
351 break;
352 case 9:
353 newReversible();
354 Airbrush(hdc, x, y, bg, airBrushWidth);
355 break;
356 case 12:
357 pointStack[pointSP].x = x;
358 pointStack[pointSP].y = y;
359 if (pointSP == 0)
360 {
361 newReversible();
362 pointSP++;
363 }
364 break;
365 case 14:
366 pointStack[pointSP].x = x;
367 pointStack[pointSP].y = y;
368 if (pointSP + 1 >= 2)
369 Poly(hdc, pointStack, pointSP + 1, bg, fg, lineWidth, shapeStyle, FALSE);
370 if (pointSP == 0)
371 {
372 newReversible();
373 pointSP++;
374 }
375 break;
376 }
377 }
378
379 void
380 whilePaintingR(HDC hdc, short x, short y, int fg, int bg)
381 {
382 switch (activeTool)
383 {
384 case 3:
385 Replace(hdc, lastX, lastY, x, y, fg, bg, rubberRadius);
386 break;
387 case 7:
388 Line(hdc, lastX, lastY, x, y, bg, 1);
389 break;
390 case 8:
391 Brush(hdc, lastX, lastY, x, y, bg, brushStyle);
392 break;
393 case 9:
394 Airbrush(hdc, x, y, bg, airBrushWidth);
395 break;
396 case 11:
397 resetToU1();
398 Line(hdc, startX, startY, x, y, bg, lineWidth);
399 break;
400 case 12:
401 resetToU1();
402 pointStack[pointSP].x = x;
403 pointStack[pointSP].y = y;
404 switch (pointSP)
405 {
406 case 1:
407 Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, bg,
408 lineWidth);
409 break;
410 case 2:
411 Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], bg, lineWidth);
412 break;
413 case 3:
414 Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], bg, lineWidth);
415 break;
416 }
417 break;
418 case 13:
419 resetToU1();
420 Rect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
421 break;
422 case 14:
423 resetToU1();
424 pointStack[pointSP].x = x;
425 pointStack[pointSP].y = y;
426 if (pointSP + 1 >= 2)
427 Poly(hdc, pointStack, pointSP + 1, bg, fg, lineWidth, shapeStyle, FALSE);
428 break;
429 case 15:
430 resetToU1();
431 Ellp(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
432 break;
433 case 16:
434 resetToU1();
435 RRect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
436 break;
437 }
438
439 lastX = x;
440 lastY = y;
441 }
442
443 void
444 endPaintingR(HDC hdc, short x, short y, int fg, int bg)
445 {
446 switch (activeTool)
447 {
448 case 3:
449 Replace(hdc, lastX, lastY, x, y, fg, bg, rubberRadius);
450 break;
451 case 7:
452 Line(hdc, lastX, lastY, x, y, bg, 1);
453 SetPixel(hdc, x, y, bg);
454 break;
455 case 11:
456 resetToU1();
457 Line(hdc, startX, startY, x, y, bg, lineWidth);
458 break;
459 case 12:
460 pointSP++;
461 if (pointSP == 4)
462 pointSP = 0;
463 break;
464 case 13:
465 resetToU1();
466 Rect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
467 break;
468 case 14:
469 resetToU1();
470 pointStack[pointSP].x = x;
471 pointStack[pointSP].y = y;
472 pointSP++;
473 if (pointSP >= 2)
474 {
475 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
476 (pointStack[0].y - y) * (pointStack[0].y - y) <= lineWidth * lineWidth + 1)
477 {
478 Poly(hdc, pointStack, pointSP, bg, fg, lineWidth, shapeStyle, TRUE);
479 pointSP = 0;
480 }
481 else
482 {
483 Poly(hdc, pointStack, pointSP, bg, fg, lineWidth, shapeStyle, FALSE);
484 }
485 }
486 if (pointSP == 255)
487 pointSP--;
488 break;
489 case 15:
490 resetToU1();
491 Ellp(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
492 break;
493 case 16:
494 resetToU1();
495 RRect(hdc, startX, startY, x, y, bg, fg, lineWidth, shapeStyle);
496 break;
497 }
498 }