migrate substitution keywords to SVN
[reactos.git] / reactos / subsys / 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 #include <w32k.h>
30
31
32 BOOL STDCALL
33 EngTransparentBlt(SURFOBJ *Dest,
34 SURFOBJ *Source,
35 CLIPOBJ *Clip,
36 XLATEOBJ *ColorTranslation,
37 PRECTL DestRect,
38 PRECTL SourceRect,
39 ULONG iTransColor,
40 ULONG Reserved)
41 {
42 BOOL Ret = TRUE;
43 BYTE ClippingType;
44 INTENG_ENTER_LEAVE EnterLeaveSource, EnterLeaveDest;
45 SURFOBJ *InputObj, *OutputObj;
46 RECTL OutputRect, InputRect;
47 POINTL Translate, InputPoint;
48
49 InputRect.left = 0;
50 InputRect.right = DestRect->right - DestRect->left;
51 InputRect.top = 0;
52 InputRect.bottom = DestRect->bottom - DestRect->top;
53
54 if(!IntEngEnter(&EnterLeaveSource, Source, &InputRect, TRUE, &Translate, &InputObj))
55 {
56 return FALSE;
57 }
58
59 InputPoint.x = SourceRect->left + Translate.x;
60 InputPoint.y = SourceRect->top + Translate.y;
61
62 OutputRect = *DestRect;
63 if(Clip)
64 {
65 if(OutputRect.left < Clip->rclBounds.left)
66 {
67 InputRect.left += Clip->rclBounds.left - OutputRect.left;
68 InputPoint.x += Clip->rclBounds.left - OutputRect.left;
69 OutputRect.left = Clip->rclBounds.left;
70 }
71 if(Clip->rclBounds.right < OutputRect.right)
72 {
73 InputRect.right -= OutputRect.right - Clip->rclBounds.right;
74 OutputRect.right = Clip->rclBounds.right;
75 }
76 if(OutputRect.top < Clip->rclBounds.top)
77 {
78 InputRect.top += Clip->rclBounds.top - OutputRect.top;
79 InputPoint.y += Clip->rclBounds.top - OutputRect.top;
80 OutputRect.top = Clip->rclBounds.top;
81 }
82 if(Clip->rclBounds.bottom < OutputRect.bottom)
83 {
84 InputRect.bottom -= OutputRect.bottom - Clip->rclBounds.bottom;
85 OutputRect.bottom = Clip->rclBounds.bottom;
86 }
87 }
88
89 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
90 nothing to do */
91 if(OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
92 {
93 IntEngLeave(&EnterLeaveSource);
94 return TRUE;
95 }
96
97 if(!IntEngEnter(&EnterLeaveDest, Dest, &OutputRect, FALSE, &Translate, &OutputObj))
98 {
99 IntEngLeave(&EnterLeaveSource);
100 return FALSE;
101 }
102
103 OutputRect.left = DestRect->left + Translate.x;
104 OutputRect.right = DestRect->right + Translate.x;
105 OutputRect.top = DestRect->top + Translate.y;
106 OutputRect.bottom = DestRect->bottom + Translate.y;
107
108 ClippingType = (Clip ? Clip->iDComplexity : DC_TRIVIAL);
109
110 switch(ClippingType)
111 {
112 case DC_TRIVIAL:
113 {
114 Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
115 OutputObj, InputObj, &OutputRect, &InputPoint, ColorTranslation, iTransColor);
116 break;
117 }
118 case DC_RECT:
119 {
120 RECTL ClipRect, CombinedRect;
121 POINTL Pt;
122
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 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
128 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
129 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
130 Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
131 OutputObj, InputObj, &CombinedRect, &Pt, ColorTranslation, iTransColor);
132 break;
133 }
134 case DC_COMPLEX:
135 {
136 ULONG Direction, i;
137 RECT_ENUM RectEnum;
138 BOOL EnumMore;
139 POINTL Pt;
140
141 if(OutputObj == InputObj)
142 {
143 if(OutputRect.top < InputPoint.y)
144 {
145 Direction = OutputRect.left < (InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN);
146 }
147 else
148 {
149 Direction = OutputRect.left < (InputPoint.x ? CD_RIGHTUP : CD_LEFTUP);
150 }
151 }
152 else
153 {
154 Direction = CD_ANY;
155 }
156
157 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, 0);
158 do
159 {
160 EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID)&RectEnum);
161 for (i = 0; i < RectEnum.c; i++)
162 {
163 RECTL ClipRect, CombinedRect;
164
165 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
166 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
167 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
168 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
169 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
170 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
171 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
172 Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
173 OutputObj, InputObj, &CombinedRect, &Pt, ColorTranslation, iTransColor);
174 if(!Ret)
175 {
176 break;
177 }
178 }
179 } while(EnumMore && Ret);
180 break;
181 }
182 default:
183 {
184 Ret = FALSE;
185 break;
186 }
187 }
188
189 IntEngLeave(&EnterLeaveDest);
190 IntEngLeave(&EnterLeaveSource);
191
192 return Ret;
193 }
194
195 BOOL FASTCALL
196 IntEngTransparentBlt(BITMAPOBJ *DestObj,
197 BITMAPOBJ *SourceObj,
198 CLIPOBJ *Clip,
199 XLATEOBJ *ColorTranslation,
200 PRECTL DestRect,
201 PRECTL SourceRect,
202 ULONG iTransColor,
203 ULONG Reserved)
204 {
205 BOOL Ret;
206 RECTL OutputRect, InputClippedRect;
207 SURFOBJ *DestSurf;
208 SURFOBJ *SourceSurf;
209
210 ASSERT(DestObj);
211 ASSERT(SourceObj);
212 ASSERT(DestRect);
213
214 DestSurf = &DestObj->SurfObj;
215 SourceSurf = &SourceObj->SurfObj;
216
217 ASSERT(DestSurf);
218 ASSERT(SourceSurf);
219
220 InputClippedRect = *DestRect;
221 if(InputClippedRect.right < InputClippedRect.left)
222 {
223 InputClippedRect.left = DestRect->right;
224 InputClippedRect.right = DestRect->left;
225 }
226 if(InputClippedRect.bottom < InputClippedRect.top)
227 {
228 InputClippedRect.top = DestRect->bottom;
229 InputClippedRect.bottom = DestRect->top;
230 }
231
232 /* Clip against the bounds of the clipping region so we won't try to write
233 * outside the surface */
234 if(Clip)
235 {
236 if(!EngIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
237 {
238 return TRUE;
239 }
240 SourceRect->left += OutputRect.left - DestRect->left;
241 SourceRect->top += OutputRect.top - DestRect->top;
242 SourceRect->right += OutputRect.left - DestRect->left;
243 SourceRect->bottom += OutputRect.top - DestRect->top;
244 }
245 else
246 {
247 OutputRect = *DestRect;
248 }
249
250 if(SourceSurf != DestSurf)
251 {
252 MouseSafetyOnDrawStart(SourceSurf, SourceRect->left, SourceRect->top,
253 SourceRect->right, SourceRect->bottom);
254 }
255 MouseSafetyOnDrawStart(DestSurf, OutputRect.left, OutputRect.top,
256 OutputRect.right, OutputRect.bottom);
257
258 if(DestObj->flHooks & HOOK_TRANSPARENTBLT)
259 {
260 Ret = GDIDEVFUNCS(DestSurf).TransparentBlt(
261 DestSurf, SourceSurf, Clip, ColorTranslation, &OutputRect,
262 SourceRect, iTransColor, Reserved);
263 }
264 else
265 Ret = FALSE;
266
267 if(!Ret)
268 {
269 Ret = EngTransparentBlt(DestSurf, SourceSurf, Clip, ColorTranslation,
270 &OutputRect, SourceRect, iTransColor, Reserved);
271 }
272
273 if(Ret)
274 {
275 /* Dummy BitBlt to let driver know that something has changed.
276 0x00AA0029 is the Rop for D (no-op) */
277 if (DestObj->flHooks & HOOK_BITBLT)
278 {
279 GDIDEVFUNCS(DestSurf).BitBlt(
280 DestSurf, NULL, NULL, Clip, ColorTranslation,
281 &OutputRect, NULL, NULL, NULL, NULL, ROP_NOOP);
282 }
283 }
284
285 MouseSafetyOnDrawEnd(DestSurf);
286 if(SourceSurf != DestSurf)
287 {
288 MouseSafetyOnDrawEnd(SourceSurf);
289 }
290
291 return Ret;
292 }
293
294 /* EOF */