1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: GDI Driver Brush Functions 5 * FILE: win32ss/gdi/eng/engbrush.c 6 * PROGRAMER: Jason Filby 7 * Timo Kreuzer 8 */ 9 10 #include <win32k.h> 11 12 DBG_DEFAULT_CHANNEL(EngBrush); 13 14 static const ULONG gaulHatchBrushes[HS_DDI_MAX][8] = 15 { 16 {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, /* HS_HORIZONTAL */ 17 {0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7}, /* HS_VERTICAL */ 18 {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}, /* HS_FDIAGONAL */ 19 {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE}, /* HS_BDIAGONAL */ 20 {0xF7, 0xF7, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0xF7}, /* HS_CROSS */ 21 {0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E} /* HS_DIAGCROSS */ 22 }; 23 24 HSURF gahsurfHatch[HS_DDI_MAX]; 25 26 /** Internal functions ********************************************************/ 27 28 INIT_FUNCTION 29 NTSTATUS 30 NTAPI 31 InitBrushImpl(VOID) 32 { 33 ULONG i; 34 SIZEL sizl = {8, 8}; 35 36 /* Loop all hatch styles */ 37 for (i = 0; i < HS_DDI_MAX; i++) 38 { 39 /* Create a default hatch bitmap */ 40 gahsurfHatch[i] = (HSURF)EngCreateBitmap(sizl, 41 0, 42 BMF_1BPP, 43 0, 44 (PVOID)gaulHatchBrushes[i]); 45 } 46 47 return STATUS_SUCCESS; 48 } 49 50 VOID 51 NTAPI 52 EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, 53 PBRUSH pbrush, 54 PSURFACE psurf, 55 COLORREF crBackgroundClr, 56 COLORREF crForegroundClr, 57 PPALETTE ppalDC) 58 { 59 ASSERT(pebo); 60 ASSERT(pbrush); 61 62 pebo->BrushObject.flColorType = 0; 63 pebo->BrushObject.pvRbrush = NULL; 64 pebo->pbrush = pbrush; 65 pebo->pengbrush = NULL; 66 pebo->flattrs = pbrush->flAttrs; 67 pebo->psoMask = NULL; 68 69 /* Initialize 1 bpp fore and back colors */ 70 pebo->crCurrentBack = crBackgroundClr; 71 pebo->crCurrentText = crForegroundClr; 72 73 pebo->psurfTrg = psurf; 74 /* We are initializing for a new memory DC */ 75 if(!pebo->psurfTrg) 76 pebo->psurfTrg = psurfDefaultBitmap; 77 ASSERT(pebo->psurfTrg); 78 ASSERT(pebo->psurfTrg->ppal); 79 80 /* Initialize palettes */ 81 pebo->ppalSurf = pebo->psurfTrg->ppal; 82 GDIOBJ_vReferenceObjectByPointer(&pebo->ppalSurf->BaseObject); 83 pebo->ppalDC = ppalDC; 84 if(!pebo->ppalDC) 85 pebo->ppalDC = gppalDefault; 86 GDIOBJ_vReferenceObjectByPointer(&pebo->ppalDC->BaseObject); 87 pebo->ppalDIB = NULL; 88 89 if (pbrush->flAttrs & BR_IS_NULL) 90 { 91 /* NULL brushes don't need a color */ 92 pebo->BrushObject.iSolidColor = 0; 93 } 94 else if (pbrush->flAttrs & BR_IS_SOLID) 95 { 96 /* Set the RGB color */ 97 EBRUSHOBJ_vSetSolidRGBColor(pebo, pbrush->BrushAttr.lbColor); 98 } 99 else 100 { 101 /* This is a pattern brush that needs realization */ 102 pebo->BrushObject.iSolidColor = 0xFFFFFFFF; 103 104 /* Use foreground color of hatch brushes */ 105 if (pbrush->flAttrs & BR_IS_HATCH) 106 pebo->crCurrentText = pbrush->BrushAttr.lbColor; 107 } 108 } 109 110 VOID 111 NTAPI 112 EBRUSHOBJ_vInitFromDC(EBRUSHOBJ *pebo, 113 PBRUSH pbrush, PDC pdc) 114 { 115 EBRUSHOBJ_vInit(pebo, pbrush, pdc->dclevel.pSurface, 116 pdc->pdcattr->crBackgroundClr, pdc->pdcattr->crForegroundClr, 117 pdc->dclevel.ppal); 118 } 119 120 VOID 121 FASTCALL 122 EBRUSHOBJ_vSetSolidRGBColor(EBRUSHOBJ *pebo, COLORREF crColor) 123 { 124 ULONG iSolidColor; 125 EXLATEOBJ exlo; 126 127 /* Never use with non-solid brushes */ 128 ASSERT(pebo->flattrs & BR_IS_SOLID); 129 130 /* Set the RGB color */ 131 crColor &= 0xFFFFFF; 132 pebo->crRealize = crColor; 133 pebo->ulRGBColor = crColor; 134 135 /* Initialize an XLATEOBJ RGB -> surface */ 136 EXLATEOBJ_vInitialize(&exlo, 137 &gpalRGB, 138 pebo->ppalSurf, 139 pebo->crCurrentBack, 140 0, 141 0); 142 143 /* Translate the brush color to the target format */ 144 iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor); 145 pebo->BrushObject.iSolidColor = iSolidColor; 146 147 /* Clean up the XLATEOBJ */ 148 EXLATEOBJ_vCleanup(&exlo); 149 } 150 151 VOID 152 NTAPI 153 EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo) 154 { 155 /* Check if there's a GDI realisation */ 156 if (pebo->pengbrush) 157 { 158 /* Unlock the bitmap again */ 159 SURFACE_ShareUnlockSurface(pebo->pengbrush); 160 pebo->pengbrush = NULL; 161 } 162 163 /* Check if there's a driver's realisation */ 164 if (pebo->BrushObject.pvRbrush) 165 { 166 /* Free allocated driver memory */ 167 EngFreeMem(pebo->BrushObject.pvRbrush); 168 pebo->BrushObject.pvRbrush = NULL; 169 } 170 171 if (pebo->psoMask != NULL) 172 { 173 SURFACE_ShareUnlockSurface(pebo->psoMask); 174 pebo->psoMask = NULL; 175 } 176 177 /* Dereference the palettes */ 178 if (pebo->ppalSurf) 179 { 180 PALETTE_ShareUnlockPalette(pebo->ppalSurf); 181 } 182 if (pebo->ppalDC) 183 { 184 PALETTE_ShareUnlockPalette(pebo->ppalDC); 185 } 186 if (pebo->ppalDIB) 187 { 188 PALETTE_ShareUnlockPalette(pebo->ppalDIB); 189 } 190 } 191 192 VOID 193 NTAPI 194 EBRUSHOBJ_vUpdateFromDC( 195 EBRUSHOBJ *pebo, 196 PBRUSH pbrush, 197 PDC pdc) 198 { 199 /* Cleanup the brush */ 200 EBRUSHOBJ_vCleanup(pebo); 201 202 /* Reinitialize */ 203 EBRUSHOBJ_vInitFromDC(pebo, pbrush, pdc); 204 } 205 206 /** 207 * This function is not exported, because it makes no sense for 208 * The driver to punt back to this function */ 209 BOOL 210 APIENTRY 211 EngRealizeBrush( 212 BRUSHOBJ *pbo, 213 SURFOBJ *psoDst, 214 SURFOBJ *psoPattern, 215 SURFOBJ *psoMask, 216 XLATEOBJ *pxlo, 217 ULONG iHatch) 218 { 219 EBRUSHOBJ *pebo; 220 HBITMAP hbmpRealize; 221 SURFOBJ *psoRealize; 222 PSURFACE psurfRealize; 223 POINTL ptlSrc = {0, 0}; 224 RECTL rclDest; 225 ULONG lWidth; 226 227 /* Calculate width in bytes of the realized brush */ 228 lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx, 229 BitsPerFormat(psoDst->iBitmapFormat)); 230 231 /* Allocate a bitmap */ 232 hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap, 233 lWidth, 234 psoDst->iBitmapFormat, 235 BMF_NOZEROINIT, 236 NULL); 237 if (!hbmpRealize) 238 { 239 return FALSE; 240 } 241 242 /* Lock the bitmap */ 243 psurfRealize = SURFACE_ShareLockSurface(hbmpRealize); 244 245 /* Already delete the pattern bitmap (will be kept until dereferenced) */ 246 EngDeleteSurface((HSURF)hbmpRealize); 247 248 if (!psurfRealize) 249 { 250 return FALSE; 251 } 252 253 /* Copy the bits to the new format bitmap */ 254 rclDest.left = rclDest.top = 0; 255 rclDest.right = psoPattern->sizlBitmap.cx; 256 rclDest.bottom = psoPattern->sizlBitmap.cy; 257 psoRealize = &psurfRealize->SurfObj; 258 EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc); 259 260 261 pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject); 262 pebo->pengbrush = (PVOID)psurfRealize; 263 264 return TRUE; 265 } 266 267 static 268 PPALETTE 269 FixupDIBBrushPalette( 270 _In_ PPALETTE ppalDIB, 271 _In_ PPALETTE ppalDC) 272 { 273 PPALETTE ppalNew; 274 ULONG i, iPalIndex, crColor; 275 276 /* Allocate a new palette */ 277 ppalNew = PALETTE_AllocPalette(PAL_INDEXED, 278 ppalDIB->NumColors, 279 NULL, 280 0, 281 0, 282 0); 283 if (ppalNew == NULL) 284 { 285 ERR("Failed to allcate palette for brush\n"); 286 return NULL; 287 } 288 289 /* Loop all colors */ 290 for (i = 0; i < ppalDIB->NumColors; i++) 291 { 292 /* Get the RGB color, which is the index into the DC palette */ 293 iPalIndex = PALETTE_ulGetRGBColorFromIndex(ppalDIB, i); 294 295 /* Roll over when index is too big */ 296 iPalIndex %= ppalDC->NumColors; 297 298 /* Set the indexed DC color as the new color */ 299 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, iPalIndex); 300 PALETTE_vSetRGBColorForIndex(ppalNew, i, crColor); 301 } 302 303 /* Return the new palette */ 304 return ppalNew; 305 } 306 307 BOOL 308 NTAPI 309 EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo, BOOL bCallDriver) 310 { 311 BOOL bResult; 312 PFN_DrvRealizeBrush pfnRealizeBrush = NULL; 313 PSURFACE psurfPattern; 314 SURFOBJ *psoMask; 315 PPDEVOBJ ppdev; 316 EXLATEOBJ exlo; 317 PPALETTE ppalPattern; 318 PBRUSH pbr = pebo->pbrush; 319 HBITMAP hbmPattern; 320 ULONG iHatch; 321 322 /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */ 323 ASSERT(pebo->psurfTrg); 324 325 ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev; 326 if (!ppdev) 327 ppdev = gppdevPrimary; 328 329 if (bCallDriver) 330 { 331 /* Get the Drv function */ 332 pfnRealizeBrush = ppdev->DriverFunctions.RealizeBrush; 333 if (pfnRealizeBrush == NULL) 334 { 335 ERR("No DrvRealizeBrush. Cannot realize brush\n"); 336 return FALSE; 337 } 338 339 /* Get the mask */ 340 psoMask = EBRUSHOBJ_psoMask(pebo); 341 } 342 else 343 { 344 /* Use the Eng function */ 345 pfnRealizeBrush = EngRealizeBrush; 346 347 /* We don't handle the mask bitmap here. We do this only on demand */ 348 psoMask = NULL; 349 } 350 351 /* Check if this is a hatch brush */ 352 if (pbr->flAttrs & BR_IS_HATCH) 353 { 354 /* Get the hatch brush pattern from the PDEV */ 355 hbmPattern = (HBITMAP)ppdev->ahsurf[pbr->iHatch]; 356 iHatch = pbr->iHatch; 357 } 358 else 359 { 360 /* Use the brushes pattern */ 361 hbmPattern = pbr->hbmPattern; 362 iHatch = -1; 363 } 364 365 psurfPattern = SURFACE_ShareLockSurface(hbmPattern); 366 ASSERT(psurfPattern); 367 ASSERT(psurfPattern->ppal); 368 369 /* DIB brushes with DIB_PAL_COLORS usage need a new palette */ 370 if (pbr->flAttrs & BR_IS_DIBPALCOLORS) 371 { 372 /* Create a palette with the colors from the DC */ 373 ppalPattern = FixupDIBBrushPalette(psurfPattern->ppal, pebo->ppalDC); 374 if (ppalPattern == NULL) 375 { 376 ERR("FixupDIBBrushPalette() failed.\n"); 377 return FALSE; 378 } 379 380 pebo->ppalDIB = ppalPattern; 381 } 382 else 383 { 384 /* The palette is already as it should be */ 385 ppalPattern = psurfPattern->ppal; 386 } 387 388 /* Initialize XLATEOBJ for the brush */ 389 EXLATEOBJ_vInitialize(&exlo, 390 ppalPattern, 391 pebo->psurfTrg->ppal, 392 0, 393 pebo->crCurrentBack, 394 pebo->crCurrentText); 395 396 /* Create the realization */ 397 bResult = pfnRealizeBrush(&pebo->BrushObject, 398 &pebo->psurfTrg->SurfObj, 399 &psurfPattern->SurfObj, 400 psoMask, 401 &exlo.xlo, 402 iHatch); 403 404 /* Cleanup the XLATEOBJ */ 405 EXLATEOBJ_vCleanup(&exlo); 406 407 /* Unlock surface */ 408 SURFACE_ShareUnlockSurface(psurfPattern); 409 410 return bResult; 411 } 412 413 PVOID 414 NTAPI 415 EBRUSHOBJ_pvGetEngBrush(EBRUSHOBJ *pebo) 416 { 417 BOOL bResult; 418 419 if (!pebo->pengbrush) 420 { 421 bResult = EBRUSHOBJ_bRealizeBrush(pebo, FALSE); 422 if (!bResult) 423 { 424 if (pebo->pengbrush) 425 EngDeleteSurface(pebo->pengbrush); 426 pebo->pengbrush = NULL; 427 } 428 } 429 430 return pebo->pengbrush; 431 } 432 433 SURFOBJ* 434 NTAPI 435 EBRUSHOBJ_psoPattern(EBRUSHOBJ *pebo) 436 { 437 PSURFACE psurfPattern; 438 439 psurfPattern = EBRUSHOBJ_pvGetEngBrush(pebo); 440 441 return psurfPattern ? &psurfPattern->SurfObj : NULL; 442 } 443 444 SURFOBJ* 445 NTAPI 446 EBRUSHOBJ_psoMask(EBRUSHOBJ *pebo) 447 { 448 HBITMAP hbmMask; 449 PSURFACE psurfMask; 450 PPDEVOBJ ppdev; 451 452 /* Check if we don't have a mask yet */ 453 if (pebo->psoMask == NULL) 454 { 455 /* Check if this is a hatch brush */ 456 if (pebo->flattrs & BR_IS_HATCH) 457 { 458 /* Get the PDEV */ 459 ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev; 460 if (!ppdev) 461 ppdev = gppdevPrimary; 462 463 /* Use the hatch bitmap as the mask */ 464 hbmMask = (HBITMAP)ppdev->ahsurf[pebo->pbrush->iHatch]; 465 psurfMask = SURFACE_ShareLockSurface(hbmMask); 466 if (psurfMask == NULL) 467 { 468 ERR("Failed to lock hatch brush for PDEV %p, iHatch %lu\n", 469 ppdev, pebo->pbrush->iHatch); 470 return NULL; 471 } 472 473 NT_ASSERT(psurfMask->SurfObj.iBitmapFormat == BMF_1BPP); 474 pebo->psoMask = &psurfMask->SurfObj; 475 } 476 } 477 478 return pebo->psoMask; 479 } 480 481 /** Exported DDI functions ****************************************************/ 482 483 /* 484 * @implemented 485 */ 486 PVOID APIENTRY 487 BRUSHOBJ_pvAllocRbrush( 488 IN BRUSHOBJ *pbo, 489 IN ULONG cj) 490 { 491 pbo->pvRbrush = EngAllocMem(0, cj, GDITAG_RBRUSH); 492 return pbo->pvRbrush; 493 } 494 495 /* 496 * @implemented 497 */ 498 PVOID APIENTRY 499 BRUSHOBJ_pvGetRbrush( 500 IN BRUSHOBJ *pbo) 501 { 502 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject); 503 BOOL bResult; 504 505 if (!pbo->pvRbrush) 506 { 507 bResult = EBRUSHOBJ_bRealizeBrush(pebo, TRUE); 508 if (!bResult) 509 { 510 if (pbo->pvRbrush) 511 { 512 EngFreeMem(pbo->pvRbrush); 513 pbo->pvRbrush = NULL; 514 } 515 } 516 } 517 518 return pbo->pvRbrush; 519 } 520 521 /* 522 * @implemented 523 */ 524 ULONG APIENTRY 525 BRUSHOBJ_ulGetBrushColor( 526 IN BRUSHOBJ *pbo) 527 { 528 EBRUSHOBJ *pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject); 529 return pebo->ulRGBColor; 530 } 531 532 /* EOF */ 533