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 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 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 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 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 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 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 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 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 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