2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI TransparentBlt Function
5 * FILE: win32ss/gdi/eng/transblt.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
20 XLATEOBJ
*ColorTranslation
,
28 INTENG_ENTER_LEAVE EnterLeaveSource
, EnterLeaveDest
;
29 SURFOBJ
*InputObj
, *OutputObj
;
30 RECTL OutputRect
, InputRect
;
38 InputRect
= *SourceRect
;
40 if (!IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
, &Translate
, &InputObj
))
44 InputRect
.left
+= Translate
.x
;
45 InputRect
.right
+= Translate
.x
;
46 InputRect
.top
+= Translate
.y
;
47 InputRect
.bottom
+= Translate
.y
;
49 OutputRect
= *DestRect
;
50 if (OutputRect
.right
< OutputRect
.left
)
52 OutputRect
.left
= DestRect
->right
;
53 OutputRect
.right
= DestRect
->left
;
55 if (OutputRect
.bottom
< OutputRect
.top
)
57 OutputRect
.top
= DestRect
->bottom
;
58 OutputRect
.bottom
= DestRect
->top
;
63 if (OutputRect
.left
< Clip
->rclBounds
.left
)
65 InputRect
.left
+= Clip
->rclBounds
.left
- OutputRect
.left
;
66 OutputRect
.left
= Clip
->rclBounds
.left
;
68 if (Clip
->rclBounds
.right
< OutputRect
.right
)
70 InputRect
.right
-= OutputRect
.right
- Clip
->rclBounds
.right
;
71 OutputRect
.right
= Clip
->rclBounds
.right
;
73 if (OutputRect
.top
< Clip
->rclBounds
.top
)
75 InputRect
.top
+= Clip
->rclBounds
.top
- OutputRect
.top
;
76 OutputRect
.top
= Clip
->rclBounds
.top
;
78 if (Clip
->rclBounds
.bottom
< OutputRect
.bottom
)
80 InputRect
.bottom
-= OutputRect
.bottom
- Clip
->rclBounds
.bottom
;
81 OutputRect
.bottom
= Clip
->rclBounds
.bottom
;
85 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
87 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
89 IntEngLeave(&EnterLeaveSource
);
93 if (!IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
95 IntEngLeave(&EnterLeaveSource
);
99 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
100 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
101 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
102 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
104 ClippingType
= (Clip
? Clip
->iDComplexity
: DC_TRIVIAL
);
106 DstHeight
= OutputRect
.bottom
- OutputRect
.top
;
107 DstWidth
= OutputRect
.right
- OutputRect
.left
;
108 SrcHeight
= InputRect
.bottom
- InputRect
.top
;
109 SrcWidth
= InputRect
.right
- InputRect
.left
;
110 switch (ClippingType
)
114 Ret
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_TransparentBlt(
115 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ColorTranslation
, iTransColor
);
120 RECTL ClipRect
, CombinedRect
;
121 RECTL InputToCombinedRect
;
123 ClipRect
.left
= Clip
->rclBounds
.left
+ Translate
.x
;
124 ClipRect
.right
= Clip
->rclBounds
.right
+ Translate
.x
;
125 ClipRect
.top
= Clip
->rclBounds
.top
+ Translate
.y
;
126 ClipRect
.bottom
= Clip
->rclBounds
.bottom
+ Translate
.y
;
127 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
129 InputToCombinedRect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
130 InputToCombinedRect
.bottom
= InputRect
.top
+ (CombinedRect
.bottom
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
131 InputToCombinedRect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
132 InputToCombinedRect
.right
= InputRect
.left
+ (CombinedRect
.right
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
133 Ret
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_TransparentBlt(
134 OutputObj
, InputObj
, &CombinedRect
, &InputToCombinedRect
, ColorTranslation
, iTransColor
);
144 if (OutputObj
== InputObj
)
146 if (OutputRect
.top
< InputRect
.top
)
148 Direction
= OutputRect
.left
< (InputRect
.left
? CD_RIGHTDOWN
: CD_LEFTDOWN
);
152 Direction
= OutputRect
.left
< (InputRect
.left
? CD_RIGHTUP
: CD_LEFTUP
);
160 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, Direction
, 0);
163 EnumMore
= CLIPOBJ_bEnum(Clip
, sizeof(RectEnum
), (PVOID
)&RectEnum
);
164 for (i
= 0; i
< RectEnum
.c
; i
++)
166 RECTL ClipRect
, CombinedRect
;
167 RECTL InputToCombinedRect
;
169 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
170 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
171 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
172 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
173 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
175 InputToCombinedRect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
176 InputToCombinedRect
.bottom
= InputRect
.top
+ (CombinedRect
.bottom
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
177 InputToCombinedRect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
178 InputToCombinedRect
.right
= InputRect
.left
+ (CombinedRect
.right
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
180 Ret
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_TransparentBlt(
181 OutputObj
, InputObj
, &CombinedRect
, &InputToCombinedRect
, ColorTranslation
, iTransColor
);
189 while (EnumMore
&& Ret
);
199 IntEngLeave(&EnterLeaveDest
);
200 IntEngLeave(&EnterLeaveSource
);
207 IntEngTransparentBlt(
211 XLATEOBJ
*ColorTranslation
,
218 RECTL OutputRect
, InputClippedRect
;
220 SURFACE
*psurfSource
;
222 LONG InputClWidth
, InputClHeight
, InputWidth
, InputHeight
;
228 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
229 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
234 /* If no clip object is given, use trivial one */
235 if (!Clip
) Clip
= &gxcoTrivial
.ClipObj
;
237 InputClippedRect
= *DestRect
;
238 if (InputClippedRect
.right
< InputClippedRect
.left
)
240 InputClippedRect
.left
= DestRect
->right
;
241 InputClippedRect
.right
= DestRect
->left
;
243 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
245 InputClippedRect
.top
= DestRect
->bottom
;
246 InputClippedRect
.bottom
= DestRect
->top
;
249 InputRect
= *SourceRect
;
250 /* Clip against the bounds of the clipping region so we won't try to write
251 * outside the surface */
252 if (Clip
->iDComplexity
!= DC_TRIVIAL
)
254 if (!RECTL_bIntersectRect(&OutputRect
, &InputClippedRect
, &Clip
->rclBounds
))
258 /* Update source rect */
259 InputClWidth
= InputClippedRect
.right
- InputClippedRect
.left
;
260 InputClHeight
= InputClippedRect
.bottom
- InputClippedRect
.top
;
261 InputWidth
= InputRect
.right
- InputRect
.left
;
262 InputHeight
= InputRect
.bottom
- InputRect
.top
;
264 InputRect
.left
+= (InputWidth
* (OutputRect
.left
- InputClippedRect
.left
)) / InputClWidth
;
265 InputRect
.right
-= (InputWidth
* (InputClippedRect
.right
- OutputRect
.right
)) / InputClWidth
;
266 InputRect
.top
+= (InputHeight
* (OutputRect
.top
- InputClippedRect
.top
)) / InputClHeight
;
267 InputRect
.bottom
-= (InputHeight
* (InputClippedRect
.bottom
- OutputRect
.bottom
)) / InputClHeight
;
271 OutputRect
= InputClippedRect
;
274 if (psurfDest
->flags
& HOOK_TRANSPARENTBLT
)
276 Ret
= GDIDEVFUNCS(psoDest
).TransparentBlt(psoDest
,
290 Ret
= EngTransparentBlt(psoDest
,