[PAINT]
[reactos.git] / reactos / base / applications / mspaint / drawing.c
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/paint/drawing.c
5 * PURPOSE: The drawing functions used by the tools
6 * PROGRAMMERS: Benedikt Freisen
7 */
8
9 /* INCLUDES *********************************************************/
10
11 #include "precomp.h"
12
13 /* FUNCTIONS ********************************************************/
14
15 void
16 Line(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, int thickness)
17 {
18 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, thickness, color));
19 MoveToEx(hdc, x1, y1, NULL);
20 LineTo(hdc, x2, y2);
21 DeleteObject(SelectObject(hdc, oldPen));
22 }
23
24 void
25 Rect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
26 {
27 HBRUSH oldBrush;
28 LOGBRUSH logbrush;
29 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
30 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
31 logbrush.lbColor = (style == 2) ? fg : bg;
32 logbrush.lbHatch = 0;
33 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
34 Rectangle(hdc, x1, y1, x2, y2);
35 DeleteObject(SelectObject(hdc, oldBrush));
36 DeleteObject(SelectObject(hdc, oldPen));
37 }
38
39 void
40 Ellp(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
41 {
42 HBRUSH oldBrush;
43 LOGBRUSH logbrush;
44 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
45 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
46 logbrush.lbColor = (style == 2) ? fg : bg;
47 logbrush.lbHatch = 0;
48 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
49 Ellipse(hdc, x1, y1, x2, y2);
50 DeleteObject(SelectObject(hdc, oldBrush));
51 DeleteObject(SelectObject(hdc, oldPen));
52 }
53
54 void
55 RRect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
56 {
57 LOGBRUSH logbrush;
58 HBRUSH oldBrush;
59 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
60 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
61 logbrush.lbColor = (style == 2) ? fg : bg;
62 logbrush.lbHatch = 0;
63 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
64 RoundRect(hdc, x1, y1, x2, y2, 16, 16);
65 DeleteObject(SelectObject(hdc, oldBrush));
66 DeleteObject(SelectObject(hdc, oldPen));
67 }
68
69 void
70 Poly(HDC hdc, POINT * lpPoints, int nCount, COLORREF fg, COLORREF bg, int thickness, int style, BOOL closed)
71 {
72 LOGBRUSH logbrush;
73 HBRUSH oldBrush;
74 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
75 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
76 logbrush.lbColor = (style == 2) ? fg : bg;
77 logbrush.lbHatch = 0;
78 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
79 if (closed)
80 Polygon(hdc, lpPoints, nCount);
81 else
82 Polyline(hdc, lpPoints, nCount);
83 DeleteObject(SelectObject(hdc, oldBrush));
84 DeleteObject(SelectObject(hdc, oldPen));
85 }
86
87 void
88 Bezier(HDC hdc, POINT p1, POINT p2, POINT p3, POINT p4, COLORREF color, int thickness)
89 {
90 HPEN oldPen;
91 POINT fourPoints[4];
92 fourPoints[0] = p1;
93 fourPoints[1] = p2;
94 fourPoints[2] = p3;
95 fourPoints[3] = p4;
96 oldPen = SelectObject(hdc, CreatePen(PS_SOLID, thickness, color));
97 PolyBezier(hdc, fourPoints, 4);
98 DeleteObject(SelectObject(hdc, oldPen));
99 }
100
101 void
102 Fill(HDC hdc, LONG x, LONG y, COLORREF color)
103 {
104 HBRUSH oldBrush = SelectObject(hdc, CreateSolidBrush(color));
105 ExtFloodFill(hdc, x, y, GetPixel(hdc, x, y), FLOODFILLSURFACE);
106 DeleteObject(SelectObject(hdc, oldBrush));
107 }
108
109 void
110 Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG radius)
111 {
112 LONG a, b;
113 b = max(1, max(abs(x2 - x1), abs(y2 - y1)));
114 HPEN oldPen;
115 HBRUSH oldBrush = SelectObject(hdc, CreateSolidBrush(color));
116 oldPen = SelectObject(hdc, CreatePen(PS_SOLID, 1, color));
117 for(a = 0; a <= b; a++)
118 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - radius + 1,
119 (y1 * (b - a) + y2 * a) / b - radius + 1, (x1 * (b - a) + x2 * a) / b + radius + 1,
120 (y1 * (b - a) + y2 * a) / b + radius + 1);
121 DeleteObject(SelectObject(hdc, oldBrush));
122 DeleteObject(SelectObject(hdc, oldPen));
123 }
124
125 void
126 Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LONG radius)
127 {
128 LONG a, b, x, y;
129 b = max(1, max(abs(x2 - x1), abs(y2 - y1)));
130
131 for(a = 0; a <= b; a++)
132 for(y = (y1 * (b - a) + y2 * a) / b - radius + 1;
133 y < (y1 * (b - a) + y2 * a) / b + radius + 1; y++)
134 for(x = (x1 * (b - a) + x2 * a) / b - radius + 1;
135 x < (x1 * (b - a) + x2 * a) / b + radius + 1; x++)
136 if (GetPixel(hdc, x, y) == fg)
137 SetPixel(hdc, x, y, bg);
138 }
139
140 void
141 Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r)
142 {
143 LONG a, b;
144
145 for(b = -r; b <= r; b++)
146 for(a = -r; a <= r; a++)
147 if ((a * a + b * b <= r * r) && (rand() % 4 == 0))
148 SetPixel(hdc, x + a, y + b, color);
149 }
150
151 void
152 Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style)
153 {
154 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, 1, color));
155 HBRUSH oldBrush = SelectObject(hdc, CreateSolidBrush(color));
156 LONG a, b;
157 b = max(1, max(abs(x2 - x1), abs(y2 - y1)));
158 switch (style)
159 {
160 case 0:
161 for(a = 0; a <= b; a++)
162 Ellipse(hdc, (x1 * (b - a) + x2 * a) / b - 3, (y1 * (b - a) + y2 * a) / b - 3,
163 (x1 * (b - a) + x2 * a) / b + 4, (y1 * (b - a) + y2 * a) / b + 4);
164 break;
165 case 1:
166 for(a = 0; a <= b; a++)
167 Ellipse(hdc, (x1 * (b - a) + x2 * a) / b - 1, (y1 * (b - a) + y2 * a) / b - 1,
168 (x1 * (b - a) + x2 * a) / b + 3, (y1 * (b - a) + y2 * a) / b + 3);
169 break;
170 case 2:
171 MoveToEx(hdc, x1, y1, NULL);
172 LineTo(hdc, x2, y2);
173 SetPixel(hdc, x2, y2, color);
174 break;
175 case 3:
176 for(a = 0; a <= b; a++)
177 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 3, (y1 * (b - a) + y2 * a) / b - 3,
178 (x1 * (b - a) + x2 * a) / b + 5, (y1 * (b - a) + y2 * a) / b + 5);
179 break;
180 case 4:
181 for(a = 0; a <= b; a++)
182 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 2, (y1 * (b - a) + y2 * a) / b - 2,
183 (x1 * (b - a) + x2 * a) / b + 3, (y1 * (b - a) + y2 * a) / b + 3);
184 break;
185 case 5:
186 for(a = 0; a <= b; a++)
187 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 1, (y1 * (b - a) + y2 * a) / b - 1,
188 (x1 * (b - a) + x2 * a) / b + 1, (y1 * (b - a) + y2 * a) / b + 1);
189 break;
190 case 6:
191 case 7:
192 case 8:
193 case 9:
194 case 10:
195 case 11:
196 {
197 POINT offsTop[] = {{.x = 4, .y = -3}, {.x = 2, .y = -2}, {.x = 0, .y = 0},
198 {.x = -3, .y = -3}, {.x = -2, .y = -2}, {.x = -1, .y = 0}};
199 POINT offsBtm[] = {{.x = -3, .y = 4}, {.x = -2, .y = 2}, {.x = -1, .y = 1},
200 {.x = 4, .y = 4}, {.x = 2, .y = 2}, {.x = 0, .y = 1}};
201 LONG idx = style - 6;
202 POINT pts[4];
203 pts[0].x = x1 + offsTop[idx].x;
204 pts[0].y = y1 + offsTop[idx].y;
205 pts[1].x = x1 + offsBtm[idx].x;
206 pts[1].y = y1 + offsBtm[idx].y;
207 pts[2].x = x2 + offsBtm[idx].x;
208 pts[2].y = y2 + offsBtm[idx].y;
209 pts[3].x = x2 + offsTop[idx].x;
210 pts[3].y = y2 + offsTop[idx].y;
211 Polygon(hdc, pts, 4);
212 break;
213 }
214 }
215 DeleteObject(SelectObject(hdc, oldBrush));
216 DeleteObject(SelectObject(hdc, oldPen));
217 }
218
219 void
220 RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
221 {
222 HBRUSH oldBrush;
223 LOGBRUSH logbrush;
224 HPEN oldPen = SelectObject(hdc, CreatePen(PS_DOT, 1, 0x00000000));
225 logbrush.lbStyle = BS_HOLLOW;
226 logbrush.lbColor = 0;
227 logbrush.lbHatch = 0;
228 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
229 Rectangle(hdc, x1, y1, x2, y2);
230 DeleteObject(SelectObject(hdc, oldBrush));
231 DeleteObject(SelectObject(hdc, oldPen));
232 }
233
234 void
235 SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
236 {
237 HBRUSH oldBrush;
238 LOGBRUSH logbrush;
239 HPEN oldPen = SelectObject(hdc, CreatePen(PS_DOT, 1, 0x00000000));
240 logbrush.lbStyle = BS_HOLLOW;
241 logbrush.lbColor = 0;
242 logbrush.lbHatch = 0;
243 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
244 Rectangle(hdc, x1, y1, x2, y2);
245 DeleteObject(SelectObject(hdc, oldBrush));
246 DeleteObject(SelectObject(hdc, oldPen));
247 oldPen = SelectObject(hdc, CreatePen(PS_SOLID, 1, 0x00000000));
248 oldBrush = SelectObject(hdc, CreateSolidBrush(0x00000000));
249 Rectangle(hdc, x1 - 1, y1 - 1, x1 + 2, y1 + 2);
250 Rectangle(hdc, x2 - 2, y1 - 1, x2 + 2, y1 + 2);
251 Rectangle(hdc, x1 - 1, y2 - 2, x1 + 2, y2 + 1);
252 Rectangle(hdc, x2 - 2, y2 - 2, x2 + 2, y2 + 1);
253 Rectangle(hdc, (x1 + x2) / 2 - 1, y1 - 1, (x1 + x2) / 2 + 2, y1 + 2);
254 Rectangle(hdc, (x1 + x2) / 2 - 1, y2 - 2, (x1 + x2) / 2 + 2, y2 + 1);
255 Rectangle(hdc, x1 - 1, (y1 + y2) / 2 - 1, x1 + 2, (y1 + y2) / 2 + 2);
256 Rectangle(hdc, x2 - 2, (y1 + y2) / 2 - 1, x2 + 1, (y1 + y2) / 2 + 2);
257 DeleteObject(SelectObject(hdc, oldBrush));
258 DeleteObject(SelectObject(hdc, oldPen));
259 }