7feeb49ddef34e89aef685b8d7795a0025bbad3a
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 /* shrinks a line -- srcWidth >= dstWidth */
29 static void ShrinkLine(DWORD
*dst
, int dstWidth
, DWORD
*src
, int srcWidth
)
37 while(dstPos
< dstWidth
)
40 while(delta
< srcWidth
)
51 /* expands a line -- srcWidth <= dstWidth */
52 static void ExpandLine(DWORD
*dst
, int dstWidth
, DWORD
*src
, int srcWidth
)
59 while(srcPos
< srcWidth
)
61 while(delta
< dstWidth
)
73 static void StretchLine(DWORD
*dst
, int dstWidth
, DWORD
*src
, int srcWidth
)
75 if(srcWidth
> dstWidth
)
76 ShrinkLine(dst
, dstWidth
, src
, srcWidth
);
77 else if(srcWidth
< dstWidth
)
78 ExpandLine(dst
, dstWidth
, src
, srcWidth
);
80 memcpy(dst
, src
, 4 * srcWidth
);
83 /* premultiply alpha channel on a line by a constant alpha
84 note : it seems that pixels are already premultiplied
85 by alpha channel content */
86 static void PemultiplyLine(DWORD
*dst
, int width
, BYTE constAlpha
)
89 BYTE
*alphaPnt
= (BYTE
*)dst
+ 3;
91 /* small optimization for 0 and 255 values of constAlpha */
93 /* fully transparent -- just sets all pix to 0 */
101 /* fully opaque, just do nothing */
102 if(constAlpha
== 255)
105 /* intermediate -- premultiply alpha values */
108 *alphaPnt
= MulDiv(*alphaPnt
, constAlpha
, 255);
115 /* alpha blends a source line onto a destination line
117 1) source and dest widths must be the same
118 2) source line should be already premultiplied by constant alpha */
119 static void BlendLine(DWORD
*dst
, DWORD
*src
, int width
)
122 BYTE
*blueDst
= (BYTE
*)dst
;
123 BYTE
*greenDst
= blueDst
+ 1;
124 BYTE
*redDst
= greenDst
+ 1;
125 BYTE
*blueSrc
= (BYTE
*)src
;
126 BYTE
*greenSrc
= blueSrc
+ 1;
127 BYTE
*redSrc
= greenSrc
+ 1;
128 BYTE
*alphaSrc
= redSrc
+ 1;
131 /* still don't know if it must take in account an eventual dest
132 alpha channel..... */
135 alpha
= 255 - *alphaSrc
;
137 *blueDst
= *blueSrc
+ MulDiv(*blueDst
, alpha
, 255);
138 *greenDst
= *greenSrc
+ MulDiv(*greenDst
, alpha
, 255);
139 *redDst
= *redSrc
+ MulDiv(*redDst
, alpha
, 255);
152 /* ------------------------------------------------------------*/
153 /* ALPHABLEND PRIMITIVES */
154 BOOL
_DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
155 INT widthDst
, INT heightDst
, const DIBDRVPHYSDEV
*physDevSrc
,
156 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, BLENDFUNCTION blendFn
)
158 /* flags indicating wether source should be stretched */
159 BOOL horStretch
= (widthSrc
!= widthDst
);
160 BOOL verStretch
= (heightSrc
!= heightDst
);
162 /* constant alpha value */
163 BYTE constAlpha
= blendFn
.SourceConstantAlpha
;
165 /* source and dest bitmaps */
166 const DIBDRVBITMAP
*srcBmp
= &physDevSrc
->physBitmap
;
167 DIBDRVBITMAP
*dstBmp
= &physDevDst
->physBitmap
;
169 /* source and destination line buffers */
170 DWORD
*sBuf
= HeapAlloc(GetProcessHeap(), 0, abs(srcBmp
->stride
));
171 DWORD
*dBuf
= HeapAlloc(GetProcessHeap(), 0, abs(dstBmp
->stride
));
178 /* in order to optimize a bit, we divide the routine in 4 parts,
179 depending on stretching modes */
180 if(!horStretch
&& !verStretch
)
182 /* simplest case, no stretching needed */
183 MAYBE(TRACE("No stretching\n"));
184 for(iLine
= 0; iLine
< heightSrc
; iLine
++, ys
++, yd
++)
186 /* load source and dest lines */
187 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
188 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
190 /* premultiply source by constant and pixel alpha */
191 PemultiplyLine(sBuf
, widthSrc
, constAlpha
);
193 /* blends source on dest */
194 BlendLine(dBuf
, sBuf
, widthSrc
);
196 /* puts dest line back */
197 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
200 else if (horStretch
&& !verStretch
)
202 /* just horizontal stretching needed */
203 DWORD
*strBuf
= HeapAlloc(GetProcessHeap(), 0, abs(dstBmp
->stride
));
204 MAYBE(TRACE("Horizontal stretching\n"));
206 for(iLine
= 0; iLine
< heightSrc
; iLine
++, ys
++, yd
++)
208 /* load source and dest lines */
209 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
210 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
212 /* stretch source line to match dest one */
213 StretchLine(strBuf
, widthDst
, sBuf
, widthSrc
);
215 /* premultiply source by constant and pixel alpha */
216 PemultiplyLine(strBuf
, widthDst
, constAlpha
);
218 /* blends source on dest */
219 BlendLine(dBuf
, strBuf
, widthDst
);
221 /* puts dest line back */
222 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
224 HeapFree(GetProcessHeap(), 0, strBuf
);
226 else if (!horStretch
&& verStretch
)
228 /* just vertical stretching needed */
229 MAYBE(TRACE("Vertical stretching\n"));
231 if(heightSrc
> heightDst
)
235 while(iLine
< heightDst
)
237 /* load source and dest lines */
238 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
239 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
241 /* premultiply source by constant and pixel alpha */
242 PemultiplyLine(sBuf
, widthSrc
, constAlpha
);
244 /* blends source on dest */
245 BlendLine(dBuf
, sBuf
, widthDst
);
247 /* puts dest line back */
248 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
250 while(delta
< heightSrc
)
260 else if(heightSrc
< heightDst
)
264 while(iLine
< heightSrc
)
266 /* load source line */
267 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
269 /* premultiply source by constant and pixel alpha */
270 PemultiplyLine(sBuf
, widthSrc
, constAlpha
);
272 while(delta
< heightDst
)
275 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
277 /* blends source on dest */
278 BlendLine(dBuf
, sBuf
, widthDst
);
280 /* puts dest line back */
281 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
293 DWORD
*strBuf
= HeapAlloc(GetProcessHeap(), 0, abs(dstBmp
->stride
));
294 /* both stretching needed -- generic case */
295 MAYBE(TRACE("Horizontal and vertical stretching\n"));
297 if(heightSrc
> heightDst
)
301 while(iLine
< heightDst
)
303 /* load source and dest lines */
304 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
305 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
307 /* stretch source line to match dest one */
308 StretchLine(strBuf
, widthDst
, sBuf
, widthSrc
);
310 /* premultiply source by constant and pixel alpha */
311 PemultiplyLine(strBuf
, widthDst
, constAlpha
);
313 /* blends source on dest */
314 BlendLine(dBuf
, strBuf
, widthDst
);
316 /* puts dest line back */
317 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
319 while(delta
< heightSrc
)
329 else if(heightSrc
< heightDst
)
333 while(iLine
< heightSrc
)
335 /* load source line */
336 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBuf
);
338 /* stretch source line to match dest one */
339 StretchLine(strBuf
, widthDst
, sBuf
, widthSrc
);
341 /* premultiply source by constant and pixel alpha */
342 PemultiplyLine(strBuf
, widthDst
, constAlpha
);
344 while(delta
< heightDst
)
347 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
349 /* blends source on dest */
350 BlendLine(dBuf
, strBuf
, widthDst
);
352 /* puts dest line back */
353 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
362 HeapFree(GetProcessHeap(), 0, strBuf
);
365 HeapFree(GetProcessHeap(), 0, sBuf
);
366 HeapFree(GetProcessHeap(), 0, dBuf
);
370 /* ------------------------------------------------------------*/
371 /* BLITTING PRIMITIVES */
372 BOOL
_DIBDRV_BitBlt_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
373 INT width
, INT height
, const DIBDRVPHYSDEV
*physDevSrc
,
374 INT xSrc
, INT ySrc
, DWORD rop
)
379 DIBDRVBITMAP
*dstBmp
, *patBmp
;
380 const DIBDRVBITMAP
*srcBmp
;
381 DWORD
*wDstPnt
, *wSrcPnt
, *wPatPnt
;
382 BOOL usePat
, useSrc
, useDst
;
386 /* 32 bit RGB source and destination buffer, if needed */
387 DWORD
*sBuf
= 0, *dBuf
= 0, *pBuf
= 0;
389 /* get elements usage */
390 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
391 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
392 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
394 /* sanity check -- MSN messenger crashes without */
395 if(useSrc
&& !physDevSrc
)
398 /* gets source, dest and pattern bitmaps, if available */
399 if(usePat
&& physDevDst
->isBrushBitmap
)
400 patBmp
= &physDevDst
->brushBmpCache
;
405 srcBmp
= &physDevSrc
->physBitmap
;
408 dstBmp
= &physDevDst
->physBitmap
;
410 /* gets pattern color, in case it's needed */
412 patColor
= physDevDst
->brushColor
;
416 /* allocate 32 bit RGB destination buffer */
417 if(!(dBuf
= (DWORD
*)HeapAlloc( GetProcessHeap(), 0, width
* 4)))
420 MAYBE(TRACE("dstBmp:%p(%s), xDst:%d, yDst:%d, width:%d, height:%d, srcBmp:%p(%s), xSrc:%d, ySrc:%d, rop:%8x\n",
421 dstBmp
, _DIBDRVBITMAP_GetFormatName(dstBmp
), xDst
, yDst
, width
, height
,
422 srcBmp
, _DIBDRVBITMAP_GetFormatName(srcBmp
), xSrc
, ySrc
, rop
));
424 /* some simple ROPs optimizations */
428 MAYBE(TRACE("BLACKNESS\n"));
429 memset(dBuf
, 0x00, width
* 4);
430 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
431 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
435 MAYBE(TRACE("WHITENESS\n"));
436 for(dwBuf
= dBuf
, i
= width
; i
; i
--)
437 *dwBuf
++ = 0x00ffffff;
438 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
439 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
443 MAYBE(TRACE("SRCCOPY\n"));
444 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
446 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
447 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
451 /* fallback for generic ROP operation */
454 if(useSrc
&& useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
456 MAYBE(TRACE("BitBlt use: src+dst+pat - pattern brush\n"));
457 if(!(sBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
459 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
461 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
463 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, sBuf
);
464 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
465 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
469 for(i
= width
; i
> 0 ; i
--)
471 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
474 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
477 else if(useSrc
&& useDst
)
480 MAYBE(TRACE("BitBlt use: src+dst+pat - solid brush\n"));
482 MAYBE(TRACE("BitBlt use: src+dst\n"));
483 if(!(sBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
485 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
487 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, sBuf
);
488 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, width
, dBuf
);
491 for(i
= width
; i
> 0 ; i
--)
493 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
496 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
499 else if(useSrc
&& usePat
&& physDevDst
->isBrushBitmap
)
501 MAYBE(TRACE("BitBlt use: src+pat -- pattern brush\n"));
502 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
504 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
506 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
507 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
511 for(i
= width
; i
> 0 ; i
--)
513 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
516 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
522 MAYBE(TRACE("BitBlt use: src+pat - solid brush\n"));
524 MAYBE(TRACE("BitBlt use: src\n"));
525 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
527 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
530 for(i
= width
; i
> 0 ; i
--)
532 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
535 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
538 else if(useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
540 MAYBE(TRACE("BitBlt use: dst+pat -- pattern brush\n"));
541 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
543 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
545 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
546 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
549 for(i
= width
; i
> 0 ; i
--)
551 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
554 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
560 MAYBE(TRACE("BitBlt use: dst+pat - solid brush\n"));
562 MAYBE(TRACE("BitBlt use: dst\n"));
563 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
565 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
567 for(i
= width
; i
> 0 ; i
--)
569 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
572 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
575 else if(usePat
&& physDevDst
->isBrushBitmap
)
577 MAYBE(TRACE("BitBlt use: pat -- pattern brush\n"));
578 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
580 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
582 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
585 for(i
= width
; i
> 0 ; i
--)
587 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
590 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
595 MAYBE(TRACE("BitBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop
, patColor
));
596 MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp
)));
597 MAYBE(TRACE("xDst = %d, yDst = %d, width = %d, height = %d\n", xDst
, yDst
, width
, height
));
598 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
601 for(i
= width
; i
> 0 ; i
--)
603 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
606 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
610 ERR("What happened ?????? \n");
615 if(sBuf
) HeapFree( GetProcessHeap(), 0, sBuf
);
616 if(dBuf
) HeapFree( GetProcessHeap(), 0, dBuf
);
617 if(pBuf
) HeapFree( GetProcessHeap(), 0, pBuf
);
621 /* ------------------------------------------------------------*/
622 /* STRETCHING PRIMITIVES */
623 BOOL
_DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
624 INT widthDst
, INT heightDst
, const DIBDRVPHYSDEV
*physDevSrc
,
625 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
630 DIBDRVBITMAP
*dstBmp
, *patBmp
;
631 const DIBDRVBITMAP
*srcBmp
;
632 DWORD
*wDstPnt
, *wSrcPnt
, *wPatPnt
;
633 BOOL usePat
, useSrc
, useDst
;
637 /* 32 bit RGB source and destination buffer, if needed */
638 DWORD
*sBufOrig
= 0, *sBufStr
= 0, *dBuf
= 0, *pBuf
= 0;
640 /* get elements usage */
641 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
642 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
643 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
645 /* sanity check -- MSN messenger crashes without */
646 if(useSrc
&& !physDevSrc
)
649 /* gets source, dest and pattern bitmaps, if available */
650 if(usePat
&& physDevDst
->isBrushBitmap
)
651 patBmp
= &physDevDst
->brushBmpCache
;
656 srcBmp
= &physDevSrc
->physBitmap
;
659 dstBmp
= &physDevDst
->physBitmap
;
661 /* gets pattern color, in case it's needed */
663 patColor
= physDevDst
->brushColor
;
667 /* allocate 32 bit RGB destination buffer */
668 if(!(dBuf
= (DWORD
*)HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
671 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",
672 dstBmp
, _DIBDRVBITMAP_GetFormatName(dstBmp
), xDst
, yDst
, widthDst
, heightDst
,
673 srcBmp
, _DIBDRVBITMAP_GetFormatName(srcBmp
), xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
675 /* some simple ROPs optimizations */
679 MAYBE(TRACE("BLACKNESS\n"));
680 memset(dBuf
, 0x00, widthDst
* 4);
681 for(yd
= yDst
; yd
< yDst
+heightDst
; yd
++)
682 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
686 MAYBE(TRACE("WHITENESS\n"));
687 for(dwBuf
= dBuf
, i
= widthDst
; i
; i
--)
688 *dwBuf
++ = 0x00ffffff;
689 for(yd
= yDst
; yd
< yDst
+heightDst
; yd
++)
690 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
694 MAYBE(TRACE("SRCCOPY\n"));
695 sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4);
696 if(heightSrc
> heightDst
)
701 while(yd
< heightDst
)
703 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
704 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
705 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
706 while(delta
< heightSrc
)
715 else if(heightSrc
< heightDst
)
720 while(ys
< heightSrc
)
722 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
723 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
724 while(delta
< heightDst
)
726 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
736 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
738 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
739 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
740 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
745 /* fallback for generic ROP operation */
748 if(useSrc
&& useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
750 MAYBE(TRACE("StretchBlt use: src+dst+pat - pattern brush\n"));
751 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
753 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
755 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
757 if(heightSrc
> heightDst
)
762 while(yd
< heightDst
)
764 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
765 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
766 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
767 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
771 for(i
= widthDst
; i
> 0 ; i
--)
773 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
776 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
777 while(delta
< heightSrc
)
786 else if(heightSrc
< heightDst
)
791 while(ys
< heightSrc
)
793 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
794 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
795 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
796 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
797 while(delta
< heightDst
)
802 for(i
= widthDst
; i
> 0 ; i
--)
804 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
807 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
817 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
819 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
820 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
821 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
822 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
826 for(i
= widthDst
; i
> 0 ; i
--)
828 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
831 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
835 else if(useSrc
&& useDst
)
838 MAYBE(TRACE("StretchBlt use: src+dst+pat - solid brush\n"));
840 MAYBE(TRACE("StretchBlt use: src+dst\n"));
841 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
843 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
845 if(heightSrc
> heightDst
)
850 while(yd
< heightDst
)
852 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
853 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
854 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
857 for(i
= widthDst
; i
> 0 ; i
--)
859 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
862 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
863 while(delta
< heightSrc
)
872 else if(heightSrc
< heightDst
)
877 while(ys
< heightSrc
)
879 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
880 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
881 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
882 while(delta
< heightDst
)
886 for(i
= widthDst
; i
> 0 ; i
--)
888 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
891 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
901 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
903 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
904 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
905 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
908 for(i
= widthDst
; i
> 0 ; i
--)
910 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
913 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
917 else if(useSrc
&& usePat
&& physDevDst
->isBrushBitmap
)
919 MAYBE(TRACE("StretchBlt use: src+pat -- pattern brush\n"));
920 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
922 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
924 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
926 if(heightSrc
> heightDst
)
931 while(yd
< heightDst
)
933 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
934 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
935 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
939 for(i
= widthDst
; i
> 0 ; i
--)
941 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
944 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
945 while(delta
< heightSrc
)
954 else if(heightSrc
< heightDst
)
959 while(ys
< heightSrc
)
961 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
962 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
963 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
964 while(delta
< heightDst
)
969 for(i
= widthDst
; i
> 0 ; i
--)
971 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
974 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
984 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
986 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
987 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
988 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
992 for(i
= widthDst
; i
> 0 ; i
--)
994 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
997 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1004 MAYBE(TRACE("StretchBlt use: src+pat - solid brush\n"));
1006 MAYBE(TRACE("StretchBlt use: src\n"));
1007 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
1009 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
1011 if(heightSrc
> heightDst
)
1016 while(yd
< heightDst
)
1018 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
1019 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1022 for(i
= widthDst
; i
> 0 ; i
--)
1024 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1027 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1028 while(delta
< heightSrc
)
1037 else if(heightSrc
< heightDst
)
1042 while(ys
< heightSrc
)
1044 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
1045 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1046 while(delta
< heightDst
)
1050 for(i
= widthDst
; i
> 0 ; i
--)
1052 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1055 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1065 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1067 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
1068 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1071 for(i
= widthDst
; i
> 0 ; i
--)
1073 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1076 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1080 else if(useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
1082 MAYBE(TRACE("StretchBlt use: dst+pat -- pattern brush\n"));
1083 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
1085 if(heightSrc
> heightDst
)
1090 while(yd
< heightDst
)
1092 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1093 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1096 for(i
= widthDst
; i
> 0 ; i
--)
1098 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1101 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1102 while(delta
< heightSrc
)
1111 else if(heightSrc
< heightDst
)
1116 while(ys
< heightSrc
)
1118 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1119 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1120 while(delta
< heightDst
)
1124 for(i
= widthDst
; i
> 0 ; i
--)
1126 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1129 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1139 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1141 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
1142 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1145 for(i
= widthDst
; i
> 0 ; i
--)
1147 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1150 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1157 MAYBE(TRACE("StretchBlt use: dst+pat - solid brush\n"));
1159 MAYBE(TRACE("StretchBlt use: dst\n"));
1160 if(heightSrc
> heightDst
)
1165 while(yd
< heightDst
)
1167 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1169 for(i
= widthDst
; i
> 0 ; i
--)
1171 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1174 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1175 while(delta
< heightSrc
)
1184 else if(heightSrc
< heightDst
)
1189 while(ys
< heightSrc
)
1191 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1192 while(delta
< heightDst
)
1195 for(i
= widthDst
; i
> 0 ; i
--)
1197 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1200 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1210 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1212 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
1214 for(i
= widthDst
; i
> 0 ; i
--)
1216 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1219 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1223 else if(usePat
&& physDevDst
->isBrushBitmap
)
1225 MAYBE(TRACE("StretchBlt use: pat -- pattern brush\n"));
1226 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
1228 if(heightSrc
> heightDst
)
1233 while(yd
< heightDst
)
1235 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1238 for(i
= widthDst
; i
> 0 ; i
--)
1240 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1243 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1244 while(delta
< heightSrc
)
1253 else if(heightSrc
< heightDst
)
1258 while(ys
< heightSrc
)
1260 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1261 while(delta
< heightDst
)
1265 for(i
= widthDst
; i
> 0 ; i
--)
1267 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1270 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1280 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1282 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1285 for(i
= widthDst
; i
> 0 ; i
--)
1287 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1290 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1296 MAYBE(TRACE("StretchBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop
, patColor
));
1297 MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp
)));
1298 MAYBE(TRACE("xDst = %d, yDst = %d, widthDst = %d, heightDst = %d\n", xDst
, yDst
, widthDst
, heightDst
));
1299 if(heightSrc
> heightDst
)
1304 while(yd
< heightDst
)
1307 for(i
= widthDst
; i
> 0 ; i
--)
1309 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1312 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1313 while(delta
< heightSrc
)
1322 else if(heightSrc
< heightDst
)
1327 while(ys
< heightSrc
)
1329 while(delta
< heightDst
)
1332 for(i
= widthDst
; i
> 0 ; i
--)
1334 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1337 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1347 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1350 for(i
= widthDst
; i
> 0 ; i
--)
1352 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1355 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1360 ERR("What happened ?????? \n");
1365 if(sBufOrig
) HeapFree( GetProcessHeap(), 0, sBufOrig
);
1366 if(sBufStr
) HeapFree( GetProcessHeap(), 0, sBufStr
);
1367 if(dBuf
) HeapFree( GetProcessHeap(), 0, dBuf
);
1368 if(pBuf
) HeapFree( GetProcessHeap(), 0, pBuf
);