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, 127 (x1 * (b - a) + x2 * a) / b - radius, 128 (y1 * (b - a) + y2 * a) / b - radius, 129 (x1 * (b - a) + x2 * a) / b + radius, 130 (y1 * (b - a) + y2 * a) / b + radius); 131 DeleteObject(SelectObject(hdc, oldBrush)); 132 DeleteObject(SelectObject(hdc, oldPen)); 133 } 134 135 void 136 Replace(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LONG radius) 137 { 138 LONG a, b, x, y; 139 b = max(1, max(abs(x2 - x1), abs(y2 - y1))); 140 141 for(a = 0; a <= b; a++) 142 for(y = (y1 * (b - a) + y2 * a) / b - radius + 1; 143 y < (y1 * (b - a) + y2 * a) / b + radius + 1; y++) 144 for(x = (x1 * (b - a) + x2 * a) / b - radius + 1; 145 x < (x1 * (b - a) + x2 * a) / b + radius + 1; x++) 146 if (GetPixel(hdc, x, y) == fg) 147 SetPixel(hdc, x, y, bg); 148 } 149 150 void 151 Airbrush(HDC hdc, LONG x, LONG y, COLORREF color, LONG r) 152 { 153 LONG a, b; 154 155 for(b = -r; b <= r; b++) 156 for(a = -r; a <= r; a++) 157 if ((a * a + b * b <= r * r) && (rand() % 4 == 0)) 158 SetPixel(hdc, x + a, y + b, color); 159 } 160 161 void 162 Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG style) 163 { 164 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, color)); 165 HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(color)); 166 LONG a, b; 167 b = max(1, max(abs(x2 - x1), abs(y2 - y1))); 168 switch (style) 169 { 170 case 0: 171 for(a = 0; a <= b; a++) 172 Ellipse(hdc, (x1 * (b - a) + x2 * a) / b - 3, (y1 * (b - a) + y2 * a) / b - 3, 173 (x1 * (b - a) + x2 * a) / b + 4, (y1 * (b - a) + y2 * a) / b + 4); 174 break; 175 case 1: 176 for(a = 0; a <= b; a++) 177 Ellipse(hdc, 178 (x1 * (b - a) + x2 * a) / b - 2, 179 (y1 * (b - a) + y2 * a) / b - 2, 180 (x1 * (b - a) + x2 * a) / b + 2, 181 (y1 * (b - a) + y2 * a) / b + 2); 182 break; 183 case 2: 184 MoveToEx(hdc, x1, y1, NULL); 185 LineTo(hdc, x2, y2); 186 SetPixel(hdc, x2, y2, color); 187 break; 188 case 3: 189 for(a = 0; a <= b; a++) 190 Rectangle(hdc, 191 (x1 * (b - a) + x2 * a) / b - 4, 192 (y1 * (b - a) + y2 * a) / b - 4, 193 (x1 * (b - a) + x2 * a) / b + 4, 194 (y1 * (b - a) + y2 * a) / b + 4); 195 break; 196 case 4: 197 for(a = 0; a <= b; a++) 198 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 2, (y1 * (b - a) + y2 * a) / b - 2, 199 (x1 * (b - a) + x2 * a) / b + 3, (y1 * (b - a) + y2 * a) / b + 3); 200 break; 201 case 5: 202 for(a = 0; a <= b; a++) 203 Rectangle(hdc, (x1 * (b - a) + x2 * a) / b - 1, (y1 * (b - a) + y2 * a) / b - 1, 204 (x1 * (b - a) + x2 * a) / b + 1, (y1 * (b - a) + y2 * a) / b + 1); 205 break; 206 case 6: 207 case 7: 208 case 8: 209 case 9: 210 case 10: 211 case 11: 212 { 213 POINT offsTop[] = {{3, -3}, {2, -2}, {0, 0}, 214 {-4, -4}, {-2, -2}, {-1, 0}}; 215 POINT offsBtm[] = {{-3, 3}, {-2, 2}, {-1, 1}, 216 {3, 3}, {2, 2}, {0, 1}}; 217 LONG idx = style - 6; 218 POINT pts[4]; 219 pts[0].x = x1 + offsTop[idx].x; 220 pts[0].y = y1 + offsTop[idx].y; 221 pts[1].x = x1 + offsBtm[idx].x; 222 pts[1].y = y1 + offsBtm[idx].y; 223 pts[2].x = x2 + offsBtm[idx].x; 224 pts[2].y = y2 + offsBtm[idx].y; 225 pts[3].x = x2 + offsTop[idx].x; 226 pts[3].y = y2 + offsTop[idx].y; 227 Polygon(hdc, pts, 4); 228 break; 229 } 230 } 231 DeleteObject(SelectObject(hdc, oldBrush)); 232 DeleteObject(SelectObject(hdc, oldPen)); 233 } 234 235 void 236 RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2) 237 { 238 HBRUSH oldBrush; 239 LOGBRUSH logbrush; 240 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_DOT, 1, GetSysColor(COLOR_HIGHLIGHT))); 241 UINT oldRop = GetROP2(hdc); 242 243 SetROP2(hdc, R2_NOTXORPEN); 244 245 logbrush.lbStyle = BS_HOLLOW; 246 logbrush.lbColor = 0; 247 logbrush.lbHatch = 0; 248 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush)); 249 Rectangle(hdc, x1, y1, x2, y2); 250 DeleteObject(SelectObject(hdc, oldBrush)); 251 DeleteObject(SelectObject(hdc, oldPen)); 252 253 SetROP2(hdc, oldRop); 254 } 255 256 void 257 Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style) 258 { 259 INT iSaveDC = SaveDC(hdc); // We will modify the clipping region. Save now. 260 261 RECT rc; 262 SetRect(&rc, x1, y1, x2, y2); 263 264 if (style == 0) // Transparent 265 { 266 SetBkMode(hdc, TRANSPARENT); 267 GetBkColor(hdc); 268 } 269 else // Opaque 270 { 271 SetBkMode(hdc, OPAQUE); 272 SetBkColor(hdc, bg); 273 274 HBRUSH hbr = CreateSolidBrush(bg); 275 FillRect(hdc, &rc, hbr); // Fill the background 276 DeleteObject(hbr); 277 } 278 279 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); 280 281 HGDIOBJ hFontOld = SelectObject(hdc, font); 282 SetTextColor(hdc, fg); 283 const UINT uFormat = DT_LEFT | DT_TOP | DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | 284 DT_EXPANDTABS | DT_WORDBREAK; 285 DrawText(hdc, lpchText, -1, &rc, uFormat); 286 SelectObject(hdc, hFontOld); 287 288 RestoreDC(hdc, iSaveDC); // Restore 289 } 290 291 BOOL 292 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, 293 HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, 294 HBITMAP hbmMask, COLORREF keyColor) 295 { 296 HDC hTempDC1, hTempDC2; 297 HBITMAP hbmTempColor, hbmTempMask; 298 HGDIOBJ hbmOld1, hbmOld2; 299 300 if (hbmMask == NULL) 301 { 302 if (keyColor == CLR_INVALID) 303 { 304 ::StretchBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, 305 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, SRCCOPY); 306 } 307 else 308 { 309 ::GdiTransparentBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, 310 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, keyColor); 311 } 312 return TRUE; 313 } 314 else if (nWidth == nSrcWidth && nHeight == nSrcHeight && keyColor == CLR_INVALID) 315 { 316 ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, 317 hdcSrc, nXSrc, nYSrc, hbmMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029)); 318 return TRUE; 319 } 320 321 hTempDC1 = ::CreateCompatibleDC(hdcDest); 322 hTempDC2 = ::CreateCompatibleDC(hdcDest); 323 hbmTempMask = ::CreateBitmap(nWidth, nHeight, 1, 1, NULL); 324 hbmTempColor = CreateColorDIB(nWidth, nHeight, RGB(255, 255, 255)); 325 326 // hbmTempMask <-- hbmMask (stretched) 327 hbmOld1 = ::SelectObject(hTempDC1, hbmMask); 328 hbmOld2 = ::SelectObject(hTempDC2, hbmTempMask); 329 ::StretchBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC1, 0, 0, nSrcWidth, nSrcHeight, SRCCOPY); 330 ::SelectObject(hTempDC2, hbmOld2); 331 ::SelectObject(hTempDC1, hbmOld1); 332 333 hbmOld1 = ::SelectObject(hTempDC1, hbmTempColor); 334 if (keyColor == CLR_INVALID) 335 { 336 // hbmTempColor <-- hdcSrc (stretched) 337 ::StretchBlt(hTempDC1, 0, 0, nWidth, nHeight, 338 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, SRCCOPY); 339 340 // hdcDest <-- hbmTempColor (masked) 341 ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hTempDC1, 0, 0, 342 hbmTempMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029)); 343 } 344 else 345 { 346 // hbmTempColor <-- hdcDest 347 ::BitBlt(hTempDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY); 348 349 // hbmTempColor <-- hdcSrc (color key) 350 ::GdiTransparentBlt(hTempDC1, 0, 0, nWidth, nHeight, 351 hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, keyColor); 352 353 // hdcDest <-- hbmTempColor (masked) 354 ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hTempDC1, 0, 0, 355 hbmTempMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029)); 356 } 357 ::SelectObject(hTempDC1, hbmOld1); 358 359 ::DeleteObject(hbmTempColor); 360 ::DeleteObject(hbmTempMask); 361 ::DeleteDC(hTempDC2); 362 ::DeleteDC(hTempDC1); 363 364 return TRUE; 365 } 366 367 void DrawXorRect(HDC hdc, const RECT *prc) 368 { 369 HGDIOBJ oldPen = ::SelectObject(hdc, ::CreatePen(PS_SOLID, 0, RGB(255, 255, 255))); 370 HGDIOBJ oldBrush = ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); 371 INT oldRop2 = SetROP2(hdc, R2_XORPEN); 372 ::Rectangle(hdc, prc->left, prc->top, prc->right, prc->bottom); 373 ::SetROP2(hdc, oldRop2); 374 ::SelectObject(hdc, oldBrush); 375 ::DeleteObject(::SelectObject(hdc, oldPen)); 376 } 377