implemented TransparentBlt() on 32bpp surfaces, but there are still some clipping...
[reactos.git] / reactos / subsys / win32k / dib / dib4bpp.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: dib4bpp.c,v 1.25 2004/04/06 17:54:32 weiden Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <win32k/bitmaps.h>
24 #include <win32k/brush.h>
25 #include <win32k/debug.h>
26 #include <debug.h>
27 #include <include/object.h>
28 #include <ddk/winddi.h>
29 #include "../eng/objects.h"
30 #include "dib.h"
31
32 VOID
33 DIB_4BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c)
34 {
35 PBYTE addr = SurfObj->pvScan0 + (x>>1) + y * SurfObj->lDelta;
36 *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2));
37 }
38
39 ULONG
40 DIB_4BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y)
41 {
42 PBYTE addr = SurfObj->pvScan0 + (x>>1) + y * SurfObj->lDelta;
43 return (*addr >> ((1-(x&1))<<2)) & 0x0f;
44 }
45
46 VOID
47 DIB_4BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
48 {
49 PBYTE addr = SurfObj->pvScan0 + (x1>>1) + y * SurfObj->lDelta;
50 LONG cx = x1;
51
52 while(cx < x2) {
53 *addr = (*addr & notmask[x1&1]) | (c << ((1-(x1&1))<<2));
54 if((++x1 & 1) == 0)
55 ++addr;
56 ++cx;
57 }
58 }
59
60 VOID
61 DIB_4BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
62 {
63 PBYTE addr = SurfObj->pvScan0;
64 int lDelta = SurfObj->lDelta;
65
66 addr += (x>>1) + y1 * lDelta;
67 while(y1++ < y2) {
68 *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2));
69 addr += lDelta;
70 }
71 }
72
73 BOOLEAN STATIC
74 DIB_4BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
75 SURFGDI *DestGDI, SURFGDI *SourceGDI,
76 PRECTL DestRect, POINTL *SourcePoint,
77 XLATEOBJ* ColorTranslation)
78 {
79 LONG i, j, sx, sy, f2, xColor;
80 PBYTE SourceBits_24BPP, SourceLine_24BPP;
81 PBYTE DestBits, DestLine, SourceBits_8BPP, SourceLine_8BPP;
82 PBYTE SourceBits, SourceLine;
83
84 DestBits = DestSurf->pvScan0 + (DestRect->left>>1) + DestRect->top * DestSurf->lDelta;
85
86 switch(SourceGDI->BitsPerPixel)
87 {
88 case 1:
89 sx = SourcePoint->x;
90 sy = SourcePoint->y;
91
92 for (j=DestRect->top; j<DestRect->bottom; j++)
93 {
94 sx = SourcePoint->x;
95 for (i=DestRect->left; i<DestRect->right; i++)
96 {
97 if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
98 {
99 DIB_4BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 0));
100 } else {
101 DIB_4BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 1));
102 }
103 sx++;
104 }
105 sy++;
106 }
107 break;
108
109 case 4:
110 sy = SourcePoint->y;
111
112 for (j=DestRect->top; j<DestRect->bottom; j++)
113 {
114 sx = SourcePoint->x;
115
116 for (i=DestRect->left; i<DestRect->right; i++)
117 {
118 if (NULL != ColorTranslation)
119 {
120 DIB_4BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy)));
121 }
122 else
123 {
124 DIB_4BPP_PutPixel(DestSurf, i, j, DIB_4BPP_GetPixel(SourceSurf, sx, sy));
125 }
126 sx++;
127 }
128 sy++;
129 }
130 break;
131
132 case 8:
133 SourceBits_8BPP = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x;
134
135 for (j=DestRect->top; j<DestRect->bottom; j++)
136 {
137 SourceLine_8BPP = SourceBits_8BPP;
138 DestLine = DestBits;
139 f2 = DestRect->left & 1;
140
141 for (i=DestRect->left; i<DestRect->right; i++)
142 {
143 *DestLine = (*DestLine & notmask[f2]) |
144 ((XLATEOBJ_iXlate(ColorTranslation, *SourceLine_8BPP)) << ((4 * (1 - f2))));
145 if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
146 SourceLine_8BPP++;
147 }
148
149 SourceBits_8BPP += SourceSurf->lDelta;
150 DestBits += DestSurf->lDelta;
151 }
152 break;
153
154 case 16:
155 SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 2 * SourcePoint->x;
156 DestLine = DestBits;
157
158 for (j = DestRect->top; j < DestRect->bottom; j++)
159 {
160 SourceBits = SourceLine;
161 DestBits = DestLine;
162 f2 = DestRect->left & 1;
163
164 for (i = DestRect->left; i < DestRect->right; i++)
165 {
166 xColor = *((PWORD) SourceBits);
167 *DestBits = (*DestBits & notmask[f2]) |
168 ((XLATEOBJ_iXlate(ColorTranslation, xColor)) << ((4 * (1 - f2))));
169 if(f2 == 1) { DestBits++; f2 = 0; } else { f2 = 1; }
170 SourceBits += 2;
171 }
172
173 SourceLine += SourceSurf->lDelta;
174 DestLine += DestSurf->lDelta;
175 }
176 break;
177
178 case 24:
179 SourceBits_24BPP = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x * 3;
180
181 for (j=DestRect->top; j<DestRect->bottom; j++)
182 {
183 SourceLine_24BPP = SourceBits_24BPP;
184 DestLine = DestBits;
185 f2 = DestRect->left & 1;
186
187 for (i=DestRect->left; i<DestRect->right; i++)
188 {
189 xColor = (*(SourceLine_24BPP + 2) << 0x10) +
190 (*(SourceLine_24BPP + 1) << 0x08) +
191 (*(SourceLine_24BPP));
192 *DestLine = (*DestLine & notmask[f2]) |
193 ((XLATEOBJ_iXlate(ColorTranslation, xColor)) << ((4 * (1 - f2))));
194 if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
195 SourceLine_24BPP+=3;
196 }
197
198 SourceBits_24BPP += SourceSurf->lDelta;
199 DestBits += DestSurf->lDelta;
200 }
201 break;
202
203 case 32:
204 SourceLine = SourceSurf->pvScan0 + (SourcePoint->y * SourceSurf->lDelta) + 4 * SourcePoint->x;
205 DestLine = DestBits;
206
207 for (j = DestRect->top; j < DestRect->bottom; j++)
208 {
209 SourceBits = SourceLine;
210 DestBits = DestLine;
211 f2 = DestRect->left & 1;
212
213 for (i = DestRect->left; i < DestRect->right; i++)
214 {
215 xColor = *((PDWORD) SourceBits);
216 *DestBits = (*DestBits & notmask[f2]) |
217 ((XLATEOBJ_iXlate(ColorTranslation, xColor)) << ((4 * (1 - f2))));
218 if(f2 == 1) { DestBits++; f2 = 0; } else { f2 = 1; }
219 SourceBits += 4;
220 }
221
222 SourceLine += SourceSurf->lDelta;
223 DestLine += DestSurf->lDelta;
224 }
225 break;
226
227 default:
228 DbgPrint("DIB_4BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
229 return FALSE;
230 }
231 return(TRUE);
232 }
233
234 BOOLEAN
235 DIB_4BPP_BitBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
236 SURFGDI *DestGDI, SURFGDI *SourceGDI,
237 PRECTL DestRect, POINTL *SourcePoint,
238 PBRUSHOBJ Brush, PPOINTL BrushOrigin,
239 XLATEOBJ *ColorTranslation, ULONG Rop4)
240 {
241 LONG i, j, sx, sy;
242 ULONG Dest, Source, Pattern;
243 PULONG DestBits;
244 BOOL UsesSource;
245 BOOL UsesPattern;
246 LONG RoundedRight;
247 /* Pattern brushes */
248 PGDIBRUSHOBJ GdiBrush;
249 HBITMAP PatternSurface = NULL;
250 PSURFOBJ PatternObj;
251 ULONG PatternWidth, PatternHeight;
252 static const ULONG ExpandSolidColor[16] =
253 {
254 0x00000000 /* 0 */,
255 0x11111111 /* 1 */,
256 0x22222222 /* 2 */,
257 0x33333333 /* 3 */,
258 0x44444444 /* 4 */,
259 0x55555555 /* 5 */,
260 0x66666666 /* 6 */,
261 0x77777777 /* 7 */,
262 0x88888888 /* 8 */,
263 0x99999999 /* 9 */,
264 0xAAAAAAAA /* 10 */,
265 0xBBBBBBBB /* 11 */,
266 0xCCCCCCCC /* 12 */,
267 0xDDDDDDDD /* 13 */,
268 0xEEEEEEEE /* 14 */,
269 0xFFFFFFFF /* 15 */,
270 };
271
272 if (Rop4 == SRCCOPY)
273 {
274 return DIB_4BPP_BitBltSrcCopy(
275 DestSurf,
276 SourceSurf,
277 DestGDI,
278 SourceGDI,
279 DestRect,
280 SourcePoint,
281 ColorTranslation);
282 }
283
284 UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
285 UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000);
286
287 if (UsesPattern)
288 {
289 if (Brush == NULL)
290 {
291 UsesPattern = FALSE;
292 } else
293 if (Brush->iSolidColor == 0xFFFFFFFF)
294 {
295 PBITMAPOBJ PatternBitmap;
296
297 GdiBrush = CONTAINING_RECORD(
298 Brush,
299 GDIBRUSHOBJ,
300 BrushObject);
301
302 PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->hbmPattern);
303 PatternSurface = BitmapToSurf(PatternBitmap, NULL);
304 BITMAPOBJ_UnlockBitmap(GdiBrush->hbmPattern);
305
306 PatternObj = (PSURFOBJ)AccessUserObject((ULONG)PatternSurface);
307 PatternWidth = PatternObj->sizlBitmap.cx;
308 PatternHeight = PatternObj->sizlBitmap.cy;
309 }
310 }
311
312 sy = SourcePoint->y;
313 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x7);
314
315 for (j = DestRect->top; j < DestRect->bottom; j++, sy++)
316 {
317 DestBits = (PULONG)(DestSurf->pvScan0 + (DestRect->left >> 1) + j * DestSurf->lDelta);
318 sx = SourcePoint->x;
319 i = DestRect->left;
320
321 if (i & 0x1)
322 {
323 Dest = DIB_4BPP_GetPixel(DestSurf, i, j);
324
325 if (UsesSource)
326 {
327 Source = DIB_GetSource(SourceSurf, SourceGDI, sx, sy, ColorTranslation);
328 }
329
330 if (UsesPattern)
331 {
332 if (Brush->iSolidColor == 0xFFFFFFFF)
333 Pattern = DIB_1BPP_GetPixel(PatternObj, i % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack;
334 else
335 Pattern = Brush->iSolidColor & 0xF;
336 }
337
338 DIB_4BPP_PutPixel(DestSurf, i, j, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xF);
339
340 i++;
341 sx++;
342 DestBits++;
343 }
344
345 for (; i < RoundedRight; i += 8, sx += 8, DestBits++)
346 {
347 Dest = *DestBits;
348 if (UsesSource)
349 {
350 Source =
351 (DIB_GetSource(SourceSurf, SourceGDI, sx + 1, sy, ColorTranslation)) |
352 (DIB_GetSource(SourceSurf, SourceGDI, sx + 0, sy, ColorTranslation) << 4) |
353 (DIB_GetSource(SourceSurf, SourceGDI, sx + 3, sy, ColorTranslation) << 8) |
354 (DIB_GetSource(SourceSurf, SourceGDI, sx + 2, sy, ColorTranslation) << 12) |
355 (DIB_GetSource(SourceSurf, SourceGDI, sx + 5, sy, ColorTranslation) << 16) |
356 (DIB_GetSource(SourceSurf, SourceGDI, sx + 4, sy, ColorTranslation) << 20) |
357 (DIB_GetSource(SourceSurf, SourceGDI, sx + 7, sy, ColorTranslation) << 24) |
358 (DIB_GetSource(SourceSurf, SourceGDI, sx + 6, sy, ColorTranslation) << 28);
359 }
360 if (UsesPattern)
361 {
362 if (Brush->iSolidColor == 0xFFFFFFFF)
363 {
364 Pattern = DIB_1BPP_GetPixel(PatternObj, i % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack;
365 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 1) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 4;
366 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 2) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 8;
367 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 3) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 12;
368 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 4) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 16;
369 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 5) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 20;
370 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 6) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 24;
371 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 7) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 28;
372 }
373 else
374 {
375 Pattern = ExpandSolidColor[Brush->iSolidColor & 0xF];
376 }
377 }
378 *DestBits = DIB_DoRop(Rop4, Dest, Source, Pattern);
379 }
380
381 /* Process the rest of pixel on the line */
382 for (; i < DestRect->right; i++, sx++)
383 {
384 Dest = DIB_4BPP_GetPixel(DestSurf, i, j);
385 if (UsesSource)
386 {
387 Source = DIB_GetSource(SourceSurf, SourceGDI, sx, sy, ColorTranslation);
388 }
389 if (UsesPattern)
390 {
391 if (Brush->iSolidColor == 0xFFFFFFFF)
392 Pattern = DIB_1BPP_GetPixel(PatternObj, i % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack;
393 else
394 Pattern = Brush->iSolidColor & 0xF;
395 }
396 DIB_4BPP_PutPixel(DestSurf, i, j, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xF);
397 }
398 }
399
400 if (PatternSurface != NULL)
401 EngDeleteSurface(PatternSurface);
402
403 return TRUE;
404 }
405
406 BOOLEAN DIB_4BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
407 SURFGDI *DestGDI, SURFGDI *SourceGDI,
408 RECTL* DestRect, RECTL *SourceRect,
409 POINTL* MaskOrigin, POINTL* BrushOrigin,
410 XLATEOBJ *ColorTranslation, ULONG Mode)
411 {
412 DbgPrint("DIB_4BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel);
413 return FALSE;
414 }
415
416 BOOLEAN
417 DIB_4BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
418 PSURFGDI DestGDI, PSURFGDI SourceGDI,
419 RECTL* DestRect, POINTL *SourcePoint,
420 XLATEOBJ *ColorTranslation, ULONG iTransColor)
421 {
422 return FALSE;
423 }
424
425 /* EOF */