1 /* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL 4 * FILE: base/applications/mspaint/drawing.cpp 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 = (HPEN) 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 = (HPEN) 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 = (HBRUSH) 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 = (HPEN) 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 = (HBRUSH) 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 = (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 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, BOOL inverted) 71 { 72 LOGBRUSH logbrush; 73 HBRUSH oldBrush; 74 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, fg)); 75 UINT oldRop = GetROP2(hdc); 76 77 if (inverted) 78 SetROP2(hdc, R2_NOTXORPEN); 79 80 logbrush.lbStyle = (style == 0) ? BS_HOLLOW : BS_SOLID; 81 logbrush.lbColor = (style == 2) ? fg : bg; 82 logbrush.lbHatch = 0; 83 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush)); 84 if (closed) 85 Polygon(hdc, lpPoints, nCount); 86 else 87 Polyline(hdc, lpPoints, nCount); 88 DeleteObject(SelectObject(hdc, oldBrush)); 89 DeleteObject(SelectObject(hdc, oldPen)); 90 91 SetROP2(hdc, oldRop); 92 } 93 94 void 95 Bezier(HDC hdc, POINT p1, POINT p2, POINT p3, POINT p4, COLORREF color, int thickness) 96 { 97 HPEN oldPen; 98 POINT fourPoints[4]; 99 fourPoints[0] = p1; 100 fourPoints[1] = p2; 101 fourPoints[2] = p3; 102 fourPoints[3] = p4; 103 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, thickness, color)); 104 PolyBezier(hdc, fourPoints, 4); 105 DeleteObject(SelectObject(hdc, oldPen)); 106 } 107 108 void 109 Fill(HDC hdc, LONG x, LONG y, COLORREF color) 110 { 111 HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(color)); 112 ExtFloodFill(hdc, x, y, GetPixel(hdc, x, y), FLOODFILLSURFACE); 113 DeleteObject(SelectObject(hdc, oldBrush)); 114 } 115 116 void 117 Erase(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG radius) 118 { 119 LONG a, b; 120 HPEN oldPen; 121 HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(color)); 122 123 b = max(1, max(abs(x2 - x1), abs(y2 - y1))); 124 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, color)); 125 for(a = 0; a <= b; a++) 126 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - radius + 1, 127 (y1 * (b - a) + y2 * a) / b - radius + 1, (x1 * (b - a) + x2 * a) / b + radius + 1, 128 (y1 * (b - a) + y2 * a) / b + radius + 1); 129 DeleteObject(SelectObject(hdc, oldBrush)); 130 DeleteObject(SelectObject(hdc, oldPen)); 131 } 132 133 void 134 Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LONG radius) 135 { 136 LONG a, b, x, y; 137 b = max(1, max(abs(x2 - x1), abs(y2 - y1))); 138 139 for(a = 0; a <= b; a++) 140 for(y = (y1 * (b - a) + y2 * a) / b - radius + 1; 141 y < (y1 * (b - a) + y2 * a) / b + radius + 1; y++) 142 for(x = (x1 * (b - a) + x2 * a) / b - radius + 1; 143 x < (x1 * (b - a) + x2 * a) / b + radius + 1; x++) 144 if (GetPixel(hdc, x, y) == fg) 145 SetPixel(hdc, x, y, bg); 146 } 147 148 void 149 Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r) 150 { 151 LONG a, b; 152 153 for(b = -r; b <= r; b++) 154 for(a = -r; a <= r; a++) 155 if ((a * a + b * b <= r * r) && (rand() % 4 == 0)) 156 SetPixel(hdc, x + a, y + b, color); 157 } 158 159 void 160 Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style) 161 { 162 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, color)); 163 HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(color)); 164 LONG a, b; 165 b = max(1, max(abs(x2 - x1), abs(y2 - y1))); 166 switch (style) 167 { 168 case 0: 169 for(a = 0; a <= b; a++) 170 Ellipse(hdc, (x1 * (b - a) + x2 * a) / b - 3, (y1 * (b - a) + y2 * a) / b - 3, 171 (x1 * (b - a) + x2 * a) / b + 4, (y1 * (b - a) + y2 * a) / b + 4); 172 break; 173 case 1: 174 for(a = 0; a <= b; a++) 175 Ellipse(hdc, (x1 * (b - a) + x2 * a) / b - 1, (y1 * (b - a) + y2 * a) / b - 1, 176 (x1 * (b - a) + x2 * a) / b + 3, (y1 * (b - a) + y2 * a) / b + 3); 177 break; 178 case 2: 179 MoveToEx(hdc, x1, y1, NULL); 180 LineTo(hdc, x2, y2); 181 SetPixel(hdc, x2, y2, color); 182 break; 183 case 3: 184 for(a = 0; a <= b; a++) 185 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 3, (y1 * (b - a) + y2 * a) / b - 3, 186 (x1 * (b - a) + x2 * a) / b + 5, (y1 * (b - a) + y2 * a) / b + 5); 187 break; 188 case 4: 189 for(a = 0; a <= b; a++) 190 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 2, (y1 * (b - a) + y2 * a) / b - 2, 191 (x1 * (b - a) + x2 * a) / b + 3, (y1 * (b - a) + y2 * a) / b + 3); 192 break; 193 case 5: 194 for(a = 0; a <= b; a++) 195 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 1, (y1 * (b - a) + y2 * a) / b - 1, 196 (x1 * (b - a) + x2 * a) / b + 1, (y1 * (b - a) + y2 * a) / b + 1); 197 break; 198 case 6: 199 case 7: 200 case 8: 201 case 9: 202 case 10: 203 case 11: 204 { 205 POINT offsTop[] = {{4, -3}, {2, -2}, {0, 0}, 206 {-3, -3}, {-2, -2}, {-1, 0}}; 207 POINT offsBtm[] = {{-3, 4}, {-2, 2}, {-1, 1}, 208 {4, 4}, {2, 2}, {0, 1}}; 209 LONG idx = style - 6; 210 POINT pts[4]; 211 pts[0].x = x1 + offsTop[idx].x; 212 pts[0].y = y1 + offsTop[idx].y; 213 pts[1].x = x1 + offsBtm[idx].x; 214 pts[1].y = y1 + offsBtm[idx].y; 215 pts[2].x = x2 + offsBtm[idx].x; 216 pts[2].y = y2 + offsBtm[idx].y; 217 pts[3].x = x2 + offsTop[idx].x; 218 pts[3].y = y2 + offsTop[idx].y; 219 Polygon(hdc, pts, 4); 220 break; 221 } 222 } 223 DeleteObject(SelectObject(hdc, oldBrush)); 224 DeleteObject(SelectObject(hdc, oldPen)); 225 } 226 227 void 228 RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2) 229 { 230 HBRUSH oldBrush; 231 LOGBRUSH logbrush; 232 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_DOT, 1, GetSysColor(COLOR_HIGHLIGHT))); 233 UINT oldRop = GetROP2(hdc); 234 235 SetROP2(hdc, R2_NOTXORPEN); 236 237 logbrush.lbStyle = BS_HOLLOW; 238 logbrush.lbColor = 0; 239 logbrush.lbHatch = 0; 240 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush)); 241 Rectangle(hdc, x1, y1, x2, y2); 242 DeleteObject(SelectObject(hdc, oldBrush)); 243 DeleteObject(SelectObject(hdc, oldPen)); 244 245 SetROP2(hdc, oldRop); 246 } 247 248 void 249 SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF system_selection_color) 250 { 251 HBRUSH oldBrush; 252 LOGBRUSH logbrush; 253 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_DOT, 1, system_selection_color)); 254 255 logbrush.lbStyle = BS_HOLLOW; 256 logbrush.lbColor = 0; 257 logbrush.lbHatch = 0; 258 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush)); 259 Rectangle(hdc, x1, y1, x2, y2); /* SEL BOX FRAME */ 260 DeleteObject(SelectObject(hdc, oldBrush)); 261 DeleteObject(SelectObject(hdc, oldPen)); 262 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, system_selection_color)); 263 oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(system_selection_color)); 264 Rectangle(hdc, x1 - 1, y1 - 1, x1 + 2, y1 + 2); 265 Rectangle(hdc, x2 - 2, y1 - 1, x2 + 2, y1 + 2); 266 Rectangle(hdc, x1 - 1, y2 - 2, x1 + 2, y2 + 1); 267 Rectangle(hdc, x2 - 2, y2 - 2, x2 + 2, y2 + 1); 268 Rectangle(hdc, (x1 + x2) / 2 - 1, y1 - 1, (x1 + x2) / 2 + 2, y1 + 2); 269 Rectangle(hdc, (x1 + x2) / 2 - 1, y2 - 2, (x1 + x2) / 2 + 2, y2 + 1); 270 Rectangle(hdc, x1 - 1, (y1 + y2) / 2 - 1, x1 + 2, (y1 + y2) / 2 + 2); 271 Rectangle(hdc, x2 - 2, (y1 + y2) / 2 - 1, x2 + 1, (y1 + y2) / 2 + 2); 272 DeleteObject(SelectObject(hdc, oldBrush)); 273 DeleteObject(SelectObject(hdc, oldPen)); 274 } 275 276 void 277 Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style) 278 { 279 INT iSaveDC = SaveDC(hdc); // We will modify the clipping region. Save now. 280 281 RECT rc; 282 SetRect(&rc, x1, y1, x2, y2); 283 284 if (style == 0) // Transparent 285 { 286 SetBkMode(hdc, TRANSPARENT); 287 GetBkColor(hdc); 288 } 289 else // Opaque 290 { 291 SetBkMode(hdc, OPAQUE); 292 SetBkColor(hdc, bg); 293 294 HBRUSH hbr = CreateSolidBrush(bg); 295 FillRect(hdc, &rc, hbr); // Fill the background 296 DeleteObject(hbr); 297 } 298 299 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); 300 301 HGDIOBJ hFontOld = SelectObject(hdc, font); 302 SetTextColor(hdc, fg); 303 const UINT uFormat = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | 304 DT_EXPANDTABS | DT_WORDBREAK; 305 DrawText(hdc, lpchText, -1, &rc, uFormat); 306 SelectObject(hdc, hFontOld); 307 308 RestoreDC(hdc, iSaveDC); // Restore 309 } 310 311 BOOL 312 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, 313 HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask, 314 DWORD dwRop, COLORREF keyColor) 315 { 316 HDC hTempDC; 317 HDC hTempDC2; 318 HBITMAP hTempBm; 319 HBRUSH hTempBrush; 320 HBITMAP hTempMask; 321 322 hTempDC = CreateCompatibleDC(hdcSrc); 323 hTempDC2 = CreateCompatibleDC(hdcSrc); 324 hTempBm = CreateCompatibleBitmap(hTempDC, nWidth, nHeight); 325 SelectObject(hTempDC, hTempBm); 326 hTempBrush = CreateSolidBrush(keyColor); 327 SelectObject(hTempDC, hTempBrush); 328 BitBlt(hTempDC, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY); 329 PatBlt(hTempDC, 0, 0, nWidth, nHeight, PATINVERT); 330 hTempMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL); 331 SelectObject(hTempDC2, hTempMask); 332 BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, 0, 0, SRCCOPY); 333 SelectObject(hTempDC, hbmMask); 334 BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, xMask, yMask, SRCAND); 335 MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hTempMask, xMask, yMask, dwRop); 336 DeleteDC(hTempDC); 337 DeleteDC(hTempDC2); 338 DeleteObject(hTempBm); 339 DeleteObject(hTempBrush); 340 DeleteObject(hTempMask); 341 return TRUE; 342 } 343