ReactOS 0.4.17-dev-470-gf9e3448
drawing.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: The drawing functions used by the tools
5 * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6 * Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9#include "precomp.h"
10
11/* FUNCTIONS ********************************************************/
12
13// WidenPath requires a geometric pen
14static HPEN
15CreateGeometricPen(COLORREF rgbColor, INT thickness)
16{
17 LOGBRUSH logbrush;
18 logbrush.lbStyle = BS_SOLID;
19 logbrush.lbColor = rgbColor;
20 logbrush.lbHatch = 0;
21 return ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_ROUND | PS_JOIN_ROUND, thickness, &logbrush, 0, NULL);
22}
23
24void
26{
27 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, color));
28 MoveToEx(hdc, x1, y1, NULL);
29 LineTo(hdc, x2, y2);
32}
33
34void
35Line(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hBrush, INT thickness)
36{
37 HGDIOBJ oldPen = SelectObject(hdc, CreateGeometricPen(0, thickness));
39 MoveToEx(hdc, x1, y1, NULL);
40 LineTo(hdc, x2, y2);
41 EndPath(hdc);
45
46 HRGN hRgn = PathToRegion(hdc);
47 FillRgn(hdc, hRgn, hBrush);
49
50 RECT rc = { x2, y2, x2 + 1, y2 + 1 };
51 FillRect(hdc, &rc, hBrush);
52}
53
54void
55Rect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
56{
57 HBRUSH oldBrush;
58 LOGBRUSH logbrush;
59 HPEN oldPen = (HPEN) 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 = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
64 Rectangle(hdc, x1, y1, x2, y2);
65 DeleteObject(SelectObject(hdc, oldBrush));
67}
68
69void
70Rect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hFgBrush, HBRUSH hBgBrush, INT thickness, INT style)
71{
72 HGDIOBJ hPenOld;
73 if (style != 0)
74 {
75 HGDIOBJ hBrushOld = SelectObject(hdc, (style == 2) ? hFgBrush : hBgBrush);
77 Rectangle(hdc, x1, y1, x2, y2);
78 SelectObject(hdc, hBrushOld);
79 SelectObject(hdc, hPenOld);
80 }
81
82 HPEN hPen = CreateGeometricPen(0, thickness);
83 hPenOld = SelectObject(hdc, hPen);
85 Rectangle(hdc, x1, y1, x2, y2);
86 EndPath(hdc);
89 SelectObject(hdc, hPenOld);
90 DeleteObject(hPen);
91
92 HRGN hRgn = PathToRegion(hdc);
93 FillRgn(hdc, hRgn, hFgBrush);
95}
96
97void
98Ellp(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
99{
100 HBRUSH oldBrush;
101 LOGBRUSH logbrush;
102 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
103 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
104 logbrush.lbColor = (style == 2) ? fg : bg;
105 logbrush.lbHatch = 0;
106 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
107 Ellipse(hdc, x1, y1, x2, y2);
108 DeleteObject(SelectObject(hdc, oldBrush));
109 DeleteObject(SelectObject(hdc, oldPen));
110}
111
112void
113Ellp(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hFgBrush, HBRUSH hBgBrush, INT thickness, INT style)
114{
115 HGDIOBJ hPenOld;
116 if (style != 0)
117 {
118 HGDIOBJ hBrushOld = SelectObject(hdc, (style == 2) ? hFgBrush : hBgBrush);
120 Ellipse(hdc, x1, y1, x2, y2);
121 SelectObject(hdc, hBrushOld);
122 SelectObject(hdc, hPenOld);
123 }
124
125 HPEN hPen = CreateGeometricPen(0, thickness);
126 hPenOld = SelectObject(hdc, hPen);
127 BeginPath(hdc);
128 Ellipse(hdc, x1, y1, x2, y2);
129 EndPath(hdc);
131 WidenPath(hdc);
132 SelectObject(hdc, hPenOld);
133 DeleteObject(hPen);
134
135 HRGN hRgn = PathToRegion(hdc);
136 FillRgn(hdc, hRgn, hFgBrush);
138}
139
140void
141RRect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
142{
143 LOGBRUSH logbrush;
144 HBRUSH oldBrush;
145 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
146 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
147 logbrush.lbColor = (style == 2) ? fg : bg;
148 logbrush.lbHatch = 0;
149 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
150 RoundRect(hdc, x1, y1, x2, y2, 16, 16);
151 DeleteObject(SelectObject(hdc, oldBrush));
152 DeleteObject(SelectObject(hdc, oldPen));
153}
154
155void
156RRect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hFgBrush, HBRUSH hBgBrush, INT thickness, INT style)
157{
158 HGDIOBJ hPenOld;
159 if (style != 0)
160 {
161 HGDIOBJ hBrushOld = SelectObject(hdc, (style == 2) ? hFgBrush : hBgBrush);
163 RoundRect(hdc, x1, y1, x2, y2, 16, 16);
164 SelectObject(hdc, hBrushOld);
165 SelectObject(hdc, hPenOld);
166 }
167
168 HPEN hPen = CreateGeometricPen(0, thickness);
169 hPenOld = SelectObject(hdc, hPen);
170 BeginPath(hdc);
171 RoundRect(hdc, x1, y1, x2, y2, 16, 16);
172 EndPath(hdc);
174 WidenPath(hdc);
175 SelectObject(hdc, hPenOld);
176 DeleteObject(hPen);
177
178 HRGN hRgn = PathToRegion(hdc);
179 FillRgn(hdc, hRgn, hFgBrush);
181}
182
183void
184Poly(HDC hdc, POINT * lpPoints, int nCount, COLORREF fg, COLORREF bg, int thickness, int style, BOOL closed, BOOL inverted)
185{
186 LOGBRUSH logbrush;
187 HBRUSH oldBrush;
188 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg));
189 UINT oldRop = GetROP2(hdc);
190
191 if (inverted)
193
194 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID;
195 logbrush.lbColor = (style == 2) ? fg : bg;
196 logbrush.lbHatch = 0;
197 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
198 if (closed)
199 Polygon(hdc, lpPoints, nCount);
200 else
201 Polyline(hdc, lpPoints, nCount);
202 DeleteObject(SelectObject(hdc, oldBrush));
203 DeleteObject(SelectObject(hdc, oldPen));
204
205 SetROP2(hdc, oldRop);
206}
207
208void
209Poly(HDC hdc, POINT *lpPoints, INT nCount, HBRUSH hFgBrush, HBRUSH hBgBrush, INT thickness, INT style, BOOL closed, BOOL inverted)
210{
211 UINT oldRop = GetROP2(hdc);
212 if (inverted)
214
215 HGDIOBJ hPenOld;
216 if (style != 0)
217 {
218 HGDIOBJ hBrushOld = SelectObject(hdc, (style == 2) ? hFgBrush : hBgBrush);
220 if (closed)
221 Polygon(hdc, lpPoints, nCount);
222 else
223 Polyline(hdc, lpPoints, nCount);
224 SelectObject(hdc, hBrushOld);
225 SelectObject(hdc, hPenOld);
226 }
227
228 HPEN hPen = CreateGeometricPen(0, thickness);
229 hPenOld = SelectObject(hdc, hPen);
230 BeginPath(hdc);
231 if (closed)
232 Polygon(hdc, lpPoints, nCount);
233 else
234 Polyline(hdc, lpPoints, nCount);
235 EndPath(hdc);
237 WidenPath(hdc);
238 SelectObject(hdc, hPenOld);
239 DeleteObject(hPen);
240
241 HRGN hRgn = PathToRegion(hdc);
242 FillRgn(hdc, hRgn, hFgBrush);
244
245 SetROP2(hdc, oldRop);
246}
247
248void
249Bezier(HDC hdc, POINT p1, POINT p2, POINT p3, POINT p4, COLORREF color, int thickness)
250{
251 HPEN oldPen;
252 POINT fourPoints[4];
253 fourPoints[0] = p1;
254 fourPoints[1] = p2;
255 fourPoints[2] = p3;
256 fourPoints[3] = p4;
257 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, color));
258 PolyBezier(hdc, fourPoints, 4);
259 DeleteObject(SelectObject(hdc, oldPen));
260}
261
262void
263Bezier(HDC hdc, POINT p1, POINT p2, POINT p3, POINT p4, HBRUSH hBrush, INT thickness)
264{
265 HPEN oldPen;
266 POINT fourPoints[4];
267 fourPoints[0] = p1;
268 fourPoints[1] = p2;
269 fourPoints[2] = p3;
270 fourPoints[3] = p4;
271 oldPen = (HPEN) SelectObject(hdc, CreateGeometricPen(0, thickness));
272 BeginPath(hdc);
273 PolyBezier(hdc, fourPoints, 4);
274 EndPath(hdc);
276 WidenPath(hdc);
277
278 HRGN hRgn = PathToRegion(hdc);
279 FillRgn(hdc, hRgn, hBrush);
281
282 DeleteObject(SelectObject(hdc, oldPen));
283}
284
285void
287{
288 HBRUSH hBrush = CreateSolidBrush(color);
289 Fill(hdc, x, y, hBrush);
290 DeleteObject(hBrush);
291}
292
293void
294Fill(HDC hdc, LONG x, LONG y, HBRUSH hBrush)
295{
296 HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
298 SelectObject(hdc, oldBrush);
299}
300
301void
303{
304 HBRUSH hBrush = ::CreateSolidBrush(color);
305 Erase(hdc, x1, y1, x2, y2, hBrush, radius);
306 ::DeleteObject(hBrush);
307}
308
309void
310Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hBrush, LONG radius)
311{
312 LONG b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
313
314 for (LONG a = 0; a <= b; a++)
315 {
316 LONG cx = (x1 * (b - a) + x2 * a) / b;
317 LONG cy = (y1 * (b - a) + y2 * a) / b;
318 RECT rc = { cx - radius, cy - radius, cx + radius, cy + radius };
319 ::FillRect(hdc, &rc, hBrush);
320 }
321}
322
323void
325{
326 LONG b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
327
328 for (LONG a = 0; a <= b; a++)
329 {
330 LONG cx = (x1 * (b - a) + x2 * a) / b;
331 LONG cy = (y1 * (b - a) + y2 * a) / b;
332 RECT rc = { cx - radius, cy - radius, cx + radius, cy + radius };
333 for (LONG y = rc.top; y < rc.bottom; ++y)
334 {
335 for (LONG x = rc.left; x < rc.right; ++x)
336 {
337 if (::GetPixel(hdc, x, y) == fg)
338 ::SetPixelV(hdc, x, y, bg);
339 }
340 }
341 }
342}
343
344void
345Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, HBRUSH hBgBrush, LONG radius)
346{
347 LONG b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
348
349 for (LONG a = 0; a <= b; a++)
350 {
351 LONG cx = (x1 * (b - a) + x2 * a) / b;
352 LONG cy = (y1 * (b - a) + y2 * a) / b;
353 RECT rc = { cx - radius, cy - radius, cx + radius, cy + radius };
354 for (LONG y = rc.top; y < rc.bottom; ++y)
355 {
356 for (LONG x = rc.left; x < rc.right; ++x)
357 {
358 if (::GetPixel(hdc, x, y) == fg)
359 {
360 RECT rc = { x, y, x + 1, y + 1 };
361 FillRect(hdc, &rc, hBgBrush);
362 }
363 }
364 }
365 }
366}
367
368void
370{
371 for (LONG dy = -r; dy <= r; dy++)
372 {
373 for (LONG dx = -r; dx <= r; dx++)
374 {
375 if ((dx * dx + dy * dy <= r * r) && (rand() % r == 0))
376 ::SetPixelV(hdc, x + dx, y + dy, color);
377 }
378 }
379}
380
381void
382Airbrush(HDC hdc, LONG x, LONG y, HBRUSH hBrush, LONG r)
383{
384 for (LONG dy = -r; dy <= r; dy++)
385 {
386 for (LONG dx = -r; dx <= r; dx++)
387 {
388 if ((dx * dx + dy * dy <= r * r) && (rand() % r == 0))
389 {
390 RECT rc = { x + dx, y + dy, x + dx + 1, y + dy + 1 };
391 FillRect(hdc, &rc, hBrush);
392 }
393 }
394 }
395}
396
397static void
399{
400 LONG a, b = max(1, max(labs(x2 - x1), labs(y2 - y1)));
401 switch ((BrushStyle)style)
402 {
403 case BrushStyleRound:
404 for (a = 0; a <= b; a++)
405 {
406 Ellipse(hdc,
407 (x1 * (b - a) + x2 * a) / b - (thickness / 2),
408 (y1 * (b - a) + y2 * a) / b - (thickness / 2),
409 (x1 * (b - a) + x2 * a) / b + (thickness / 2) + 1,
410 (y1 * (b - a) + y2 * a) / b + (thickness / 2) + 1);
411 }
412 break;
413
414 case BrushStyleSquare:
415 for (a = 0; a <= b; a++)
416 {
418 (x1 * (b - a) + x2 * a) / b - (thickness / 2),
419 (y1 * (b - a) + y2 * a) / b - (thickness / 2),
420 (x1 * (b - a) + x2 * a) / b + (thickness / 2) + 1,
421 (y1 * (b - a) + y2 * a) / b + (thickness / 2) + 1);
422 }
423 break;
424
427 {
428 POINT offsetTop, offsetBottom;
430 {
431 offsetTop = { (thickness - 1) / 2 + 1, -(thickness - 1) / 2 };
432 offsetBottom = { -thickness / 2 , thickness / 2 + 1 };
433 }
434 else
435 {
436 offsetTop = { -thickness / 2 , -thickness / 2 };
437 offsetBottom = { (thickness - 1) / 2 + 1, (thickness - 1) / 2 + 1 };
438 }
439 if (x1 == x2 && y1 == y2)
440 {
441 ++x2;
442 }
443 POINT points[4] =
444 {
445 { x1 + offsetTop.x, y1 + offsetTop.y },
446 { x1 + offsetBottom.x, y1 + offsetBottom.y },
447 { x2 + offsetBottom.x, y2 + offsetBottom.y },
448 { x2 + offsetTop.x, y2 + offsetTop.y },
449 };
451 break;
452 }
453 }
454}
455
456void
458{
459 HBRUSH hBrush = CreateSolidBrush(color);
460 Brush(hdc, x1, y1, x2, y2, hBrush, style, thickness);
461 DeleteObject(hBrush);
462}
463
464void
465Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hBrush, LONG style, INT thickness)
466{
467 if (thickness <= 1)
468 {
469 Line(hdc, x1, y1, x2, y2, hBrush, thickness);
470 return;
471 }
472
473 HGDIOBJ oldPen = SelectObject(hdc, GetStockObject(NULL_PEN)); // 1px off
474 HGDIOBJ oldBrush = SelectObject(hdc, hBrush);
475 BrushInternal(hdc, x1, y1, x2, y2, style, thickness);
476 SelectObject(hdc, oldBrush);
477 SelectObject(hdc, oldPen);
478}
479
480void
482{
483 HBRUSH oldBrush;
484 LOGBRUSH logbrush;
485 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_DOT, 1, GetSysColor(COLOR_HIGHLIGHT)));
486 UINT oldRop = GetROP2(hdc);
487
489
490 logbrush.lbStyle = BS_HOLLOW;
491 logbrush.lbColor = 0;
492 logbrush.lbHatch = 0;
493 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
494 Rectangle(hdc, x1, y1, x2, y2);
495 DeleteObject(SelectObject(hdc, oldBrush));
496 DeleteObject(SelectObject(hdc, oldPen));
497
498 SetROP2(hdc, oldRop);
499}
500
501void
503{
504 INT iSaveDC = ::SaveDC(hdc); // We will modify the clipping region. Save now.
505
506 CRect rc = { x1, y1, x2, y2 };
507
508 if (style == 0) // Transparent
509 {
511 }
512 else // Opaque
513 {
515 ::SetBkColor(hdc, bg);
516
517 HBRUSH hbr = ::CreateSolidBrush(bg);
518 ::FillRect(hdc, &rc, hbr); // Fill the background
519 ::DeleteObject(hbr);
520 }
521
522 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
523
524 HGDIOBJ hFontOld = ::SelectObject(hdc, font);
525 ::SetTextColor(hdc, fg);
526 const UINT uFormat = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP |
528 ::DrawTextW(hdc, lpchText, -1, &rc, uFormat);
529 ::SelectObject(hdc, hFontOld);
530
531 ::RestoreDC(hdc, iSaveDC); // Restore
532}
533
534void
535Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, HBRUSH hFgBrush, HBRUSH hBgBrush, LPCWSTR lpchText, HFONT font, LONG style)
536{
537 INT iSaveDC = ::SaveDC(hdc); // We will modify the clipping region. Save now.
538
539 CRect rc = { x1, y1, x2, y2 };
540
542 if (style != 0) // Not Transparent
543 ::FillRect(hdc, &rc, hBgBrush); // Fill the background
544
545 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
546
547 HGDIOBJ hFontOld = ::SelectObject(hdc, font);
548 const UINT uFormat = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP |
551 ::DrawTextW(hdc, lpchText, -1, &rc, uFormat);
552 ::EndPath(hdc);
553
554 HRGN hRgn = PathToRegion(hdc);
555 FillRgn(hdc, hRgn, hFgBrush);
557
558 ::SelectObject(hdc, hFontOld);
559
560 ::RestoreDC(hdc, iSaveDC); // Restore
561}
562
563BOOL
564ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
565 HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight,
566 HBITMAP hbmMask, COLORREF keyColor)
567{
568 HDC hTempDC1, hTempDC2;
569 HBITMAP hbmTempColor, hbmTempMask;
570 HGDIOBJ hbmOld1, hbmOld2;
571
572 if (hbmMask == NULL)
573 {
574 if (keyColor == CLR_INVALID)
575 {
576 ::StretchBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,
577 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, SRCCOPY);
578 }
579 else
580 {
581 ::GdiTransparentBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,
582 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, keyColor);
583 }
584 return TRUE;
585 }
586 else if (nWidth == nSrcWidth && nHeight == nSrcHeight && keyColor == CLR_INVALID)
587 {
588 ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,
589 hdcSrc, nXSrc, nYSrc, hbmMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029));
590 return TRUE;
591 }
592
593 hTempDC1 = ::CreateCompatibleDC(hdcDest);
594 hTempDC2 = ::CreateCompatibleDC(hdcDest);
595 hbmTempMask = ::CreateBitmap(nWidth, nHeight, 1, 1, NULL);
596 hbmTempColor = CreateColorDIB(nWidth, nHeight, RGB(255, 255, 255));
597
598 // hbmTempMask <-- hbmMask (stretched)
599 hbmOld1 = ::SelectObject(hTempDC1, hbmMask);
600 hbmOld2 = ::SelectObject(hTempDC2, hbmTempMask);
601 ::StretchBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC1, 0, 0, nSrcWidth, nSrcHeight, SRCCOPY);
602 ::SelectObject(hTempDC2, hbmOld2);
603 ::SelectObject(hTempDC1, hbmOld1);
604
605 hbmOld1 = ::SelectObject(hTempDC1, hbmTempColor);
606 if (keyColor == CLR_INVALID)
607 {
608 // hbmTempColor <-- hdcSrc (stretched)
609 ::StretchBlt(hTempDC1, 0, 0, nWidth, nHeight,
610 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, SRCCOPY);
611
612 // hdcDest <-- hbmTempColor (masked)
613 ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hTempDC1, 0, 0,
614 hbmTempMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029));
615 }
616 else
617 {
618 // hbmTempColor <-- hdcDest
619 ::BitBlt(hTempDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
620
621 // hbmTempColor <-- hdcSrc (color key)
622 ::GdiTransparentBlt(hTempDC1, 0, 0, nWidth, nHeight,
623 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, keyColor);
624
625 // hdcDest <-- hbmTempColor (masked)
626 ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hTempDC1, 0, 0,
627 hbmTempMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029));
628 }
629 ::SelectObject(hTempDC1, hbmOld1);
630
631 ::DeleteObject(hbmTempColor);
632 ::DeleteObject(hbmTempMask);
633 ::DeleteDC(hTempDC2);
634 ::DeleteDC(hTempDC1);
635
636 return TRUE;
637}
638
640{
641 HGDIOBJ oldPen = ::SelectObject(hdc, ::CreatePen(PS_SOLID, 0, RGB(0, 0, 0)));
643 INT oldRop2 = SetROP2(hdc, R2_NOTXORPEN);
645 ::SetROP2(hdc, oldRop2);
646 ::SelectObject(hdc, oldBrush);
648}
649
650HBRUSH CreateDitherBrush(COLORREF color, COLORREF monoColor0, COLORREF monoColor1)
651{
652 // 8x8 Bayer ordered dithering matrix (0 to 63)
653 static const BYTE s_bayerMatrix[8][8] =
654 {
655 { 0, 32, 8, 40, 2, 34, 10, 42 },
656 { 48, 16, 56, 24, 50, 18, 58, 26 },
657 { 12, 44, 4, 36, 14, 46, 6, 38 },
658 { 60, 28, 52, 20, 62, 30, 54, 22 },
659 { 3, 35, 11, 43, 1, 33, 9, 41 },
660 { 51, 19, 59, 27, 49, 17, 57, 25 },
661 { 15, 47, 7, 39, 13, 45, 5, 37 },
662 { 63, 31, 55, 23, 61, 29, 53, 21 },
663 };
665 INT brightness = sum / 3;
666 if (brightness < 0)
667 brightness = 0;
668 if (brightness >= 255)
669 brightness = 256; // White out
670
671 BITMAPINFO bmi = {};
672 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
673 bmi.bmiHeader.biWidth = 8;
674 bmi.bmiHeader.biHeight = -8; // Top-down
675 bmi.bmiHeader.biPlanes = 1;
676 bmi.bmiHeader.biBitCount = 24;
677
678 const BYTE b0 = GetBValue(monoColor0), g0 = GetGValue(monoColor0), r0 = GetRValue(monoColor0);
679 const BYTE b1 = GetBValue(monoColor1), g1 = GetGValue(monoColor1), r1 = GetRValue(monoColor1);
680
681 BYTE pixels[8 * 8 * 3];
682 for (INT y = 0; y < 8; ++y)
683 {
684 INT index = y * (3 * CHAR_BIT);
685 for (INT x = 0; x < 8; ++x)
686 {
687 const INT threshold = s_bayerMatrix[y][x] * 255 / 63;
688 if (brightness > threshold)
689 {
690 pixels[index++] = b1; // Blue
691 pixels[index++] = g1; // Green
692 pixels[index++] = r1; // Red
693 }
694 else
695 {
696 pixels[index++] = b0; // Blue
697 pixels[index++] = g0; // Green
698 pixels[index++] = r0; // Red
699 }
700 }
701 }
702
703 HDC hdc = GetDC(NULL);
706
707 if (!hBitmap)
708 return NULL;
709
710 HBRUSH hBrush = CreatePatternBrush(hBitmap);
712
713 return hBrush;
714}
Arabic default style
Definition: afstyles.h:94
#define WINDING
Definition: constants.h:279
DWORD GetPixel(LPDIRECTDRAWSURFACE7 Surface, UINT x, UINT y)
Definition: blt.cpp:2
char * Text
Definition: combotst.c:136
HBITMAP CreateColorDIB(int width, int height, COLORREF rgb)
Definition: dib.cpp:65
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
static HBITMAP hBitmap
Definition: timezone.c:26
#define CHAR_BIT
Definition: limits.h:6
_ACRTIMP __msvcrt_long __cdecl labs(__msvcrt_long)
Definition: math.c:680
_ACRTIMP int __cdecl rand(void)
Definition: misc.c:59
void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
Definition: drawing.cpp:481
void Bezier(HDC hdc, POINT p1, POINT p2, POINT p3, POINT p4, COLORREF color, int thickness)
Definition: drawing.cpp:249
HBRUSH CreateDitherBrush(COLORREF color, COLORREF monoColor0, COLORREF monoColor1)
Definition: drawing.cpp:650
void Ellp(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
Definition: drawing.cpp:98
void Poly(HDC hdc, POINT *lpPoints, int nCount, COLORREF fg, COLORREF bg, int thickness, int style, BOOL closed, BOOL inverted)
Definition: drawing.cpp:184
BOOL ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, HBITMAP hbmMask, COLORREF keyColor)
Definition: drawing.cpp:564
void DrawXorRect(HDC hdc, const RECT *prc)
Definition: drawing.cpp:639
void RRect(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, int thickness, int style)
Definition: drawing.cpp:141
void Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LONG radius)
Definition: drawing.cpp:324
void Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG radius)
Definition: drawing.cpp:302
static void BrushInternal(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, LONG style, INT thickness)
Definition: drawing.cpp:398
void Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r)
Definition: drawing.cpp:369
static HPEN CreateGeometricPen(COLORREF rgbColor, INT thickness)
Definition: drawing.cpp:15
void Fill(HDC hdc, LONG x, LONG y, COLORREF color)
Definition: drawing.cpp:286
static VOID BitBlt(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_reads_bytes_(Height *Stride) PUCHAR Buffer, _In_ ULONG BitsPerPixel, _In_ ULONG Stride)
Definition: common.c:42
#define RGB(r, g, b)
Definition: precomp.h:67
#define GetBValue(quad)
Definition: precomp.h:71
#define GetGValue(quad)
Definition: precomp.h:70
#define GetRValue(quad)
Definition: precomp.h:69
unsigned int BOOL
Definition: ntddk_ex.h:94
pKey DeleteObject()
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: gl.h:1546
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint color
Definition: glext.h:6243
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei const GLfloat * points
Definition: glext.h:8112
unsigned int UINT
Definition: sysinfo.c:13
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:529
static DNS_RECORDW r1
Definition: record.c:37
static HRGN hRgn
Definition: mapping.c:32
Definition: mk_font.cpp:20
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:16
long LONG
Definition: pedump.c:60
BOOL Polygon(CONST PPOINT UnsafePoints, int Count, int polyFillMode)
Definition: polytest.cpp:730
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
_Out_ LPRECT prc
Definition: ntgdi.h:1658
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
#define _countof(array)
Definition: sndvol32.h:70
Definition: ncftp.h:79
USHORT biBitCount
Definition: precomp.h:34
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1922
UINT lbStyle
Definition: wingdi.h:2193
ULONG_PTR lbHatch
Definition: wingdi.h:2195
COLORREF lbColor
Definition: wingdi.h:2194
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
#define max(a, b)
Definition: svc.c:63
BrushStyle
Definition: toolsmodel.h:32
@ BrushStyleForeSlash
Definition: toolsmodel.h:35
@ BrushStyleRound
Definition: toolsmodel.h:33
@ BrushStyleBackSlash
Definition: toolsmodel.h:36
@ BrushStyleSquare
Definition: toolsmodel.h:34
const uint16_t * LPCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
BOOL WINAPI GdiTransparentBlt(HDC hdcDst, int xDst, int yDst, int wDst, int hDst, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, UINT crTransparent)
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
DWORD COLORREF
Definition: windef.h:100
HBRUSH WINAPI CreateBrushIndirect(_In_ const LOGBRUSH *plb)
#define DIB_RGB_COLORS
Definition: wingdi.h:367
BOOL WINAPI PolyBezier(_In_ HDC hdc, _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt)
Definition: painting.c:263
HGDIOBJ WINAPI GetStockObject(_In_ int)
BOOL WINAPI Polyline(_In_ HDC hdc, _In_reads_(cpt) const POINT *apt, _In_ int cpt)
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
BOOL WINAPI Ellipse(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
HPEN WINAPI ExtCreatePen(_In_ DWORD iPenStyle, _In_ DWORD cWidth, _In_ const LOGBRUSH *plbrush, _In_ DWORD cStyle, _In_reads_opt_(cStyle) const DWORD *pstyle)
#define PS_DOT
Definition: wingdi.h:588
#define PS_JOIN_ROUND
Definition: wingdi.h:599
int WINAPI IntersectClipRect(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
#define FLOODFILLSURFACE
Definition: wingdi.h:645
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
BOOL WINAPI MoveToEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
BOOL WINAPI MaskBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ HDC, _In_ int, _In_ int, _In_ HBITMAP, _In_ int, _In_ int, _In_ DWORD)
#define R2_NOTXORPEN
Definition: wingdi.h:351
#define PS_ENDCAP_ROUND
Definition: wingdi.h:594
#define PS_GEOMETRIC
Definition: wingdi.h:583
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define TRANSPARENT
Definition: wingdi.h:950
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define CLR_INVALID
Definition: wingdi.h:883
BOOL WINAPI RestoreDC(_In_ HDC, _In_ int)
#define SRCCOPY
Definition: wingdi.h:333
#define BS_HOLLOW
Definition: wingdi.h:1088
int WINAPI GetROP2(_In_ HDC)
Definition: dc.c:1093
HRGN WINAPI PathToRegion(_In_ HDC)
#define NULL_BRUSH
Definition: wingdi.h:901
#define OPAQUE
Definition: wingdi.h:949
#define NULL_PEN
Definition: wingdi.h:904
BOOL WINAPI SetPixelV(_In_ HDC, _In_ int, _In_ int, _In_ COLORREF)
int WINAPI FillRgn(_In_ HDC, _In_ HRGN, _In_ HBRUSH)
Definition: painting.c:183
BOOL WINAPI WidenPath(_In_ HDC)
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
BOOL WINAPI Rectangle(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
#define CBM_INIT
Definition: wingdi.h:365
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:917
int WINAPI SetROP2(_In_ HDC, _In_ int)
Definition: dc.c:1114
BOOL WINAPI RoundRect(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int)
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
BOOL WINAPI DeleteDC(_In_ HDC)
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
HBITMAP WINAPI CreateDIBitmap(_In_ HDC hdc, _In_opt_ const BITMAPINFOHEADER *pbmih, _In_ DWORD fdwInit, _In_opt_ const VOID *pvInit, _In_opt_ const BITMAPINFO *pbmi, _In_ UINT uUsage)
BOOL WINAPI EndPath(_In_ HDC)
BOOL WINAPI ExtFloodFill(_In_ HDC, _In_ int, _In_ int, _In_ COLORREF, _In_ UINT)
BOOL WINAPI LineTo(_In_ HDC, _In_ int, _In_ int)
BOOL WINAPI BeginPath(_In_ HDC hdc)
#define BS_SOLID
Definition: wingdi.h:1086
#define PS_SOLID
Definition: wingdi.h:586
int WINAPI SaveDC(_In_ HDC)
HBRUSH WINAPI CreatePatternBrush(_In_ HBITMAP)
#define MAKEROP4(f, b)
Definition: wingdi.h:3392
int WINAPI SetPolyFillMode(_In_ HDC, _In_ int)
Definition: dc.c:1174
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
DWORD WINAPI GetSysColor(_In_ int)
#define DT_NOPREFIX
Definition: winuser.h:537
#define COLOR_HIGHLIGHT
Definition: winuser.h:937
#define DT_NOCLIP
Definition: winuser.h:536
#define DT_LEFT
Definition: winuser.h:534
#define DT_TOP
Definition: winuser.h:542
#define DT_WORDBREAK
Definition: winuser.h:544
HDC WINAPI GetDC(_In_opt_ HWND)
#define DT_EXPANDTABS
Definition: winuser.h:532
#define DT_EDITCONTROL
Definition: winuser.h:528
static HDC hdcSrc
Definition: xlate.c:32
unsigned char BYTE
Definition: xxhash.c:193