2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: GDI BitBlt Functions
24 * FILE: subsys/win32k/eng/bitblt.c
25 * PROGRAMER: Jason Filby
35 typedef BOOLEAN (APIENTRY
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
38 XLATEOBJ
* ColorTranslation
,
45 typedef BOOLEAN (APIENTRY
*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
48 XLATEOBJ
* ColorTranslation
,
56 BOOL APIENTRY
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
58 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
60 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
61 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
63 if (prcDst
->left
< prcDst
->right
)
65 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
66 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
68 if (prcDst
->top
< prcDst
->bottom
)
79 static BOOLEAN APIENTRY
80 BltMask(SURFOBJ
* psoDest
,
81 SURFOBJ
* psoSource
, // unused
83 XLATEOBJ
* ColorTranslation
, // unused
85 POINTL
* pptlSource
, // unused
92 BYTE
*pjMskLine
, *pjMskCurrent
;
93 BYTE fjMaskBit0
, fjMaskBit
;
95 PEBRUSHOBJ pebo
= NULL
;
96 SURFOBJ
*psoPattern
= NULL
;
97 PSURFACE psurfPattern
;
98 ULONG PatternWidth
= 0, PatternHeight
= 0;
99 LONG PatternX0
= 0, PatternX
= 0, PatternY
= 0;
100 PFN_DIB_PutPixel fnDest_PutPixel
= NULL
;
101 PFN_DIB_GetPixel fnPattern_GetPixel
= NULL
;
110 if (pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
112 pebo
= CONTAINING_RECORD(pbo
, EBRUSHOBJ
, BrushObject
);
114 psurfPattern
= SURFACE_LockSurface(pebo
->pbrush
->hbmPattern
);
115 if (psurfPattern
!= NULL
)
117 psoPattern
= &psurfPattern
->SurfObj
;
118 PatternWidth
= psoPattern
->sizlBitmap
.cx
;
119 PatternHeight
= psoPattern
->sizlBitmap
.cy
;
121 fnPattern_GetPixel
= DibFunctionsForBitmapFormat
[psoPattern
->iBitmapFormat
].DIB_GetPixel
;
126 pjMskLine
= (PBYTE
)psoMask
->pvScan0
+ pptlMask
->y
* psoMask
->lDelta
+ (pptlMask
->x
>> 3);
127 fjMaskBit0
= 0x80 >> (pptlMask
->x
& 0x07);
129 fnDest_PutPixel
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel
;
132 XlateObj
= pebo
? pebo
->XlateObject
: NULL
;
133 PatternY
= (prclDest
->top
- pptlBrush
->y
) % PatternHeight
;
136 PatternY
+= PatternHeight
;
138 PatternX0
= (prclDest
->left
- pptlBrush
->x
) % PatternWidth
;
141 PatternX0
+= PatternWidth
;
144 for (y
= prclDest
->top
; y
< prclDest
->bottom
; y
++)
146 pjMskCurrent
= pjMskLine
;
147 fjMaskBit
= fjMaskBit0
;
148 PatternX
= PatternX0
;
150 for (x
= prclDest
->left
; x
< prclDest
->right
; x
++)
152 if (*pjMskCurrent
& fjMaskBit
)
154 fnDest_PutPixel(psoDest
, x
, y
,
155 XLATEOBJ_iXlate(XlateObj
,
156 fnPattern_GetPixel(psoPattern
, PatternX
, PatternY
)));
158 fjMaskBit
= _rotr8(fjMaskBit
, 1);
159 pjMskCurrent
+= (fjMaskBit
>> 7);
161 PatternX
%= PatternWidth
;
163 pjMskLine
+= psoMask
->lDelta
;
165 PatternY
%= PatternHeight
;
170 Pattern
= pbo
? pbo
->iSolidColor
: 0;
171 for (y
= prclDest
->top
; y
< prclDest
->bottom
; y
++)
173 pjMskCurrent
= pjMskLine
;
174 fjMaskBit
= fjMaskBit0
;
176 for (x
= prclDest
->left
; x
< prclDest
->right
; x
++)
178 if (*pjMskCurrent
& fjMaskBit
)
180 fnDest_PutPixel(psoDest
, x
, y
, Pattern
);
182 fjMaskBit
= _rotr8(fjMaskBit
, 1);
183 pjMskCurrent
+= (fjMaskBit
>> 7);
185 pjMskLine
+= psoMask
->lDelta
;
190 SURFACE_UnlockSurface(psurfPattern
);
195 static BOOLEAN APIENTRY
196 BltPatCopy(SURFOBJ
* Dest
,
199 XLATEOBJ
* ColorTranslation
,
207 // These functions are assigned if we're working with a DIB
208 // The assigned functions depend on the bitsPerPixel of the DIB
210 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_ColorFill(Dest
, DestRect
, pbo
? pbo
->iSolidColor
: 0);
215 static BOOLEAN APIENTRY
216 CallDibBitBlt(SURFOBJ
* OutputObj
,
219 XLATEOBJ
* ColorTranslation
,
228 PEBRUSHOBJ GdiBrush
= NULL
;
229 SURFACE
*psurfPattern
;
232 BltInfo
.DestSurface
= OutputObj
;
233 BltInfo
.SourceSurface
= InputObj
;
234 BltInfo
.PatternSurface
= NULL
;
235 BltInfo
.XlateSourceToDest
= ColorTranslation
;
236 BltInfo
.DestRect
= *OutputRect
;
237 BltInfo
.SourcePoint
= *InputPoint
;
239 if (ROP3_TO_ROP4(SRCCOPY
) == Rop4
)
240 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBltSrcCopy(&BltInfo
);
242 BltInfo
.XlatePatternToDest
= NULL
;
244 BltInfo
.BrushOrigin
= *BrushOrigin
;
248 if (ROP4_USES_PATTERN(Rop4
) && pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
250 GdiBrush
= CONTAINING_RECORD(pbo
, EBRUSHOBJ
, BrushObject
);
251 if ((psurfPattern
= SURFACE_LockSurface(GdiBrush
->pbrush
->hbmPattern
)))
253 BltInfo
.PatternSurface
= &psurfPattern
->SurfObj
;
257 /* FIXME - What to do here? */
259 BltInfo
.XlatePatternToDest
= GdiBrush
->XlateObject
;
266 Result
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBlt(&BltInfo
);
269 if (psurfPattern
!= NULL
)
271 SURFACE_UnlockSurface(psurfPattern
);
277 INT __cdecl
abs(INT nm
);
294 IN POINTL
*pptlBrush
,
304 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
305 RtlCopyMemory(&rclTrg
,prclTrg
, sizeof(RECTL
));
307 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
308 RtlCopyMemory(&ptlSrc
, pptlSrc
, sizeof(POINTL
));
310 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
311 RtlCopyMemory(&ptlMask
, pptlMask
, sizeof(POINTL
));
313 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
314 RtlCopyMemory(&ptlBrush
, pptlBrush
, sizeof(POINTL
));
317 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
319 _SEH2_YIELD(return FALSE
);
323 return EngBitBlt(psoTrg
, psoSrc
, psoMask
, pco
, pxlo
, &rclTrg
, &ptlSrc
, &ptlMask
, pbo
, &ptlBrush
, rop4
);
330 EngBitBlt(SURFOBJ
*DestObj
,
334 XLATEOBJ
*ColorTranslation
,
350 INTENG_ENTER_LEAVE EnterLeaveSource
;
351 INTENG_ENTER_LEAVE EnterLeaveDest
;
354 PBLTRECTFUNC BltRectFunc
;
362 POINTL AdjustedBrushOrigin
;
364 UsesSource
= ROP4_USES_SOURCE(Rop4
);
365 UsesPattern
= ROP4_USES_PATTERN(Rop4
);
368 /* Copy destination onto itself: nop */
372 OutputRect
= *DestRect
;
373 if (OutputRect
.right
< OutputRect
.left
)
375 OutputRect
.left
= DestRect
->right
;
376 OutputRect
.right
= DestRect
->left
;
378 if (OutputRect
.bottom
< OutputRect
.top
)
380 OutputRect
.left
= DestRect
->right
;
381 OutputRect
.right
= DestRect
->left
;
386 if (NULL
== SourcePoint
)
391 /* Make sure we don't try to copy anything outside the valid source
393 InputPoint
= *SourcePoint
;
394 if (InputPoint
.x
< 0)
396 OutputRect
.left
-= InputPoint
.x
;
399 if (InputPoint
.y
< 0)
401 OutputRect
.top
-= InputPoint
.y
;
404 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+
405 OutputRect
.right
- OutputRect
.left
)
407 OutputRect
.right
= OutputRect
.left
+
408 SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
410 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+
411 OutputRect
.bottom
- OutputRect
.top
)
413 OutputRect
.bottom
= OutputRect
.top
+
414 SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
417 InputRect
.left
= InputPoint
.x
;
418 InputRect
.right
= InputPoint
.x
+ (OutputRect
.right
- OutputRect
.left
);
419 InputRect
.top
= InputPoint
.y
;
420 InputRect
.bottom
= InputPoint
.y
+ (OutputRect
.bottom
- OutputRect
.top
);
422 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
,
423 &Translate
, &InputObj
))
428 InputPoint
.x
+= Translate
.x
;
429 InputPoint
.y
+= Translate
.y
;
434 InputRect
.right
= DestRect
->right
- DestRect
->left
;
436 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
439 if (NULL
!= ClipRegion
)
441 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
443 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
444 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
445 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
447 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
449 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
450 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
452 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
454 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
455 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
456 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
458 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
460 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
461 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
465 /* Check for degenerate case: if height or width of OutputRect is 0 pixels
466 there's nothing to do */
467 if (OutputRect
.right
<= OutputRect
.left
||
468 OutputRect
.bottom
<= OutputRect
.top
)
472 IntEngLeave(&EnterLeaveSource
);
477 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
,
482 IntEngLeave(&EnterLeaveSource
);
487 OutputRect
.left
+= Translate
.x
;
488 OutputRect
.right
+= Translate
.x
;
489 OutputRect
.top
+= Translate
.y
;
490 OutputRect
.bottom
+= Translate
.y
;
494 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
495 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
499 AdjustedBrushOrigin
= Translate
;
502 /* Determine clipping type */
503 if (ClipRegion
== (CLIPOBJ
*) NULL
)
505 clippingType
= DC_TRIVIAL
;
509 clippingType
= ClipRegion
->iDComplexity
;
514 BltRectFunc
= BltMask
;
516 else if (ROP3_TO_ROP4(PATCOPY
) == Rop4
)
518 if (pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
519 BltRectFunc
= CallDibBitBlt
;
521 BltRectFunc
= BltPatCopy
;
525 BltRectFunc
= CallDibBitBlt
;
529 switch (clippingType
)
532 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
533 &OutputRect
, &InputPoint
, MaskOrigin
, pbo
,
534 &AdjustedBrushOrigin
, Rop4
);
537 /* Clip the blt to the clip rectangle */
538 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
539 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
540 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
541 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
542 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
544 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
545 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
546 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
547 &CombinedRect
, &Pt
, MaskOrigin
, pbo
,
548 &AdjustedBrushOrigin
, Rop4
);
553 if (OutputObj
== InputObj
)
555 if (OutputRect
.top
< InputPoint
.y
)
557 Direction
= OutputRect
.left
< InputPoint
.x
?
558 CD_RIGHTDOWN
: CD_LEFTDOWN
;
562 Direction
= OutputRect
.left
< InputPoint
.x
?
563 CD_RIGHTUP
: CD_LEFTUP
;
570 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
573 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
576 for (i
= 0; i
< RectEnum
.c
; i
++)
578 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
579 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
580 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
581 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
582 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
584 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
585 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
586 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
,
587 ColorTranslation
, &CombinedRect
, &Pt
,
588 MaskOrigin
, pbo
, &AdjustedBrushOrigin
,
598 IntEngLeave(&EnterLeaveDest
);
601 IntEngLeave(&EnterLeaveSource
);
608 IntEngBitBltEx(SURFOBJ
*psoDest
,
612 XLATEOBJ
*ColorTranslation
,
622 RECTL InputClippedRect
;
627 SURFACE
*psurfSource
= NULL
;
632 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
635 InputClippedRect
= *DestRect
;
636 if (InputClippedRect
.right
< InputClippedRect
.left
)
638 InputClippedRect
.left
= DestRect
->right
;
639 InputClippedRect
.right
= DestRect
->left
;
641 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
643 InputClippedRect
.top
= DestRect
->bottom
;
644 InputClippedRect
.bottom
= DestRect
->top
;
646 UsesSource
= ROP4_USES_SOURCE(Rop4
);
649 if (NULL
== SourcePoint
|| NULL
== psoSource
)
653 InputPoint
= *SourcePoint
;
655 /* Make sure we don't try to copy anything outside the valid source
657 if (InputPoint
.x
< 0)
659 InputClippedRect
.left
-= InputPoint
.x
;
662 if (InputPoint
.y
< 0)
664 InputClippedRect
.top
-= InputPoint
.y
;
667 if (psoSource
->sizlBitmap
.cx
< InputPoint
.x
+
668 InputClippedRect
.right
-
669 InputClippedRect
.left
)
671 InputClippedRect
.right
= InputClippedRect
.left
+
672 psoSource
->sizlBitmap
.cx
- InputPoint
.x
;
674 if (psoSource
->sizlBitmap
.cy
< InputPoint
.y
+
675 InputClippedRect
.bottom
-
676 InputClippedRect
.top
)
678 InputClippedRect
.bottom
= InputClippedRect
.top
+
679 psoSource
->sizlBitmap
.cy
- InputPoint
.y
;
682 if (InputClippedRect
.right
< InputClippedRect
.left
||
683 InputClippedRect
.bottom
< InputClippedRect
.top
)
685 /* Everything clipped away, nothing to do */
690 /* Clip against the bounds of the clipping region so we won't try to write
691 * outside the surface */
692 if (NULL
!= ClipRegion
)
694 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
695 &ClipRegion
->rclBounds
))
699 InputPoint
.x
+= OutputRect
.left
- InputClippedRect
.left
;
700 InputPoint
.y
+= OutputRect
.top
- InputClippedRect
.top
;
704 OutputRect
= InputClippedRect
;
709 SURFACE_LockBitmapBits(psurfDest
);
713 if (psoSource
!= psoDest
)
715 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
716 SURFACE_LockBitmapBits(psurfSource
);
718 MouseSafetyOnDrawStart(psoSource
, InputPoint
.x
, InputPoint
.y
,
719 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
720 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
722 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
723 OutputRect
.right
, OutputRect
.bottom
);
729 /* Call the driver's DrvBitBlt if available */
730 if (psurfDest
->flHooks
& HOOK_BITBLT
)
732 ret
= GDIDEVFUNCS(psoDest
).BitBlt(
733 psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
734 &OutputRect
, &InputPoint
, MaskOrigin
, pbo
, BrushOrigin
,
740 ret
= EngBitBlt(psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
741 &OutputRect
, &InputPoint
, MaskOrigin
, pbo
, BrushOrigin
,
747 MouseSafetyOnDrawEnd(psoDest
);
750 MouseSafetyOnDrawEnd(psoSource
);
751 if (psoSource
!= psoDest
)
753 SURFACE_UnlockBitmapBits(psurfSource
);
757 SURFACE_UnlockBitmapBits(psurfDest
);
763 static BOOLEAN APIENTRY
764 CallDibStretchBlt(SURFOBJ
* psoDest
,
767 XLATEOBJ
* ColorTranslation
,
775 POINTL RealBrushOrigin
;
776 SURFACE
* psurfPattern
;
777 PEBRUSHOBJ GdiBrush
= NULL
;
778 SURFOBJ
* PatternSurface
= NULL
;
779 XLATEOBJ
* XlatePatternToDest
= NULL
;
781 if (BrushOrigin
== NULL
)
783 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
787 RealBrushOrigin
= *BrushOrigin
;
791 if (ROP4_USES_PATTERN(Rop4
) && pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
793 GdiBrush
= CONTAINING_RECORD(pbo
, EBRUSHOBJ
, BrushObject
);
794 psurfPattern
= SURFACE_LockSurface(GdiBrush
->pbrush
->hbmPattern
);
797 PatternSurface
= &psurfPattern
->SurfObj
;
801 /* FIXME - What to do here? */
803 XlatePatternToDest
= GdiBrush
->XlateObject
;
810 return DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_StretchBlt(
811 psoDest
, psoSource
, Mask
, PatternSurface
,
812 OutputRect
, InputRect
, MaskOrigin
, pbo
, &RealBrushOrigin
,
813 ColorTranslation
, XlatePatternToDest
, Rop4
);
818 SURFACE_UnlockSurface(psurfPattern
);
827 IN SURFOBJ
*psoSource
,
829 IN CLIPOBJ
*ClipRegion
,
830 IN XLATEOBJ
*ColorTranslation
,
831 IN COLORADJUSTMENT
*pca
,
832 IN POINTL
*BrushOrigin
,
835 IN POINTL
*MaskOrigin
,
846 ProbeForRead(pca
, sizeof(COLORADJUSTMENT
), 1);
847 RtlCopyMemory(&ca
,pca
, sizeof(COLORADJUSTMENT
));
849 ProbeForRead(BrushOrigin
, sizeof(POINTL
), 1);
850 RtlCopyMemory(&lBrushOrigin
, BrushOrigin
, sizeof(POINTL
));
852 ProbeForRead(prclDest
, sizeof(RECTL
), 1);
853 RtlCopyMemory(&rclDest
, prclDest
, sizeof(RECTL
));
855 ProbeForRead(prclSrc
, sizeof(RECTL
), 1);
856 RtlCopyMemory(&rclSrc
, prclSrc
, sizeof(RECTL
));
858 ProbeForRead(MaskOrigin
, sizeof(POINTL
), 1);
859 RtlCopyMemory(&lMaskOrigin
, MaskOrigin
, sizeof(POINTL
));
862 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
864 _SEH2_YIELD(return FALSE
);
868 return EngStretchBlt(psoDest
, psoSource
, Mask
, ClipRegion
, ColorTranslation
, &ca
, &lBrushOrigin
, &rclDest
, &rclSrc
, &lMaskOrigin
, Mode
);
878 IN SURFOBJ
*psoSource
,
880 IN CLIPOBJ
*ClipRegion
,
881 IN XLATEOBJ
*ColorTranslation
,
882 IN COLORADJUSTMENT
*pca
,
883 IN POINTL
*BrushOrigin
,
886 IN POINTL
*MaskOrigin
,
894 INTENG_ENTER_LEAVE EnterLeaveSource
;
895 INTENG_ENTER_LEAVE EnterLeaveDest
;
898 PSTRETCHRECTFUNC BltRectFunc
;
900 POINTL AdjustedBrushOrigin
;
901 BOOL UsesSource
= ROP4_USES_SOURCE(ROP4
);
909 RECTL InputToCombinedRect
;
917 /* Determine clipping type */
918 if (ClipRegion
== (CLIPOBJ
*) NULL
)
920 clippingType
= DC_TRIVIAL
;
924 clippingType
= ClipRegion
->iDComplexity
;
929 /* Copy destination onto itself: nop */
933 OutputRect
= *prclDest
;
934 if (OutputRect
.right
< OutputRect
.left
)
936 OutputRect
.left
= prclDest
->right
;
937 OutputRect
.right
= prclDest
->left
;
939 if (OutputRect
.bottom
< OutputRect
.top
)
941 OutputRect
.top
= prclDest
->bottom
;
942 OutputRect
.bottom
= prclDest
->top
;
945 InputRect
= *prclSrc
;
953 if (! IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
,
954 &Translate
, &psoInput
))
959 InputRect
.left
+= Translate
.x
;
960 InputRect
.right
+= Translate
.x
;
961 InputRect
.top
+= Translate
.y
;
962 InputRect
.bottom
+= Translate
.y
;
965 if (NULL
!= ClipRegion
)
967 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
969 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
970 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
972 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
974 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
975 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
977 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
979 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
980 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
982 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
984 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
985 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
989 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
991 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
995 IntEngLeave(&EnterLeaveSource
);
1000 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
1004 IntEngLeave(&EnterLeaveSource
);
1009 OutputRect
.left
+= Translate
.x
;
1010 OutputRect
.right
+= Translate
.x
;
1011 OutputRect
.top
+= Translate
.y
;
1012 OutputRect
.bottom
+= Translate
.y
;
1016 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1017 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1021 AdjustedBrushOrigin
= Translate
;
1024 BltRectFunc
= CallDibStretchBlt
;
1026 DstHeight
= OutputRect
.bottom
- OutputRect
.top
;
1027 DstWidth
= OutputRect
.right
- OutputRect
.left
;
1028 SrcHeight
= InputRect
.bottom
- InputRect
.top
;
1029 SrcWidth
= InputRect
.right
- InputRect
.left
;
1030 switch (clippingType
)
1033 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
,
1034 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
1035 pbo
, &AdjustedBrushOrigin
, ROP4
);
1038 // Clip the blt to the clip rectangle
1039 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1040 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1041 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1042 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1043 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1045 InputToCombinedRect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
1046 InputToCombinedRect
.bottom
= InputRect
.top
+ (CombinedRect
.bottom
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
1047 InputToCombinedRect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
1048 InputToCombinedRect
.right
= InputRect
.left
+ (CombinedRect
.right
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
1049 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
,
1052 &InputToCombinedRect
,
1055 &AdjustedBrushOrigin
,
1060 if (psoOutput
== psoInput
)
1062 if (OutputRect
.top
< InputRect
.top
)
1064 Direction
= OutputRect
.left
< InputRect
.left
?
1065 CD_RIGHTDOWN
: CD_LEFTDOWN
;
1069 Direction
= OutputRect
.left
< InputRect
.left
?
1070 CD_RIGHTUP
: CD_LEFTUP
;
1077 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1080 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
1082 for (i
= 0; i
< RectEnum
.c
; i
++)
1084 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1085 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1086 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1087 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1088 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1090 InputToCombinedRect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
1091 InputToCombinedRect
.bottom
= InputRect
.top
+ (CombinedRect
.bottom
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
1092 InputToCombinedRect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
1093 InputToCombinedRect
.right
= InputRect
.left
+ (CombinedRect
.right
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
1094 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
,
1097 &InputToCombinedRect
,
1100 &AdjustedBrushOrigin
,
1109 IntEngLeave(&EnterLeaveDest
);
1112 IntEngLeave(&EnterLeaveSource
);
1124 IN SURFOBJ
*psoDest
,
1125 IN SURFOBJ
*psoSource
,
1127 IN CLIPOBJ
*ClipRegion
,
1128 IN XLATEOBJ
*ColorTranslation
,
1129 IN COLORADJUSTMENT
*pca
,
1130 IN POINTL
*BrushOrigin
,
1133 IN POINTL
*MaskOrigin
,
1136 return EngStretchBltROP(
1149 ROP3_TO_ROP4(SRCCOPY
));
1153 IntEngStretchBlt(SURFOBJ
*psoDest
,
1156 CLIPOBJ
*ClipRegion
,
1157 XLATEOBJ
*ColorTranslation
,
1160 POINTL
*pMaskOrigin
,
1162 POINTL
*BrushOrigin
,
1169 SURFACE
*psurfSource
= NULL
;
1170 RECTL InputClippedRect
;
1173 BOOL UsesSource
= ROP4_USES_SOURCE(ROP
);
1174 LONG InputClWidth
, InputClHeight
, InputWidth
, InputHeight
;
1177 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1181 InputClippedRect
= *DestRect
;
1182 if (InputClippedRect
.right
< InputClippedRect
.left
)
1184 InputClippedRect
.left
= DestRect
->right
;
1185 InputClippedRect
.right
= DestRect
->left
;
1187 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
1189 InputClippedRect
.top
= DestRect
->bottom
;
1190 InputClippedRect
.bottom
= DestRect
->top
;
1195 if (NULL
== SourceRect
|| NULL
== psoSource
)
1199 InputRect
= *SourceRect
;
1201 if (InputRect
.right
< InputRect
.left
||
1202 InputRect
.bottom
< InputRect
.top
)
1204 /* Everything clipped away, nothing to do */
1211 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
1212 &ClipRegion
->rclBounds
))
1216 /* Update source rect */
1217 InputClWidth
= InputClippedRect
.right
- InputClippedRect
.left
;
1218 InputClHeight
= InputClippedRect
.bottom
- InputClippedRect
.top
;
1219 InputWidth
= InputRect
.right
- InputRect
.left
;
1220 InputHeight
= InputRect
.bottom
- InputRect
.top
;
1222 InputRect
.left
+= (InputWidth
* (OutputRect
.left
- InputClippedRect
.left
)) / InputClWidth
;
1223 InputRect
.right
-= (InputWidth
* (InputClippedRect
.right
- OutputRect
.right
)) / InputClWidth
;
1224 InputRect
.top
+= (InputHeight
* (OutputRect
.top
- InputClippedRect
.top
)) / InputClHeight
;
1225 InputRect
.bottom
-= (InputHeight
* (InputClippedRect
.bottom
- OutputRect
.bottom
)) / InputClHeight
;
1229 OutputRect
= InputClippedRect
;
1232 if (pMaskOrigin
!= NULL
)
1234 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
1237 /* No success yet */
1239 SURFACE_LockBitmapBits(psurfDest
);
1240 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
1241 OutputRect
.right
, OutputRect
.bottom
);
1245 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
1246 if (psoSource
!= psoDest
)
1248 SURFACE_LockBitmapBits(psurfSource
);
1250 MouseSafetyOnDrawStart(psoSource
, InputRect
.left
, InputRect
.top
,
1251 InputRect
.right
, InputRect
.bottom
);
1254 /* Prepare color adjustment */
1256 /* Call the driver's DrvStretchBlt if available */
1257 if (psurfDest
->flHooks
& HOOK_STRETCHBLTROP
)
1259 /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
1260 // FIXME: MaskOrigin is always NULL !
1261 ret
= GDIDEVFUNCS(psoDest
).StretchBltROP(psoDest
, (UsesSource
) ? psoSource
: NULL
, MaskSurf
, ClipRegion
, ColorTranslation
,
1262 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, COLORONCOLOR
, pbo
, ROP
);
1267 // FIXME: see previous fixme
1268 ret
= EngStretchBltROP(psoDest
, (UsesSource
) ? psoSource
: NULL
, MaskSurf
, ClipRegion
, ColorTranslation
,
1269 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, COLORONCOLOR
, pbo
, ROP
);
1274 MouseSafetyOnDrawEnd(psoSource
);
1275 if (psoSource
!= psoDest
)
1277 SURFACE_UnlockBitmapBits(psurfSource
);
1280 MouseSafetyOnDrawEnd(psoDest
);
1281 SURFACE_UnlockBitmapBits(psurfDest
);
1292 NtGdiEngAlphaBlend(IN SURFOBJ
*psoDest
,
1293 IN SURFOBJ
*psoSource
,
1294 IN CLIPOBJ
*ClipRegion
,
1295 IN XLATEOBJ
*ColorTranslation
,
1296 IN PRECTL upDestRect
,
1297 IN PRECTL upSourceRect
,
1298 IN BLENDOBJ
*BlendObj
)
1305 ProbeForRead(upDestRect
, sizeof(RECTL
), 1);
1306 RtlCopyMemory(&DestRect
,upDestRect
, sizeof(RECTL
));
1308 ProbeForRead(upSourceRect
, sizeof(RECTL
), 1);
1309 RtlCopyMemory(&SourceRect
, upSourceRect
, sizeof(RECTL
));
1312 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1314 _SEH2_YIELD(return FALSE
);
1318 return EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
, &DestRect
, &SourceRect
, BlendObj
);
1326 EngAlphaBlend(IN SURFOBJ
*psoDest
,
1327 IN SURFOBJ
*psoSource
,
1328 IN CLIPOBJ
*ClipRegion
,
1329 IN XLATEOBJ
*ColorTranslation
,
1331 IN PRECTL SourceRect
,
1332 IN BLENDOBJ
*BlendObj
)
1334 RECTL SourceStretchedRect
;
1335 SIZEL SourceStretchedSize
;
1336 HBITMAP SourceStretchedBitmap
= 0;
1337 SURFOBJ
* SourceStretchedObj
= NULL
;
1344 INTENG_ENTER_LEAVE EnterLeaveSource
;
1345 INTENG_ENTER_LEAVE EnterLeaveDest
;
1355 DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest
, psoSource
, ClipRegion
, ColorTranslation
);
1356 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
1357 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
1358 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
1359 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
1360 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
1361 BlendObj
->BlendFunction
.AlphaFormat
);
1364 /* Validate output */
1365 OutputRect
= *DestRect
;
1366 if (OutputRect
.right
< OutputRect
.left
)
1368 OutputRect
.left
= DestRect
->right
;
1369 OutputRect
.right
= DestRect
->left
;
1371 if (OutputRect
.bottom
< OutputRect
.top
)
1373 OutputRect
.left
= DestRect
->right
;
1374 OutputRect
.right
= DestRect
->left
;
1378 /* Validate input */
1380 /* FIXME when WindowOrg.x or .y are negitve this check are not vaild,
1381 * we need convert the inputRect to the windows org and do it right */
1382 InputRect
= *SourceRect
;
1383 if ( (InputRect
.top
< 0) || (InputRect
.bottom
< 0) ||
1384 (InputRect
.left
< 0) || (InputRect
.right
< 0) )
1386 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1390 if (psoDest
== psoSource
&&
1391 !(OutputRect
.left
>= SourceRect
->right
|| InputRect
.left
>= OutputRect
.right
||
1392 OutputRect
.top
>= SourceRect
->bottom
|| InputRect
.top
>= OutputRect
.bottom
))
1394 DPRINT1("Source and destination rectangles overlap!\n");
1398 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
1400 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
1403 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
1405 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
1408 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
1410 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
1414 /* Check if there is anything to draw */
1415 if (ClipRegion
!= NULL
&&
1416 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1417 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1423 /* Stretch source if needed */
1424 if (OutputRect
.right
- OutputRect
.left
!= InputRect
.right
- InputRect
.left
||
1425 OutputRect
.bottom
- OutputRect
.top
!= InputRect
.bottom
- InputRect
.top
)
1427 SourceStretchedSize
.cx
= OutputRect
.right
- OutputRect
.left
;
1428 SourceStretchedSize
.cy
= OutputRect
.bottom
- OutputRect
.top
;
1429 Width
= DIB_GetDIBWidthBytes(SourceStretchedSize
.cx
, BitsPerFormat(psoSource
->iBitmapFormat
));
1430 /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
1431 if possible to get a HW accelerated stretch. */
1432 SourceStretchedBitmap
= EngCreateBitmap(SourceStretchedSize
, Width
, psoSource
->iBitmapFormat
,
1433 BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
1434 if (SourceStretchedBitmap
== 0)
1436 DPRINT1("EngCreateBitmap failed!\n");
1439 SourceStretchedObj
= EngLockSurface((HSURF
)SourceStretchedBitmap
);
1440 if (SourceStretchedObj
== NULL
)
1442 DPRINT1("EngLockSurface failed!\n");
1443 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1447 SourceStretchedRect
.left
= 0;
1448 SourceStretchedRect
.right
= SourceStretchedSize
.cx
;
1449 SourceStretchedRect
.top
= 0;
1450 SourceStretchedRect
.bottom
= SourceStretchedSize
.cy
;
1451 /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
1452 try to acquire an already acquired mutex (lock the already locked source surface) */
1453 /*if (!IntEngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL,
1454 NULL, &SourceStretchedRect, SourceRect, NULL,
1455 NULL, NULL, COLORONCOLOR))*/
1456 if (!EngStretchBlt(SourceStretchedObj
, psoSource
, NULL
, NULL
, NULL
,
1457 NULL
, NULL
, &SourceStretchedRect
, &InputRect
,
1458 NULL
, COLORONCOLOR
))
1460 DPRINT1("EngStretchBlt failed!\n");
1461 EngFreeMem(SourceStretchedObj
->pvBits
);
1462 EngUnlockSurface(SourceStretchedObj
);
1463 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1466 InputRect
.top
= SourceStretchedRect
.top
;
1467 InputRect
.bottom
= SourceStretchedRect
.bottom
;
1468 InputRect
.left
= SourceStretchedRect
.left
;
1469 InputRect
.right
= SourceStretchedRect
.right
;
1470 psoSource
= SourceStretchedObj
;
1473 /* Now call the DIB function */
1474 if (!IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1476 if (SourceStretchedObj
!= NULL
)
1478 EngFreeMem(SourceStretchedObj
->pvBits
);
1479 EngUnlockSurface(SourceStretchedObj
);
1481 if (SourceStretchedBitmap
!= 0)
1483 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1487 InputRect
.left
+= Translate
.x
;
1488 InputRect
.right
+= Translate
.x
;
1489 InputRect
.top
+= Translate
.y
;
1490 InputRect
.bottom
+= Translate
.y
;
1492 if (!IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1494 IntEngLeave(&EnterLeaveSource
);
1495 if (SourceStretchedObj
!= NULL
)
1497 EngFreeMem(SourceStretchedObj
->pvBits
);
1498 EngUnlockSurface(SourceStretchedObj
);
1500 if (SourceStretchedBitmap
!= 0)
1502 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1506 OutputRect
.left
+= Translate
.x
;
1507 OutputRect
.right
+= Translate
.x
;
1508 OutputRect
.top
+= Translate
.y
;
1509 OutputRect
.bottom
+= Translate
.y
;
1512 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
1513 switch (ClippingType
)
1516 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1517 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
1521 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1522 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1523 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1524 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1525 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1527 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1528 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1529 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1530 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1531 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1532 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
1538 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
1541 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
1544 for (i
= 0; i
< RectEnum
.c
; i
++)
1546 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1547 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1548 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1549 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1550 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1552 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1553 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1554 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1555 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1556 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1557 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
1570 IntEngLeave(&EnterLeaveDest
);
1571 IntEngLeave(&EnterLeaveSource
);
1573 if (SourceStretchedObj
!= NULL
)
1575 EngFreeMem(SourceStretchedObj
->pvBits
);
1576 EngUnlockSurface(SourceStretchedObj
);
1578 if (SourceStretchedBitmap
!= 0)
1580 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1587 IntEngAlphaBlend(IN SURFOBJ
*psoDest
,
1588 IN SURFOBJ
*psoSource
,
1589 IN CLIPOBJ
*ClipRegion
,
1590 IN XLATEOBJ
*ColorTranslation
,
1592 IN PRECTL SourceRect
,
1593 IN BLENDOBJ
*BlendObj
)
1597 SURFACE
*psurfSource
;
1600 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1603 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
1608 /* Check if there is anything to draw */
1609 if (ClipRegion
!= NULL
&&
1610 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1611 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1617 SURFACE_LockBitmapBits(psurfDest
);
1618 MouseSafetyOnDrawStart(psoDest
, DestRect
->left
, DestRect
->top
,
1619 DestRect
->right
, DestRect
->bottom
);
1621 if (psoSource
!= psoDest
)
1622 SURFACE_LockBitmapBits(psurfSource
);
1623 MouseSafetyOnDrawStart(psoSource
, SourceRect
->left
, SourceRect
->top
,
1624 SourceRect
->right
, SourceRect
->bottom
);
1626 /* Call the driver's DrvAlphaBlend if available */
1627 if (psurfDest
->flHooks
& HOOK_ALPHABLEND
)
1629 ret
= GDIDEVFUNCS(psoDest
).AlphaBlend(
1630 psoDest
, psoSource
, ClipRegion
, ColorTranslation
,
1631 DestRect
, SourceRect
, BlendObj
);
1636 ret
= EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
,
1637 DestRect
, SourceRect
, BlendObj
);
1640 MouseSafetyOnDrawEnd(psoSource
);
1641 if (psoSource
!= psoDest
)
1642 SURFACE_UnlockBitmapBits(psurfSource
);
1643 MouseSafetyOnDrawEnd(psoDest
);
1644 SURFACE_UnlockBitmapBits(psurfDest
);
1649 /**** REACTOS FONT RENDERING CODE *********************************************/
1651 /* renders the alpha mask bitmap */
1652 static BOOLEAN APIENTRY
1653 AlphaBltMask(SURFOBJ
* psoDest
,
1654 SURFOBJ
* psoSource
, // unused
1656 XLATEOBJ
* ColorTranslation
,
1657 XLATEOBJ
* SrcColorTranslation
,
1659 POINTL
* pptlSource
, // unused
1666 ULONG Background
, BrushColor
, NewColor
;
1667 BYTE
*tMask
, *lMask
;
1669 dx
= prclDest
->right
- prclDest
->left
;
1670 dy
= prclDest
->bottom
- prclDest
->top
;
1672 if (psoMask
!= NULL
)
1674 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, pbo
? pbo
->iSolidColor
: 0);
1675 r
= (int)GetRValue(BrushColor
);
1676 g
= (int)GetGValue(BrushColor
);
1677 b
= (int)GetBValue(BrushColor
);
1679 tMask
= (PBYTE
)psoMask
->pvScan0
+ (pptlMask
->y
* psoMask
->lDelta
) + pptlMask
->x
;
1680 for (j
= 0; j
< dy
; j
++)
1683 for (i
= 0; i
< dx
; i
++)
1689 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
1690 psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
, pbo
? pbo
->iSolidColor
: 0);
1694 Background
= DIB_GetSource(psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
,
1695 SrcColorTranslation
);
1698 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
1699 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
1700 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
1702 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
1703 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
1704 psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
, Background
);
1709 tMask
+= psoMask
->lDelta
;
1721 EngMaskBitBlt(SURFOBJ
*psoDest
,
1723 CLIPOBJ
*ClipRegion
,
1724 XLATEOBJ
*DestColorTranslation
,
1725 XLATEOBJ
*SourceColorTranslation
,
1729 POINTL
*BrushOrigin
)
1739 INTENG_ENTER_LEAVE EnterLeaveSource
;
1740 INTENG_ENTER_LEAVE EnterLeaveDest
;
1748 POINTL AdjustedBrushOrigin
;
1754 InputRect
.left
= pptlMask
->x
;
1755 InputRect
.right
= pptlMask
->x
+ (DestRect
->right
- DestRect
->left
);
1756 InputRect
.top
= pptlMask
->y
;
1757 InputRect
.bottom
= pptlMask
->y
+ (DestRect
->bottom
- DestRect
->top
);
1762 InputRect
.right
= DestRect
->right
- DestRect
->left
;
1764 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
1767 OutputRect
= *DestRect
;
1768 if (NULL
!= ClipRegion
)
1770 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1772 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1773 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1775 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1777 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1778 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1780 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1782 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1783 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1785 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1787 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1788 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1792 if (! IntEngEnter(&EnterLeaveSource
, psoMask
, &InputRect
, TRUE
, &Translate
, &psoInput
))
1797 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
1798 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
1800 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1802 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1804 IntEngLeave(&EnterLeaveSource
);
1808 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
1810 IntEngLeave(&EnterLeaveSource
);
1814 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1815 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1816 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1817 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1821 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1822 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1825 AdjustedBrushOrigin
= Translate
;
1827 // Determine clipping type
1828 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1830 clippingType
= DC_TRIVIAL
;
1832 clippingType
= ClipRegion
->iDComplexity
;
1835 switch (clippingType
)
1838 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
1839 Ret
= AlphaBltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
, SourceColorTranslation
,
1840 &OutputRect
, &InputPoint
, pptlMask
, pbo
, &AdjustedBrushOrigin
);
1842 Ret
= BltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
,
1843 &OutputRect
, &InputPoint
, pptlMask
, pbo
, &AdjustedBrushOrigin
,
1847 // Clip the blt to the clip rectangle
1848 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1849 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1850 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1851 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1852 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1854 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1855 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1856 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
1858 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
, SourceColorTranslation
,
1859 &CombinedRect
, &Pt
, pptlMask
, pbo
, &AdjustedBrushOrigin
);
1863 Ret
= BltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
,
1864 &CombinedRect
, &Pt
, pptlMask
, pbo
, &AdjustedBrushOrigin
, R4_MASK
);
1870 if (psoOutput
== psoInput
)
1872 if (OutputRect
.top
< InputPoint
.y
)
1874 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1878 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1885 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1888 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1890 for (i
= 0; i
< RectEnum
.c
; i
++)
1892 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1893 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1894 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1895 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1896 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1898 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1899 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1900 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
1902 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
,
1903 DestColorTranslation
,
1904 SourceColorTranslation
,
1905 &CombinedRect
, &Pt
, pptlMask
, pbo
,
1906 &AdjustedBrushOrigin
) && Ret
;
1910 Ret
= BltMask(psoOutput
, psoInput
, psoMask
,
1911 DestColorTranslation
, &CombinedRect
, &Pt
,
1912 pptlMask
, pbo
, &AdjustedBrushOrigin
,
1923 IntEngLeave(&EnterLeaveDest
);
1924 IntEngLeave(&EnterLeaveSource
);
1930 IntEngMaskBlt(SURFOBJ
*psoDest
,
1932 CLIPOBJ
*ClipRegion
,
1933 XLATEOBJ
*DestColorTranslation
,
1934 XLATEOBJ
*SourceColorTranslation
,
1938 POINTL
*BrushOrigin
)
1949 InputPoint
= *pptlMask
;
1952 /* Clip against the bounds of the clipping region so we won't try to write
1953 * outside the surface */
1954 if (NULL
!= ClipRegion
)
1956 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1960 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1961 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1965 OutputRect
= *DestRect
;
1968 /* No success yet */
1971 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1973 SURFACE_LockBitmapBits(psurfDest
);
1974 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
1975 OutputRect
.right
, OutputRect
.bottom
);
1977 /* Dummy BitBlt to let driver know that it should flush its changes.
1978 This should really be done using a call to DrvSynchronizeSurface,
1979 but the VMware driver doesn't hook that call. */
1980 IntEngBitBltEx(psoDest
, NULL
, psoMask
, ClipRegion
, DestColorTranslation
,
1981 DestRect
, pptlMask
, pptlMask
, pbo
, BrushOrigin
,
1984 ret
= EngMaskBitBlt(psoDest
, psoMask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1985 &OutputRect
, &InputPoint
, pbo
, BrushOrigin
);
1987 /* Dummy BitBlt to let driver know that something has changed. */
1988 IntEngBitBltEx(psoDest
, NULL
, psoMask
, ClipRegion
, DestColorTranslation
,
1989 DestRect
, pptlMask
, pptlMask
, pbo
, BrushOrigin
,
1992 MouseSafetyOnDrawEnd(psoDest
);
1993 SURFACE_UnlockBitmapBits(psurfDest
);