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
, sBuf
, 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 /* gets source, dest and pattern bitmaps, if available */
395 if(usePat
&& physDevDst
->isBrushBitmap
)
396 patBmp
= &physDevDst
->brushBmpCache
;
401 srcBmp
= &physDevSrc
->physBitmap
;
404 dstBmp
= &physDevDst
->physBitmap
;
406 /* gets pattern color, in case it's needed */
408 patColor
= physDevDst
->brushColor
;
412 /* allocate 32 bit RGB destination buffer */
413 if(!(dBuf
= (DWORD
*)HeapAlloc( GetProcessHeap(), 0, width
* 4)))
416 MAYBE(TRACE("dstBmp:%p(%s), xDst:%d, yDst:%d, width:%d, height:%d, srcBmp:%p(%s), xSrc:%d, ySrc:%d, rop:%8x\n",
417 dstBmp
, _DIBDRVBITMAP_GetFormatName(dstBmp
), xDst
, yDst
, width
, height
,
418 srcBmp
, _DIBDRVBITMAP_GetFormatName(srcBmp
), xSrc
, ySrc
, rop
));
420 /* some simple ROPs optimizations */
424 MAYBE(TRACE("BLACKNESS\n"));
425 memset(dBuf
, 0x00, width
* 4);
426 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
427 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
431 MAYBE(TRACE("WHITENESS\n"));
432 for(dwBuf
= dBuf
, i
= width
; i
; i
--)
433 *dwBuf
++ = 0x00ffffff;
434 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
435 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
439 MAYBE(TRACE("SRCCOPY\n"));
440 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
442 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
443 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
447 /* fallback for generic ROP operation */
450 if(useSrc
&& useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
452 MAYBE(TRACE("BitBlt use: src+dst+pat - pattern brush\n"));
453 if(!(sBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
455 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
457 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
459 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, sBuf
);
460 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, width
, dBuf
);
461 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
465 for(i
= width
; i
> 0 ; i
--)
467 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
470 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
473 else if(useSrc
&& useDst
)
476 MAYBE(TRACE("BitBlt use: src+dst+pat - solid brush\n"));
478 MAYBE(TRACE("BitBlt use: src+dst\n"));
479 if(!(sBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
481 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
483 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, sBuf
);
484 dstBmp
->funcs
->GetLine(dstBmp
, yd
, xDst
, width
, dBuf
);
487 for(i
= width
; i
> 0 ; i
--)
489 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
492 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
495 else if(useSrc
&& usePat
&& physDevDst
->isBrushBitmap
)
497 MAYBE(TRACE("BitBlt use: src+pat -- pattern brush\n"));
498 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
500 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
502 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
503 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
507 for(i
= width
; i
> 0 ; i
--)
509 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
512 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
518 MAYBE(TRACE("BitBlt use: src+pat - solid brush\n"));
520 MAYBE(TRACE("BitBlt use: src\n"));
521 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
523 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, width
, dBuf
);
526 for(i
= width
; i
> 0 ; i
--)
528 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
531 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
534 else if(useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
536 MAYBE(TRACE("BitBlt use: dst+pat -- pattern brush\n"));
537 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
539 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
541 dstBmp
->funcs
->GetLine(srcBmp
, ys
, xDst
, width
, dBuf
);
542 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
545 for(i
= width
; i
> 0 ; i
--)
547 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
550 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
556 MAYBE(TRACE("BitBlt use: dst+pat - solid brush\n"));
558 MAYBE(TRACE("BitBlt use: dst\n"));
559 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
561 dstBmp
->funcs
->GetLine(srcBmp
, ys
, xDst
, width
, dBuf
);
563 for(i
= width
; i
> 0 ; i
--)
565 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
568 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
571 else if(usePat
&& physDevDst
->isBrushBitmap
)
573 MAYBE(TRACE("BitBlt use: pat -- pattern brush\n"));
574 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, width
* 4)))
576 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+height
; ys
++, yd
++)
578 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, width
, pBuf
);
581 for(i
= width
; i
> 0 ; i
--)
583 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
586 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
591 MAYBE(TRACE("BitBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop
, patColor
));
592 MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp
)));
593 MAYBE(TRACE("xDst = %d, yDst = %d, width = %d, height = %d\n", xDst
, yDst
, width
, height
));
594 for(yd
= yDst
; yd
< yDst
+height
; yd
++)
597 for(i
= width
; i
> 0 ; i
--)
599 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
602 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, width
, dBuf
);
606 ERR("What happened ?????? \n");
611 if(sBuf
) HeapFree( GetProcessHeap(), 0, sBuf
);
612 if(dBuf
) HeapFree( GetProcessHeap(), 0, dBuf
);
613 if(pBuf
) HeapFree( GetProcessHeap(), 0, pBuf
);
617 /* ------------------------------------------------------------*/
618 /* STRETCHING PRIMITIVES */
619 BOOL
_DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
620 INT widthDst
, INT heightDst
, const DIBDRVPHYSDEV
*physDevSrc
,
621 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
626 DIBDRVBITMAP
*dstBmp
, *patBmp
;
627 const DIBDRVBITMAP
*srcBmp
;
628 DWORD
*wDstPnt
, *wSrcPnt
, *wPatPnt
;
629 BOOL usePat
, useSrc
, useDst
;
633 /* 32 bit RGB source and destination buffer, if needed */
634 DWORD
*sBufOrig
= 0, *sBufStr
= 0, *dBuf
= 0, *pBuf
= 0;
636 /* get elements usage */
637 usePat
= (((rop
>> 4) & 0x0f0000) != (rop
& 0x0f0000));
638 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
639 useDst
= (((rop
>> 1) & 0x550000) != (rop
& 0x550000));
641 /* gets source, dest and pattern bitmaps, if available */
642 if(usePat
&& physDevDst
->isBrushBitmap
)
643 patBmp
= &physDevDst
->brushBmpCache
;
648 srcBmp
= &physDevSrc
->physBitmap
;
651 dstBmp
= &physDevDst
->physBitmap
;
653 /* gets pattern color, in case it's needed */
655 patColor
= physDevDst
->brushColor
;
659 /* allocate 32 bit RGB destination buffer */
660 if(!(dBuf
= (DWORD
*)HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
663 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",
664 dstBmp
, _DIBDRVBITMAP_GetFormatName(dstBmp
), xDst
, yDst
, widthDst
, heightDst
,
665 srcBmp
, _DIBDRVBITMAP_GetFormatName(srcBmp
), xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
667 /* some simple ROPs optimizations */
671 MAYBE(TRACE("BLACKNESS\n"));
672 memset(dBuf
, 0x00, widthDst
* 4);
673 for(yd
= yDst
; yd
< yDst
+heightDst
; yd
++)
674 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
678 MAYBE(TRACE("WHITENESS\n"));
679 for(dwBuf
= dBuf
, i
= widthDst
; i
; i
--)
680 *dwBuf
++ = 0x00ffffff;
681 for(yd
= yDst
; yd
< yDst
+heightDst
; yd
++)
682 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
686 MAYBE(TRACE("SRCCOPY\n"));
687 sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4);
688 if(heightSrc
> heightDst
)
693 while(yd
< heightDst
)
695 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
696 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
697 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
698 while(delta
< heightSrc
)
707 else if(heightSrc
< heightDst
)
712 while(ys
< heightSrc
)
714 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
715 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
716 while(delta
< heightDst
)
718 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
728 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
730 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
731 StretchLine(dBuf
, widthDst
, sBufOrig
, widthSrc
);
732 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
737 /* fallback for generic ROP operation */
740 if(useSrc
&& useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
742 MAYBE(TRACE("StretchBlt use: src+dst+pat - pattern brush\n"));
743 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
745 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
747 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
749 if(heightSrc
> heightDst
)
754 while(yd
< heightDst
)
756 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
757 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
758 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
759 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
763 for(i
= widthDst
; i
> 0 ; i
--)
765 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
768 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
769 while(delta
< heightSrc
)
778 else if(heightSrc
< heightDst
)
783 while(ys
< heightSrc
)
785 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
786 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
787 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
788 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
789 while(delta
< heightDst
)
794 for(i
= widthDst
; i
> 0 ; i
--)
796 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
799 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
809 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
811 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
812 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
813 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
814 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
818 for(i
= widthDst
; i
> 0 ; i
--)
820 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, *wDstPnt
, rop
);
823 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
827 else if(useSrc
&& useDst
)
830 MAYBE(TRACE("StretchBlt use: src+dst+pat - solid brush\n"));
832 MAYBE(TRACE("StretchBlt use: src+dst\n"));
833 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
835 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
837 if(heightSrc
> heightDst
)
842 while(yd
< heightDst
)
844 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
845 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
846 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
849 for(i
= widthDst
; i
> 0 ; i
--)
851 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
854 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
855 while(delta
< heightSrc
)
864 else if(heightSrc
< heightDst
)
869 while(ys
< heightSrc
)
871 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
872 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
873 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
874 while(delta
< heightDst
)
878 for(i
= widthDst
; i
> 0 ; i
--)
880 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
883 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
893 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
895 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
896 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
897 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
900 for(i
= widthDst
; i
> 0 ; i
--)
902 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, *wDstPnt
, rop
);
905 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
909 else if(useSrc
&& usePat
&& physDevDst
->isBrushBitmap
)
911 MAYBE(TRACE("StretchBlt use: src+pat -- pattern brush\n"));
912 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
914 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
916 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
918 if(heightSrc
> heightDst
)
923 while(yd
< heightDst
)
925 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
926 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
927 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
931 for(i
= widthDst
; i
> 0 ; i
--)
933 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
936 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
937 while(delta
< heightSrc
)
946 else if(heightSrc
< heightDst
)
951 while(ys
< heightSrc
)
953 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
954 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
955 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
956 while(delta
< heightDst
)
961 for(i
= widthDst
; i
> 0 ; i
--)
963 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
966 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
976 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
978 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
979 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
980 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
984 for(i
= widthDst
; i
> 0 ; i
--)
986 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, *wSrcPnt
++, 0, rop
);
989 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
996 MAYBE(TRACE("StretchBlt use: src+pat - solid brush\n"));
998 MAYBE(TRACE("StretchBlt use: src\n"));
999 if(!(sBufOrig
= HeapAlloc(GetProcessHeap(), 0, widthSrc
* 4)))
1001 if(!(sBufStr
= HeapAlloc(GetProcessHeap(), 0, widthDst
* 4)))
1003 if(heightSrc
> heightDst
)
1008 while(yd
< heightDst
)
1010 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
1011 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1014 for(i
= widthDst
; i
> 0 ; i
--)
1016 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1019 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1020 while(delta
< heightSrc
)
1029 else if(heightSrc
< heightDst
)
1034 while(ys
< heightSrc
)
1036 srcBmp
->funcs
->GetLine(srcBmp
, ys
+ ySrc
, xSrc
, widthSrc
, sBufOrig
);
1037 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1038 while(delta
< heightDst
)
1042 for(i
= widthDst
; i
> 0 ; i
--)
1044 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1047 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1057 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1059 srcBmp
->funcs
->GetLine(srcBmp
, ys
, xSrc
, widthSrc
, sBufOrig
);
1060 StretchLine(sBufStr
, widthDst
, sBufOrig
, widthSrc
);
1063 for(i
= widthDst
; i
> 0 ; i
--)
1065 *wDstPnt
= _DIBDRV_ROP3(patColor
, *wSrcPnt
++, 0, rop
);
1068 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1072 else if(useDst
&& usePat
&& physDevDst
->isBrushBitmap
)
1074 MAYBE(TRACE("StretchBlt use: dst+pat -- pattern brush\n"));
1075 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
1077 if(heightSrc
> heightDst
)
1082 while(yd
< heightDst
)
1084 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1085 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1088 for(i
= widthDst
; i
> 0 ; i
--)
1090 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1093 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1094 while(delta
< heightSrc
)
1103 else if(heightSrc
< heightDst
)
1108 while(ys
< heightSrc
)
1110 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1111 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1112 while(delta
< heightDst
)
1116 for(i
= widthDst
; i
> 0 ; i
--)
1118 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1121 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1131 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1133 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
1134 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1137 for(i
= widthDst
; i
> 0 ; i
--)
1139 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, *wDstPnt
, rop
);
1142 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1149 MAYBE(TRACE("StretchBlt use: dst+pat - solid brush\n"));
1151 MAYBE(TRACE("StretchBlt use: dst\n"));
1152 if(heightSrc
> heightDst
)
1157 while(yd
< heightDst
)
1159 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1161 for(i
= widthDst
; i
> 0 ; i
--)
1163 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1166 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1167 while(delta
< heightSrc
)
1176 else if(heightSrc
< heightDst
)
1181 while(ys
< heightSrc
)
1183 dstBmp
->funcs
->GetLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1184 while(delta
< heightDst
)
1187 for(i
= widthDst
; i
> 0 ; i
--)
1189 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1192 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1202 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1204 dstBmp
->funcs
->GetLine(dstBmp
, ys
, xDst
, widthDst
, dBuf
);
1206 for(i
= widthDst
; i
> 0 ; i
--)
1208 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, *wDstPnt
, rop
);
1211 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1215 else if(usePat
&& physDevDst
->isBrushBitmap
)
1217 MAYBE(TRACE("StretchBlt use: pat -- pattern brush\n"));
1218 if(!(pBuf
= HeapAlloc( GetProcessHeap(), 0, widthDst
* 4)))
1220 if(heightSrc
> heightDst
)
1225 while(yd
< heightDst
)
1227 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1230 for(i
= widthDst
; i
> 0 ; i
--)
1232 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1235 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1236 while(delta
< heightSrc
)
1245 else if(heightSrc
< heightDst
)
1250 while(ys
< heightSrc
)
1252 patBmp
->funcs
->GetLine(patBmp
, (yd
+ yDst
)%patBmp
->height
, 0, widthDst
, pBuf
);
1253 while(delta
< heightDst
)
1257 for(i
= widthDst
; i
> 0 ; i
--)
1259 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1262 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1272 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1274 patBmp
->funcs
->GetLine(patBmp
, ys
%patBmp
->height
, 0, widthDst
, pBuf
);
1277 for(i
= widthDst
; i
> 0 ; i
--)
1279 *wDstPnt
= _DIBDRV_ROP3(*wPatPnt
++, 0, 0, rop
);
1282 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1288 MAYBE(TRACE("StretchBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop
, patColor
));
1289 MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp
)));
1290 MAYBE(TRACE("xDst = %d, yDst = %d, widthDst = %d, heightDst = %d\n", xDst
, yDst
, widthDst
, heightDst
));
1291 if(heightSrc
> heightDst
)
1296 while(yd
< heightDst
)
1299 for(i
= widthDst
; i
> 0 ; i
--)
1301 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1304 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1305 while(delta
< heightSrc
)
1314 else if(heightSrc
< heightDst
)
1319 while(ys
< heightSrc
)
1321 while(delta
< heightDst
)
1324 for(i
= widthDst
; i
> 0 ; i
--)
1326 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1329 dstBmp
->funcs
->PutLine(dstBmp
, yd
+ yDst
, xDst
, widthDst
, dBuf
);
1339 for(ys
= ySrc
, yd
= yDst
; ys
< ySrc
+heightSrc
; ys
++, yd
++)
1342 for(i
= widthDst
; i
> 0 ; i
--)
1344 *wDstPnt
= _DIBDRV_ROP3(patColor
, 0, 0, rop
);
1347 dstBmp
->funcs
->PutLine(dstBmp
, yd
, xDst
, widthDst
, dBuf
);
1352 ERR("What happened ?????? \n");
1357 if(sBufOrig
) HeapFree( GetProcessHeap(), 0, sBufOrig
);
1358 if(sBufStr
) HeapFree( GetProcessHeap(), 0, sBufStr
);
1359 if(dBuf
) HeapFree( GetProcessHeap(), 0, dBuf
);
1360 if(pBuf
) HeapFree( GetProcessHeap(), 0, pBuf
);