WIN32K code cleanup.
[reactos.git] / reactos / subsys / win32k / eng / bitblt.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: bitblt.c,v 1.20 2003/05/18 17:16:17 ea Exp $
20 *
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
26 * REVISION HISTORY:
27 * 2/10/1999: Created
28 */
29
30 #include <ddk/winddi.h>
31 #include <ddk/ntddk.h>
32 #include <ddk/ntddmou.h>
33 #include <ntos/minmax.h>
34 #include "brush.h"
35 #include "clip.h"
36 #include "objects.h"
37 #include "../dib/dib.h"
38 #include "misc.h"
39 #include <include/mouse.h>
40 #include <include/object.h>
41 #include <include/dib.h>
42 #include <include/surface.h>
43 #include <include/copybits.h>
44 #include <include/inteng.h>
45
46 #define NDEBUG
47 #include <win32k/debug1.h>
48
49 BOOL STDCALL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
50 {
51 static const RECTL rclEmpty = { 0, 0, 0, 0 };
52
53 prcDst->left = max(prcSrc1->left, prcSrc2->left);
54 prcDst->right = min(prcSrc1->right, prcSrc2->right);
55
56 if (prcDst->left < prcDst->right)
57 {
58 prcDst->top = max(prcSrc1->top, prcSrc2->top);
59 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
60
61 if (prcDst->top < prcDst->bottom) return(TRUE);
62 }
63
64 *prcDst = rclEmpty;
65
66 return(FALSE);
67 }
68
69 static BOOL STDCALL
70 BltMask(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
71 RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
72 POINTL* BrushPoint)
73 {
74 LONG i, j, dx, dy, c8;
75 BYTE *tMask, *lMask;
76 static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
77
78 dx = DestRect->right - DestRect->left;
79 dy = DestRect->bottom - DestRect->top;
80
81 if (Mask != NULL)
82 {
83 tMask = Mask->pvBits;
84 for (j = 0; j < dy; j++)
85 {
86 lMask = tMask;
87 c8 = 0;
88 for (i = 0; i < dx; i++)
89 {
90 if (0 != (*lMask & maskbit[c8]))
91 {
92 DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
93 }
94 c8++;
95 if (8 == c8)
96 {
97 lMask++;
98 c8=0;
99 }
100 }
101 tMask += Mask->lDelta;
102 }
103 return TRUE;
104 }
105 else
106 {
107 return FALSE;
108 }
109 }
110
111 static BOOL STDCALL
112 BltPatCopy(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
113 RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
114 POINTL* BrushPoint)
115 {
116 // These functions are assigned if we're working with a DIB
117 // The assigned functions depend on the bitsPerPixel of the DIB
118 LONG y;
119 ULONG LineWidth;
120
121 LineWidth = DestRect->right - DestRect->left;
122 for (y = DestRect->top; y < DestRect->bottom; y++)
123 {
124 DestGDI->DIB_HLine(Dest, DestRect->left, DestRect->right, y, Brush->iSolidColor);
125 }
126
127 return TRUE;
128 }
129
130 INT abs(INT nm);
131
132 BOOL STDCALL
133 EngBitBlt(SURFOBJ *DestObj,
134 SURFOBJ *SourceObj,
135 SURFOBJ *Mask,
136 CLIPOBJ *ClipRegion,
137 XLATEOBJ *ColorTranslation,
138 RECTL *DestRect,
139 POINTL *SourcePoint,
140 POINTL *MaskOrigin,
141 BRUSHOBJ *Brush,
142 POINTL *BrushOrigin,
143 ROP4 rop4)
144 {
145 BOOLEAN ret;
146 BYTE clippingType;
147 RECTL rclTmp;
148 POINTL ptlTmp;
149 RECT_ENUM RectEnum;
150 BOOL EnumMore;
151 PSURFGDI OutputGDI, InputGDI;
152 POINTL InputPoint;
153 RECTL InputRect;
154 RECTL OutputRect;
155 POINTL Translate;
156 INTENG_ENTER_LEAVE EnterLeaveSource;
157 INTENG_ENTER_LEAVE EnterLeaveDest;
158 PSURFOBJ InputObj;
159 PSURFOBJ OutputObj;
160
161 /* Check for degenerate case: if height or width of DestRect is 0 pixels there's
162 nothing to do */
163 if (DestRect->right == DestRect->left || DestRect->bottom == DestRect->top)
164 {
165 return TRUE;
166 }
167
168 if (NULL != SourcePoint)
169 {
170 InputRect.left = SourcePoint->x;
171 InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
172 InputRect.top = SourcePoint->y;
173 InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top);
174 }
175 else
176 {
177 InputRect.left = 0;
178 InputRect.right = DestRect->right - DestRect->left;
179 InputRect.top = 0;
180 InputRect.bottom = DestRect->bottom - DestRect->top;
181 }
182
183 if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj))
184 {
185 return FALSE;
186 }
187
188 if (NULL != SourcePoint)
189 {
190 InputPoint.x = SourcePoint->x + Translate.x;
191 InputPoint.y = SourcePoint->y + Translate.y;
192 }
193 else
194 {
195 InputPoint.x = 0;
196 InputPoint.y = 0;
197 }
198
199 if (NULL != InputObj)
200 {
201 InputGDI = (PSURFGDI) AccessInternalObjectFromUserObject(InputObj);
202 }
203
204 OutputRect = *DestRect;
205
206 if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
207 {
208 IntEngLeave(&EnterLeaveSource);
209 return FALSE;
210 }
211
212 OutputRect.left = DestRect->left + Translate.x;
213 OutputRect.right = DestRect->right + Translate.x;
214 OutputRect.top = DestRect->top + Translate.y;
215 OutputRect.bottom = DestRect->bottom + Translate.y;
216
217
218 if (NULL != OutputObj)
219 {
220 OutputGDI = (PSURFGDI)AccessInternalObjectFromUserObject(OutputObj);
221 }
222
223 /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to
224 * paint a brush pattern on the destination. */
225 if (NULL == InputObj && 0xaacc != rop4 && PATCOPY != rop4)
226 {
227 DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n");
228 return FALSE;
229 }
230
231 // Determine clipping type
232 if (ClipRegion == (CLIPOBJ *) NULL)
233 {
234 clippingType = DC_TRIVIAL;
235 } else {
236 clippingType = ClipRegion->iDComplexity;
237 }
238
239 if (0xaacc == rop4)
240 {
241 ret = BltMask(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin);
242 IntEngLeave(&EnterLeaveDest);
243 IntEngLeave(&EnterLeaveSource);
244 return ret;
245 } else if (PATCOPY == rop4) {
246 ret = BltPatCopy(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin);
247 IntEngLeave(&EnterLeaveDest);
248 IntEngLeave(&EnterLeaveSource);
249 return ret;
250 }
251
252
253 // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
254 switch(clippingType)
255 {
256 case DC_TRIVIAL:
257 OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, &OutputRect, &InputPoint, ColorTranslation);
258
259 IntEngLeave(&EnterLeaveDest);
260 IntEngLeave(&EnterLeaveSource);
261
262 return(TRUE);
263
264 case DC_RECT:
265
266 // Clip the blt to the clip rectangle
267 EngIntersectRect(&rclTmp, &OutputRect, &ClipRegion->rclBounds);
268
269 ptlTmp.x = InputPoint.x + rclTmp.left - OutputRect.left;
270 ptlTmp.y = InputPoint.y + rclTmp.top - OutputRect.top;
271
272 IntEngLeave(&EnterLeaveDest);
273 IntEngLeave(&EnterLeaveSource);
274
275 return(TRUE);
276
277 case DC_COMPLEX:
278
279 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
280
281 do {
282 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
283
284 if (RectEnum.c > 0)
285 {
286 RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
287 RECTL* prcl = &RectEnum.arcl[0];
288
289 do {
290 EngIntersectRect(prcl, prcl, &OutputRect);
291
292 ptlTmp.x = InputPoint.x + prcl->left - OutputRect.left;
293 ptlTmp.y = InputPoint.y + prcl->top - OutputRect.top;
294
295 prcl++;
296
297 } while (prcl < prclEnd);
298 }
299
300 } while(EnumMore);
301
302 IntEngLeave(&EnterLeaveDest);
303 IntEngLeave(&EnterLeaveSource);
304
305 return(TRUE);
306 }
307
308 IntEngLeave(&EnterLeaveDest);
309 IntEngLeave(&EnterLeaveSource);
310
311 return(FALSE);
312 }
313
314 BOOL STDCALL
315 IntEngBitBlt(SURFOBJ *DestObj,
316 SURFOBJ *SourceObj,
317 SURFOBJ *Mask,
318 CLIPOBJ *ClipRegion,
319 XLATEOBJ *ColorTranslation,
320 RECTL *DestRect,
321 POINTL *SourcePoint,
322 POINTL *MaskOrigin,
323 BRUSHOBJ *Brush,
324 POINTL *BrushOrigin,
325 ROP4 rop4)
326 {
327 BOOLEAN ret;
328 SURFGDI *DestGDI;
329 SURFGDI *SourceGDI;
330
331 if (NULL != SourceObj)
332 {
333 SourceGDI = (PSURFGDI) AccessInternalObjectFromUserObject(SourceObj);
334 MouseSafetyOnDrawStart(SourceObj, SourceGDI, SourcePoint->x, SourcePoint->y,
335 (SourcePoint->x + abs(DestRect->right - DestRect->left)),
336 (SourcePoint->y + abs(DestRect->bottom - DestRect->top)));
337 }
338
339 /* No success yet */
340 ret = FALSE;
341 DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
342 MouseSafetyOnDrawStart(DestObj, DestGDI, DestRect->left, DestRect->top,
343 DestRect->right, DestRect->bottom);
344
345 /* Call the driver's DrvBitBlt if available */
346 if (NULL != DestGDI->BitBlt) {
347 ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
348 DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4);
349 }
350
351 if (! ret) {
352 ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
353 DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4);
354 }
355
356 MouseSafetyOnDrawEnd(DestObj, DestGDI);
357 if (NULL != SourceObj)
358 {
359 MouseSafetyOnDrawEnd(SourceObj, SourceGDI);
360 }
361
362 return ret;
363 }
364 /* EOF */