2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gdi_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
28 /***********************************************************************
31 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
32 INT width, INT height, DWORD rop)
34 DC * dc = DC_GetDCUpdate( hdc );
37 if (!dc) return FALSE;
39 if (dc->funcs->pPatBlt)
41 TRACE("%p %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
42 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
44 GDI_ReleaseObj( hdc );
49 /***********************************************************************
52 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
53 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
58 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
59 /* FIXME: there is a race condition here */
60 if ((dcDst = DC_GetDCUpdate( hdcDst )))
62 dcSrc = DC_GetDCPtr( hdcSrc );
63 TRACE("hdcSrc=%p %d,%d -> hdcDest=%p %d,%d %dx%d rop=%06lx\n",
64 hdcSrc, xSrc, ySrc, hdcDst, xDst, yDst, width, height, rop);
65 if (dcDst->funcs->pBitBlt)
66 ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
67 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
68 if (dcSrc) GDI_ReleaseObj( hdcSrc );
69 GDI_ReleaseObj( hdcDst );
75 /***********************************************************************
76 * StretchBlt (GDI32.@)
78 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
79 INT widthDst, INT heightDst,
80 HDC hdcSrc, INT xSrc, INT ySrc,
81 INT widthSrc, INT heightSrc,
87 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
88 /* FIXME: there is a race condition here */
89 if ((dcDst = DC_GetDCUpdate( hdcDst )))
91 dcSrc = DC_GetDCPtr( hdcSrc );
93 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06lx\n",
94 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
95 hdcDst, xDst, yDst, widthDst, heightDst, rop );
98 if (dcDst->funcs->pStretchBlt)
99 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
100 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
102 GDI_ReleaseObj( hdcSrc );
104 GDI_ReleaseObj( hdcDst );
109 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
110 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
112 /***********************************************************************
115 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
116 INT nWidth, INT nHeight, HDC hdcSrc,
117 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
118 INT xMask, INT yMask, DWORD dwRop)
120 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
122 HBRUSH hbrMask, hbrDst, hbrTmp;
124 static const DWORD ROP3Table[256] =
126 0x00000042, 0x00010289,
127 0x00020C89, 0x000300AA,
128 0x00040C88, 0x000500A9,
129 0x00060865, 0x000702C5,
130 0x00080F08, 0x00090245,
131 0x000A0329, 0x000B0B2A,
132 0x000C0324, 0x000D0B25,
133 0x000E08A5, 0x000F0001,
134 0x00100C85, 0x001100A6,
135 0x00120868, 0x001302C8,
136 0x00140869, 0x001502C9,
137 0x00165CCA, 0x00171D54,
138 0x00180D59, 0x00191CC8,
139 0x001A06C5, 0x001B0768,
140 0x001C06CA, 0x001D0766,
141 0x001E01A5, 0x001F0385,
142 0x00200F09, 0x00210248,
143 0x00220326, 0x00230B24,
144 0x00240D55, 0x00251CC5,
145 0x002606C8, 0x00271868,
146 0x00280369, 0x002916CA,
147 0x002A0CC9, 0x002B1D58,
148 0x002C0784, 0x002D060A,
149 0x002E064A, 0x002F0E2A,
150 0x0030032A, 0x00310B28,
151 0x00320688, 0x00330008,
152 0x003406C4, 0x00351864,
153 0x003601A8, 0x00370388,
154 0x0038078A, 0x00390604,
155 0x003A0644, 0x003B0E24,
156 0x003C004A, 0x003D18A4,
157 0x003E1B24, 0x003F00EA,
158 0x00400F0A, 0x00410249,
159 0x00420D5D, 0x00431CC4,
160 0x00440328, 0x00450B29,
161 0x004606C6, 0x0047076A,
162 0x00480368, 0x004916C5,
163 0x004A0789, 0x004B0605,
164 0x004C0CC8, 0x004D1954,
165 0x004E0645, 0x004F0E25,
166 0x00500325, 0x00510B26,
167 0x005206C9, 0x00530764,
168 0x005408A9, 0x00550009,
169 0x005601A9, 0x00570389,
170 0x00580785, 0x00590609,
171 0x005A0049, 0x005B18A9,
172 0x005C0649, 0x005D0E29,
173 0x005E1B29, 0x005F00E9,
174 0x00600365, 0x006116C6,
175 0x00620786, 0x00630608,
176 0x00640788, 0x00650606,
177 0x00660046, 0x006718A8,
178 0x006858A6, 0x00690145,
179 0x006A01E9, 0x006B178A,
180 0x006C01E8, 0x006D1785,
181 0x006E1E28, 0x006F0C65,
182 0x00700CC5, 0x00711D5C,
183 0x00720648, 0x00730E28,
184 0x00740646, 0x00750E26,
185 0x00761B28, 0x007700E6,
186 0x007801E5, 0x00791786,
187 0x007A1E29, 0x007B0C68,
188 0x007C1E24, 0x007D0C69,
189 0x007E0955, 0x007F03C9,
190 0x008003E9, 0x00810975,
191 0x00820C49, 0x00831E04,
192 0x00840C48, 0x00851E05,
193 0x008617A6, 0x008701C5,
194 0x008800C6, 0x00891B08,
195 0x008A0E06, 0x008B0666,
196 0x008C0E08, 0x008D0668,
197 0x008E1D7C, 0x008F0CE5,
198 0x00900C45, 0x00911E08,
199 0x009217A9, 0x009301C4,
200 0x009417AA, 0x009501C9,
201 0x00960169, 0x0097588A,
202 0x00981888, 0x00990066,
203 0x009A0709, 0x009B07A8,
204 0x009C0704, 0x009D07A6,
205 0x009E16E6, 0x009F0345,
206 0x00A000C9, 0x00A11B05,
207 0x00A20E09, 0x00A30669,
208 0x00A41885, 0x00A50065,
209 0x00A60706, 0x00A707A5,
210 0x00A803A9, 0x00A90189,
211 0x00AA0029, 0x00AB0889,
212 0x00AC0744, 0x00AD06E9,
213 0x00AE0B06, 0x00AF0229,
214 0x00B00E05, 0x00B10665,
215 0x00B21974, 0x00B30CE8,
216 0x00B4070A, 0x00B507A9,
217 0x00B616E9, 0x00B70348,
218 0x00B8074A, 0x00B906E6,
219 0x00BA0B09, 0x00BB0226,
220 0x00BC1CE4, 0x00BD0D7D,
221 0x00BE0269, 0x00BF08C9,
222 0x00C000CA, 0x00C11B04,
223 0x00C21884, 0x00C3006A,
224 0x00C40E04, 0x00C50664,
225 0x00C60708, 0x00C707AA,
226 0x00C803A8, 0x00C90184,
227 0x00CA0749, 0x00CB06E4,
228 0x00CC0020, 0x00CD0888,
229 0x00CE0B08, 0x00CF0224,
230 0x00D00E0A, 0x00D1066A,
231 0x00D20705, 0x00D307A4,
232 0x00D41D78, 0x00D50CE9,
233 0x00D616EA, 0x00D70349,
234 0x00D80745, 0x00D906E8,
235 0x00DA1CE9, 0x00DB0D75,
236 0x00DC0B04, 0x00DD0228,
237 0x00DE0268, 0x00DF08C8,
238 0x00E003A5, 0x00E10185,
239 0x00E20746, 0x00E306EA,
240 0x00E40748, 0x00E506E5,
241 0x00E61CE8, 0x00E70D79,
242 0x00E81D74, 0x00E95CE6,
243 0x00EA02E9, 0x00EB0849,
244 0x00EC02E8, 0x00ED0848,
245 0x00EE0086, 0x00EF0A08,
246 0x00F00021, 0x00F10885,
247 0x00F20B05, 0x00F3022A,
248 0x00F40B0A, 0x00F50225,
249 0x00F60265, 0x00F708C5,
250 0x00F802E5, 0x00F90845,
251 0x00FA0089, 0x00FB0A09,
252 0x00FC008A, 0x00FD0A0A,
253 0x00FE02A9, 0x00FF0062,
257 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
259 hbrMask = CreatePatternBrush(hbmMask);
260 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
263 hDC1 = CreateCompatibleDC(hdcDest);
264 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
265 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
267 /* draw using bkgnd rop */
268 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
269 hbrTmp = SelectObject(hDC1, hbrDst);
270 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
271 SelectObject(hDC1, hbrTmp);
274 hDC2 = CreateCompatibleDC(hdcDest);
275 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
276 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
278 /* draw using foregnd rop */
279 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
280 hbrTmp = SelectObject(hDC2, hbrDst);
281 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
283 /* combine both using the mask as a pattern brush */
284 SelectObject(hDC2, hbrMask);
285 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
286 SelectObject(hDC2, hbrTmp);
289 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
291 /* restore all objects */
292 SelectObject(hdcDest, hbrDst);
293 SelectObject(hDC1, hOldBitmap1);
294 SelectObject(hDC2, hOldBitmap2);
296 /* delete all temp objects */
297 DeleteObject(hBitmap1);
298 DeleteObject(hBitmap1);
299 DeleteObject(hbrMask);
307 /******************************************************************************
308 * GdiTransparentBlt [GDI32.@]
310 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
311 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
319 HBITMAP bmpMask = NULL;
320 HBITMAP oldMask = NULL;
321 COLORREF oldBackground;
322 COLORREF oldForeground;
325 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
326 TRACE("Can not mirror\n");
330 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
331 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
334 oldStretchMode = GetStretchBltMode(hdcSrc);
335 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
336 SetStretchBltMode(hdcSrc, COLORONCOLOR);
337 hdcWork = CreateCompatibleDC(hdcDest);
338 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
339 oldWork = SelectObject(hdcWork, bmpWork);
340 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
341 TRACE("Failed to stretch\n");
344 SetBkColor(hdcWork, crTransparent);
347 hdcMask = CreateCompatibleDC(hdcDest);
348 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
349 oldMask = SelectObject(hdcMask, bmpMask);
350 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
351 TRACE("Failed to create mask\n");
355 /* Replace transparent color with black */
356 SetBkColor(hdcWork, RGB(0,0,0));
357 SetTextColor(hdcWork, RGB(255,255,255));
358 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
359 TRACE("Failed to mask out background\n");
363 /* Replace non-transparent area on destination with black */
364 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
365 TRACE("Failed to clear destination area\n");
370 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
371 TRACE("Failed to paint image\n");
377 SetStretchBltMode(hdcSrc, oldStretchMode);
378 SetBkColor(hdcDest, oldBackground);
379 SetTextColor(hdcDest, oldForeground);
381 SelectObject(hdcWork, oldWork);
384 if(bmpWork) DeleteObject(bmpWork);
386 SelectObject(hdcMask, oldMask);
389 if(bmpMask) DeleteObject(bmpMask);
393 /******************************************************************************
394 * GdiAlphaBlend [GDI32.@]
396 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
397 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
398 BLENDFUNCTION blendFunction)
403 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
404 /* FIXME: there is a race condition here */
405 if ((dcDst = DC_GetDCUpdate( hdcDst )))
407 dcSrc = DC_GetDCPtr( hdcSrc );
408 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
409 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
410 hdcDst, xDst, yDst, widthDst, heightDst,
411 blendFunction.BlendOp, blendFunction.BlendFlags,
412 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
413 if (dcDst->funcs->pAlphaBlend)
414 ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
415 dcSrc ? dcSrc->physDev : NULL,
416 xSrc, ySrc, widthSrc, heightSrc, blendFunction );
417 if (dcSrc) GDI_ReleaseObj( hdcSrc );
418 GDI_ReleaseObj( hdcDst );
423 /*********************************************************************
427 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
428 HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
429 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
431 FIXME("PlgBlt, stub\n");