- Fixed order of bits in a byte for pattern brushes.
[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.31 2004/04/07 20:23:38 navaraf 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 = 0, PatternY;
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)) && Brush;
286
287 if (UsesPattern)
288 {
289 if (Brush->iSolidColor == 0xFFFFFFFF)
290 {
291 PBITMAPOBJ PatternBitmap;
292
293 GdiBrush = CONTAINING_RECORD(
294 Brush,
295 GDIBRUSHOBJ,
296 BrushObject);
297
298 PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->hbmPattern);
299 PatternSurface = BitmapToSurf(PatternBitmap, NULL);
300 BITMAPOBJ_UnlockBitmap(GdiBrush->hbmPattern);
301
302 PatternObj = (PSURFOBJ)AccessUserObject((ULONG)PatternSurface);
303 PatternWidth = PatternObj->sizlBitmap.cx;
304 PatternHeight = PatternObj->sizlBitmap.cy;
305
306 UsesPattern = TRUE;
307 }
308 else
309 {
310 UsesPattern = FALSE;
311 Pattern = ExpandSolidColor[Brush->iSolidColor & 0xF];
312 }
313 }
314
315 sy = SourcePoint->y;
316 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x7);
317
318 for (j = DestRect->top; j < DestRect->bottom; j++, sy++)
319 {
320 DestBits = (PULONG)(DestSurf->pvScan0 + (DestRect->left >> 1) + j * DestSurf->lDelta);
321 sx = SourcePoint->x;
322 i = DestRect->left;
323
324 if (UsesPattern)
325 PatternY = j % PatternHeight;
326
327 if (i & 0x1)
328 {
329 Dest = DIB_4BPP_GetPixel(DestSurf, i, j);
330
331 if (UsesSource)
332 {
333 Source = DIB_GetSource(SourceSurf, SourceGDI, sx, sy, ColorTranslation);
334 }
335
336 if (UsesPattern)
337 {
338 Pattern = DIB_1BPP_GetPixel(PatternObj, i % PatternWidth, PatternY) ? GdiBrush->crFore : GdiBrush->crBack;
339 }
340
341 DIB_4BPP_PutPixel(DestSurf, i, j, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xF);
342
343 i++;
344 sx++;
345 DestBits = (PULONG)((ULONG_PTR)DestBits + 1);
346 }
347
348 for (; i < RoundedRight; i += 8, sx += 8, DestBits++)
349 {
350 Dest = *DestBits;
351 if (UsesSource)
352 {
353 Source =
354 (DIB_GetSource(SourceSurf, SourceGDI, sx + 1, sy, ColorTranslation)) |
355 (DIB_GetSource(SourceSurf, SourceGDI, sx + 0, sy, ColorTranslation) << 4) |
356 (DIB_GetSource(SourceSurf, SourceGDI, sx + 3, sy, ColorTranslation) << 8) |
357 (DIB_GetSource(SourceSurf, SourceGDI, sx + 2, sy, ColorTranslation) << 12) |
358 (DIB_GetSource(SourceSurf, SourceGDI, sx + 5, sy, ColorTranslation) << 16) |
359 (DIB_GetSource(SourceSurf, SourceGDI, sx + 4, sy, ColorTranslation) << 20) |
360 (DIB_GetSource(SourceSurf, SourceGDI, sx + 7, sy, ColorTranslation) << 24) |
361 (DIB_GetSource(SourceSurf, SourceGDI, sx + 6, sy, ColorTranslation) << 28);
362 }
363 if (UsesPattern)
364 {
365 Pattern = DIB_1BPP_GetPixel(PatternObj, (i + 1) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack;
366 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 0) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 4;
367 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 3) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 8;
368 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 2) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 12;
369 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 5) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 16;
370 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 4) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 20;
371 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 7) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 24;
372 Pattern |= (DIB_1BPP_GetPixel(PatternObj, (i + 6) % PatternWidth, j % PatternHeight) ? GdiBrush->crFore : GdiBrush->crBack) << 28;
373 }
374 *DestBits = DIB_DoRop(Rop4, Dest, Source, Pattern);
375 }
376
377 /* Process the rest of pixel on the line */
378 for (; i < DestRect->right; i++, sx++)
379 {
380 Dest = DIB_4BPP_GetPixel(DestSurf, i, j);
381 if (UsesSource)
382 {
383 Source = DIB_GetSource(SourceSurf, SourceGDI, sx, sy, ColorTranslation);
384 }
385 if (UsesPattern)
386 {
387 Pattern = DIB_1BPP_GetPixel(PatternObj, i % PatternWidth, PatternY) ? GdiBrush->crFore : GdiBrush->crBack;
388 }
389 DIB_4BPP_PutPixel(DestSurf, i, j, DIB_DoRop(Rop4, Dest, Source, Pattern) & 0xF);
390 }
391 }
392
393 if (PatternSurface != NULL)
394 EngDeleteSurface(PatternSurface);
395
396 return TRUE;
397 }
398
399 BOOLEAN DIB_4BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
400 SURFGDI *DestGDI, SURFGDI *SourceGDI,
401 RECTL* DestRect, RECTL *SourceRect,
402 POINTL* MaskOrigin, POINTL* BrushOrigin,
403 XLATEOBJ *ColorTranslation, ULONG Mode)
404 {
405 DbgPrint("DIB_4BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel);
406 return FALSE;
407 }
408
409 BOOLEAN
410 DIB_4BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
411 PSURFGDI DestGDI, PSURFGDI SourceGDI,
412 RECTL* DestRect, POINTL *SourcePoint,
413 XLATEOBJ *ColorTranslation, ULONG iTransColor)
414 {
415 return FALSE;
416 }
417
418 /* EOF */