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, HBITMAP hbmMask, int xMask, int yMask, 294 DWORD dwRop, COLORREF keyColor) 295 { 296 HDC hTempDC; 297 HDC hTempDC2; 298 HBITMAP hTempBm; 299 HBRUSH hTempBrush; 300 HBITMAP hTempMask; 301 302 hTempDC = CreateCompatibleDC(hdcSrc); 303 hTempDC2 = CreateCompatibleDC(hdcSrc); 304 hTempBm = CreateCompatibleBitmap(hTempDC, nWidth, nHeight); 305 SelectObject(hTempDC, hTempBm); 306 hTempBrush = CreateSolidBrush(keyColor); 307 SelectObject(hTempDC, hTempBrush); 308 BitBlt(hTempDC, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY); 309 PatBlt(hTempDC, 0, 0, nWidth, nHeight, PATINVERT); 310 hTempMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL); 311 SelectObject(hTempDC2, hTempMask); 312 BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, 0, 0, SRCCOPY); 313 SelectObject(hTempDC, hbmMask); 314 BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, xMask, yMask, SRCAND); 315 MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hTempMask, xMask, yMask, dwRop); 316 DeleteDC(hTempDC); 317 DeleteDC(hTempDC2); 318 DeleteObject(hTempBm); 319 DeleteObject(hTempBrush); 320 DeleteObject(hTempMask); 321 return TRUE; 322 } 323