sync to trunk head (37853) (except rbuild changes)
[reactos.git] / reactos / subsystems / win32 / win32k / eng / transblt.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: GDI TransparentBlt Function
24 * FILE: subsys/win32k/eng/transblt.c
25 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
26 * REVISION HISTORY:
27 * 4/6/2004: Created
28 */
29
30 #include <w32k.h>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 BOOL APIENTRY
36 EngTransparentBlt(SURFOBJ *Dest,
37 SURFOBJ *Source,
38 CLIPOBJ *Clip,
39 XLATEOBJ *ColorTranslation,
40 PRECTL DestRect,
41 PRECTL SourceRect,
42 ULONG iTransColor,
43 ULONG Reserved)
44 {
45 BOOL Ret = TRUE;
46 BYTE ClippingType;
47 INTENG_ENTER_LEAVE EnterLeaveSource, EnterLeaveDest;
48 SURFOBJ *InputObj, *OutputObj;
49 RECTL OutputRect, InputRect;
50 POINTL Translate, InputPoint;
51
52 InputRect.left = 0;
53 InputRect.right = DestRect->right - DestRect->left;
54 InputRect.top = 0;
55 InputRect.bottom = DestRect->bottom - DestRect->top;
56
57 if(!IntEngEnter(&EnterLeaveSource, Source, &InputRect, TRUE, &Translate, &InputObj))
58 {
59 return FALSE;
60 }
61
62 InputPoint.x = SourceRect->left + Translate.x;
63 InputPoint.y = SourceRect->top + Translate.y;
64
65 OutputRect = *DestRect;
66 if(Clip)
67 {
68 if(OutputRect.left < Clip->rclBounds.left)
69 {
70 InputRect.left += Clip->rclBounds.left - OutputRect.left;
71 InputPoint.x += Clip->rclBounds.left - OutputRect.left;
72 OutputRect.left = Clip->rclBounds.left;
73 }
74 if(Clip->rclBounds.right < OutputRect.right)
75 {
76 InputRect.right -= OutputRect.right - Clip->rclBounds.right;
77 OutputRect.right = Clip->rclBounds.right;
78 }
79 if(OutputRect.top < Clip->rclBounds.top)
80 {
81 InputRect.top += Clip->rclBounds.top - OutputRect.top;
82 InputPoint.y += Clip->rclBounds.top - OutputRect.top;
83 OutputRect.top = Clip->rclBounds.top;
84 }
85 if(Clip->rclBounds.bottom < OutputRect.bottom)
86 {
87 InputRect.bottom -= OutputRect.bottom - Clip->rclBounds.bottom;
88 OutputRect.bottom = Clip->rclBounds.bottom;
89 }
90 }
91
92 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
93 nothing to do */
94 if(OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
95 {
96 IntEngLeave(&EnterLeaveSource);
97 return TRUE;
98 }
99
100 if(!IntEngEnter(&EnterLeaveDest, Dest, &OutputRect, FALSE, &Translate, &OutputObj))
101 {
102 IntEngLeave(&EnterLeaveSource);
103 return FALSE;
104 }
105
106 OutputRect.left = DestRect->left + Translate.x;
107 OutputRect.right = DestRect->right + Translate.x;
108 OutputRect.top = DestRect->top + Translate.y;
109 OutputRect.bottom = DestRect->bottom + Translate.y;
110
111 ClippingType = (Clip ? Clip->iDComplexity : DC_TRIVIAL);
112
113 switch(ClippingType)
114 {
115 case DC_TRIVIAL:
116 {
117 Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
118 OutputObj, InputObj, &OutputRect, &InputPoint, ColorTranslation, iTransColor);
119 break;
120 }
121 case DC_RECT:
122 {
123 RECTL ClipRect, CombinedRect;
124 POINTL Pt;
125
126 ClipRect.left = Clip->rclBounds.left + Translate.x;
127 ClipRect.right = Clip->rclBounds.right + Translate.x;
128 ClipRect.top = Clip->rclBounds.top + Translate.y;
129 ClipRect.bottom = Clip->rclBounds.bottom + Translate.y;
130 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
131 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
132 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
133 Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
134 OutputObj, InputObj, &CombinedRect, &Pt, ColorTranslation, iTransColor);
135 break;
136 }
137 case DC_COMPLEX:
138 {
139 ULONG Direction, i;
140 RECT_ENUM RectEnum;
141 BOOL EnumMore;
142 POINTL Pt;
143
144 if(OutputObj == InputObj)
145 {
146 if(OutputRect.top < InputPoint.y)
147 {
148 Direction = OutputRect.left < (InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN);
149 }
150 else
151 {
152 Direction = OutputRect.left < (InputPoint.x ? CD_RIGHTUP : CD_LEFTUP);
153 }
154 }
155 else
156 {
157 Direction = CD_ANY;
158 }
159
160 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, 0);
161 do
162 {
163 EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID)&RectEnum);
164 for (i = 0; i < RectEnum.c; i++)
165 {
166 RECTL ClipRect, CombinedRect;
167
168 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
169 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
170 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
171 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
172 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
173 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
174 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
175 Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
176 OutputObj, InputObj, &CombinedRect, &Pt, ColorTranslation, iTransColor);
177 if(!Ret)
178 {
179 break;
180 }
181 }
182 } while(EnumMore && Ret);
183 break;
184 }
185 default:
186 {
187 Ret = FALSE;
188 break;
189 }
190 }
191
192 IntEngLeave(&EnterLeaveDest);
193 IntEngLeave(&EnterLeaveSource);
194
195 return Ret;
196 }
197
198 BOOL FASTCALL
199 IntEngTransparentBlt(SURFOBJ *DestSurf,
200 SURFOBJ *SourceSurf,
201 CLIPOBJ *Clip,
202 XLATEOBJ *ColorTranslation,
203 PRECTL DestRect,
204 PRECTL SourceRect,
205 ULONG iTransColor,
206 ULONG Reserved)
207 {
208 BOOL Ret;
209 RECTL OutputRect, InputClippedRect;
210 BITMAPOBJ *DestObj;
211 BITMAPOBJ *SourceObj;
212
213 ASSERT(DestSurf);
214 ASSERT(SourceSurf);
215 ASSERT(DestRect);
216
217 DestObj = CONTAINING_RECORD(DestSurf, BITMAPOBJ, SurfObj);
218 SourceObj = CONTAINING_RECORD(SourceSurf, BITMAPOBJ, SurfObj);
219
220 ASSERT(DestObj);
221 ASSERT(SourceObj);
222
223 InputClippedRect = *DestRect;
224 if(InputClippedRect.right < InputClippedRect.left)
225 {
226 InputClippedRect.left = DestRect->right;
227 InputClippedRect.right = DestRect->left;
228 }
229 if(InputClippedRect.bottom < InputClippedRect.top)
230 {
231 InputClippedRect.top = DestRect->bottom;
232 InputClippedRect.bottom = DestRect->top;
233 }
234
235 /* Clip against the bounds of the clipping region so we won't try to write
236 * outside the surface */
237 if(Clip)
238 {
239 if(!EngIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
240 {
241 return TRUE;
242 }
243 SourceRect->left += OutputRect.left - DestRect->left;
244 SourceRect->top += OutputRect.top - DestRect->top;
245 SourceRect->right += OutputRect.left - DestRect->left;
246 SourceRect->bottom += OutputRect.top - DestRect->top;
247 }
248 else
249 {
250 OutputRect = *DestRect;
251 }
252
253 if(SourceSurf != DestSurf)
254 {
255 BITMAPOBJ_LockBitmapBits(SourceObj);
256 MouseSafetyOnDrawStart(SourceSurf, SourceRect->left, SourceRect->top,
257 SourceRect->right, SourceRect->bottom);
258 }
259 BITMAPOBJ_LockBitmapBits(DestObj);
260 MouseSafetyOnDrawStart(DestSurf, OutputRect.left, OutputRect.top,
261 OutputRect.right, OutputRect.bottom);
262
263 if(DestObj->flHooks & HOOK_TRANSPARENTBLT)
264 {
265 Ret = GDIDEVFUNCS(DestSurf).TransparentBlt(
266 DestSurf, SourceSurf, Clip, ColorTranslation, &OutputRect,
267 SourceRect, iTransColor, Reserved);
268 }
269 else
270 Ret = FALSE;
271
272 if(!Ret)
273 {
274 Ret = EngTransparentBlt(DestSurf, SourceSurf, Clip, ColorTranslation,
275 &OutputRect, SourceRect, iTransColor, Reserved);
276 }
277
278 MouseSafetyOnDrawEnd(DestSurf);
279 BITMAPOBJ_UnlockBitmapBits(DestObj);
280 if(SourceSurf != DestSurf)
281 {
282 MouseSafetyOnDrawEnd(SourceSurf);
283 BITMAPOBJ_UnlockBitmapBits(SourceObj);
284 }
285
286 return Ret;
287 }
288
289 /* EOF */