implemented TransparentBlt() on 32bpp surfaces, but there are still some clipping...
[reactos.git] / reactos / subsys / win32k / dib / dib1bpp.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: dib1bpp.c,v 1.18 2004/04/06 17:54:32 weiden Exp $ */
20
21 #undef WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23 #include <stdlib.h>
24 #include <win32k/bitmaps.h>
25 #include <win32k/brush.h>
26 #include <win32k/debug.h>
27 #include <include/object.h>
28 #include <debug.h>
29 #include <ddk/winddi.h>
30 #include "../eng/objects.h"
31 #include "dib.h"
32
33 VOID
34 DIB_1BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c)
35 {
36 PBYTE addr = SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
37
38 if ( !c )
39 *addr &= ~MASK1BPP(x);
40 else
41 *addr |= MASK1BPP(x);
42 }
43
44 ULONG
45 DIB_1BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y)
46 {
47 PBYTE addr = SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
48
49 return (*addr & MASK1BPP(x) ? 1 : 0);
50 }
51
52 VOID
53 DIB_1BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
54 {
55 while(x1 < x2) {
56 DIB_1BPP_PutPixel(SurfObj, x1, y, c);
57 x1++;
58 }
59 }
60
61 VOID
62 DIB_1BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
63 {
64 while(y1 < y2) {
65 DIB_1BPP_PutPixel(SurfObj, x, y1, c);
66 y1++;
67 }
68 }
69
70 static
71 void
72 DIB_1BPP_BitBltSrcCopy_From1BPP (
73 SURFOBJ* DestSurf, SURFOBJ* SourceSurf,
74 PRECTL DestRect, POINTL *SourcePoint )
75 {
76 // the 'window' in this sense is the x-position that corresponds
77 // to the left-edge of the 8-pixel byte we are currently working with.
78 // dwx is current x-window, dwx2 is the 'last' window we need to process
79 int dwx, dwx2; // destination window x-position
80 int swx; // source window y-position
81
82 // left and right edges of source and dest rectangles
83 int dl = DestRect->left; // dest left
84 int dr = DestRect->right-1; // dest right (inclusive)
85 int sl = SourcePoint->x; // source left
86 int sr = sl + dr - dl; // source right (inclusive)
87
88 // which direction are we going?
89 int xinc;
90 int yinc;
91
92 // following 4 variables are used for the y-sweep
93 int dy; // dest y
94 int dy1; // dest y start
95 int dy2; // dest y end
96 int sy1; // src y start
97
98 int shift;
99 BYTE srcmask, dstmask;
100
101 // 'd' and 's' are the dest & src buffer pointers that I use on my x-sweep
102 // 'pd' and 'ps' are the dest & src buffer pointers used on the inner y-sweep
103 PBYTE d, pd; // dest ptrs
104 PBYTE s, ps; // src ptrs
105
106 shift = (dl-sl)&7;
107
108 if ( DestRect->top <= SourcePoint->y )
109 {
110 // moving up ( scan top -> bottom )
111 dy1 = DestRect->top;
112 dy2 = DestRect->bottom - 1;
113 sy1 = SourcePoint->y;
114 yinc = 1;
115 }
116 else
117 {
118 // moving down ( scan bottom -> top )
119 dy1 = DestRect->bottom - 1;
120 dy2 = DestRect->top;
121 sy1 = SourcePoint->y + dy1 - dy2;
122 yinc = -1;
123 }
124 if ( DestRect->left <= SourcePoint->x )
125 {
126 // moving left ( scan left->right )
127 dwx = dl&~7;
128 swx = (sl-(dl&7))&~7;
129 dwx2 = dr&~7;
130 xinc = 1;
131 }
132 else
133 {
134 // moving right ( scan right->left )
135 dwx = dr&~7;
136 swx = (sr-(dr&7))&~7; //(sr-7)&~7; // we need the left edge of this block... thus the -7
137 dwx2 = dl&~7;
138 xinc = -1;
139 }
140 d = &(((PBYTE)DestSurf->pvScan0)[dy1*DestSurf->lDelta + (dwx>>3)]);
141 s = &(((PBYTE)SourceSurf->pvScan0)[sy1*SourceSurf->lDelta + (swx>>3)]);
142 for ( ;; )
143 {
144 dy = dy1;
145 pd = d;
146 ps = s;
147 srcmask = 0xff;
148 int dx = dwx; /* dest x for this pass */
149 if ( dwx < dl )
150 {
151 int diff = dl-dwx;
152 srcmask &= (1<<(8-diff))-1;
153 dx = dl;
154 }
155 if ( dwx+7 > dr )
156 {
157 int diff = dr-dwx+1;
158 srcmask &= ~((1<<(8-diff))-1);
159 }
160 dstmask = ~srcmask;
161
162 // we unfortunately *must* have 5 different versions of the inner
163 // loop to be certain we don't try to read from memory that is not
164 // needed and may in fact be invalid
165 if ( !shift )
166 {
167 for ( ;; )
168 {
169 *pd = (BYTE)((*pd & dstmask) | (*ps & srcmask));
170
171 // this *must* be here, because we could be going up *or* down...
172 if ( dy == dy2 )
173 break;
174 dy += yinc;
175 pd += yinc * DestSurf->lDelta;
176 ps += yinc * SourceSurf->lDelta;
177 }
178 }
179 else if ( !(0xFF00 & (srcmask<<shift) ) ) // check if ps[0] not needed...
180 {
181 for ( ;; )
182 {
183 *pd = (BYTE)((*pd & dstmask)
184 | ( ( ps[1] >> shift ) & srcmask ));
185
186 // this *must* be here, because we could be going up *or* down...
187 if ( dy == dy2 )
188 break;
189 dy += yinc;
190 pd += yinc * DestSurf->lDelta;
191 ps += yinc * SourceSurf->lDelta;
192 }
193 }
194 else if ( !(0xFF & (srcmask<<shift) ) ) // check if ps[1] not needed...
195 {
196 for ( ;; )
197 {
198 *pd = (*pd & dstmask)
199 | ( ( ps[0] << ( 8 - shift ) ) & srcmask );
200
201 // this *must* be here, because we could be going up *or* down...
202 if ( dy == dy2 )
203 break;
204 dy += yinc;
205 pd += yinc * DestSurf->lDelta;
206 ps += yinc * SourceSurf->lDelta;
207 }
208 }
209 else // both ps[0] and ps[1] are needed
210 {
211 for ( ;; )
212 {
213 *pd = (*pd & dstmask)
214 | ( ( ( (ps[1])|(ps[0]<<8) ) >> shift ) & srcmask );
215
216 // this *must* be here, because we could be going up *or* down...
217 if ( dy == dy2 )
218 break;
219 dy += yinc;
220 pd += yinc * DestSurf->lDelta;
221 ps += yinc * SourceSurf->lDelta;
222 }
223 }
224
225 // this *must* be here, because we could be going right *or* left...
226 if ( dwx == dwx2 )
227 break;
228 d += xinc;
229 s += xinc;
230 dwx += xinc<<3;
231 swx += xinc<<3;
232 }
233 }
234
235 BOOLEAN
236 DIB_1BPP_BitBltSrcCopy(
237 SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
238 SURFGDI *DestGDI, SURFGDI *SourceGDI,
239 PRECTL DestRect, POINTL *SourcePoint,
240 XLATEOBJ *ColorTranslation)
241 {
242 LONG i, j, sx, sy = SourcePoint->y;
243
244 switch ( SourceGDI->BitsPerPixel )
245 {
246 case 1:
247 DIB_1BPP_BitBltSrcCopy_From1BPP ( DestSurf, SourceSurf, DestRect, SourcePoint );
248 break;
249
250 case 4:
251 for (j=DestRect->top; j<DestRect->bottom; j++)
252 {
253 sx = SourcePoint->x;
254 for (i=DestRect->left; i<DestRect->right; i++)
255 {
256 if(XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy)) == 0)
257 {
258 DIB_1BPP_PutPixel(DestSurf, i, j, 0);
259 } else {
260 DIB_1BPP_PutPixel(DestSurf, i, j, 1);
261 }
262 sx++;
263 }
264 sy++;
265 }
266 break;
267
268 case 8:
269 for (j=DestRect->top; j<DestRect->bottom; j++)
270 {
271 sx = SourcePoint->x;
272 for (i=DestRect->left; i<DestRect->right; i++)
273 {
274 if(XLATEOBJ_iXlate(ColorTranslation, DIB_8BPP_GetPixel(SourceSurf, sx, sy)) == 0)
275 {
276 DIB_1BPP_PutPixel(DestSurf, i, j, 0);
277 } else {
278 DIB_1BPP_PutPixel(DestSurf, i, j, 1);
279 }
280 sx++;
281 }
282 sy++;
283 }
284 break;
285
286 case 16:
287 for (j=DestRect->top; j<DestRect->bottom; j++)
288 {
289 sx = SourcePoint->x;
290 for (i=DestRect->left; i<DestRect->right; i++)
291 {
292 if(XLATEOBJ_iXlate(ColorTranslation, DIB_16BPP_GetPixel(SourceSurf, sx, sy)) == 0)
293 {
294 DIB_1BPP_PutPixel(DestSurf, i, j, 0);
295 } else {
296 DIB_1BPP_PutPixel(DestSurf, i, j, 1);
297 }
298 sx++;
299 }
300 sy++;
301 }
302 break;
303
304 case 24:
305 for (j=DestRect->top; j<DestRect->bottom; j++)
306 {
307 sx = SourcePoint->x;
308 for (i=DestRect->left; i<DestRect->right; i++)
309 {
310 if(XLATEOBJ_iXlate(ColorTranslation, DIB_24BPP_GetPixel(SourceSurf, sx, sy)) == 0)
311 {
312 DIB_1BPP_PutPixel(DestSurf, i, j, 0);
313 } else {
314 DIB_1BPP_PutPixel(DestSurf, i, j, 1);
315 }
316 sx++;
317 }
318 sy++;
319 }
320 break;
321
322 case 32:
323 for (j=DestRect->top; j<DestRect->bottom; j++)
324 {
325 sx = SourcePoint->x;
326 for (i=DestRect->left; i<DestRect->right; i++)
327 {
328 if(XLATEOBJ_iXlate(ColorTranslation, DIB_32BPP_GetPixel(SourceSurf, sx, sy)) == 0)
329 {
330 DIB_1BPP_PutPixel(DestSurf, i, j, 0);
331 } else {
332 DIB_1BPP_PutPixel(DestSurf, i, j, 1);
333 }
334 sx++;
335 }
336 sy++;
337 }
338 break;
339
340 default:
341 DbgPrint("DIB_1BPP_BitBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel);
342 return FALSE;
343 }
344
345 return TRUE;
346 }
347
348 BOOLEAN
349 DIB_1BPP_BitBlt(
350 SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
351 SURFGDI *DestGDI, SURFGDI *SourceGDI,
352 PRECTL DestRect, POINTL *SourcePoint,
353 PBRUSHOBJ Brush, PPOINTL BrushOrigin,
354 XLATEOBJ *ColorTranslation, ULONG Rop4)
355 {
356 ULONG X, Y, SourceX, SourceY, k;
357 ULONG Dest, Source, Pattern;
358 PULONG DestBits;
359 BOOL UsesSource;
360 BOOL UsesPattern;
361 LONG RoundedRight;
362 BYTE NoBits;
363 /* Pattern brushes */
364 PGDIBRUSHOBJ GdiBrush;
365 HBITMAP PatternSurface = NULL;
366 PSURFOBJ PatternObj;
367 ULONG PatternWidth, PatternHeight;
368
369 if (Rop4 == SRCCOPY)
370 {
371 return DIB_1BPP_BitBltSrcCopy(
372 DestSurf,
373 SourceSurf,
374 DestGDI,
375 SourceGDI,
376 DestRect,
377 SourcePoint,
378 ColorTranslation);
379 }
380
381 if (UsesPattern)
382 {
383 if (Brush == NULL)
384 {
385 UsesPattern = FALSE;
386 } else
387 if (Brush->iSolidColor == 0xFFFFFFFF)
388 {
389 PBITMAPOBJ PatternBitmap;
390
391 GdiBrush = CONTAINING_RECORD(
392 Brush,
393 GDIBRUSHOBJ,
394 BrushObject);
395
396 PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->hbmPattern);
397 PatternSurface = BitmapToSurf(PatternBitmap, NULL);
398 BITMAPOBJ_UnlockBitmap(GdiBrush->hbmPattern);
399
400 PatternObj = (PSURFOBJ)AccessUserObject((ULONG)PatternSurface);
401 PatternWidth = PatternObj->sizlBitmap.cx;
402 PatternHeight = PatternObj->sizlBitmap.cy;
403 }
404 }
405
406 UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
407 UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000);
408 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x7);
409 SourceY = SourcePoint->y;
410
411 for (Y = DestRect->top; Y < DestRect->bottom; Y++)
412 {
413 SourceX = SourcePoint->x;
414 DestBits = (PULONG)(
415 DestSurf->pvScan0 +
416 (DestRect->left >> 3) +
417 Y * DestSurf->lDelta);
418
419 X = DestRect->left;
420 if (X & 7)
421 {
422 Dest = *((PBYTE)DestBits);
423 NoBits = 7 - (X & 7);
424
425 if (UsesSource)
426 {
427 Source = 0;
428 for (k = 7 - NoBits; k < NoBits; k++)
429 Source |= (DIB_GetSource(SourceSurf, SourceGDI, SourceX + k, SourceY, ColorTranslation) << (7 - k));
430 }
431
432 if (UsesPattern)
433 {
434 if (Brush->iSolidColor == 0xFFFFFFFF)
435 {
436 Pattern = 0;
437 for (k = 7 - NoBits; k < NoBits; k++)
438 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (X + k) % PatternWidth, Y % PatternHeight) << (7 - k));
439 }
440 else
441 {
442 Pattern = Brush->iSolidColor ? 0xFFFFFFFF : 0x00000000;
443 }
444 }
445
446 Dest = DIB_DoRop(Rop4, Dest, Source, Pattern);
447 Dest &= ~((1 << (7 - NoBits)) - 1);
448 Dest |= *((PBYTE)DestBits) & ((1 << (7 - NoBits)) - 1);
449
450 X += NoBits;
451 SourceX += NoBits;
452 }
453
454 for (; X < RoundedRight; X += 32, DestBits++, SourceX++)
455 {
456 Dest = *DestBits;
457
458 if (UsesSource)
459 {
460 Source = 0;
461 for (k = 0; k < 8; k++)
462 {
463 Source |= (DIB_GetSource(SourceSurf, SourceGDI, SourceX + k, SourceY, ColorTranslation) << (7 - k));
464 Source |= (DIB_GetSource(SourceSurf, SourceGDI, SourceX + k + 8, SourceY, ColorTranslation) << (8 + (7 - k)));
465 Source |= (DIB_GetSource(SourceSurf, SourceGDI, SourceX + k + 16, SourceY, ColorTranslation) << (16 + (7 - k)));
466 Source |= (DIB_GetSource(SourceSurf, SourceGDI, SourceX + k + 24, SourceY, ColorTranslation) << (24 + (7 - k)));
467 }
468 }
469
470 if (UsesPattern)
471 {
472 if (Brush->iSolidColor == 0xFFFFFFFF)
473 {
474 Pattern = 0;
475 for (k = 0; k < 8; k++)
476 {
477 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (X + k) % PatternWidth, Y % PatternHeight) << (7 - k));
478 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (X + k + 8) % PatternWidth, Y % PatternHeight) << (8 + (7 - k)));
479 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (X + k + 16) % PatternWidth, Y % PatternHeight) << (16 + (7 - k)));
480 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (X + k + 24) % PatternWidth, Y % PatternHeight) << (24 + (7 - k)));
481 }
482 }
483 else
484 {
485 Pattern = Brush->iSolidColor ? 0xFFFFFFFF : 0x00000000;
486 }
487 }
488
489 *DestBits = DIB_DoRop(Rop4, Dest, Source, Pattern);
490 }
491
492 if (X < DestRect->right)
493 {
494 // Dest = *DestBits;
495 for (; X < DestRect->right; X++, SourceX++)
496 {
497 // Dest = *DestBits;
498 Dest = DIB_1BPP_GetPixel(DestSurf, X, Y);
499
500 if (UsesSource)
501 {
502 Source = DIB_GetSource(SourceSurf, SourceGDI, SourceX, SourceY, ColorTranslation);
503 }
504
505 if (UsesPattern)
506 {
507 if (Brush->iSolidColor == 0xFFFFFFFF)
508 Pattern = DIB_1BPP_GetPixel(PatternObj, X % PatternWidth, Y % PatternHeight);
509 else
510 Pattern = Brush->iSolidColor ? 0xFFFFFFFF : 0x00000000;
511 }
512
513 DIB_1BPP_PutPixel(DestSurf, X, Y, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xF);
514 // Dest >>= 1;
515 }
516 }
517
518 SourceY++;
519 }
520
521 if (PatternSurface != NULL)
522 EngDeleteSurface(PatternSurface);
523
524 return TRUE;
525 }
526
527 BOOLEAN
528 DIB_1BPP_StretchBlt (
529 SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
530 SURFGDI *DestGDI, SURFGDI *SourceGDI,
531 RECTL* DestRect, RECTL *SourceRect,
532 POINTL* MaskOrigin, POINTL* BrushOrigin,
533 XLATEOBJ *ColorTranslation, ULONG Mode)
534 {
535 DbgPrint("DIB_1BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel);
536 return FALSE;
537 }
538
539 BOOLEAN
540 DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
541 PSURFGDI DestGDI, PSURFGDI SourceGDI,
542 RECTL* DestRect, POINTL *SourcePoint,
543 XLATEOBJ *ColorTranslation, ULONG iTransColor)
544 {
545 return FALSE;
546 }
547
548 /* EOF */