2 * DIB Engine BitBlt Primitives
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
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
28 static inline COLORREF
SwapColors(DWORD c
)
30 return ((c
& 0x0000ff) << 16) | (c
& 0x00ff00) | ((c
& 0xff0000) >> 16);
34 /* shrinks a line -- srcWidth >= dstWidth */
35 static void ShrinkLine(DWORD
*dst
, int dstWidth
, DWORD
*src
, int srcWidth
)
43 while(dstPos
< dstWidth
)
46 while(delta
< srcWidth
)
57 /* expands a line -- srcWidth <= dstWidth */
58 static void ExpandLine(DWORD
*dst
, int dstWidth
, DWORD
*src
, int srcWidth
)
65 while(srcPos
< srcWidth
)
67 while(delta
< dstWidth
)
79 static void StretchLine(DWORD
*dst
, int dstWidth
, DWORD
*src
, int srcWidth
)
81 if(srcWidth
> dstWidth
)
82 ShrinkLine(dst
, dstWidth
, src
, srcWidth
);
83 else if(srcWidth
< dstWidth
)
84 ExpandLine(dst
, dstWidth
, src
, srcWidth
);
86 memcpy(dst
, src
, 4 * srcWidth
);
89 /* premultiply alpha channel on a line by a constant alpha
90 note : it seems that pixels are already premultiplied
91 by alpha channel content */
92 static void PemultiplyLine(DWORD
*dst
, int width
, BYTE constAlpha
)
95 BYTE
*alphaPnt
= (BYTE
*)dst
+ 3;
97 /* small optimization for 0 and 255 values of constAlpha */
99 /* fully transparent -- just sets all pix to 0 */
107 /* fully opaque, just do nothing */
108 if(constAlpha
== 255)
111 /* intermediate -- premultiply alpha values */
114 *alphaPnt
= MulDiv(*alphaPnt
, constAlpha
, 255);
121 /* alpha blends a source line onto a destination line
123 1) source and dest widths must be the same
124 2) source line should be already premultiplied by constant alpha */
125 static void BlendLine(DWORD
*dst
, DWORD
*src
, int width
)
128 BYTE
*blueDst
= (BYTE
*)dst
;
129 BYTE
*greenDst
= blueDst
+ 1;
130 BYTE
*redDst
= greenDst
+ 1;
131 BYTE
*blueSrc
= (BYTE
*)src
;
132 BYTE
*greenSrc
= blueSrc
+ 1;
133 BYTE
*redSrc
= greenSrc
+ 1;
134 BYTE
*alphaSrc
= redSrc
+ 1;
137 /* still don't know if it must take in account an eventual dest
138 alpha channel..... */
141 alpha
= 255 - *alphaSrc
;
143 *blueDst
= *blueSrc
+ MulDiv(*blueDst
, alpha
, 255);
144 *greenDst
= *greenSrc
+ MulDiv(*greenDst
, alpha
, 255);
145 *redDst
= *redSrc
+ MulDiv(*redDst
, alpha
, 255);
158 /* ------------------------------------------------------------*/
159 /* ALPHABLEND PRIMITIVES */
160 BOOL
_DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
161 INT widthDst
, INT heightDst
, const DIBDRVPHYSDEV
*physDevSrc
,
162 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, BLENDFUNCTION blendFn
)
164 /* flags indicating wether source should be stretched */
165 BOOL horStretch
= (widthSrc
!= widthDst
);
166 BOOL verStretch
= (heightSrc
!= heightDst
);
168 /* constant alpha value */
169 BYTE constAlpha
= blendFn
.SourceConstantAlpha
;
171 /* source and dest bitmaps */
172 const DIBDRVBITMAP
*srcBmp
= &physDevSrc
->physBitmap
;
173 DIBDRVBITMAP
*dstBmp
= &physDevDst
->physBitmap
;
175 /* source and destination line buffers */
176 DWORD
*sBuf
= HeapAlloc(GetProcessHeap(), 0, abs(srcBmp
->stride
));
177 DWORD
*dBuf
= HeapAlloc(GetProcessHeap(), 0, abs(dstBmp
->stride
));
184 /* in order to optimize a bit, we divide the routine in 4 parts,
185 depending on stretching modes */
186 if(!horStretch
&& !verStretch
)
188 /* simplest case, no stretching needed */
189 MAYBE(TRACE("No stretching\n"));
190 for(iLine
= 0; iLine
< heightSrc
; iLine
++, ys
++, yd
++)
192 /* load source and dest lines */
193 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
194 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
196 /* premultiply source by constant and pixel alpha */
197 PemultiplyLine(sBuf
, widthSrc
, constAlpha
);
199 /* blends source on dest */
200 BlendLine(dBuf
, sBuf
, widthSrc
);
202 /* puts dest line back */
203 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
206 else if (horStretch
&& !verStretch
)
208 /* just horizontal stretching needed */
209 DWORD
*strBuf
= HeapAlloc(GetProcessHeap(), 0, abs(dstBmp
->stride
));
210 MAYBE(TRACE("Horizontal stretching\n"));
212 for(iLine
= 0; iLine
< heightSrc
; iLine
++, ys
++, yd
++)
214 /* load source and dest lines */
215 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
216 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
218 /* stretch source line to match dest one */
219 StretchLine(strBuf
, widthDst
, sBuf
, widthSrc
);
221 /* premultiply source by constant and pixel alpha */
222 PemultiplyLine(strBuf
, widthDst
, constAlpha
);
224 /* blends source on dest */
225 BlendLine(dBuf
, strBuf
, widthDst
);
227 /* puts dest line back */
228 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
230 HeapFree(GetProcessHeap(), 0, strBuf
);
232 else if (!horStretch
&& verStretch
)
234 /* just vertical stretching needed */
235 MAYBE(TRACE("Vertical stretching\n"));
237 if(heightSrc
> heightDst
)
241 while(iLine
< heightDst
)
243 /* load source and dest lines */
244 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
245 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
247 /* premultiply source by constant and pixel alpha */
248 PemultiplyLine(sBuf
, widthSrc
, constAlpha
);
250 /* blends source on dest */
251 BlendLine(dBuf
, sBuf
, widthDst
);
253 /* puts dest line back */
254 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
256 while(delta
< heightSrc
)
266 else if(heightSrc
< heightDst
)
270 while(iLine
< heightSrc
)
272 /* load source line */
273 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
275 /* premultiply source by constant and pixel alpha */
276 PemultiplyLine(sBuf
, widthSrc
, constAlpha
);
278 while(delta
< heightDst
)
281 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
283 /* blends source on dest */
284 BlendLine(dBuf
, sBuf
, widthDst
);
286 /* puts dest line back */
287 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
299 DWORD
*strBuf
= HeapAlloc(GetProcessHeap(), 0, abs(dstBmp
->stride
));
300 /* both stretching needed -- generic case */
301 MAYBE(TRACE("Horizontal and vertical stretching\n"));
303 if(heightSrc
> heightDst
)
307 while(iLine
< heightDst
)
309 /* load source and dest lines */
310 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
311 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
313 /* stretch source line to match dest one */
314 StretchLine(strBuf
, widthDst
, sBuf
, widthSrc
);
316 /* premultiply source by constant and pixel alpha */
317 PemultiplyLine(strBuf
, widthDst
, constAlpha
);
319 /* blends source on dest */
320 BlendLine(dBuf
, strBuf
, widthDst
);
322 /* puts dest line back */
323 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
325 while(delta
< heightSrc
)
335 else if(heightSrc
< heightDst
)
339 while(iLine
< heightSrc
)
341 /* load source line */
342 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
344 /* stretch source line to match dest one */
345 StretchLine(strBuf
, widthDst
, sBuf
, widthSrc
);
347 /* premultiply source by constant and pixel alpha */
348 PemultiplyLine(strBuf
, widthDst
, constAlpha
);
350 while(delta
< heightDst
)
353 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
355 /* blends source on dest */
356 BlendLine(dBuf
, strBuf
, widthDst
);
358 /* puts dest line back */
359 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
368 HeapFree(GetProcessHeap(), 0, strBuf
);
371 HeapFree(GetProcessHeap(), 0, sBuf
);
372 HeapFree(GetProcessHeap(), 0, dBuf
);
376 /* ------------------------------------------------------------*/
377 /* BLITTING PRIMITIVES */
378 BOOL
_DIBDRV_BitBlt_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
379 INT width
, INT height
, const DIBDRVPHYSDEV
*physDevSrc
,
380 INT xSrc
, INT ySrc
, DWORD rop
)
385 DIBDRVBITMAP
*dstBmp
, *patBmp
;
386 const DIBDRVBITMAP
*srcBmp
;
387 DWORD
*wDstPnt
, *wSrcPnt
, *wPatPnt
;
388 BOOL usePat
, useSrc
, useDst
;
392 /* 32 bit RGB source and destination buffer, if needed */
393 DWORD
*sBuf
= 0, *dBuf
= 0, *pBuf
= 0;
395 /* get elements usage */
396 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
397 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
398 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
400 /* sanity check -- MSN messenger crashes without */
401 if(useSrc
&& !physDevSrc
)
404 /* gets source, dest and pattern bitmaps, if available */
405 if(usePat
&& physDevDst
->isBrushBitmap
)
406 patBmp
= &physDevDst
->brushBmpCache
;
411 srcBmp
= &physDevSrc
->physBitmap
;
414 dstBmp
= &physDevDst
->physBitmap
;
416 /* gets pattern color, in case it's needed
417 it's NOT the COLORREF value (colors are swapped
418 NOR the pixel value (it's applied to a 32 BPP BI_RGB */
420 patColor
= SwapColors(physDevDst
->brushColorref
);
424 /* allocate 32 bit RGB destination buffer */
425 if(!(dBuf
= (DWORD
*)HeapAlloc( GetProcessHeap(), 0, width
* 4)))
428 MAYBE(TRACE("dstBmp:%p(%s), xDst:%d, yDst:%d, width:%d, height:%d, srcBmp:%p(%s), xSrc:%d, ySrc:%d, rop:%8x\n",
429 dstBmp
, _DIBDRVBITMAP_GetFormatName(dstBmp
), xDst
, yDst
, width
, height
,
430 srcBmp
, _DIBDRVBITMAP_GetFormatName(srcBmp
), xSrc
, ySrc
, rop
));
432 /* some simple ROPs optimizations */
436 MAYBE(TRACE("BLACKNESS\n"));
437 memset(dBuf
, 0x00, width
* 4);
438 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
439 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
443 MAYBE(TRACE("WHITENESS\n"));
444 for(dwBuf
= dBuf
, i
= width
; i
; i
--)
445 *dwBuf
++ = 0x00ffffff;
446 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
447 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
451 MAYBE(TRACE("SRCCOPY\n"));
452 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
454 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
455 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
459 /* fallback for generic ROP operation */
462 if(useSrc
&& useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
464 MAYBE(TRACE("BitBlt use: src+dst+pat - pattern brush\n"));
465 if(!(sBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
467 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
469 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
471 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, sBuf
);
472 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
473 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
477 for(i
= width
; i
> 0 ; i
--)
479 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
482 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
485 else if(useSrc
&& useDst
)
488 MAYBE(TRACE("BitBlt use: src+dst+pat - solid brush\n"));
490 MAYBE(TRACE("BitBlt use: src+dst\n"));
491 if(!(sBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
493 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
495 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, sBuf
);
496 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, width
, dBuf
);
499 for(i
= width
; i
> 0 ; i
--)
501 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
504 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
507 else if(useSrc
&& usePat
&& physDevDst
->isBrushBitmap
)
509 MAYBE(TRACE("BitBlt use: src+pat -- pattern brush\n"));
510 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
512 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
514 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
515 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
519 for(i
= width
; i
> 0 ; i
--)
521 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
524 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
530 MAYBE(TRACE("BitBlt use: src+pat - solid brush\n"));
532 MAYBE(TRACE("BitBlt use: src\n"));
533 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
535 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
538 for(i
= width
; i
> 0 ; i
--)
540 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
543 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
546 else if(useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
548 MAYBE(TRACE("BitBlt use: dst+pat -- pattern brush\n"));
549 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
551 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
553 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
554 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
557 for(i
= width
; i
> 0 ; i
--)
559 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
562 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
568 MAYBE(TRACE("BitBlt use: dst+pat - solid brush\n"));
570 MAYBE(TRACE("BitBlt use: dst\n"));
571 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
573 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
575 for(i
= width
; i
> 0 ; i
--)
577 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
580 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
583 else if(usePat
&& physDevDst
->isBrushBitmap
)
585 MAYBE(TRACE("BitBlt use: pat -- pattern brush\n"));
586 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
588 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
590 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
593 for(i
= width
; i
> 0 ; i
--)
595 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
598 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
603 MAYBE(TRACE("BitBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop
, patColor
));
604 MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp
)));
605 MAYBE(TRACE("xDst = %d, yDst = %d, width = %d, height = %d\n", xDst
, yDst
, width
, height
));
606 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
609 for(i
= width
; i
> 0 ; i
--)
611 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
614 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
618 ERR("What happened ?????? \n");
623 if(sBuf
) HeapFree( GetProcessHeap(), 0, sBuf
);
624 if(dBuf
) HeapFree( GetProcessHeap(), 0, dBuf
);
625 if(pBuf
) HeapFree( GetProcessHeap(), 0, pBuf
);
629 /* ------------------------------------------------------------*/
630 /* STRETCHING PRIMITIVES */
631 BOOL
_DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
632 INT widthDst
, INT heightDst
, const DIBDRVPHYSDEV
*physDevSrc
,
633 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
638 DIBDRVBITMAP
*dstBmp
, *patBmp
;
639 const DIBDRVBITMAP
*srcBmp
;
640 DWORD
*wDstPnt
, *wSrcPnt
, *wPatPnt
;
641 BOOL usePat
, useSrc
, useDst
;
645 /* 32 bit RGB source and destination buffer, if needed */
646 DWORD
*sBufOrig
= 0, *sBufStr
= 0, *dBuf
= 0, *pBuf
= 0;
648 /* get elements usage */
649 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
650 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
651 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
653 /* sanity check -- MSN messenger crashes without */
654 if(useSrc
&& !physDevSrc
)
657 /* gets source, dest and pattern bitmaps, if available */
658 if(usePat
&& physDevDst
->isBrushBitmap
)
659 patBmp
= &physDevDst
->brushBmpCache
;
664 srcBmp
= &physDevSrc
->physBitmap
;
667 dstBmp
= &physDevDst
->physBitmap
;
669 /* gets pattern color, in case it's needed
670 it's NOT the COLORREF value (colors are swapped
671 NOR the pixel value (it's applied to a 32 BPP BI_RGB */
673 patColor
= SwapColors(physDevDst
->brushColorref
);
677 /* allocate 32 bit RGB destination buffer */
678 if(!(dBuf
= (DWORD
*)HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
681 MAYBE(TRACE("dstBmp:%p(%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, srcBmp:%p(%s), xSrc:%d, ySrc:%d, , widthSrc:%d, heightSrc:%drop:%8x\n",
682 dstBmp
, _DIBDRVBITMAP_GetFormatName(dstBmp
), xDst
, yDst
, widthDst
, heightDst
,
683 srcBmp
, _DIBDRVBITMAP_GetFormatName(srcBmp
), xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
685 /* some simple ROPs optimizations */
689 MAYBE(TRACE("BLACKNESS\n"));
690 memset(dBuf
, 0x00, widthDst
* 4);
691 for(yd
= yDst
; yd
< yDst
+heightDst
; yd
++)
692 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
696 MAYBE(TRACE("WHITENESS\n"));
697 for(dwBuf
= dBuf
, i
= widthDst
; i
; i
--)
698 *dwBuf
++ = 0x00ffffff;
699 for(yd
= yDst
; yd
< yDst
+heightDst
; yd
++)
700 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
704 MAYBE(TRACE("SRCCOPY\n"));
705 sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4);
706 if(heightSrc
> heightDst
)
711 while(yd
< heightDst
)
713 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
714 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
715 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
716 while(delta
< heightSrc
)
725 else if(heightSrc
< heightDst
)
730 while(ys
< heightSrc
)
732 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
733 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
734 while(delta
< heightDst
)
736 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
746 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
748 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
749 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
750 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
755 /* fallback for generic ROP operation */
758 if(useSrc
&& useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
760 MAYBE(TRACE("StretchBlt use: src+dst+pat - pattern brush\n"));
761 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
763 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
765 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
767 if(heightSrc
> heightDst
)
772 while(yd
< heightDst
)
774 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
775 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
776 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
777 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
781 for(i
= widthDst
; i
> 0 ; i
--)
783 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
786 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
787 while(delta
< heightSrc
)
796 else if(heightSrc
< heightDst
)
801 while(ys
< heightSrc
)
803 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
804 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
805 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
806 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
807 while(delta
< heightDst
)
812 for(i
= widthDst
; i
> 0 ; i
--)
814 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
817 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
827 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
829 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
830 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
831 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
832 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
836 for(i
= widthDst
; i
> 0 ; i
--)
838 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
841 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
845 else if(useSrc
&& useDst
)
848 MAYBE(TRACE("StretchBlt use: src+dst+pat - solid brush\n"));
850 MAYBE(TRACE("StretchBlt use: src+dst\n"));
851 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
853 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
855 if(heightSrc
> heightDst
)
860 while(yd
< heightDst
)
862 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
863 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
864 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
867 for(i
= widthDst
; i
> 0 ; i
--)
869 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
872 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
873 while(delta
< heightSrc
)
882 else if(heightSrc
< heightDst
)
887 while(ys
< heightSrc
)
889 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
890 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
891 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
892 while(delta
< heightDst
)
896 for(i
= widthDst
; i
> 0 ; i
--)
898 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
901 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
911 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
913 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
914 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
915 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
918 for(i
= widthDst
; i
> 0 ; i
--)
920 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
923 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
927 else if(useSrc
&& usePat
&& physDevDst
->isBrushBitmap
)
929 MAYBE(TRACE("StretchBlt use: src+pat -- pattern brush\n"));
930 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
932 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
934 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
936 if(heightSrc
> heightDst
)
941 while(yd
< heightDst
)
943 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
944 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
945 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
949 for(i
= widthDst
; i
> 0 ; i
--)
951 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
954 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
955 while(delta
< heightSrc
)
964 else if(heightSrc
< heightDst
)
969 while(ys
< heightSrc
)
971 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
972 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
973 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
974 while(delta
< heightDst
)
979 for(i
= widthDst
; i
> 0 ; i
--)
981 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
984 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
994 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
996 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
997 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
998 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1002 for(i
= widthDst
; i
> 0 ; i
--)
1004 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
1007 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1014 MAYBE(TRACE("StretchBlt use: src+pat - solid brush\n"));
1016 MAYBE(TRACE("StretchBlt use: src\n"));
1017 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
1019 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
1021 if(heightSrc
> heightDst
)
1026 while(yd
< heightDst
)
1028 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
1029 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1032 for(i
= widthDst
; i
> 0 ; i
--)
1034 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1037 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1038 while(delta
< heightSrc
)
1047 else if(heightSrc
< heightDst
)
1052 while(ys
< heightSrc
)
1054 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
1055 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1056 while(delta
< heightDst
)
1060 for(i
= widthDst
; i
> 0 ; i
--)
1062 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1065 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1075 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1077 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
1078 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1081 for(i
= widthDst
; i
> 0 ; i
--)
1083 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1086 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1090 else if(useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
1092 MAYBE(TRACE("StretchBlt use: dst+pat -- pattern brush\n"));
1093 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
1095 if(heightSrc
> heightDst
)
1100 while(yd
< heightDst
)
1102 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1103 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1106 for(i
= widthDst
; i
> 0 ; i
--)
1108 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1111 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1112 while(delta
< heightSrc
)
1121 else if(heightSrc
< heightDst
)
1126 while(ys
< heightSrc
)
1128 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1129 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1130 while(delta
< heightDst
)
1134 for(i
= widthDst
; i
> 0 ; i
--)
1136 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1139 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1149 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1151 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
1152 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1155 for(i
= widthDst
; i
> 0 ; i
--)
1157 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1160 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1167 MAYBE(TRACE("StretchBlt use: dst+pat - solid brush\n"));
1169 MAYBE(TRACE("StretchBlt use: dst\n"));
1170 if(heightSrc
> heightDst
)
1175 while(yd
< heightDst
)
1177 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1179 for(i
= widthDst
; i
> 0 ; i
--)
1181 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1184 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1185 while(delta
< heightSrc
)
1194 else if(heightSrc
< heightDst
)
1199 while(ys
< heightSrc
)
1201 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1202 while(delta
< heightDst
)
1205 for(i
= widthDst
; i
> 0 ; i
--)
1207 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1210 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1220 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1222 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
1224 for(i
= widthDst
; i
> 0 ; i
--)
1226 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1229 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1233 else if(usePat
&& physDevDst
->isBrushBitmap
)
1235 MAYBE(TRACE("StretchBlt use: pat -- pattern brush\n"));
1236 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
1238 if(heightSrc
> heightDst
)
1243 while(yd
< heightDst
)
1245 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1248 for(i
= widthDst
; i
> 0 ; i
--)
1250 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1253 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1254 while(delta
< heightSrc
)
1263 else if(heightSrc
< heightDst
)
1268 while(ys
< heightSrc
)
1270 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1271 while(delta
< heightDst
)
1275 for(i
= widthDst
; i
> 0 ; i
--)
1277 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1280 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1290 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1292 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1295 for(i
= widthDst
; i
> 0 ; i
--)
1297 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1300 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1306 MAYBE(TRACE("StretchBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop
, patColor
));
1307 MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp
)));
1308 MAYBE(TRACE("xDst = %d, yDst = %d, widthDst = %d, heightDst = %d\n", xDst
, yDst
, widthDst
, heightDst
));
1309 if(heightSrc
> heightDst
)
1314 while(yd
< heightDst
)
1317 for(i
= widthDst
; i
> 0 ; i
--)
1319 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1322 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1323 while(delta
< heightSrc
)
1332 else if(heightSrc
< heightDst
)
1337 while(ys
< heightSrc
)
1339 while(delta
< heightDst
)
1342 for(i
= widthDst
; i
> 0 ; i
--)
1344 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1347 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1357 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1360 for(i
= widthDst
; i
> 0 ; i
--)
1362 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1365 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1370 ERR("What happened ?????? \n");
1375 if(sBufOrig
) HeapFree( GetProcessHeap(), 0, sBufOrig
);
1376 if(sBufStr
) HeapFree( GetProcessHeap(), 0, sBufStr
);
1377 if(dBuf
) HeapFree( GetProcessHeap(), 0, dBuf
);
1378 if(pBuf
) HeapFree( GetProcessHeap(), 0, pBuf
);