1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: win32ss/gdi/dib/dib1bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 1bpp
6 * PROGRAMMERS: Jason Filby
7 * Doug Lyons
8 */
9
10 #include <win32k.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #define DEC_OR_INC(var, decTrue, amount) \
16 ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
17
18 VOID
DIB_1BPP_PutPixel(SURFOBJ * SurfObj,LONG x,LONG y,ULONG c)19 DIB_1BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
20 {
21 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
22
23 if (0 == (c & 0x01))
24 *addr &= ~MASK1BPP(x);
25 else
26 *addr |= MASK1BPP(x);
27 }
28
29 ULONG
DIB_1BPP_GetPixel(SURFOBJ * SurfObj,LONG x,LONG y)30 DIB_1BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
31 {
32 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
33
34 return (*addr & MASK1BPP(x) ? 1 : 0);
35 }
36
37 VOID
DIB_1BPP_HLine(SURFOBJ * SurfObj,LONG x1,LONG x2,LONG y,ULONG c)38 DIB_1BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
39 {
40 while(x1 < x2)
41 {
42 DIB_1BPP_PutPixel(SurfObj, x1, y, c);
43 x1++;
44 }
45 }
46
47 VOID
DIB_1BPP_VLine(SURFOBJ * SurfObj,LONG x,LONG y1,LONG y2,ULONG c)48 DIB_1BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
49 {
50 while(y1 < y2)
51 {
52 DIB_1BPP_PutPixel(SurfObj, x, y1, c);
53 y1++;
54 }
55 }
56
57 static
58 BOOLEAN
DIB_1BPP_BitBltSrcCopy_From1BPP(SURFOBJ * DestSurf,SURFOBJ * SourceSurf,XLATEOBJ * pxlo,PRECTL DestRect,POINTL * SourcePoint,BOOLEAN bTopToBottom,BOOLEAN bLeftToRight)59 DIB_1BPP_BitBltSrcCopy_From1BPP (
60 SURFOBJ* DestSurf,
61 SURFOBJ* SourceSurf,
62 XLATEOBJ* pxlo,
63 PRECTL DestRect,
64 POINTL *SourcePoint,
65 BOOLEAN bTopToBottom,
66 BOOLEAN bLeftToRight )
67 {
68 LONG Height = RECTL_lGetHeight(DestRect);
69 LONG Width = RECTL_lGetWidth(DestRect);
70 BOOLEAN XorBit = !!XLATEOBJ_iXlate(pxlo, 0);
71 BOOLEAN Overlap = FALSE;
72 BYTE *DstStart, *DstEnd, *SrcStart, *SrcEnd;
73
74 /* Make sure this is as expected */
75 ASSERT(DestRect->left >= 0);
76 ASSERT(DestRect->top >= 0);
77 ASSERT(Height > 0);
78 ASSERT(Width > 0);
79
80 /*
81 * Check if we need to allocate a buffer for our operation.
82 */
83 DstStart = (BYTE*)DestSurf->pvScan0 + DestRect->top * DestSurf->lDelta + DestRect->left / 8;
84 DstEnd = (BYTE*)DestSurf->pvScan0 + (DestRect->bottom - 1) * DestSurf->lDelta + (DestRect->right) / 8;
85 SrcStart = (BYTE*)SourceSurf->pvScan0 + SourcePoint->y * SourceSurf->lDelta + SourcePoint->x / 8;
86 SrcEnd = (BYTE*)SourceSurf->pvScan0 + (SourcePoint->y + Height - 1) * SourceSurf->lDelta + (SourcePoint->x + Width) / 8;
87
88 /* Beware of bitmaps with negative pitch! */
89 if (DstStart > DstEnd)
90 {
91 BYTE* tmp = DstStart;
92 DstStart = DstEnd;
93 DstEnd = tmp;
94 }
95
96 if (SrcStart > SrcEnd)
97 {
98 BYTE* tmp = SrcStart;
99 SrcStart = SrcEnd;
100 SrcEnd = tmp;
101 }
102
103 /* We allocate a new buffer when the two buffers overlap */
104 Overlap = ((SrcStart >= DstStart) && (SrcStart < DstEnd)) || ((SrcEnd >= DstStart) && (SrcEnd < DstEnd));
105
106 if (!Overlap)
107 {
108 LONG y;
109 for (y = 0; y < Height; y++)
110 {
111 LONG ySrc = bTopToBottom ? SourcePoint->y + Height - y - 1 : SourcePoint->y + y;
112 LONG x;
113
114 for(x = 0; x < Width; x++)
115 {
116 LONG xSrc = bLeftToRight ? SourcePoint->x + Width - x - 1 : SourcePoint->x + x;
117 ULONG Pixel = DIB_1BPP_GetPixel(SourceSurf, xSrc, ySrc);
118 if (XorBit)
119 Pixel = !Pixel;
120 DIB_1BPP_PutPixel(DestSurf, DestRect->left + x, DestRect->top + y, Pixel);
121 }
122 }
123 }
124 else
125 {
126 LONG y;
127 BYTE* PixBuf = ExAllocatePoolZero(PagedPool, Height * (ALIGN_UP_BY(Width, 8) / 8), TAG_DIB);
128 if (!PixBuf)
129 return FALSE;
130 for (y = 0; y < Height; y++)
131 {
132 BYTE* Row = PixBuf + y * ALIGN_UP_BY(Width, 8) / 8;
133 LONG ySrc = bTopToBottom ? SourcePoint->y + Height - y - 1 : SourcePoint->y + y;
134 LONG x;
135
136 for (x = 0; x < Width; x++)
137 {
138 LONG xSrc = bLeftToRight ? SourcePoint->x + Width - x - 1 : SourcePoint->x + x;
139 if ((!DIB_1BPP_GetPixel(SourceSurf, xSrc, ySrc)) == XorBit)
140 Row[x / 8] |= 1 << (x & 7);
141 }
142 }
143
144 for (y = 0; y < Height; y++)
145 {
146 BYTE* Row = PixBuf + y * ALIGN_UP_BY(Width, 8) / 8;
147 LONG x;
148 for (x = 0; x < Width; x++)
149 DIB_1BPP_PutPixel(DestSurf, DestRect->left + x, DestRect->top + y, !!(Row[x/8] & (1 << (x&7))));
150 }
151
152 ExFreePoolWithTag(PixBuf, TAG_DIB);
153 }
154
155 return TRUE;
156 }
157
158 BOOLEAN
DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)159 DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
160 {
161 ULONG Color;
162 LONG i, j, sx, sy;
163 BOOLEAN bTopToBottom, bLeftToRight;
164
165 // This sets sy to the top line
166 sy = BltInfo->SourcePoint.y;
167
168 DPRINT("DIB_1BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
169 BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
170 BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
171 BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
172
173 /* Get back left to right flip here */
174 bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
175
176 /* Check for top to bottom flip needed. */
177 bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
178
179 // Make WellOrdered with top < bottom and left < right
180 RECTL_vMakeWellOrdered(&BltInfo->DestRect);
181
182 DPRINT("BPP is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
183 BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
184
185 switch ( BltInfo->SourceSurface->iBitmapFormat )
186 {
187 case BMF_1BPP:
188 DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
189 BltInfo->DestRect.right - BltInfo->DestRect.left);
190
191 return DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface,
192 BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint,
193 bTopToBottom, bLeftToRight );
194
195 case BMF_4BPP:
196 DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
197 BltInfo->DestRect.right - BltInfo->DestRect.left);
198
199 if (bTopToBottom)
200 {
201 // This sets sy to the bottom line
202 sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
203 }
204
205 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
206 {
207 sx = BltInfo->SourcePoint.x;
208
209 if (bLeftToRight)
210 {
211 // This sets the sx to the rightmost pixel
212 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
213 }
214
215 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
216 {
217 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
218 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
219
220 DEC_OR_INC(sx, bLeftToRight, 1);
221 }
222 DEC_OR_INC(sy, bTopToBottom, 1);
223 }
224 break;
225
226 case BMF_8BPP:
227 DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
228 BltInfo->DestRect.left, BltInfo->DestRect.top,
229 BltInfo->DestRect.right, BltInfo->DestRect.bottom,
230 BltInfo->DestRect.right - BltInfo->DestRect.left);
231
232 if (bTopToBottom)
233 {
234 // This sets sy to the bottom line
235 sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
236 }
237
238 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
239 {
240 sx = BltInfo->SourcePoint.x;
241
242 if (bLeftToRight)
243 {
244 // This sets sx to the rightmost pixel
245 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
246 }
247
248 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
249 {
250 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_8BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
251 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
252
253 DEC_OR_INC(sx, bLeftToRight, 1);
254 }
255 DEC_OR_INC(sy, bTopToBottom, 1);
256 }
257 break;
258
259 case BMF_16BPP:
260 DPRINT("16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
261 BltInfo->DestRect.left, BltInfo->DestRect.top,
262 BltInfo->DestRect.right, BltInfo->DestRect.bottom,
263 BltInfo->DestRect.right - BltInfo->DestRect.left);
264
265 if (bTopToBottom)
266 {
267 // This sets sy to the bottom line
268 sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;;
269 }
270
271 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
272 {
273 sx = BltInfo->SourcePoint.x;
274
275 if (bLeftToRight)
276 {
277 // This sets the sx to the rightmost pixel
278 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
279 }
280
281 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
282 {
283 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_16BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
284 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
285 DEC_OR_INC(sx, bLeftToRight, 1);
286 }
287 DEC_OR_INC(sy, bTopToBottom, 1);
288 }
289 break;
290
291 case BMF_24BPP:
292
293 DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
294 BltInfo->DestRect.left, BltInfo->DestRect.top,
295 BltInfo->DestRect.right, BltInfo->DestRect.bottom,
296 BltInfo->DestRect.right - BltInfo->DestRect.left);
297
298 if (bTopToBottom)
299 {
300 // This sets sy to the bottom line
301 sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
302 }
303
304 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
305 {
306 sx = BltInfo->SourcePoint.x;
307
308 if (bLeftToRight)
309 {
310 // This sets the sx to the rightmost pixel
311 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
312 }
313
314 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
315 {
316 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
317 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
318 DEC_OR_INC(sx, bLeftToRight, 1);
319 }
320 DEC_OR_INC(sy, bTopToBottom, 1);
321 }
322 break;
323
324 case BMF_32BPP:
325
326 DPRINT("32BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
327 BltInfo->DestRect.left, BltInfo->DestRect.top,
328 BltInfo->DestRect.right, BltInfo->DestRect.bottom,
329 BltInfo->DestRect.right - BltInfo->DestRect.left);
330
331 if (bTopToBottom)
332 {
333 // This sets sy to the bottom line
334 sy += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
335 }
336
337 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
338 {
339 sx = BltInfo->SourcePoint.x;
340
341 if (bLeftToRight)
342 {
343 // This sets the sx to the rightmost pixel
344 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
345 }
346
347 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
348 {
349 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_32BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
350 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
351 DEC_OR_INC(sx, bLeftToRight, 1);
352 }
353 DEC_OR_INC(sy, bTopToBottom, 1);
354 }
355 break;
356
357 default:
358 DbgPrint("DIB_1BPP_BitBlt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
359 return FALSE;
360 }
361
362 return TRUE;
363 }
364
365 #ifndef _USE_DIBLIB_
366 BOOLEAN
DIB_1BPP_BitBlt(PBLTINFO BltInfo)367 DIB_1BPP_BitBlt(PBLTINFO BltInfo)
368 {
369 LONG DestX, DestY;
370 LONG SourceX, SourceY;
371 LONG PatternY = 0;
372 ULONG Dest, Source = 0, Pattern = 0;
373 ULONG Index;
374 BOOLEAN UsesSource;
375 BOOLEAN UsesPattern;
376 PULONG DestBits;
377 LONG RoundedRight;
378
379 UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);
380 UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);
381
382 RoundedRight = BltInfo->DestRect.right -
383 ((BltInfo->DestRect.right - BltInfo->DestRect.left) & 31);
384 SourceY = BltInfo->SourcePoint.y;
385
386 if (UsesPattern)
387 {
388 if (BltInfo->PatternSurface)
389 {
390 PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %
391 BltInfo->PatternSurface->sizlBitmap.cy;
392 }
393 else
394 {
395 /* FIXME: Shouldn't it be expanded? */
396 if (BltInfo->Brush)
397 Pattern = BltInfo->Brush->iSolidColor;
398 }
399 }
400
401 for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)
402 {
403 DestX = BltInfo->DestRect.left;
404 SourceX = BltInfo->SourcePoint.x;
405 DestBits = (PULONG)(
406 (PBYTE)BltInfo->DestSurface->pvScan0 +
407 (BltInfo->DestRect.left >> 3) +
408 DestY * BltInfo->DestSurface->lDelta);
409
410 if (DestX & 31)
411 {
412 #if 0
413 /* FIXME: This case is completely untested!!! */
414
415 Dest = *((PBYTE)DestBits);
416 NoBits = 31 - (DestX & 31);
417
418 if (UsesSource)
419 {
420 Source = 0;
421 /* FIXME: This is incorrect! */
422 for (Index = 31 - NoBits; Index >= 0; Index++)
423 Source |= (DIB_GetSource(SourceSurf, SourceX + Index, SourceY, ColorTranslation) << (31 - Index));
424 }
425
426 if (BltInfo->PatternSurface)
427 {
428 Pattern = 0;
429 for (k = 31 - NoBits; k >= 0; k++)
430 Pattern |= (DIB_GetSourceIndex(PatternObj, (X + BrushOrigin.x + k) % PatternWidth, PatternY) << (31 - k));
431 }
432
433 Dest = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern);
434 Dest &= ~((1 << (31 - NoBits)) - 1);
435 Dest |= *((PBYTE)DestBits) & ((1 << (31 - NoBits)) - 1);
436
437 *DestBits = Dest;
438
439 DestX += NoBits;
440 SourceX += NoBits;
441 #endif
442 }
443
444 for (; DestX < RoundedRight; DestX += 32, DestBits++, SourceX += 32)
445 {
446 Dest = *DestBits;
447
448 if (UsesSource)
449 {
450 Source = 0;
451 for (Index = 0; Index < 8; Index++)
452 {
453 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index, SourceY, BltInfo->XlateSourceToDest) << (7 - Index);
454 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 8, SourceY, BltInfo->XlateSourceToDest) << (8 + (7 - Index));
455 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 16, SourceY, BltInfo->XlateSourceToDest) << (16 + (7 - Index));
456 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 24, SourceY, BltInfo->XlateSourceToDest) << (24 + (7 - Index));
457 }
458 }
459
460 if (BltInfo->PatternSurface)
461 {
462 Pattern = 0;
463 for (Index = 0; Index < 8; Index++)
464 {
465 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (7 - Index);
466 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 8) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (8 + (7 - Index));
467 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 16) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (16 + (7 - Index));
468 Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 24) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY) << (24 + (7 - Index));
469 }
470 }
471
472 *DestBits = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern);
473 }
474
475 if (DestX < BltInfo->DestRect.right)
476 {
477 for (; DestX < BltInfo->DestRect.right; DestX++, SourceX++)
478 {
479 Dest = DIB_1BPP_GetPixel(BltInfo->DestSurface, DestX, DestY);
480
481 if (UsesSource)
482 {
483 Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);
484 }
485
486 if (BltInfo->PatternSurface)
487 {
488 Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
489 }
490
491 DIB_1BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
492 }
493 }
494
495 SourceY++;
496 if (BltInfo->PatternSurface)
497 {
498 PatternY++;
499 PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;
500 }
501 }
502
503 return TRUE;
504 }
505
506 /* BitBlt Optimize */
507 BOOLEAN
DIB_1BPP_ColorFill(SURFOBJ * DestSurface,RECTL * DestRect,ULONG color)508 DIB_1BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
509 {
510 LONG DestY;
511
512 /* Make WellOrdered with top < bottom and left < right */
513 RECTL_vMakeWellOrdered(DestRect);
514
515 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
516 {
517 DIB_1BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
518 }
519 return TRUE;
520 }
521 #endif // !_USE_DIBLIB_
522
523 BOOLEAN
DIB_1BPP_TransparentBlt(SURFOBJ * DestSurf,SURFOBJ * SourceSurf,RECTL * DestRect,RECTL * SourceRect,XLATEOBJ * ColorTranslation,ULONG iTransColor)524 DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
525 RECTL* DestRect, RECTL *SourceRect,
526 XLATEOBJ *ColorTranslation, ULONG iTransColor)
527 {
528 return FALSE;
529 }
530
531 /* EOF */
532