b245c528611e7541423bb2706c59735594095b79
[reactos.git] / reactos / subsystems / win32 / win32k / dib / dib1bpp.c
1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/dib/dib1bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 1bpp
6 * PROGRAMMERS: Jason Filby
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 VOID
15 DIB_1BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
16 {
17 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
18
19 if (0 == (c & 0x01))
20 *addr &= ~MASK1BPP(x);
21 else
22 *addr |= MASK1BPP(x);
23 }
24
25 ULONG
26 DIB_1BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
27 {
28 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
29
30 return (*addr & MASK1BPP(x) ? 1 : 0);
31 }
32
33 VOID
34 DIB_1BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
35 {
36 while(x1 < x2)
37 {
38 DIB_1BPP_PutPixel(SurfObj, x1, y, c);
39 x1++;
40 }
41 }
42
43 VOID
44 DIB_1BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
45 {
46 while(y1 < y2)
47 {
48 DIB_1BPP_PutPixel(SurfObj, x, y1, c);
49 y1++;
50 }
51 }
52
53 static
54 void
55 DIB_1BPP_BitBltSrcCopy_From1BPP (
56 SURFOBJ* DestSurf,
57 SURFOBJ* SourceSurf,
58 XLATEOBJ* pxlo,
59 PRECTL DestRect,
60 POINTL *SourcePoint )
61 {
62 // the 'window' in this sense is the x-position that corresponds
63 // to the left-edge of the 8-pixel byte we are currently working with.
64 // dwx is current x-window, dwx2 is the 'last' window we need to process
65 int dwx, dwx2; // destination window x-position
66 int swx; // source window y-position
67
68 // left and right edges of source and dest rectangles
69 int dl = DestRect->left; // dest left
70 int dr = DestRect->right-1; // dest right (inclusive)
71 int sl = SourcePoint->x; // source left
72 int sr = sl + dr - dl; // source right (inclusive)
73
74 // which direction are we going?
75 int xinc;
76 int yinc;
77 int ySrcDelta, yDstDelta;
78
79 // following 4 variables are used for the y-sweep
80 int dy; // dest y
81 int dy1; // dest y start
82 int dy2; // dest y end
83 int sy1; // src y start
84
85 int shift;
86 BYTE srcmask, dstmask, xormask;
87
88 // 'd' and 's' are the dest & src buffer pointers that I use on my x-sweep
89 // 'pd' and 'ps' are the dest & src buffer pointers used on the inner y-sweep
90 PBYTE d, pd; // dest ptrs
91 PBYTE s, ps; // src ptrs
92
93 shift = (dl-sl)&7;
94
95 xormask = 0xFF * XLATEOBJ_iXlate(pxlo, 0);
96
97 if ( DestRect->top <= SourcePoint->y )
98 {
99 // moving up ( scan top -> bottom )
100 dy1 = DestRect->top;
101 dy2 = DestRect->bottom - 1;
102 sy1 = SourcePoint->y;
103 yinc = 1;
104 ySrcDelta = SourceSurf->lDelta;
105 yDstDelta = DestSurf->lDelta;
106 }
107 else
108 {
109 // moving down ( scan bottom -> top )
110 dy1 = DestRect->bottom - 1;
111 dy2 = DestRect->top;
112 sy1 = SourcePoint->y + dy1 - dy2;
113 yinc = -1;
114 ySrcDelta = -SourceSurf->lDelta;
115 yDstDelta = -DestSurf->lDelta;
116 }
117 if ( DestRect->left <= SourcePoint->x )
118 {
119 // moving left ( scan left->right )
120 dwx = dl&~7;
121 swx = (sl-(dl&7))&~7;
122 dwx2 = dr&~7;
123 xinc = 1;
124 }
125 else
126 {
127 // moving right ( scan right->left )
128 dwx = dr&~7;
129 swx = (sr-(dr&7))&~7; //(sr-7)&~7; // we need the left edge of this block... thus the -7
130 dwx2 = dl&~7;
131 xinc = -1;
132 }
133 d = &(((PBYTE)DestSurf->pvScan0)[dy1*DestSurf->lDelta + (dwx>>3)]);
134 s = &(((PBYTE)SourceSurf->pvScan0)[sy1*SourceSurf->lDelta + (swx>>3)]);
135 for ( ;; )
136 {
137 dy = dy1;
138 pd = d;
139 ps = s;
140 srcmask = 0xff;
141 if ( dwx < dl )
142 {
143 int diff = dl-dwx;
144 srcmask &= (1<<(8-diff))-1;
145 }
146 if ( dwx+7 > dr )
147 {
148 int diff = dr-dwx+1;
149 srcmask &= ~((1<<(8-diff))-1);
150 }
151 dstmask = ~srcmask;
152
153 // we unfortunately *must* have 5 different versions of the inner
154 // loop to be certain we don't try to read from memory that is not
155 // needed and may in fact be invalid
156 if ( !shift )
157 {
158 for ( ;; )
159 {
160 *pd = (BYTE)((*pd & dstmask) | ((ps[0]^xormask) & srcmask));
161
162 // this *must* be here, because we could be going up *or* down...
163 if ( dy == dy2 )
164 break;
165 dy += yinc;
166 pd += yDstDelta;
167 ps += ySrcDelta;
168 }
169 }
170 else if ( !(0xFF00 & (srcmask<<shift) ) ) // check if ps[0] not needed...
171 {
172 for ( ;; )
173 {
174 *pd = (BYTE)((*pd & dstmask)
175 | ( ( (ps[1]^xormask) >> shift ) & srcmask ));
176
177 // this *must* be here, because we could be going up *or* down...
178 if ( dy == dy2 )
179 break;
180 dy += yinc;
181 pd += yDstDelta;
182 ps += ySrcDelta;
183 }
184 }
185 else if ( !(0xFF & (srcmask<<shift) ) ) // check if ps[1] not needed...
186 {
187 for ( ;; )
188 {
189 *pd = (*pd & dstmask)
190 | ( ( (ps[0]^xormask) << ( 8 - shift ) ) & srcmask );
191
192 // this *must* be here, because we could be going up *or* down...
193 if ( dy == dy2 )
194 break;
195 dy += yinc;
196 pd += yDstDelta;
197 ps += ySrcDelta;
198 }
199 }
200 else // both ps[0] and ps[1] are needed
201 {
202 for ( ;; )
203 {
204 *pd = (*pd & dstmask)
205 | ( ( ( ((ps[1]^xormask))|((ps[0]^xormask)<<8) ) >> shift ) & srcmask );
206
207 // this *must* be here, because we could be going up *or* down...
208 if ( dy == dy2 )
209 break;
210 dy += yinc;
211 pd += yDstDelta;
212 ps += ySrcDelta;
213 }
214 }
215
216 // this *must* be here, because we could be going right *or* left...
217 if ( dwx == dwx2 )
218 break;
219 d += xinc;
220 s += xinc;
221 dwx += xinc<<3;
222 swx += xinc<<3;
223 }
224 }
225
226 BOOLEAN
227 DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
228 {
229 ULONG Color;
230 LONG i, j, sx, sy = BltInfo->SourcePoint.y;
231
232 switch ( BltInfo->SourceSurface->iBitmapFormat )
233 {
234 case BMF_1BPP:
235 DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface, BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint );
236 break;
237
238 case BMF_4BPP:
239 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
240 {
241 sx = BltInfo->SourcePoint.x;
242 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
243 {
244 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
245 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
246 sx++;
247 }
248 sy++;
249 }
250 break;
251
252 case BMF_8BPP:
253 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
254 {
255 sx = BltInfo->SourcePoint.x;
256 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
257 {
258 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_8BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
259 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
260 sx++;
261 }
262 sy++;
263 }
264 break;
265
266 case BMF_16BPP:
267 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
268 {
269 sx = BltInfo->SourcePoint.x;
270 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
271 {
272 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_16BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
273 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
274 sx++;
275 }
276 sy++;
277 }
278 break;
279
280 case BMF_24BPP:
281 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
282 {
283 sx = BltInfo->SourcePoint.x;
284 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
285 {
286 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
287 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
288 sx++;
289 }
290 sy++;
291 }
292 break;
293
294 case BMF_32BPP:
295 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
296 {
297 sx = BltInfo->SourcePoint.x;
298 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
299 {
300 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_32BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
301 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
302 sx++;
303 }
304 sy++;
305 }
306 break;
307
308 default:
309 DbgPrint("DIB_1BPP_BitBlt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
310 return FALSE;
311 }
312
313 return TRUE;
314 }
315
316 BOOLEAN
317 DIB_1BPP_BitBlt(PBLTINFO BltInfo)
318 {
319 ULONG DestX, DestY;
320 ULONG SourceX, SourceY;
321 ULONG PatternY = 0;
322 ULONG Dest, Source = 0, Pattern = 0;
323 ULONG Index;
324 BOOLEAN UsesSource;
325 BOOLEAN UsesPattern;
326 PULONG DestBits;
327 ULONG RoundedRight;
328
329 UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);
330 UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);
331
332 RoundedRight = BltInfo->DestRect.right -
333 ((BltInfo->DestRect.right - BltInfo->DestRect.left) & 31);
334 SourceY = BltInfo->SourcePoint.y;
335
336 if (UsesPattern)
337 {
338 if (BltInfo->PatternSurface)
339 {
340 PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %
341 BltInfo->PatternSurface->sizlBitmap.cy;
342 }
343 else
344 {
345 /* FIXME: Shouldn't it be expanded? */
346 if (BltInfo->Brush)
347 Pattern = BltInfo->Brush->iSolidColor;
348 }
349 }
350
351 for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)
352 {
353 DestX = BltInfo->DestRect.left;
354 SourceX = BltInfo->SourcePoint.x;
355 DestBits = (PULONG)(
356 (PBYTE)BltInfo->DestSurface->pvScan0 +
357 (BltInfo->DestRect.left >> 3) +
358 DestY * BltInfo->DestSurface->lDelta);
359
360 if (DestX & 31)
361 {
362 #if 0
363 /* FIXME: This case is completely untested!!! */
364
365 Dest = *((PBYTE)DestBits);
366 NoBits = 31 - (DestX & 31);
367
368 if (UsesSource)
369 {
370 Source = 0;
371 /* FIXME: This is incorrect! */
372 for (Index = 31 - NoBits; Index >= 0; Index++)
373 Source |= (DIB_GetSource(SourceSurf, SourceX + Index, SourceY, ColorTranslation) << (31 - Index));
374 }
375
376 if (BltInfo->PatternSurface)
377 {
378 Pattern = 0;
379 for (k = 31 - NoBits; k >= 0; k++)
380 Pattern |= (DIB_GetSourceIndex(PatternObj, (X + BrushOrigin.x + k) % PatternWidth, PatternY) << (31 - k));
381 }
382
383 Dest = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern);
384 Dest &= ~((1 << (31 - NoBits)) - 1);
385 Dest |= *((PBYTE)DestBits) & ((1 << (31 - NoBits)) - 1);
386
387 *DestBits = Dest;
388
389 DestX += NoBits;
390 SourceX += NoBits;
391 #endif
392 }
393
394 for (; DestX < RoundedRight; DestX += 32, DestBits++, SourceX += 32)
395 {
396 Dest = *DestBits;
397
398 if (UsesSource)
399 {
400 Source = 0;
401 for (Index = 0; Index < 8; Index++)
402 {
403 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index, SourceY, BltInfo->XlateSourceToDest) << (7 - Index);
404 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 8, SourceY, BltInfo->XlateSourceToDest) << (8 + (7 - Index));
405 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 16, SourceY, BltInfo->XlateSourceToDest) << (16 + (7 - Index));
406 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 24, SourceY, BltInfo->XlateSourceToDest) << (24 + (7 - Index));
407 }
408 }
409
410 if (BltInfo->PatternSurface)
411 {
412 Pattern = 0;
413 for (Index = 0; Index < 8; Index++)
414 {
415 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (7 - Index);
416 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 8) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (8 + (7 - Index));
417 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 16) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (16 + (7 - Index));
418 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 24) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (24 + (7 - Index));
419 }
420 }
421
422 *DestBits = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern);
423 }
424
425 if (DestX < BltInfo->DestRect.right)
426 {
427 for (; DestX < BltInfo->DestRect.right; DestX++, SourceX++)
428 {
429 Dest = DIB_1BPP_GetPixel(BltInfo->DestSurface, DestX, DestY);
430
431 if (UsesSource)
432 {
433 Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);
434 }
435
436 if (BltInfo->PatternSurface)
437 {
438 Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
439 }
440
441 DIB_1BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
442 }
443 }
444
445 SourceY++;
446 if (BltInfo->PatternSurface)
447 {
448 PatternY++;
449 PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;
450 }
451 }
452
453 return TRUE;
454 }
455
456 /* BitBlt Optimize */
457 BOOLEAN
458 DIB_1BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
459 {
460 ULONG DestY;
461
462 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
463 {
464 DIB_1BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
465 }
466 return TRUE;
467 }
468
469 BOOLEAN
470 DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
471 RECTL* DestRect, RECTL *SourceRect,
472 XLATEOBJ *ColorTranslation, ULONG iTransColor)
473 {
474 return FALSE;
475 }
476
477 /* EOF */