xref: /reactos/base/applications/mspaint/mouse.cpp (revision 845faec4)
1 /*
2  * PROJECT:     PAINT for ReactOS
3  * LICENSE:     LGPL
4  * FILE:        base/applications/mspaint/mouse.cpp
5  * PURPOSE:     Things which should not be in the mouse event handler itself
6  * PROGRAMMERS: Benedikt Freisen
7  */
8 
9 /* INCLUDES *********************************************************/
10 
11 #include "precomp.h"
12 
13 /* FUNCTIONS ********************************************************/
14 
15 void
16 placeSelWin()
17 {
18     selectionWindow.MoveWindow(selectionModel.GetDestRectLeft() * toolsModel.GetZoom() / 1000, selectionModel.GetDestRectTop() * toolsModel.GetZoom() / 1000,
19         selectionModel.GetDestRectWidth() * toolsModel.GetZoom() / 1000 + 6, selectionModel.GetDestRectHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
20     selectionWindow.BringWindowToTop();
21     imageArea.InvalidateRect(NULL, FALSE);
22 }
23 
24 void
25 regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
26 {
27     if (abs(x1 - x0) >= abs(y1 - y0))
28         y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
29     else
30         x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
31 }
32 
33 void
34 roundTo8Directions(LONG x0, LONG y0, LONG& x1, LONG& y1)
35 {
36     if (abs(x1 - x0) >= abs(y1 - y0))
37     {
38         if (abs(y1 - y0) * 5 < abs(x1 - x0) * 2)
39             y1 = y0;
40         else
41             y1 = y0 + (y1 > y0 ? abs(x1 - x0) : -abs(x1 - x0));
42     }
43     else
44     {
45         if (abs(x1 - x0) * 5 < abs(y1 - y0) * 2)
46             x1 = x0;
47         else
48             x1 = x0 + (x1 > x0 ? abs(y1 - y0) : -abs(y1 - y0));
49     }
50 }
51 
52 POINT pointStack[256];
53 short pointSP;
54 
55 void
56 startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
57 {
58     start.x = x;
59     start.y = y;
60     last.x = x;
61     last.y = y;
62     switch (toolsModel.GetActiveTool())
63     {
64         case TOOL_FREESEL:
65             selectionWindow.ShowWindow(SW_HIDE);
66             selectionModel.ResetPtStack();
67             selectionModel.PushToPtStack(x, y);
68             break;
69         case TOOL_LINE:
70         case TOOL_RECT:
71         case TOOL_ELLIPSE:
72         case TOOL_RRECT:
73             imageModel.CopyPrevious();
74             break;
75         case TOOL_RECTSEL:
76         case TOOL_TEXT:
77             imageModel.CopyPrevious();
78             selectionWindow.ShowWindow(SW_HIDE);
79             selectionModel.SetSrcRectSizeToZero();
80             break;
81         case TOOL_RUBBER:
82             imageModel.CopyPrevious();
83             Erase(hdc, x, y, x, y, bg, toolsModel.GetRubberRadius());
84             break;
85         case TOOL_FILL:
86             imageModel.CopyPrevious();
87             Fill(hdc, x, y, fg);
88             break;
89         case TOOL_PEN:
90             imageModel.CopyPrevious();
91             SetPixel(hdc, x, y, fg);
92             break;
93         case TOOL_BRUSH:
94             imageModel.CopyPrevious();
95             Brush(hdc, x, y, x, y, fg, toolsModel.GetBrushStyle());
96             break;
97         case TOOL_AIRBRUSH:
98             imageModel.CopyPrevious();
99             Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth());
100             break;
101         case TOOL_BEZIER:
102             pointStack[pointSP].x = x;
103             pointStack[pointSP].y = y;
104             if (pointSP == 0)
105             {
106                 imageModel.CopyPrevious();
107                 pointSP++;
108             }
109             break;
110         case TOOL_SHAPE:
111             pointStack[pointSP].x = x;
112             pointStack[pointSP].y = y;
113             if (pointSP + 1 >= 2)
114                 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
115             if (pointSP == 0)
116             {
117                 imageModel.CopyPrevious();
118                 pointSP++;
119             }
120             break;
121     }
122 }
123 
124 void
125 whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
126 {
127     switch (toolsModel.GetActiveTool())
128     {
129         case TOOL_FREESEL:
130             if (selectionModel.PtStackSize() == 1)
131                 imageModel.CopyPrevious();
132             selectionModel.PushToPtStack(max(0, min(x, imageModel.GetWidth())), max(0, min(y, imageModel.GetHeight())));
133             imageModel.ResetToPrevious();
134             selectionModel.DrawFramePoly(hdc);
135             break;
136         case TOOL_RECTSEL:
137         case TOOL_TEXT:
138         {
139             POINT temp;
140             imageModel.ResetToPrevious();
141             temp.x = max(0, min(x, imageModel.GetWidth()));
142             temp.y = max(0, min(y, imageModel.GetHeight()));
143             selectionModel.SetSrcAndDestRectFromPoints(start, temp);
144             RectSel(hdc, start.x, start.y, temp.x, temp.y);
145             break;
146         }
147         case TOOL_RUBBER:
148             Erase(hdc, last.x, last.y, x, y, bg, toolsModel.GetRubberRadius());
149             break;
150         case TOOL_PEN:
151             Line(hdc, last.x, last.y, x, y, fg, 1);
152             break;
153         case TOOL_BRUSH:
154             Brush(hdc, last.x, last.y, x, y, fg, toolsModel.GetBrushStyle());
155             break;
156         case TOOL_AIRBRUSH:
157             Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth());
158             break;
159         case TOOL_LINE:
160             imageModel.ResetToPrevious();
161             if (GetAsyncKeyState(VK_SHIFT) < 0)
162                 roundTo8Directions(start.x, start.y, x, y);
163             Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
164             break;
165         case TOOL_BEZIER:
166             imageModel.ResetToPrevious();
167             pointStack[pointSP].x = x;
168             pointStack[pointSP].y = y;
169             switch (pointSP)
170             {
171                 case 1:
172                     Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, fg,
173                          toolsModel.GetLineWidth());
174                     break;
175                 case 2:
176                     Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], fg, toolsModel.GetLineWidth());
177                     break;
178                 case 3:
179                     Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], fg, toolsModel.GetLineWidth());
180                     break;
181             }
182             break;
183         case TOOL_RECT:
184             imageModel.ResetToPrevious();
185             if (GetAsyncKeyState(VK_SHIFT) < 0)
186                 regularize(start.x, start.y, x, y);
187             Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
188             break;
189         case TOOL_SHAPE:
190             imageModel.ResetToPrevious();
191             pointStack[pointSP].x = x;
192             pointStack[pointSP].y = y;
193             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
194                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
195                                    pointStack[pointSP].x, pointStack[pointSP].y);
196             if (pointSP + 1 >= 2)
197                 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
198             break;
199         case TOOL_ELLIPSE:
200             imageModel.ResetToPrevious();
201             if (GetAsyncKeyState(VK_SHIFT) < 0)
202                 regularize(start.x, start.y, x, y);
203             Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
204             break;
205         case TOOL_RRECT:
206             imageModel.ResetToPrevious();
207             if (GetAsyncKeyState(VK_SHIFT) < 0)
208                 regularize(start.x, start.y, x, y);
209             RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
210             break;
211     }
212 
213     last.x = x;
214     last.y = y;
215 }
216 
217 void
218 endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
219 {
220     switch (toolsModel.GetActiveTool())
221     {
222         case TOOL_FREESEL:
223         {
224             selectionModel.CalculateBoundingBoxAndContents(hdc);
225             if (selectionModel.PtStackSize() > 1)
226             {
227                 selectionModel.DrawBackgroundPoly(hdc, bg);
228                 imageModel.CopyPrevious();
229 
230                 selectionModel.DrawSelection(hdc);
231 
232                 placeSelWin();
233                 selectionWindow.ShowWindow(SW_SHOW);
234                 ForceRefreshSelectionContents();
235             }
236             selectionModel.ResetPtStack();
237             break;
238         }
239         case TOOL_RECTSEL:
240             imageModel.ResetToPrevious();
241             if (selectionModel.IsSrcRectSizeNonzero())
242             {
243                 selectionModel.CalculateContents(hdc);
244                 selectionModel.DrawBackgroundRect(hdc, bg);
245                 imageModel.CopyPrevious();
246 
247                 selectionModel.DrawSelection(hdc);
248 
249                 placeSelWin();
250                 selectionWindow.ShowWindow(SW_SHOW);
251                 ForceRefreshSelectionContents();
252             }
253             break;
254         case TOOL_TEXT:
255             imageModel.ResetToPrevious();
256             if (selectionModel.IsSrcRectSizeNonzero())
257             {
258                 imageModel.CopyPrevious();
259 
260                 placeSelWin();
261                 selectionWindow.ShowWindow(SW_SHOW);
262                 ForceRefreshSelectionContents();
263             }
264             break;
265         case TOOL_RUBBER:
266             Erase(hdc, last.x, last.y, x, y, bg, toolsModel.GetRubberRadius());
267             break;
268         case TOOL_PEN:
269             Line(hdc, last.x, last.y, x, y, fg, 1);
270             SetPixel(hdc, x, y, fg);
271             break;
272         case TOOL_LINE:
273             imageModel.ResetToPrevious();
274             if (GetAsyncKeyState(VK_SHIFT) < 0)
275                 roundTo8Directions(start.x, start.y, x, y);
276             Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
277             break;
278         case TOOL_BEZIER:
279             pointSP++;
280             if (pointSP == 4)
281                 pointSP = 0;
282             break;
283         case TOOL_RECT:
284             imageModel.ResetToPrevious();
285             if (GetAsyncKeyState(VK_SHIFT) < 0)
286                 regularize(start.x, start.y, x, y);
287             Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
288             break;
289         case TOOL_SHAPE:
290             imageModel.ResetToPrevious();
291             pointStack[pointSP].x = x;
292             pointStack[pointSP].y = y;
293             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
294                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
295                                    pointStack[pointSP].x, pointStack[pointSP].y);
296             pointSP++;
297             if (pointSP >= 2)
298             {
299                 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
300                     (pointStack[0].y - y) * (pointStack[0].y - y) <= toolsModel.GetLineWidth() * toolsModel.GetLineWidth() + 1)
301                 {
302                     Poly(hdc, pointStack, pointSP, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), TRUE, FALSE);
303                     pointSP = 0;
304                 }
305                 else
306                 {
307                     Poly(hdc, pointStack, pointSP, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
308                 }
309             }
310             if (pointSP == 255)
311                 pointSP--;
312             break;
313         case TOOL_ELLIPSE:
314             imageModel.ResetToPrevious();
315             if (GetAsyncKeyState(VK_SHIFT) < 0)
316                 regularize(start.x, start.y, x, y);
317             Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
318             break;
319         case TOOL_RRECT:
320             imageModel.ResetToPrevious();
321             if (GetAsyncKeyState(VK_SHIFT) < 0)
322                 regularize(start.x, start.y, x, y);
323             RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
324             break;
325     }
326 }
327 
328 void
329 startPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
330 {
331     start.x = x;
332     start.y = y;
333     last.x = x;
334     last.y = y;
335     switch (toolsModel.GetActiveTool())
336     {
337         case TOOL_FREESEL:
338         case TOOL_TEXT:
339         case TOOL_LINE:
340         case TOOL_RECT:
341         case TOOL_ELLIPSE:
342         case TOOL_RRECT:
343             imageModel.CopyPrevious();
344             break;
345         case TOOL_RUBBER:
346             imageModel.CopyPrevious();
347             Replace(hdc, x, y, x, y, fg, bg, toolsModel.GetRubberRadius());
348             break;
349         case TOOL_FILL:
350             imageModel.CopyPrevious();
351             Fill(hdc, x, y, bg);
352             break;
353         case TOOL_PEN:
354             imageModel.CopyPrevious();
355             SetPixel(hdc, x, y, bg);
356             break;
357         case TOOL_BRUSH:
358             imageModel.CopyPrevious();
359             Brush(hdc, x, y, x, y, bg, toolsModel.GetBrushStyle());
360             break;
361         case TOOL_AIRBRUSH:
362             imageModel.CopyPrevious();
363             Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth());
364             break;
365         case TOOL_BEZIER:
366             pointStack[pointSP].x = x;
367             pointStack[pointSP].y = y;
368             if (pointSP == 0)
369             {
370                 imageModel.CopyPrevious();
371                 pointSP++;
372             }
373             break;
374         case TOOL_SHAPE:
375             pointStack[pointSP].x = x;
376             pointStack[pointSP].y = y;
377             if (pointSP + 1 >= 2)
378                 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
379             if (pointSP == 0)
380             {
381                 imageModel.CopyPrevious();
382                 pointSP++;
383             }
384             break;
385     }
386 }
387 
388 void
389 whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
390 {
391     switch (toolsModel.GetActiveTool())
392     {
393         case TOOL_RUBBER:
394             Replace(hdc, last.x, last.y, x, y, fg, bg, toolsModel.GetRubberRadius());
395             break;
396         case TOOL_PEN:
397             Line(hdc, last.x, last.y, x, y, bg, 1);
398             break;
399         case TOOL_BRUSH:
400             Brush(hdc, last.x, last.y, x, y, bg, toolsModel.GetBrushStyle());
401             break;
402         case TOOL_AIRBRUSH:
403             Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth());
404             break;
405         case TOOL_LINE:
406             imageModel.ResetToPrevious();
407             if (GetAsyncKeyState(VK_SHIFT) < 0)
408                 roundTo8Directions(start.x, start.y, x, y);
409             Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
410             break;
411         case TOOL_BEZIER:
412             imageModel.ResetToPrevious();
413             pointStack[pointSP].x = x;
414             pointStack[pointSP].y = y;
415             switch (pointSP)
416             {
417                 case 1:
418                     Line(hdc, pointStack[0].x, pointStack[0].y, pointStack[1].x, pointStack[1].y, bg,
419                          toolsModel.GetLineWidth());
420                     break;
421                 case 2:
422                     Bezier(hdc, pointStack[0], pointStack[2], pointStack[2], pointStack[1], bg, toolsModel.GetLineWidth());
423                     break;
424                 case 3:
425                     Bezier(hdc, pointStack[0], pointStack[2], pointStack[3], pointStack[1], bg, toolsModel.GetLineWidth());
426                     break;
427             }
428             break;
429         case TOOL_RECT:
430             imageModel.ResetToPrevious();
431             if (GetAsyncKeyState(VK_SHIFT) < 0)
432                 regularize(start.x, start.y, x, y);
433             Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
434             break;
435         case TOOL_SHAPE:
436             imageModel.ResetToPrevious();
437             pointStack[pointSP].x = x;
438             pointStack[pointSP].y = y;
439             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
440                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
441                                    pointStack[pointSP].x, pointStack[pointSP].y);
442             if (pointSP + 1 >= 2)
443                 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
444             break;
445         case TOOL_ELLIPSE:
446             imageModel.ResetToPrevious();
447             if (GetAsyncKeyState(VK_SHIFT) < 0)
448                 regularize(start.x, start.y, x, y);
449             Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
450             break;
451         case TOOL_RRECT:
452             imageModel.ResetToPrevious();
453             if (GetAsyncKeyState(VK_SHIFT) < 0)
454                 regularize(start.x, start.y, x, y);
455             RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
456             break;
457     }
458 
459     last.x = x;
460     last.y = y;
461 }
462 
463 void
464 endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
465 {
466     switch (toolsModel.GetActiveTool())
467     {
468         case TOOL_RUBBER:
469             Replace(hdc, last.x, last.y, x, y, fg, bg, toolsModel.GetRubberRadius());
470             break;
471         case TOOL_PEN:
472             Line(hdc, last.x, last.y, x, y, bg, 1);
473             SetPixel(hdc, x, y, bg);
474             break;
475         case TOOL_LINE:
476             imageModel.ResetToPrevious();
477             if (GetAsyncKeyState(VK_SHIFT) < 0)
478                 roundTo8Directions(start.x, start.y, x, y);
479             Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
480             break;
481         case TOOL_BEZIER:
482             pointSP++;
483             if (pointSP == 4)
484                 pointSP = 0;
485             break;
486         case TOOL_RECT:
487             imageModel.ResetToPrevious();
488             if (GetAsyncKeyState(VK_SHIFT) < 0)
489                 regularize(start.x, start.y, x, y);
490             Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
491             break;
492         case TOOL_SHAPE:
493             imageModel.ResetToPrevious();
494             pointStack[pointSP].x = x;
495             pointStack[pointSP].y = y;
496             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
497                 roundTo8Directions(pointStack[pointSP - 1].x, pointStack[pointSP - 1].y,
498                                    pointStack[pointSP].x, pointStack[pointSP].y);
499             pointSP++;
500             if (pointSP >= 2)
501             {
502                 if ((pointStack[0].x - x) * (pointStack[0].x - x) +
503                     (pointStack[0].y - y) * (pointStack[0].y - y) <= toolsModel.GetLineWidth() * toolsModel.GetLineWidth() + 1)
504                 {
505                     Poly(hdc, pointStack, pointSP, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), TRUE, FALSE);
506                     pointSP = 0;
507                 }
508                 else
509                 {
510                     Poly(hdc, pointStack, pointSP, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
511                 }
512             }
513             if (pointSP == 255)
514                 pointSP--;
515             break;
516         case TOOL_ELLIPSE:
517             imageModel.ResetToPrevious();
518             if (GetAsyncKeyState(VK_SHIFT) < 0)
519                 regularize(start.x, start.y, x, y);
520             Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
521             break;
522         case TOOL_RRECT:
523             imageModel.ResetToPrevious();
524             if (GetAsyncKeyState(VK_SHIFT) < 0)
525                 regularize(start.x, start.y, x, y);
526             RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
527             break;
528     }
529 }
530