DIB Engine:dont use now missing winex11.drv BitBlt and PatBlt funcs
[wine/hacks.git] / dlls / winedib.drv / bitblt.c
blob680e1fdd04116d5f69fa2606f3e47d86d5630269
1 /*
2 * DIBDRV bit-blit operations
4 * Copyright 2009 Massimo Del Fedele
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include "dibdrv.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
28 void CheckMapping(const char *func, const char *s, DIBDRVPHYSDEV *physDev)
30 int a, b;
32 if(!physDev)
33 return;
35 a=10;b=20;
36 _DIBDRV_Position_ws2ds(physDev, &a, &b);
37 if(a != 10 || b != 20)
38 FIXME("%s:%s:Position(10, 20) translated to(%d, %d)\n", func, s, a, b);
39 a=10;b=20;
40 _DIBDRV_Sizes_ws2ds(physDev, &a, &b);
41 if(a != 10 || b != 20)
42 FIXME("%s:%s:sizes (10, 20) translated to(%d, %d)\n", func, s, a, b);
45 static inline void intSwap(int *a, int *b)
47 int tmp;
48 tmp = *a;
49 *a = *b;
50 *b = tmp;
53 static inline void setRect(RECT *r, int x1, int y1, int x2, int y2)
55 r->left = x1;
56 r->top = y1;
57 r->right = x2;
58 r->bottom = y2;
61 static inline void setPoint(POINT *p, int x, int y)
63 p->x = x;
64 p->y = y;
67 static inline void setSize(SIZE *sz, int cx, int cy)
69 sz->cx = cx;
70 sz->cy = cy;
73 /* clips a source and destination areas to their respective clip rectangles
74 returning both source and dest modified; result is TRUE if clipping
75 leads to a non null rectangle, FALSE otherwise */
76 static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*dstClip)
78 int xs1, ys1, xs2, ys2;
79 int xsc1, ysc1, xsc2, ysc2;
80 int xd1, yd1, xd2, yd2;
81 int xdc1, ydc1, xdc2, ydc2;
82 int w, h, dx, dy;
84 /* extract sizes */
85 w = sz->cx; h = sz->cy;
87 /* if sizes null or negative, just return false */
88 if(w <= 0 || h <= 0)
89 return FALSE;
91 /* extract dest area data */
92 xd1 = pd->x;
93 yd1 = pd->y;
94 xd2 = xd1 + w;
95 yd2 = yd1 + h;
97 /* extract source data */
98 xs1 = ps->x;
99 ys1 = ps->y;
100 xs2 = xs1 + w;
101 ys2 = ys1 + h;
103 /* if source clip area is not null, do first clipping on it */
104 if(srcClip)
106 /* extract source clipping area */
107 xsc1 = srcClip->left;
108 ysc1 = srcClip->top;
109 xsc2 = srcClip->right;
110 ysc2 = srcClip->bottom;
112 /* order clip area rectangle points */
113 if(xsc1 > xsc2) intSwap(&xsc1, &xsc2);
114 if(ysc1 > ysc2) intSwap(&ysc1, &ysc2);
116 /* clip on source clipping start point */
117 if(xs1 < xsc1) { dx = xsc1 - xs1; w -= dx; xd1 += dx; xs1 = xsc1; }
118 if(ys1 < ysc1) { dy = ysc1 - ys1; h -= dy; yd1 += dy; ys1 = ysc1; }
120 /* clip on source clipping end point */
121 if(xs2 > xsc2) { dx = xs2 - xsc2; w -= dx; xd2 -= dx; xs2 = xsc2; }
122 if(ys2 > ysc2) { dy = ys2 - ysc2; h -= dy; yd2 -= dy; ys2 = ysc2; }
124 /* if already zero area, return false */
125 if(w <= 0 || h <= 0)
126 return FALSE;
128 /* now do clipping on destination area */
129 if(dstClip)
131 /* extract destination clipping area */
132 xdc1 = dstClip->left;
133 ydc1 = dstClip->top;
134 xdc2 = dstClip->right;
135 ydc2 = dstClip->bottom;
137 /* order clip area rectangle points */
138 if(xdc1 > xdc2) intSwap(&xdc1, &xdc2);
139 if(ydc1 > ydc2) intSwap(&ydc1, &ydc2);
141 /* clip on dest clipping start point */
142 if(xd1 < xdc1) { dx = xdc1 - xd1; w -= dx; xs1 += dx; xd1 = xdc1; }
143 if(yd1 < ydc1) { dy = ydc1 - yd1; h -= dy; ys1 += dy; yd1 = ydc1; }
145 /* clip on dest clipping end point */
146 if(xd2 > xdc2) { dx = xd2 - xdc2; w -= dx; xs2 -= dx; xd2 = xdc2; }
147 if(yd2 > ydc2) { dy = yd2 - ydc2; h -= dy; ys2 -= dy; yd2 = ydc2; }
149 /* if already zero area, return false */
150 if(w <= 0 || h <= 0)
151 return FALSE;
154 /* sets clipped/translated points and sizes and returns TRUE */
155 ps->x = xs1; ps->y = ys1;
156 pd->x = xd1; pd->y = yd1;
157 sz->cx = w; sz->cy = h;
159 return TRUE;
164 /* clips a source and destination areas to their respective clip rectangles
165 returning both source and dest modified; result is TRUE if clipping
166 leads to a non null rectangle, FALSE otherwise */
167 static BOOL StretchBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *szSrc, SIZE *szDst, RECT*srcClip, RECT*dstClip)
169 int xs1, ys1, xs2, ys2;
170 int xsc1, ysc1, xsc2, ysc2;
171 int xd1, yd1, xd2, yd2;
172 int xdc1, ydc1, xdc2, ydc2;
173 int ws, hs, wd, hd, dx, dy;
174 int mulh, divh, mulv, divv;
176 /* extract sizes */
177 ws = szSrc->cx; hs = szSrc->cy;
178 wd = szDst->cx; hd = szDst->cy;
180 /* if sizes null or negative, just return false */
181 /* FIXME : add support for mirror stretch */
182 if(ws <= 0 || hs <= 0 || wd <= 0 || hd <= 0)
183 return FALSE;
185 /* stores scaling factors from source rect to dest one */
186 mulh = wd; divh = ws;
187 mulv = hd; divv = hs;
189 /* extract dest area data */
190 xd1 = pd->x;
191 yd1 = pd->y;
192 xd2 = xd1 + wd;
193 yd2 = yd1 + hd;
195 /* extract source data */
196 xs1 = ps->x;
197 ys1 = ps->y;
198 xs2 = xs1 + ws;
199 ys2 = ys1 + hs;
201 /* if source clip area is not null, do first clipping on it */
202 if(srcClip)
204 /* extract source clipping area */
205 xsc1 = srcClip->left;
206 ysc1 = srcClip->top;
207 xsc2 = srcClip->right;
208 ysc2 = srcClip->bottom;
210 /* order clip area rectangle points */
211 if(xsc1 > xsc2) intSwap(&xsc1, &xsc2);
212 if(ysc1 > ysc2) intSwap(&ysc1, &ysc2);
214 /* clip on source clipping start point */
215 if(xs1 < xsc1) { dx = xsc1 - xs1; ws -= dx; xd1 += MulDiv(dx, mulh, divh); xs1 = xsc1; }
216 if(ys1 < ysc1) { dy = ysc1 - ys1; hs -= dy; yd1 += MulDiv(dy, mulv, divv); ys1 = ysc1; }
218 /* clip on source clipping end point */
219 if(xs2 > xsc2) { dx = xs2 - xsc2; ws -= dx; xd2 -= MulDiv(dx, mulh, divh); xs2 = xsc2; }
220 if(ys2 > ysc2) { dy = ys2 - ysc2; hs -= dy; yd2 -= MulDiv(dy, mulv, divv); ys2 = ysc2; }
222 /* if already zero area, return false */
223 if(ws <= 0 || hs <= 0)
224 return FALSE;
225 wd = xd2 - xd1;
226 hd = yd2 - yd1;
228 /* now do clipping on destination area */
230 if(dstClip)
232 /* extract destination clipping area */
233 xdc1 = dstClip->left;
234 ydc1 = dstClip->top;
235 xdc2 = dstClip->right;
236 ydc2 = dstClip->bottom;
238 /* order clip area rectangle points */
239 if(xdc1 > xdc2) intSwap(&xdc1, &xdc2);
240 if(ydc1 > ydc2) intSwap(&ydc1, &ydc2);
242 /* clip on dest clipping start point */
243 if(xd1 < xdc1) { dx = xdc1 - xd1; wd -= dx; xs1 += MulDiv(dx, divh, mulh); xd1 = xdc1; }
244 if(yd1 < ydc1) { dy = ydc1 - yd1; hd -= dy; ys1 += MulDiv(dy, divv, mulv); yd1 = ydc1; }
246 /* clip on dest clipping end point */
247 if(xd2 > xdc2) { dx = xd2 - xdc2; wd -= dx; xs2 -= MulDiv(dx, divh, mulh); xd2 = xdc2; }
248 if(yd2 > ydc2) { dy = yd2 - ydc2; hd -= dy; ys2 -= MulDiv(dy, divv, mulv); yd2 = ydc2; }
250 /* if already zero area, return false */
251 if(wd <= 0 || hd <= 0)
252 return FALSE;
254 ws = xs2 - xs1;
255 hs = ys2 - ys1;
258 /* sets clipped/translated points and sizes and returns TRUE */
259 ps->x = xs1; ps->y = ys1;
260 pd->x = xd1; pd->y = yd1;
261 szSrc->cx = ws; szSrc->cy = hs;
262 szDst->cx = wd; szDst->cy = hd;
264 return TRUE;
268 /***********************************************************************
269 * _DIBDRV_InternalAlphaBlend
271 BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
272 DIBDRVPHYSDEV *physDevSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
273 BLENDFUNCTION blendfn)
275 BOOL res;
276 POINT pd, ps;
277 SIZE szSrc, szDst;
278 int iRec;
279 RECT dstClip, srcClip;
281 /* converts to device spaces */
282 _DIBDRV_Position_ws2ds(physDevDst, &xDst, &yDst);
283 _DIBDRV_Sizes_ws2ds(physDevDst, &widthDst, &heightDst);
284 _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc);
285 _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc);
287 /* from tests, it seems that coords out of phys spaces are not allowed */
288 if(xDst < 0 || yDst < 0 || xSrc < 0 || ySrc < 0 ||
289 xDst + widthDst > physDevDst->physBitmap->width ||
290 yDst + heightDst > physDevDst->physBitmap->height ||
291 xSrc + widthSrc > physDevSrc->physBitmap->width ||
292 ySrc + heightSrc > physDevSrc->physBitmap->height)
294 SetLastError(ERROR_INVALID_PARAMETER);
295 return FALSE;
298 /* first clip on physical DC sizes */
299 setPoint(&pd, xDst, yDst);
300 setPoint(&ps, xSrc, ySrc);
301 setSize(&szDst, widthDst, heightDst);
302 setSize(&szSrc, widthSrc, heightSrc);
303 setRect(&dstClip, 0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height);
304 setRect(&srcClip, 0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height);
305 res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
306 if(!res)
307 return TRUE;
308 xDst = pd.x; yDst = pd.y;
309 xSrc = ps.x; ySrc = ps.y;
310 widthDst = szDst.cx; heightDst = szDst.cy;
311 widthSrc = szSrc.cx; heightSrc = szSrc.cy;
313 /* then, do blitting for each dest clip area (no clipping on source) */
314 res = FALSE;
315 for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
317 RECT *r = physDevDst->regionRects + iRec;
318 setRect(&dstClip, r->left, r->top, r->right, r->bottom);
319 setPoint(&pd, xDst, yDst);
320 setPoint(&ps, xSrc, ySrc);
321 setSize(&szDst, widthDst, heightDst);
322 setSize(&szSrc, widthSrc, heightSrc);
323 if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
324 continue;
325 if(physDevDst->physBitmap->funcs->AlphaBlend(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
326 physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, blendfn))
327 res = TRUE;
329 return res;
332 /***********************************************************************
333 * DIBDRV_AlphaBlend
335 BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
336 DIBDRVPHYSDEV *physDevSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
337 BLENDFUNCTION blendfn)
339 BOOL res;
341 POINT pd = {xDst, yDst};
342 SIZE szDst = {widthDst, heightDst};
344 CheckMapping(__FUNCTION__, "DEST", physDevDst);
345 CheckMapping(__FUNCTION__, "SOURCE",physDevSrc);
347 MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
348 physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevDst->physBitmap) : "",
349 xDst, yDst, widthDst, heightDst,
350 physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevSrc->physBitmap) : "",
351 xSrc, ySrc, widthSrc, heightSrc));
353 /* if sizes are null or negative, or source positions are negatives, returns false */
354 if(widthSrc <= 0 || heightSrc <= 0 ||
355 widthDst <= 0 || heightDst <= 0)
357 res = FALSE;
358 SetLastError(ERROR_INVALID_PARAMETER);
359 goto fin;
362 /* source sould be a 32 bit DIB */
363 if(!physDevSrc)
365 FIXME("Null source bitmap -- shouldn't happen\n");
366 res = FALSE;
367 goto fin;
369 else if(!physDevSrc->hasDIB)
371 FIXME("DDB source bitmap still not supported\n");
372 res = FALSE;
373 goto fin;
376 if(physDevDst->hasDIB)
378 /* DIB section selected in dest DC, use DIB Engine */
379 MAYBE(TRACE("Blending DIB->DIB\n"));
380 res = _DIBDRV_InternalAlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
381 physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
383 else
385 /* DDB selected on dest DC -- must double-convert */
386 HBITMAP tmpDIB, stock;
387 HDC tmpDC;
388 MAYBE(TRACE("Blending DIB->DDB\n"));
390 /* we should anyways convert dest to physical coordinates here before processing
391 in order to check its consistency -- source coords will be converted/clipped later
392 As we do a conversion to a temporary DIB for destination, we don't care about it */
393 _DIBDRV_Position_ws2ds(physDevDst, &pd.x, &pd.y);
394 _DIBDRV_Sizes_ws2ds(physDevDst, &szDst.cx, &szDst.cy);
396 /* test shows that negatives origins are not allowed */
397 if(pd.x < 0 || pd.y < 0)
399 SetLastError(ERROR_INVALID_PARAMETER);
400 res = FALSE;
401 goto fin;
404 /* converts dest DDB onto a temporary DIB -- just the needed part */
405 /* WARNING -- that one could fail if rectangle on dest id out of range */
406 tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, pd.x, pd.y, szDst.cx, szDst.cy);
407 if(!tmpDIB)
409 ERR("Couldn't convert dest DDB to DIB\n");
410 res = FALSE;
411 goto fin;
414 /* selects the temporary DIB into a temporary DC */
415 tmpDC = CreateCompatibleDC(physDevDst->hdc);
416 if(!tmpDC)
418 ERR("Couldn't create temporary DC\n");
419 DeleteObject(tmpDIB);
420 res = FALSE;
421 goto fin;
423 stock = SelectObject(tmpDC, tmpDIB);
424 if(!stock)
426 ERR("Couldn't select temporary DIB into temporary DC\n");
427 DeleteDC(tmpDC);
428 DeleteObject(tmpDIB);
429 res = FALSE;
430 goto fin;
433 /* blends source DIB onto temp DIB and re-blits onto dest DC */
434 res = GdiAlphaBlend(tmpDC, 0, 0, szDst.cx, szDst.cy, physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
435 if(!res)
436 MAYBE(TRACE("AlphaBlend failed\n"));
437 else
438 res = BitBlt(physDevDst->hdc, xDst, yDst, widthDst, heightDst, tmpDC, 0, 0, SRCCOPY);
440 /* frees resources */
441 SelectObject(tmpDC, stock);
442 DeleteDC(tmpDC);
443 DeleteObject(tmpDIB);
445 fin:
446 return res;
449 /***********************************************************************
450 * _DIBDRV_InternalBitBlt
452 BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
453 INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
454 INT xSrc, INT ySrc, DWORD rop )
456 BOOL res;
457 POINT pd, ps;
458 SIZE sz;
459 int iRec;
460 RECT dstClip, srcClip;
462 /* converts to device spaces */
463 _DIBDRV_Position_ws2ds(physDevDst, &xDst, &yDst);
464 _DIBDRV_Sizes_ws2ds(physDevDst, &width, &height);
465 if(physDevSrc)
466 _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc);
468 /* first clip on physical DC sizes */
469 setPoint(&pd, xDst, yDst);
470 setPoint(&ps, xSrc, ySrc);
471 setSize(&sz, width, height);
472 setRect(&dstClip, 0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height);
474 if(physDevSrc)
476 setRect(&srcClip, 0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height);
477 res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
479 else
480 res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
481 if(!res)
482 return TRUE;
483 xDst = pd.x; yDst = pd.y;
484 xSrc = ps.x; ySrc = ps.y;
485 width = sz.cx; height = sz.cy;
487 /* then, do blitting for each dest clip area (no clipping on source) */
488 res = TRUE;
489 for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
491 RECT *r = physDevDst->regionRects + iRec;
492 setRect(&dstClip, r->left, r->top, r->right, r->bottom);
493 setPoint(&pd, xDst, yDst);
494 setPoint(&ps, xSrc, ySrc);
495 setSize(&sz, width, height);
496 if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip))
497 continue;
498 if(!physDevDst->physBitmap->funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
499 res = FALSE;
501 return res;
504 /***********************************************************************
505 * DIBDRV_BitBlt */
506 BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
507 INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
508 INT xSrc, INT ySrc, DWORD rop )
510 BOOL res;
511 int dummy;
512 int devXSrc, devWidth;
513 int devYSrc, devHeight, zeroYSrc;
515 // CheckMapping(__FUNCTION__, "DEST", physDevDst);
516 // CheckMapping(__FUNCTION__, "SOURCE",physDevSrc);
517 MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, width:%d, height:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, rop:%08x\n",
518 physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevDst->physBitmap) : "",
519 xDst, yDst, width, height,
520 physDevSrc, physDevSrc ? (physDevSrc->hasDIB ? "DIB-" : "DDB"): "---", physDevSrc && physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevSrc->physBitmap) : "",
521 xSrc, ySrc, rop));
523 if(physDevDst->hasDIB)
525 /* DIB section selected in dest DC, use DIB Engine */
527 if(!physDevSrc || physDevSrc->hasDIB)
529 /* source is null or has a DIB, no need to convert anyting */
530 res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
532 else
534 /* source is a DDB, must convert it to DIB */
536 /* we must differentiate from 2 cases :
537 1) source DC is a memory DC
538 2) source DC is a device DC */
539 if(GetObjectType(physDevSrc->hdc) == OBJ_MEMDC)
541 /* memory DC */
542 HBITMAP dib, ddb;
544 ddb = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
545 if(!ddb)
547 ERR("Couldn't select out DDB from source HDC\n");
548 res = 0;
549 goto noBlt1;
552 /* we need device coordinates for ySrc and height, as the conversion
553 functions operates directly on bitmap without the hdc */
554 devYSrc = ySrc;
555 _DIBDRV_Position_ws2ds(physDevSrc, &dummy, &devYSrc);
556 devHeight = height;
557 _DIBDRV_Sizes_ws2ds(physDevSrc, &dummy, &devHeight);
559 dib = _DIBDRV_ConvertDDBtoDIB(physDevSrc->hdc, ddb, devYSrc, devHeight);
560 if(!dib)
562 ERR("Failed converting source DDB to DIB\n");
563 SelectObject(physDevSrc->hdc, ddb);
564 res = 0;
565 goto noBlt1;
567 SelectObject(physDevSrc->hdc, dib);
569 /* we need to convert the '0' starting position on converted bitmap tp the world
570 space of bitmap's hdc */
571 zeroYSrc = 0;
572 _DIBDRV_Position_ds2ws(physDevSrc, &dummy, &zeroYSrc);
573 res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, zeroYSrc, rop);
574 SelectObject(physDevSrc->hdc, ddb);
575 DeleteObject(dib);
576 noBlt1:
579 else
581 /* device DC */
582 HBITMAP dib, stock;
583 HDC memHdc;
585 /* we need device coordinates for ySrc and height, as the conversion
586 functions operates directly on bitmap without the hdc */
587 devXSrc = xSrc;
588 devYSrc = ySrc;
589 _DIBDRV_Position_ws2ds(physDevSrc, &devXSrc, &devYSrc);
590 devWidth = width;
591 devHeight = height;
592 _DIBDRV_Sizes_ws2ds(physDevSrc, &devWidth, &devHeight);
594 dib = _DIBDRV_ConvertDevDDBtoDIB(physDevSrc->hdc, physDevDst->hdc, devXSrc, devYSrc, devWidth, devHeight);
595 if(!dib)
597 ERR("Failed converting source DDB tp DIB for device DC\n");
598 res = 0;
599 goto noBlt2;
601 memHdc = CreateCompatibleDC(physDevDst->hdc);
602 if(!memHdc)
604 ERR("Failed creating temporary memory DC\n");
605 DeleteObject(dib);
606 res = 0;
607 goto noBlt2;
609 stock = SelectObject(memHdc, dib);
610 if(!stock)
612 ERR("Failed selecting converted DIB into temporary memory DC\n");
613 DeleteObject(dib);
614 DeleteDC(memHdc);
615 res = 0;
616 goto noBlt2;
618 res = BitBlt(physDevDst->hdc, xDst, yDst, width, height, memHdc, 0, 0, rop);
620 SelectObject(memHdc, stock);
621 DeleteObject(dib);
622 DeleteDC(memHdc);
623 noBlt2:
628 else /* dest is a DDB */
630 /* DDB selected on dest DC, use X11 Driver */
631 if(!physDevSrc || !physDevSrc->hasDIB)
633 /* source is null or has also a DDB, no need to convert anything */
634 if(_DIBDRV_GetDisplayDriver()->pBitBlt)
635 res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
636 physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, ySrc, rop);
637 else
638 res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
639 physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, ySrc, width, height, rop);
641 else
643 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
644 HBITMAP dib, ddb;
645 dib = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
646 if(!dib)
648 ERR("Couldn't select out DIB from source HDC\n");
649 res = 0;
650 goto noBlt3;
653 /* we need device coordinates for ySrc and height, as the conversion
654 functions operates directly on bitmap without the hdc */
655 devYSrc = ySrc;
656 _DIBDRV_Position_ws2ds(physDevSrc, &dummy, &devYSrc);
657 devHeight = height;
658 _DIBDRV_Sizes_ws2ds(physDevSrc, &dummy, &devHeight);
660 ddb = _DIBDRV_ConvertDIBtoDDB(physDevSrc->hdc, dib, devYSrc, devHeight);
661 if(!ddb)
663 ERR("Failed converting source DIB to DDB\n");
664 SelectObject(physDevSrc->hdc, dib);
665 res = 0;
666 goto noBlt3;
668 SelectObject(physDevSrc->hdc, ddb);
670 /* we need to convert the '0' starting position on converted bitmap tp the world
671 space of bitmap's hdc */
672 zeroYSrc = 0;
673 _DIBDRV_Position_ds2ws(physDevSrc, &dummy, &zeroYSrc);
675 if(_DIBDRV_GetDisplayDriver()->pBitBlt)
676 res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
677 physDevSrc->X11PhysDev, xSrc, zeroYSrc, rop);
678 else
679 res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
680 physDevSrc->X11PhysDev, xSrc, zeroYSrc, width, height, rop);
681 SelectObject(physDevSrc->hdc, dib);
682 DeleteObject(ddb);
683 noBlt3:
687 return res;
690 /***********************************************************************
691 * _DIBDRV_InternalStretchBlt
693 BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
694 INT widthDst, INT heightDst, DIBDRVPHYSDEV *physDevSrc,
695 INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop )
697 BOOL res;
698 POINT pd, ps;
699 SIZE szSrc, szDst;
700 int iRec;
701 RECT dstClip, srcClip;
703 /* converts to device spaces */
704 _DIBDRV_Position_ws2ds(physDevDst, &xDst, &yDst);
705 _DIBDRV_Sizes_ws2ds(physDevDst, &widthDst, &heightDst);
706 if(physDevSrc)
708 _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc);
709 _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc);
712 /* first clip on physical DC sizes */
713 setPoint(&pd, xDst, yDst);
714 setPoint(&ps, xSrc, ySrc);
715 setSize(&szDst, widthDst, heightDst);
716 setSize(&szSrc, widthSrc, heightSrc);
717 setRect(&dstClip, 0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height);
718 if(physDevSrc)
720 setRect(&srcClip, 0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height);
721 res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
723 else
724 res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
725 if(!res)
726 return FALSE;
727 xDst = pd.x; yDst = pd.y;
728 xSrc = ps.x; ySrc = ps.y;
729 widthDst = szDst.cx; heightDst = szDst.cy;
730 widthSrc = szSrc.cx; heightSrc = szSrc.cy;
732 /* then, do blitting for each dest clip area (no clipping on source) */
733 res = FALSE;
734 for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
736 RECT *r = physDevDst->regionRects + iRec;
737 setRect(&dstClip, r->left, r->top, r->right, r->bottom);
738 setPoint(&pd, xDst, yDst);
739 setPoint(&ps, xSrc, ySrc);
740 setSize(&szDst, widthDst, heightDst);
741 setSize(&szSrc, widthSrc, heightSrc);
742 if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
743 continue;
744 if(physDevDst->physBitmap->funcs->StretchBlt(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
745 physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, rop))
746 res = TRUE;
748 return res;
751 /***********************************************************************
752 * DIBDRV_StretchBlt
754 BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
755 INT widthDst, INT heightDst,
756 DIBDRVPHYSDEV *physDevSrc, INT xSrc, INT ySrc,
757 INT widthSrc, INT heightSrc, DWORD rop )
759 BOOL res;
760 int dummy;
761 int devXSrc, devWidthSrc;
762 int devYSrc, devHeightSrc, zeroYSrc;
764 /* if source and dest sizes match, just call BitBlt(), it's faster */
765 if(!physDevSrc || (widthDst == widthSrc && heightDst == heightSrc))
766 return DIBDRV_BitBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, rop);
768 CheckMapping(__FUNCTION__, "DEST", physDevDst);
769 CheckMapping(__FUNCTION__, "SOURCE",physDevSrc);
770 MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d, rop:%08x\n",
771 physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevDst->physBitmap) : "",
772 xDst, yDst, widthDst, heightDst,
773 physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevSrc->physBitmap) : "",
774 xSrc, ySrc, widthSrc, heightSrc, rop));
776 if(physDevDst->hasDIB)
778 /* DIB section selected in dest DC, use DIB Engine */
780 if(!physDevSrc || physDevSrc->hasDIB)
782 /* source is null or has a DIB, no need to convert anyting */
783 res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
785 else
787 /* source is a DDB, must convert it to DIB */
789 /* we must differentiate from 2 cases :
790 1) source DC is a memory DC
791 2) source DC is a device DC */
792 if(GetObjectType(physDevSrc->hdc) == OBJ_MEMDC)
794 /* memory DC */
795 HBITMAP dib, ddb;
797 ddb = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
798 if(!ddb)
800 ERR("Couldn't select out DDB from source HDC\n");
801 res = 0;
802 goto noBlt1;
805 /* we need device coordinates for ySrc and height, as the conversion
806 functions operates directly on bitmap without the hdc */
807 devYSrc = ySrc;
808 _DIBDRV_Position_ws2ds(physDevSrc, &dummy, &devYSrc);
809 devHeightSrc = heightSrc;
810 _DIBDRV_Sizes_ws2ds(physDevSrc, &dummy, &devHeightSrc);
812 dib = _DIBDRV_ConvertDDBtoDIB(physDevSrc->hdc, ddb, devYSrc, devHeightSrc);
813 if(!dib)
815 ERR("Failed converting source DDB to DIB\n");
816 SelectObject(physDevSrc->hdc, ddb);
817 res = 0;
818 goto noBlt1;
820 SelectObject(physDevSrc->hdc, dib);
823 /* we need to convert the '0' starting position on converted bitmap tp the world
824 space of bitmap's hdc */
825 zeroYSrc = 0;
826 _DIBDRV_Position_ds2ws(physDevSrc, &dummy, &zeroYSrc);
828 res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
829 physDevSrc, xSrc, zeroYSrc, widthSrc, heightSrc, rop);
830 SelectObject(physDevSrc->hdc, ddb);
831 DeleteObject(dib);
832 noBlt1:
835 else
837 /* device DC */
838 HBITMAP dib, stock;
839 HDC memHdc;
841 /* we need device coordinates for ySrc and height, as the conversion
842 functions operates directly on bitmap without the hdc */
843 devXSrc = xSrc;
844 devYSrc = ySrc;
845 _DIBDRV_Position_ws2ds(physDevSrc, &devXSrc, &devYSrc);
846 devWidthSrc = widthSrc;
847 devHeightSrc = heightSrc;
848 _DIBDRV_Sizes_ws2ds(physDevSrc, &devWidthSrc, &devHeightSrc);
850 dib = _DIBDRV_ConvertDevDDBtoDIB(physDevSrc->hdc, physDevDst->hdc, devXSrc, devYSrc, devWidthSrc, devHeightSrc);
851 if(!dib)
853 ERR("Failed converting source DDB tp DIB for device DC\n");
854 res = 0;
855 goto noBlt2;
857 memHdc = CreateCompatibleDC(physDevDst->hdc);
858 if(!memHdc)
860 ERR("Failed creating temporary memory DC\n");
861 DeleteObject(dib);
862 res = 0;
863 goto noBlt2;
865 stock = SelectObject(memHdc, dib);
866 if(!stock)
868 ERR("Failed selecting converted DIB into temporary memory DC\n");
869 DeleteObject(dib);
870 DeleteDC(memHdc);
871 res = 0;
872 goto noBlt2;
874 res = StretchBlt(physDevDst->hdc, xDst, yDst, widthDst, heightDst, memHdc, 0, 0, widthSrc, widthDst, rop);
876 SelectObject(memHdc, stock);
877 DeleteObject(dib);
878 DeleteDC(memHdc);
879 noBlt2:
884 else /* dest is a DDB */
886 /* DDB selected on dest DC, use X11 Driver */
887 if(!physDevSrc || !physDevSrc->hasDIB)
889 /* source is null or has also a DDB, no need to convert anything */
890 res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
891 physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, ySrc, widthSrc, heightSrc, rop);
893 else
895 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
896 HBITMAP dib, ddb;
898 dib = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
899 if(!dib)
901 ERR("Couldn't select out DIB from source HDC\n");
902 res = 0;
903 goto noBlt3;
906 /* we need device coordinates for ySrc and height, as the conversion
907 functions operates directly on bitmap without the hdc */
908 devYSrc = ySrc;
909 _DIBDRV_Position_ws2ds(physDevSrc, &dummy, &devYSrc);
910 devHeightSrc = heightSrc;
911 _DIBDRV_Sizes_ws2ds(physDevSrc, &dummy, &devHeightSrc);
913 ddb = _DIBDRV_ConvertDIBtoDDB(physDevSrc->hdc, dib, devYSrc, devHeightSrc);
914 if(!ddb)
916 ERR("Failed converting source DIB to DDB\n");
917 SelectObject(physDevSrc->hdc, dib);
918 res = 0;
919 goto noBlt3;
921 if(!SelectObject(physDevSrc->hdc, ddb))
923 ERR("Failed to select converted DDB into source HDC\n");
924 SelectObject(physDevSrc->hdc, dib);
925 DeleteObject(ddb);
926 res = 0;
927 goto noBlt3;
930 /* we need to convert the '0' starting position on converted bitmap tp the world
931 space of bitmap's hdc */
932 zeroYSrc = 0;
933 _DIBDRV_Position_ds2ws(physDevSrc, &dummy, &zeroYSrc);
934 res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
935 physDevSrc->X11PhysDev, xSrc, zeroYSrc, widthSrc, heightSrc, rop);
936 SelectObject(physDevSrc->hdc, dib);
937 DeleteObject(ddb);
938 noBlt3:
942 return res;
945 /***********************************************************************
946 * DIBDRV_PatBlt
948 BOOL DIBDRV_PatBlt( DIBDRVPHYSDEV *physDev, INT left, INT top, INT width, INT height, DWORD rop )
950 BOOL res;
952 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev, left, top, width, height, rop));
954 if(physDev->hasDIB)
956 /* DIB section selected in, use DIB Engine */
957 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
958 res = DIBDRV_BitBlt(physDev, left, top, width, height, NULL, 0, 0, rop);
960 else
962 /* DDB selected in, use X11 driver */
963 if(_DIBDRV_GetDisplayDriver()->pPatBlt)
964 res = _DIBDRV_GetDisplayDriver()->pPatBlt(physDev->X11PhysDev, left, top, width, height, rop);
965 else
966 res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDev->X11PhysDev, left, top, width, height, 0, left, top, width, height, rop);
968 return res;