Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendibobj.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS win32 kernel mode subsystem 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: subsystems/win32/win32k/objects/dibobj.c 00005 * PURPOSE: Dib object functions 00006 * PROGRAMMER: 00007 */ 00008 00009 #include <win32k.h> 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 static const RGBQUAD EGAColorsQuads[16] = 00015 { 00016 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */ 00017 { 0x00, 0x00, 0x00, 0x00 }, 00018 { 0x00, 0x00, 0x80, 0x00 }, 00019 { 0x00, 0x80, 0x00, 0x00 }, 00020 { 0x00, 0x80, 0x80, 0x00 }, 00021 { 0x80, 0x00, 0x00, 0x00 }, 00022 { 0x80, 0x00, 0x80, 0x00 }, 00023 { 0x80, 0x80, 0x00, 0x00 }, 00024 { 0x80, 0x80, 0x80, 0x00 }, 00025 { 0xc0, 0xc0, 0xc0, 0x00 }, 00026 { 0x00, 0x00, 0xff, 0x00 }, 00027 { 0x00, 0xff, 0x00, 0x00 }, 00028 { 0x00, 0xff, 0xff, 0x00 }, 00029 { 0xff, 0x00, 0x00, 0x00 }, 00030 { 0xff, 0x00, 0xff, 0x00 }, 00031 { 0xff, 0xff, 0x00, 0x00 }, 00032 { 0xff, 0xff, 0xff, 0x00 } 00033 }; 00034 00035 static const RGBTRIPLE EGAColorsTriples[16] = 00036 { 00037 /* rgbBlue, rgbGreen, rgbRed */ 00038 { 0x00, 0x00, 0x00 }, 00039 { 0x00, 0x00, 0x80 }, 00040 { 0x00, 0x80, 0x00 }, 00041 { 0x00, 0x80, 0x80 }, 00042 { 0x80, 0x00, 0x00 }, 00043 { 0x80, 0x00, 0x80 }, 00044 { 0x80, 0x80, 0x00 }, 00045 { 0x80, 0x80, 0x80 }, 00046 { 0xc0, 0xc0, 0xc0 }, 00047 { 0x00, 0x00, 0xff }, 00048 { 0x00, 0xff, 0x00 }, 00049 { 0x00, 0xff, 0xff }, 00050 { 0xff, 0x00, 0x00 }, 00051 { 0xff, 0x00, 0xff }, 00052 { 0xff, 0xff, 0x00 }, 00053 { 0xff, 0xff, 0xff } 00054 }; 00055 00056 static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */ 00057 { 00058 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */ 00059 { 0x00, 0x00, 0x00, 0x00 }, 00060 { 0x00, 0x00, 0x80, 0x00 }, 00061 { 0x00, 0x80, 0x00, 0x00 }, 00062 { 0x00, 0x80, 0x80, 0x00 }, 00063 { 0x80, 0x00, 0x00, 0x00 }, 00064 { 0x80, 0x00, 0x80, 0x00 }, 00065 { 0x80, 0x80, 0x00, 0x00 }, 00066 { 0xc0, 0xc0, 0xc0, 0x00 }, 00067 { 0xc0, 0xdc, 0xc0, 0x00 }, 00068 { 0xf0, 0xca, 0xa6, 0x00 }, 00069 { 0xf0, 0xfb, 0xff, 0x00 }, 00070 { 0xa4, 0xa0, 0xa0, 0x00 }, 00071 { 0x80, 0x80, 0x80, 0x00 }, 00072 { 0x00, 0x00, 0xf0, 0x00 }, 00073 { 0x00, 0xff, 0x00, 0x00 }, 00074 { 0x00, 0xff, 0xff, 0x00 }, 00075 { 0xff, 0x00, 0x00, 0x00 }, 00076 { 0xff, 0x00, 0xff, 0x00 }, 00077 { 0xff, 0xff, 0x00, 0x00 }, 00078 { 0xff, 0xff, 0xff, 0x00 } 00079 }; 00080 00081 static const RGBQUAD DefLogPaletteTriples[20] = /* Copy of Default Logical Palette */ 00082 { 00083 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */ 00084 { 0x00, 0x00, 0x00 }, 00085 { 0x00, 0x00, 0x80 }, 00086 { 0x00, 0x80, 0x00 }, 00087 { 0x00, 0x80, 0x80 }, 00088 { 0x80, 0x00, 0x00 }, 00089 { 0x80, 0x00, 0x80 }, 00090 { 0x80, 0x80, 0x00 }, 00091 { 0xc0, 0xc0, 0xc0 }, 00092 { 0xc0, 0xdc, 0xc0 }, 00093 { 0xf0, 0xca, 0xa6 }, 00094 { 0xf0, 0xfb, 0xff }, 00095 { 0xa4, 0xa0, 0xa0 }, 00096 { 0x80, 0x80, 0x80 }, 00097 { 0x00, 0x00, 0xf0 }, 00098 { 0x00, 0xff, 0x00 }, 00099 { 0x00, 0xff, 0xff }, 00100 { 0xff, 0x00, 0x00 }, 00101 { 0xff, 0x00, 0xff }, 00102 { 0xff, 0xff, 0x00 }, 00103 { 0xff, 0xff, 0xff } 00104 }; 00105 00106 PPALETTE 00107 NTAPI 00108 CreateDIBPalette( 00109 _In_ const BITMAPINFO *pbmi, 00110 _In_ PDC pdc, 00111 _In_ ULONG iUsage) 00112 { 00113 PPALETTE ppal; 00114 ULONG i, cBitsPixel, cColors; 00115 00116 if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) 00117 { 00118 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi; 00119 cBitsPixel = pbci->bmciHeader.bcBitCount; 00120 } 00121 else 00122 { 00123 cBitsPixel = pbmi->bmiHeader.biBitCount; 00124 } 00125 00126 /* Check if the colors are indexed */ 00127 if (cBitsPixel <= 8) 00128 { 00129 /* We create a "full" palette */ 00130 cColors = 1 << cBitsPixel; 00131 00132 /* Allocate the palette */ 00133 ppal = PALETTE_AllocPalette(PAL_INDEXED, 00134 cColors, 00135 NULL, 00136 0, 00137 0, 00138 0); 00139 00140 /* Check if the BITMAPINFO specifies how many colors to use */ 00141 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && 00142 (pbmi->bmiHeader.biClrUsed != 0)) 00143 { 00144 /* This is how many colors we can actually process */ 00145 cColors = min(cColors, pbmi->bmiHeader.biClrUsed); 00146 } 00147 00148 /* Check how to use the colors */ 00149 if (iUsage == DIB_PAL_COLORS) 00150 { 00151 COLORREF crColor; 00152 00153 /* The colors are an array of WORD indices into the DC palette */ 00154 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize); 00155 00156 /* Use the DCs palette or, if no DC is given, the default one */ 00157 PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault; 00158 00159 /* Loop all color indices in the DIB */ 00160 for (i = 0; i < cColors; i++) 00161 { 00162 /* Get the palette index and handle wraparound when exceeding 00163 the number of colors in the DC palette */ 00164 WORD wIndex = pwColors[i] % ppalDC->NumColors; 00165 00166 /* USe the RGB value from the DC palette */ 00167 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex); 00168 PALETTE_vSetRGBColorForIndex(ppal, i, crColor); 00169 } 00170 } 00171 else if (iUsage == DIB_PAL_BRUSHHACK) 00172 { 00173 /* The colors are an array of WORD indices into the DC palette */ 00174 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize); 00175 00176 /* Loop all color indices in the DIB */ 00177 for (i = 0; i < cColors; i++) 00178 { 00179 /* Set the index directly as the RGB color, the real palette 00180 containing RGB values will be calculated when the brush is 00181 realized */ 00182 PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]); 00183 } 00184 00185 /* Mark the palette as a brush hack palette */ 00186 ppal->flFlags |= PAL_BRUSHHACK; 00187 } 00188 // else if (iUsage == 2) 00189 // { 00190 // FIXME: this one is undocumented 00191 // ASSERT(FALSE); 00192 // } 00193 else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) 00194 { 00195 /* The colors are an array of RGBQUAD values */ 00196 RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize); 00197 00198 // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro? 00199 00200 /* Loop all color indices in the DIB */ 00201 for (i = 0; i < cColors; i++) 00202 { 00203 /* Get the color value and translate it to a COLORREF */ 00204 RGBQUAD rgb = prgb[i]; 00205 COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue); 00206 00207 /* Set the RGB value in the palette */ 00208 PALETTE_vSetRGBColorForIndex(ppal, i, crColor); 00209 } 00210 } 00211 else 00212 { 00213 /* The colors are an array of RGBTRIPLE values */ 00214 RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize); 00215 00216 /* Loop all color indices in the DIB */ 00217 for (i = 0; i < cColors; i++) 00218 { 00219 /* Get the color value and translate it to a COLORREF */ 00220 RGBTRIPLE rgb = prgb[i]; 00221 COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue); 00222 00223 /* Set the RGB value in the palette */ 00224 PALETTE_vSetRGBColorForIndex(ppal, i, crColor); 00225 } 00226 } 00227 } 00228 else 00229 { 00230 /* This is a bitfield / RGB palette */ 00231 ULONG flRedMask, flGreenMask, flBlueMask; 00232 00233 /* Check if the DIB contains bitfield values */ 00234 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && 00235 (pbmi->bmiHeader.biCompression == BI_BITFIELDS)) 00236 { 00237 /* Check if we have a v4/v5 header */ 00238 if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER)) 00239 { 00240 /* The masks are dedicated fields in the header */ 00241 PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader; 00242 flRedMask = pbmV4Header->bV4RedMask; 00243 flGreenMask = pbmV4Header->bV4GreenMask; 00244 flBlueMask = pbmV4Header->bV4BlueMask; 00245 } 00246 else 00247 { 00248 /* The masks are the first 3 values in the DIB color table */ 00249 PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize); 00250 flRedMask = pdwColors[0]; 00251 flGreenMask = pdwColors[1]; 00252 flBlueMask = pdwColors[2]; 00253 } 00254 } 00255 else 00256 { 00257 /* Check what bit depth we have. Note: optimization flags are 00258 calculated in PALETTE_AllocPalette() */ 00259 if (cBitsPixel == 16) 00260 { 00261 /* This is an RGB 555 palette */ 00262 flRedMask = 0x7C00; 00263 flGreenMask = 0x03E0; 00264 flBlueMask = 0x001F; 00265 } 00266 else 00267 { 00268 /* This is an RGB 888 palette */ 00269 flRedMask = 0xFF0000; 00270 flGreenMask = 0x00FF00; 00271 flBlueMask = 0x0000FF; 00272 } 00273 } 00274 00275 /* Allocate the bitfield palette */ 00276 ppal = PALETTE_AllocPalette(PAL_BITFIELDS, 00277 0, 00278 NULL, 00279 flRedMask, 00280 flGreenMask, 00281 flBlueMask); 00282 } 00283 00284 /* We're done, return the palette */ 00285 return ppal; 00286 } 00287 00288 // Converts a DIB to a device-dependent bitmap 00289 static INT 00290 FASTCALL 00291 IntSetDIBits( 00292 PDC DC, 00293 HBITMAP hBitmap, 00294 UINT StartScan, 00295 UINT ScanLines, 00296 CONST VOID *Bits, 00297 CONST BITMAPINFO *bmi, 00298 UINT ColorUse) 00299 { 00300 HBITMAP SourceBitmap; 00301 PSURFACE psurfDst, psurfSrc; 00302 INT result = 0; 00303 RECT rcDst; 00304 POINTL ptSrc; 00305 EXLATEOBJ exlo; 00306 PPALETTE ppalDIB = 0; 00307 00308 if (!bmi) return 0; 00309 00310 SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth, 00311 ScanLines, 00312 0, 00313 BitmapFormat(bmi->bmiHeader.biBitCount, 00314 bmi->bmiHeader.biCompression), 00315 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0, 00316 bmi->bmiHeader.biSizeImage, 00317 (PVOID)Bits, 00318 0); 00319 if (!SourceBitmap) 00320 { 00321 DPRINT1("Error: Could not create a bitmap.\n"); 00322 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES); 00323 return 0; 00324 } 00325 00326 psurfDst = SURFACE_ShareLockSurface(hBitmap); 00327 psurfSrc = SURFACE_ShareLockSurface(SourceBitmap); 00328 00329 if(!(psurfSrc && psurfDst)) 00330 { 00331 DPRINT1("Error: Could not lock surfaces\n"); 00332 goto cleanup; 00333 } 00334 00335 /* Create a palette for the DIB */ 00336 ppalDIB = CreateDIBPalette(bmi, DC, ColorUse); 00337 if (!ppalDIB) 00338 { 00339 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES); 00340 goto cleanup; 00341 } 00342 00343 /* Initialize EXLATEOBJ */ 00344 EXLATEOBJ_vInitialize(&exlo, 00345 ppalDIB, 00346 psurfDst->ppal, 00347 RGB(0xff, 0xff, 0xff), 00348 RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr, 00349 0); // DC->pdcattr->crForegroundClr); 00350 00351 rcDst.top = StartScan; 00352 rcDst.left = 0; 00353 rcDst.bottom = rcDst.top + ScanLines; 00354 rcDst.right = psurfDst->SurfObj.sizlBitmap.cx; 00355 ptSrc.x = 0; 00356 ptSrc.y = 0; 00357 00358 result = IntEngCopyBits(&psurfDst->SurfObj, 00359 &psurfSrc->SurfObj, 00360 NULL, 00361 &exlo.xlo, 00362 &rcDst, 00363 &ptSrc); 00364 if(result) 00365 result = ScanLines; 00366 00367 EXLATEOBJ_vCleanup(&exlo); 00368 00369 cleanup: 00370 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB); 00371 if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc); 00372 if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst); 00373 GreDeleteObject(SourceBitmap); 00374 00375 return result; 00376 } 00377 00378 W32KAPI 00379 INT 00380 APIENTRY 00381 NtGdiSetDIBitsToDeviceInternal( 00382 IN HDC hDC, 00383 IN INT XDest, 00384 IN INT YDest, 00385 IN DWORD Width, 00386 IN DWORD Height, 00387 IN INT XSrc, 00388 IN INT YSrc, 00389 IN DWORD StartScan, 00390 IN DWORD ScanLines, 00391 IN LPBYTE Bits, 00392 IN LPBITMAPINFO bmi, 00393 IN DWORD ColorUse, 00394 IN UINT cjMaxBits, 00395 IN UINT cjMaxInfo, 00396 IN BOOL bTransformCoordinates, 00397 IN OPTIONAL HANDLE hcmXform) 00398 { 00399 INT ret = 0; 00400 NTSTATUS Status = STATUS_SUCCESS; 00401 PDC pDC; 00402 HBITMAP hSourceBitmap = NULL; 00403 SURFOBJ *pDestSurf, *pSourceSurf = NULL; 00404 SURFACE *pSurf; 00405 RECTL rcDest; 00406 POINTL ptSource; 00407 //INT DIBWidth; 00408 SIZEL SourceSize; 00409 EXLATEOBJ exlo; 00410 PPALETTE ppalDIB = NULL; 00411 LPBITMAPINFO pbmiSafe; 00412 00413 if (!Bits) return 0; 00414 00415 pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG'); 00416 if (!pbmiSafe) return 0; 00417 00418 _SEH2_TRY 00419 { 00420 ProbeForRead(bmi, cjMaxInfo, 1); 00421 ProbeForRead(Bits, cjMaxBits, 1); 00422 RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo); 00423 bmi = pbmiSafe; 00424 } 00425 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00426 { 00427 Status = _SEH2_GetExceptionCode(); 00428 } 00429 _SEH2_END 00430 00431 if (!NT_SUCCESS(Status)) 00432 { 00433 goto Exit2; 00434 } 00435 00436 pDC = DC_LockDc(hDC); 00437 if (!pDC) 00438 { 00439 EngSetLastError(ERROR_INVALID_HANDLE); 00440 goto Exit2; 00441 } 00442 if (pDC->dctype == DC_TYPE_INFO) 00443 { 00444 DC_UnlockDc(pDC); 00445 goto Exit2; 00446 } 00447 00448 pSurf = pDC->dclevel.pSurface; 00449 00450 pDestSurf = pSurf ? &pSurf->SurfObj : NULL; 00451 00452 ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan); 00453 00454 rcDest.left = XDest; 00455 rcDest.top = YDest; 00456 if (bTransformCoordinates) 00457 { 00458 IntLPtoDP(pDC, (LPPOINT)&rcDest, 2); 00459 } 00460 rcDest.left += pDC->ptlDCOrig.x; 00461 rcDest.top += pDC->ptlDCOrig.y; 00462 rcDest.right = rcDest.left + Width; 00463 rcDest.bottom = rcDest.top + Height; 00464 rcDest.top += StartScan; 00465 00466 ptSource.x = XSrc; 00467 ptSource.y = YSrc; 00468 00469 SourceSize.cx = bmi->bmiHeader.biWidth; 00470 SourceSize.cy = ScanLines; 00471 00472 //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount); 00473 00474 hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth, 00475 ScanLines, 00476 0, 00477 BitmapFormat(bmi->bmiHeader.biBitCount, 00478 bmi->bmiHeader.biCompression), 00479 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0, 00480 bmi->bmiHeader.biSizeImage, 00481 Bits, 00482 0); 00483 00484 if (!hSourceBitmap) 00485 { 00486 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES); 00487 Status = STATUS_NO_MEMORY; 00488 goto Exit; 00489 } 00490 00491 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap); 00492 if (!pSourceSurf) 00493 { 00494 Status = STATUS_UNSUCCESSFUL; 00495 goto Exit; 00496 } 00497 00498 ASSERT(pSurf->ppal); 00499 00500 /* Create a palette for the DIB */ 00501 ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse); 00502 if (!ppalDIB) 00503 { 00504 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES); 00505 Status = STATUS_NO_MEMORY; 00506 goto Exit; 00507 } 00508 00509 /* Initialize EXLATEOBJ */ 00510 EXLATEOBJ_vInitialize(&exlo, 00511 ppalDIB, 00512 pSurf->ppal, 00513 RGB(0xff, 0xff, 0xff), 00514 pDC->pdcattr->crBackgroundClr, 00515 pDC->pdcattr->crForegroundClr); 00516 00517 /* Copy the bits */ 00518 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n", 00519 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, 00520 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy); 00521 Status = IntEngBitBlt(pDestSurf, 00522 pSourceSurf, 00523 NULL, 00524 pDC->rosdc.CombinedClip, 00525 &exlo.xlo, 00526 &rcDest, 00527 &ptSource, 00528 NULL, 00529 NULL, 00530 NULL, 00531 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); 00532 00533 /* Cleanup EXLATEOBJ */ 00534 EXLATEOBJ_vCleanup(&exlo); 00535 00536 Exit: 00537 if (NT_SUCCESS(Status)) 00538 { 00539 ret = ScanLines; 00540 } 00541 00542 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB); 00543 00544 if (pSourceSurf) EngUnlockSurface(pSourceSurf); 00545 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap); 00546 DC_UnlockDc(pDC); 00547 Exit2: 00548 ExFreePool(pbmiSafe); 00549 return ret; 00550 } 00551 00552 00553 /* Converts a device-dependent bitmap to a DIB */ 00554 INT 00555 APIENTRY 00556 NtGdiGetDIBitsInternal( 00557 HDC hDC, 00558 HBITMAP hBitmap, 00559 UINT StartScan, 00560 UINT ScanLines, 00561 LPBYTE Bits, 00562 LPBITMAPINFO Info, 00563 UINT Usage, 00564 UINT MaxBits, 00565 UINT MaxInfo) 00566 { 00567 BITMAPCOREINFO* pbmci = NULL; 00568 PSURFACE psurf = NULL; 00569 PDC pDC; 00570 LONG width, height; 00571 WORD planes, bpp; 00572 DWORD compr, size ; 00573 USHORT i; 00574 int bitmap_type; 00575 RGBTRIPLE* rgbTriples; 00576 RGBQUAD* rgbQuads; 00577 VOID* colorPtr; 00578 NTSTATUS Status = STATUS_SUCCESS; 00579 00580 DPRINT("Entered NtGdiGetDIBitsInternal()\n"); 00581 00582 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap) 00583 return 0; 00584 00585 _SEH2_TRY 00586 { 00587 /* Probe for read and write */ 00588 ProbeForRead(Info, MaxInfo, 1); 00589 ProbeForWrite(Info, MaxInfo, 1); 00590 if (Bits) ProbeForWrite(Bits, MaxBits, 1); 00591 } 00592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00593 { 00594 Status = _SEH2_GetExceptionCode(); 00595 } 00596 _SEH2_END 00597 00598 if (!NT_SUCCESS(Status)) 00599 { 00600 return 0; 00601 } 00602 00603 colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize; 00604 rgbTriples = colorPtr; 00605 rgbQuads = colorPtr; 00606 00607 bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader, 00608 &width, 00609 &height, 00610 &planes, 00611 &bpp, 00612 &compr, 00613 &size); 00614 if(bitmap_type == -1) 00615 { 00616 DPRINT("Wrong bitmap format\n"); 00617 EngSetLastError(ERROR_INVALID_PARAMETER); 00618 return 0; 00619 } 00620 else if(bitmap_type == 0) 00621 { 00622 /* We need a BITMAPINFO to create a DIB, but we have to fill 00623 * the BITMAPCOREINFO we're provided */ 00624 pbmci = (BITMAPCOREINFO*)Info; 00625 Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage); 00626 if(Info == NULL) 00627 { 00628 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n"); 00629 return 0; 00630 } 00631 rgbQuads = Info->bmiColors; 00632 } 00633 00634 pDC = DC_LockDc(hDC); 00635 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO) 00636 { 00637 ScanLines = 0; 00638 goto done; 00639 } 00640 00641 /* Get a pointer to the source bitmap object */ 00642 psurf = SURFACE_ShareLockSurface(hBitmap); 00643 if (psurf == NULL) 00644 { 00645 ScanLines = 0; 00646 goto done; 00647 } 00648 00649 /* Fill in the structure */ 00650 switch(bpp) 00651 { 00652 case 0: /* Only info */ 00653 if(pbmci) 00654 { 00655 pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx; 00656 pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ? 00657 -psurf->SurfObj.sizlBitmap.cy : 00658 psurf->SurfObj.sizlBitmap.cy); 00659 pbmci->bmciHeader.bcPlanes = 1; 00660 pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 00661 } 00662 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx; 00663 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ? 00664 -psurf->SurfObj.sizlBitmap.cy : 00665 psurf->SurfObj.sizlBitmap.cy;; 00666 Info->bmiHeader.biPlanes = 1; 00667 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 00668 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth, 00669 Info->bmiHeader.biHeight, 00670 Info->bmiHeader.biBitCount); 00671 if(psurf->hSecure) 00672 { 00673 switch(Info->bmiHeader.biBitCount) 00674 { 00675 case 16: 00676 case 32: 00677 Info->bmiHeader.biCompression = BI_BITFIELDS; 00678 break; 00679 default: 00680 Info->bmiHeader.biCompression = BI_RGB; 00681 break; 00682 } 00683 } 00684 else if(Info->bmiHeader.biBitCount > 8) 00685 { 00686 Info->bmiHeader.biCompression = BI_BITFIELDS; 00687 } 00688 else 00689 { 00690 Info->bmiHeader.biCompression = BI_RGB; 00691 } 00692 Info->bmiHeader.biXPelsPerMeter = 0; 00693 Info->bmiHeader.biYPelsPerMeter = 0; 00694 Info->bmiHeader.biClrUsed = 0; 00695 Info->bmiHeader.biClrImportant = 0; 00696 ScanLines = abs(Info->bmiHeader.biHeight); 00697 goto done; 00698 00699 case 1: 00700 case 4: 00701 case 8: 00702 Info->bmiHeader.biClrUsed = 0; 00703 00704 /* If the bitmap if a DIB section and has the same format than what 00705 * we're asked, go ahead! */ 00706 if((psurf->hSecure) && 00707 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp)) 00708 { 00709 if(Usage == DIB_RGB_COLORS) 00710 { 00711 ULONG colors = min(psurf->ppal->NumColors, 256); 00712 00713 if(pbmci) 00714 { 00715 for(i = 0; i < colors; i++) 00716 { 00717 rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed; 00718 rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen; 00719 rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue; 00720 } 00721 } 00722 if(colors != 256) Info->bmiHeader.biClrUsed = colors; 00723 for(i = 0; i < colors; i++) 00724 { 00725 rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed; 00726 rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen; 00727 rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue; 00728 } 00729 } 00730 else 00731 { 00732 for(i = 0; i < 256; i++) 00733 { 00734 if(pbmci) ((WORD*)rgbTriples)[i] = i; 00735 ((WORD*)rgbQuads)[i] = i; 00736 } 00737 } 00738 } 00739 else 00740 { 00741 if(Usage == DIB_PAL_COLORS) 00742 { 00743 for(i = 0; i < 256; i++) 00744 { 00745 if(pbmci) ((WORD*)rgbTriples)[i] = i; 00746 ((WORD*)rgbQuads)[i] = i; 00747 } 00748 } 00749 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat)) 00750 { 00751 /* For color DDBs in native depth (mono DDBs always have 00752 a black/white palette): 00753 Generate the color map from the selected palette */ 00754 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal); 00755 if(!pDcPal) 00756 { 00757 ScanLines = 0 ; 00758 goto done ; 00759 } 00760 for (i = 0; i < pDcPal->NumColors; i++) 00761 { 00762 if (pbmci) 00763 { 00764 rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed; 00765 rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen; 00766 rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue; 00767 } 00768 00769 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed; 00770 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen; 00771 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue; 00772 rgbQuads[i].rgbReserved = 0; 00773 } 00774 PALETTE_ShareUnlockPalette(pDcPal); 00775 } 00776 else 00777 { 00778 switch (bpp) 00779 { 00780 case 1: 00781 if (pbmci) 00782 { 00783 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen = 00784 rgbTriples[0].rgbtBlue = 0; 00785 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen = 00786 rgbTriples[1].rgbtBlue = 0xff; 00787 } 00788 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = 00789 rgbQuads[0].rgbBlue = 0; 00790 rgbQuads[0].rgbReserved = 0; 00791 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = 00792 rgbQuads[1].rgbBlue = 0xff; 00793 rgbQuads[1].rgbReserved = 0; 00794 break; 00795 00796 case 4: 00797 if (pbmci) 00798 RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples)); 00799 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads)); 00800 00801 break; 00802 00803 case 8: 00804 { 00805 INT r, g, b; 00806 RGBQUAD *color; 00807 if (pbmci) 00808 { 00809 RGBTRIPLE *colorTriple; 00810 00811 RtlCopyMemory(rgbTriples, DefLogPaletteTriples, 00812 10 * sizeof(RGBTRIPLE)); 00813 RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10, 00814 10 * sizeof(RGBTRIPLE)); 00815 colorTriple = rgbTriples + 10; 00816 for(r = 0; r <= 5; r++) /* FIXME */ 00817 { 00818 for(g = 0; g <= 5; g++) 00819 { 00820 for(b = 0; b <= 5; b++) 00821 { 00822 colorTriple->rgbtRed = (r * 0xff) / 5; 00823 colorTriple->rgbtGreen = (g * 0xff) / 5; 00824 colorTriple->rgbtBlue = (b * 0xff) / 5; 00825 color++; 00826 } 00827 } 00828 } 00829 } 00830 memcpy(rgbQuads, DefLogPaletteQuads, 00831 10 * sizeof(RGBQUAD)); 00832 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10, 00833 10 * sizeof(RGBQUAD)); 00834 color = rgbQuads + 10; 00835 for(r = 0; r <= 5; r++) /* FIXME */ 00836 { 00837 for(g = 0; g <= 5; g++) 00838 { 00839 for(b = 0; b <= 5; b++) 00840 { 00841 color->rgbRed = (r * 0xff) / 5; 00842 color->rgbGreen = (g * 0xff) / 5; 00843 color->rgbBlue = (b * 0xff) / 5; 00844 color->rgbReserved = 0; 00845 color++; 00846 } 00847 } 00848 } 00849 } 00850 } 00851 } 00852 } 00853 break; 00854 00855 case 15: 00856 if (Info->bmiHeader.biCompression == BI_BITFIELDS) 00857 { 00858 ((PDWORD)Info->bmiColors)[0] = 0x7c00; 00859 ((PDWORD)Info->bmiColors)[1] = 0x03e0; 00860 ((PDWORD)Info->bmiColors)[2] = 0x001f; 00861 } 00862 break; 00863 00864 case 16: 00865 if (Info->bmiHeader.biCompression == BI_BITFIELDS) 00866 { 00867 if (psurf->hSecure) 00868 { 00869 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask; 00870 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask; 00871 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask; 00872 } 00873 else 00874 { 00875 ((PDWORD)Info->bmiColors)[0] = 0xf800; 00876 ((PDWORD)Info->bmiColors)[1] = 0x07e0; 00877 ((PDWORD)Info->bmiColors)[2] = 0x001f; 00878 } 00879 } 00880 break; 00881 00882 case 24: 00883 case 32: 00884 if (Info->bmiHeader.biCompression == BI_BITFIELDS) 00885 { 00886 if (psurf->hSecure) 00887 { 00888 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask; 00889 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask; 00890 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask; 00891 } 00892 else 00893 { 00894 ((PDWORD)Info->bmiColors)[0] = 0xff0000; 00895 ((PDWORD)Info->bmiColors)[1] = 0x00ff00; 00896 ((PDWORD)Info->bmiColors)[2] = 0x0000ff; 00897 } 00898 } 00899 break; 00900 } 00901 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp); 00902 00903 if(Bits && ScanLines) 00904 { 00905 /* Create a DIBSECTION, blt it, profit */ 00906 PVOID pDIBits ; 00907 HBITMAP hBmpDest; 00908 PSURFACE psurfDest; 00909 EXLATEOBJ exlo; 00910 RECT rcDest; 00911 POINTL srcPoint; 00912 BOOL ret ; 00913 00914 if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy) 00915 { 00916 ScanLines = 0; 00917 goto done; 00918 } 00919 else 00920 { 00921 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan); 00922 } 00923 00924 /* Fixup values */ 00925 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx; 00926 Info->bmiHeader.biHeight = (height < 0) ? 00927 -(LONG)ScanLines : ScanLines; 00928 /* Create the DIB */ 00929 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0); 00930 /* Restore them */ 00931 Info->bmiHeader.biWidth = width; 00932 Info->bmiHeader.biHeight = height; 00933 00934 if(!hBmpDest) 00935 { 00936 DPRINT1("Unable to create a DIB Section!\n"); 00937 EngSetLastError(ERROR_INVALID_PARAMETER); 00938 ScanLines = 0; 00939 goto done ; 00940 } 00941 00942 psurfDest = SURFACE_ShareLockSurface(hBmpDest); 00943 00944 rcDest.left = 0; 00945 rcDest.top = 0; 00946 rcDest.bottom = ScanLines; 00947 rcDest.right = psurf->SurfObj.sizlBitmap.cx; 00948 00949 srcPoint.x = 0; 00950 00951 if(height < 0) 00952 { 00953 srcPoint.y = 0; 00954 00955 if(ScanLines <= StartScan) 00956 { 00957 ScanLines = 1; 00958 SURFACE_ShareUnlockSurface(psurfDest); 00959 GreDeleteObject(hBmpDest); 00960 goto done; 00961 } 00962 00963 ScanLines -= StartScan; 00964 } 00965 else 00966 { 00967 srcPoint.y = StartScan; 00968 } 00969 00970 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0); 00971 00972 ret = IntEngCopyBits(&psurfDest->SurfObj, 00973 &psurf->SurfObj, 00974 NULL, 00975 &exlo.xlo, 00976 &rcDest, 00977 &srcPoint); 00978 00979 SURFACE_ShareUnlockSurface(psurfDest); 00980 00981 if(!ret) 00982 ScanLines = 0; 00983 else 00984 { 00985 Status = STATUS_SUCCESS; 00986 _SEH2_TRY 00987 { 00988 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp)); 00989 } 00990 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00991 { 00992 Status = _SEH2_GetExceptionCode(); 00993 } 00994 _SEH2_END 00995 00996 if(!NT_SUCCESS(Status)) 00997 { 00998 DPRINT1("Unable to copy bits to the user provided pointer\n"); 00999 ScanLines = 0; 01000 } 01001 } 01002 01003 GreDeleteObject(hBmpDest); 01004 EXLATEOBJ_vCleanup(&exlo); 01005 } 01006 else ScanLines = abs(height); 01007 01008 done: 01009 01010 if(pDC) DC_UnlockDc(pDC); 01011 if(psurf) SURFACE_ShareUnlockSurface(psurf); 01012 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci); 01013 01014 return ScanLines; 01015 } 01016 01017 #define ROP_TO_ROP4(Rop) ((Rop) >> 16) 01018 01019 W32KAPI 01020 INT 01021 APIENTRY 01022 NtGdiStretchDIBitsInternal( 01023 IN HDC hdc, 01024 IN INT xDst, 01025 IN INT yDst, 01026 IN INT cxDst, 01027 IN INT cyDst, 01028 IN INT xSrc, 01029 IN INT ySrc, 01030 IN INT cxSrc, 01031 IN INT cySrc, 01032 IN OPTIONAL LPBYTE pjInit, 01033 IN LPBITMAPINFO pbmi, 01034 IN DWORD dwUsage, 01035 IN DWORD dwRop, // MS ntgdi.h says dwRop4(?) 01036 IN UINT cjMaxInfo, 01037 IN UINT cjMaxBits, 01038 IN HANDLE hcmXform) 01039 { 01040 BOOL bResult = FALSE; 01041 SIZEL sizel; 01042 RECTL rcSrc, rcDst; 01043 PDC pdc; 01044 HBITMAP hbmTmp = 0; 01045 PSURFACE psurfTmp = 0, psurfDst = 0; 01046 PPALETTE ppalDIB = 0; 01047 EXLATEOBJ exlo; 01048 PVOID pvBits; 01049 01050 if (!(pdc = DC_LockDc(hdc))) 01051 { 01052 EngSetLastError(ERROR_INVALID_HANDLE); 01053 return 0; 01054 } 01055 01056 /* Transform dest size */ 01057 sizel.cx = cxDst; 01058 sizel.cy = cyDst; 01059 IntLPtoDP(pdc, (POINTL*)&sizel, 1); 01060 DC_UnlockDc(pdc); 01061 01062 /* Check if we can use NtGdiSetDIBitsToDeviceInternal */ 01063 if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY) 01064 { 01065 /* Yes, we can! */ 01066 return NtGdiSetDIBitsToDeviceInternal(hdc, 01067 xDst, 01068 yDst, 01069 cxDst, 01070 cyDst, 01071 xSrc, 01072 ySrc, 01073 0, 01074 cySrc, 01075 pjInit, 01076 pbmi, 01077 dwUsage, 01078 cjMaxBits, 01079 cjMaxInfo, 01080 TRUE, 01081 hcmXform); 01082 } 01083 01084 pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT'); 01085 if (!pvBits) 01086 { 01087 return 0; 01088 } 01089 01090 _SEH2_TRY 01091 { 01092 ProbeForRead(pjInit, cjMaxBits, 1); 01093 RtlCopyMemory(pvBits, pjInit, cjMaxBits); 01094 } 01095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01096 { 01097 _SEH2_YIELD(return 0); 01098 } 01099 _SEH2_END 01100 01101 /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */ 01102 if (!(pdc = DC_LockDc(hdc))) 01103 { 01104 DPRINT1("Could not lock dc\n"); 01105 EngSetLastError(ERROR_INVALID_HANDLE); 01106 goto cleanup; 01107 } 01108 01109 psurfDst = pdc->dclevel.pSurface; 01110 if (!psurfDst) 01111 { 01112 // CHECKME 01113 bResult = TRUE; 01114 goto cleanup; 01115 } 01116 01117 /* Calculate source and destination rect */ 01118 rcSrc.left = xSrc; 01119 rcSrc.top = ySrc; 01120 rcSrc.right = xSrc + abs(cxSrc); 01121 rcSrc.bottom = ySrc + abs(cySrc); 01122 rcDst.left = xDst; 01123 rcDst.top = yDst; 01124 rcDst.right = rcDst.left + cxDst; 01125 rcDst.bottom = rcDst.top + cyDst; 01126 IntLPtoDP(pdc, (POINTL*)&rcDst, 2); 01127 RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); 01128 01129 hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth, 01130 pbmi->bmiHeader.biHeight, 01131 0, 01132 BitmapFormat(pbmi->bmiHeader.biBitCount, 01133 pbmi->bmiHeader.biCompression), 01134 pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0, 01135 pbmi->bmiHeader.biSizeImage, 01136 pvBits, 01137 0); 01138 01139 if (!hbmTmp) 01140 { 01141 bResult = FALSE; 01142 goto cleanup; 01143 } 01144 01145 psurfTmp = SURFACE_ShareLockSurface(hbmTmp); 01146 if (!psurfTmp) 01147 { 01148 bResult = FALSE; 01149 goto cleanup; 01150 } 01151 01152 /* Create a palette for the DIB */ 01153 ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage); 01154 if (!ppalDIB) 01155 { 01156 bResult = FALSE; 01157 goto cleanup; 01158 } 01159 01160 /* Initialize XLATEOBJ */ 01161 EXLATEOBJ_vInitialize(&exlo, 01162 ppalDIB, 01163 psurfDst->ppal, 01164 RGB(0xff, 0xff, 0xff), 01165 pdc->pdcattr->crBackgroundClr, 01166 pdc->pdcattr->crForegroundClr); 01167 01168 /* Prepare DC for blit */ 01169 DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc); 01170 01171 /* Perform the stretch operation */ 01172 bResult = IntEngStretchBlt(&psurfDst->SurfObj, 01173 &psurfTmp->SurfObj, 01174 NULL, 01175 pdc->rosdc.CombinedClip, 01176 &exlo.xlo, 01177 &rcDst, 01178 &rcSrc, 01179 NULL, 01180 &pdc->eboFill.BrushObject, 01181 NULL, 01182 ROP_TO_ROP4(dwRop)); 01183 01184 /* Cleanup */ 01185 DC_vFinishBlit(pdc, NULL); 01186 EXLATEOBJ_vCleanup(&exlo); 01187 cleanup: 01188 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB); 01189 if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp); 01190 if (hbmTmp) GreDeleteObject(hbmTmp); 01191 if (pdc) DC_UnlockDc(pdc); 01192 ExFreePoolWithTag(pvBits, 'pmeT'); 01193 01194 return bResult; 01195 } 01196 01197 01198 HBITMAP 01199 FASTCALL 01200 IntCreateDIBitmap( 01201 PDC Dc, 01202 INT width, 01203 INT height, 01204 UINT bpp, 01205 DWORD init, 01206 LPBYTE bits, 01207 PBITMAPINFO data, 01208 DWORD coloruse) 01209 { 01210 HBITMAP handle; 01211 BOOL fColor; 01212 01213 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2 01214 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap. 01215 01216 if (bpp != 1) fColor = TRUE; 01217 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE; 01218 else 01219 { 01220 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize); 01221 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); 01222 01223 // Check if the first color of the colormap is black 01224 if ((col == RGB(0, 0, 0))) 01225 { 01226 rgb++; 01227 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue); 01228 01229 // If the second color is white, create a monochrome bitmap 01230 fColor = (col != RGB(0xff,0xff,0xff)); 01231 } 01232 else fColor = TRUE; 01233 } 01234 01235 // Now create the bitmap 01236 if (fColor) 01237 { 01238 handle = IntCreateCompatibleBitmap(Dc, width, height); 01239 } 01240 else 01241 { 01242 handle = GreCreateBitmap(width, 01243 height, 01244 1, 01245 1, 01246 NULL); 01247 } 01248 01249 if (height < 0) 01250 height = -height; 01251 01252 if (NULL != handle && CBM_INIT == init) 01253 { 01254 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse); 01255 } 01256 01257 return handle; 01258 } 01259 01260 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits 01261 // The DDB that is created will be whatever bit depth your reference DC is 01262 HBITMAP 01263 APIENTRY 01264 NtGdiCreateDIBitmapInternal( 01265 IN HDC hDc, 01266 IN INT cx, 01267 IN INT cy, 01268 IN DWORD fInit, 01269 IN OPTIONAL LPBYTE pjInit, 01270 IN OPTIONAL LPBITMAPINFO pbmi, 01271 IN DWORD iUsage, 01272 IN UINT cjMaxInitInfo, 01273 IN UINT cjMaxBits, 01274 IN FLONG fl, 01275 IN HANDLE hcmXform) 01276 { 01277 NTSTATUS Status = STATUS_SUCCESS; 01278 PBYTE safeBits = NULL; 01279 HBITMAP hbmResult = NULL; 01280 01281 if(pjInit && (fInit == CBM_INIT)) 01282 { 01283 if (cjMaxBits == 0) return NULL; 01284 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB); 01285 if(!safeBits) 01286 { 01287 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 01288 return NULL; 01289 } 01290 } 01291 01292 _SEH2_TRY 01293 { 01294 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1); 01295 if(pjInit && (fInit == CBM_INIT)) 01296 { 01297 ProbeForRead(pjInit, cjMaxBits, 1); 01298 RtlCopyMemory(safeBits, pjInit, cjMaxBits); 01299 } 01300 } 01301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01302 { 01303 Status = _SEH2_GetExceptionCode(); 01304 } 01305 _SEH2_END 01306 01307 if(!NT_SUCCESS(Status)) 01308 { 01309 SetLastNtError(Status); 01310 goto cleanup; 01311 } 01312 01313 hbmResult = GreCreateDIBitmapInternal(hDc, 01314 cx, 01315 cy, 01316 fInit, 01317 safeBits, 01318 pbmi, 01319 iUsage, 01320 fl, 01321 cjMaxBits, 01322 hcmXform); 01323 01324 cleanup: 01325 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB); 01326 return hbmResult; 01327 } 01328 01329 HBITMAP 01330 NTAPI 01331 GreCreateDIBitmapInternal( 01332 IN HDC hDc, 01333 IN INT cx, 01334 IN INT cy, 01335 IN DWORD fInit, 01336 IN OPTIONAL LPBYTE pjInit, 01337 IN OPTIONAL PBITMAPINFO pbmi, 01338 IN DWORD iUsage, 01339 IN FLONG fl, 01340 IN UINT cjMaxBits, 01341 IN HANDLE hcmXform) 01342 { 01343 PDC Dc; 01344 HBITMAP Bmp; 01345 WORD bpp; 01346 HDC hdcDest; 01347 01348 if (!hDc) /* 1bpp monochrome bitmap */ 01349 { 01350 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this. 01351 hdcDest = NtGdiCreateCompatibleDC(0); 01352 if(!hdcDest) 01353 { 01354 return NULL; 01355 } 01356 } 01357 else 01358 { 01359 hdcDest = hDc; 01360 } 01361 01362 Dc = DC_LockDc(hdcDest); 01363 if (!Dc) 01364 { 01365 EngSetLastError(ERROR_INVALID_HANDLE); 01366 return NULL; 01367 } 01368 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap 01369 * if bpp != 1 and ignore the real value that was passed */ 01370 if (pbmi) 01371 bpp = pbmi->bmiHeader.biBitCount; 01372 else 01373 bpp = 0; 01374 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage); 01375 DC_UnlockDc(Dc); 01376 01377 if(!hDc) 01378 { 01379 NtGdiDeleteObjectApp(hdcDest); 01380 } 01381 return Bmp; 01382 } 01383 01384 01385 HBITMAP 01386 APIENTRY 01387 NtGdiCreateDIBSection( 01388 IN HDC hDC, 01389 IN OPTIONAL HANDLE hSection, 01390 IN DWORD dwOffset, 01391 IN BITMAPINFO* bmi, 01392 IN DWORD Usage, 01393 IN UINT cjHeader, 01394 IN FLONG fl, 01395 IN ULONG_PTR dwColorSpace, 01396 OUT PVOID *Bits) 01397 { 01398 HBITMAP hbitmap = 0; 01399 DC *dc; 01400 BOOL bDesktopDC = FALSE; 01401 NTSTATUS Status = STATUS_SUCCESS; 01402 01403 if (!bmi) return hbitmap; // Make sure. 01404 01405 _SEH2_TRY 01406 { 01407 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1); 01408 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1); 01409 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1); 01410 } 01411 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01412 { 01413 Status = _SEH2_GetExceptionCode(); 01414 } 01415 _SEH2_END 01416 01417 if(!NT_SUCCESS(Status)) 01418 { 01419 SetLastNtError(Status); 01420 return NULL; 01421 } 01422 01423 // If the reference hdc is null, take the desktop dc 01424 if (hDC == 0) 01425 { 01426 hDC = NtGdiCreateCompatibleDC(0); 01427 bDesktopDC = TRUE; 01428 } 01429 01430 if ((dc = DC_LockDc(hDC))) 01431 { 01432 hbitmap = DIB_CreateDIBSection(dc, 01433 bmi, 01434 Usage, 01435 Bits, 01436 hSection, 01437 dwOffset, 01438 0); 01439 DC_UnlockDc(dc); 01440 } 01441 else 01442 { 01443 EngSetLastError(ERROR_INVALID_HANDLE); 01444 } 01445 01446 if (bDesktopDC) 01447 NtGdiDeleteObjectApp(hDC); 01448 01449 return hbitmap; 01450 } 01451 01452 HBITMAP 01453 APIENTRY 01454 DIB_CreateDIBSection( 01455 PDC dc, 01456 CONST BITMAPINFO *bmi, 01457 UINT usage, 01458 LPVOID *bits, 01459 HANDLE section, 01460 DWORD offset, 01461 DWORD ovr_pitch) 01462 { 01463 HBITMAP res = 0; 01464 SURFACE *bmp = NULL; 01465 void *mapBits = NULL; 01466 PPALETTE ppalDIB; 01467 01468 // Fill BITMAP32 structure with DIB data 01469 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader; 01470 INT effHeight; 01471 ULONG totalSize; 01472 BITMAP bm; 01473 //SIZEL Size; 01474 HANDLE hSecure; 01475 01476 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n", 01477 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount, 01478 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB"); 01479 01480 /* CreateDIBSection should fail for compressed formats */ 01481 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8) 01482 { 01483 DPRINT1("no compressed format allowed\n"); 01484 return (HBITMAP)NULL; 01485 } 01486 01487 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight; 01488 bm.bmType = 0; 01489 bm.bmWidth = bi->biWidth; 01490 bm.bmHeight = effHeight; 01491 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount); 01492 01493 bm.bmPlanes = bi->biPlanes; 01494 bm.bmBitsPixel = bi->biBitCount; 01495 bm.bmBits = NULL; 01496 01497 // Get storage location for DIB bits. Only use biSizeImage if it's valid and 01498 // we're dealing with a compressed bitmap. Otherwise, use width * height. 01499 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS 01500 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight); 01501 01502 if (section) 01503 { 01504 SYSTEM_BASIC_INFORMATION Sbi; 01505 NTSTATUS Status; 01506 DWORD mapOffset; 01507 LARGE_INTEGER SectionOffset; 01508 SIZE_T mapSize; 01509 01510 Status = ZwQuerySystemInformation(SystemBasicInformation, 01511 &Sbi, 01512 sizeof Sbi, 01513 0); 01514 if (!NT_SUCCESS(Status)) 01515 { 01516 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status); 01517 return NULL; 01518 } 01519 01520 mapOffset = offset - (offset % Sbi.AllocationGranularity); 01521 mapSize = bi->biSizeImage + (offset - mapOffset); 01522 01523 SectionOffset.LowPart = mapOffset; 01524 SectionOffset.HighPart = 0; 01525 01526 Status = ZwMapViewOfSection(section, 01527 NtCurrentProcess(), 01528 &mapBits, 01529 0, 01530 0, 01531 &SectionOffset, 01532 &mapSize, 01533 ViewShare, 01534 0, 01535 PAGE_READWRITE); 01536 if (!NT_SUCCESS(Status)) 01537 { 01538 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status); 01539 EngSetLastError(ERROR_INVALID_PARAMETER); 01540 return NULL; 01541 } 01542 01543 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset); 01544 } 01545 else if (ovr_pitch && offset) 01546 bm.bmBits = (LPVOID) offset; 01547 else 01548 { 01549 offset = 0; 01550 bm.bmBits = EngAllocUserMem(totalSize, 0); 01551 if(!bm.bmBits) 01552 { 01553 DPRINT1("Failed to allocate memory\n"); 01554 goto cleanup; 01555 } 01556 } 01557 01558 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE); 01559 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!! 01560 01561 01562 // Create Device Dependent Bitmap and add DIB pointer 01563 //Size.cx = bm.bmWidth; 01564 //Size.cy = abs(bm.bmHeight); 01565 res = GreCreateBitmapEx(bm.bmWidth, 01566 abs(bm.bmHeight), 01567 bm.bmWidthBytes, 01568 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression), 01569 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT | 01570 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0), 01571 bi->biSizeImage, 01572 bm.bmBits, 01573 0); 01574 if (!res) 01575 { 01576 DPRINT1("GreCreateBitmapEx failed\n"); 01577 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES); 01578 goto cleanup; 01579 } 01580 bmp = SURFACE_ShareLockSurface(res); // HACK 01581 if (NULL == bmp) 01582 { 01583 DPRINT1("SURFACE_LockSurface failed\n"); 01584 EngSetLastError(ERROR_INVALID_HANDLE); 01585 goto cleanup; 01586 } 01587 01588 /* WINE NOTE: WINE makes use of a colormap, which is a color translation 01589 table between the DIB and the X physical device. Obviously, 01590 this is left out of the ReactOS implementation. Instead, 01591 we call NtGdiSetDIBColorTable. */ 01592 bmp->hDIBSection = section; 01593 bmp->hSecure = hSecure; 01594 bmp->dwOffset = offset; 01595 bmp->flags = API_BITMAP; 01596 bmp->biClrImportant = bi->biClrImportant; 01597 01598 /* Create a palette for the DIB */ 01599 ppalDIB = CreateDIBPalette(bmi, dc, usage); 01600 if (ppalDIB) 01601 { 01602 if (bmp->ppal) PALETTE_ShareUnlockPalette(bmp->ppal); 01603 bmp->ppal = ppalDIB; 01604 } 01605 01606 // Clean up in case of errors 01607 cleanup: 01608 if (!res || !bmp || !bm.bmBits) 01609 { 01610 DPRINT("Got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits); 01611 if (bm.bmBits) 01612 { 01613 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this! 01614 if (section) 01615 { 01616 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits); 01617 bm.bmBits = NULL; 01618 } 01619 else if (!offset) 01620 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL; 01621 } 01622 01623 if (bmp) 01624 bmp = NULL; 01625 01626 if (res) 01627 { 01628 GreDeleteObject(res); 01629 res = 0; 01630 } 01631 } 01632 01633 if (bmp) 01634 { 01635 SURFACE_ShareUnlockSurface(bmp); 01636 } 01637 01638 // Return BITMAP handle and storage location 01639 if (NULL != bm.bmBits && NULL != bits) 01640 { 01641 *bits = bm.bmBits; 01642 } 01643 01644 return res; 01645 } 01646 01647 /*********************************************************************** 01648 * DIB_GetBitmapInfo 01649 * 01650 * Get the info from a bitmap header. 01651 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error. 01652 */ 01653 int 01654 FASTCALL 01655 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width, 01656 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size ) 01657 { 01658 if (header->biSize == sizeof(BITMAPCOREHEADER)) 01659 { 01660 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header; 01661 *width = core->bcWidth; 01662 *height = core->bcHeight; 01663 *planes = core->bcPlanes; 01664 *bpp = core->bcBitCount; 01665 *compr = BI_RGB; 01666 *size = 0; 01667 return 0; 01668 } 01669 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */ 01670 { 01671 *width = header->biWidth; 01672 *height = header->biHeight; 01673 *planes = header->biPlanes; 01674 *bpp = header->biBitCount; 01675 *compr = header->biCompression; 01676 *size = header->biSizeImage; 01677 return 1; 01678 } 01679 DPRINT1("(%d): unknown/wrong size for header\n", header->biSize ); 01680 return -1; 01681 } 01682 01683 /*********************************************************************** 01684 * DIB_GetDIBImageBytes 01685 * 01686 * Return the number of bytes used to hold the image in a DIB bitmap. 01687 * 11/16/1999 (RJJ) lifted from wine 01688 */ 01689 01690 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth) 01691 { 01692 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height); 01693 } 01694 01695 /*********************************************************************** 01696 * DIB_BitmapInfoSize 01697 * 01698 * Return the size of the bitmap info structure including color table. 01699 * 11/16/1999 (RJJ) lifted from wine 01700 */ 01701 01702 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse) 01703 { 01704 unsigned int colors, size, masks = 0; 01705 01706 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) 01707 { 01708 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info; 01709 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0; 01710 return sizeof(BITMAPCOREHEADER) + colors * 01711 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD)); 01712 } 01713 else /* Assume BITMAPINFOHEADER */ 01714 { 01715 colors = info->bmiHeader.biClrUsed; 01716 if (colors > 256) colors = 256; 01717 if (!colors && (info->bmiHeader.biBitCount <= 8)) 01718 colors = 1 << info->bmiHeader.biBitCount; 01719 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3; 01720 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ); 01721 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); 01722 } 01723 } 01724 01725 HPALETTE 01726 FASTCALL 01727 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi) 01728 { 01729 PPALETTE ppalNew; 01730 ULONG nNumColors,i; 01731 USHORT *lpIndex; 01732 HPALETTE hpal; 01733 01734 if (!(ppalDc->flFlags & PAL_INDEXED)) 01735 { 01736 return NULL; 01737 } 01738 01739 nNumColors = 1 << lpbmi->bmiHeader.biBitCount; 01740 if (lpbmi->bmiHeader.biClrUsed) 01741 { 01742 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed); 01743 } 01744 01745 ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0); 01746 if (ppalNew == NULL) 01747 { 01748 DPRINT1("Could not allocate palette\n"); 01749 return NULL; 01750 } 01751 01752 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize); 01753 01754 for (i = 0; i < nNumColors; i++) 01755 { 01756 ULONG iColorIndex = *lpIndex % ppalDc->NumColors; 01757 ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex]; 01758 lpIndex++; 01759 } 01760 01761 hpal = ppalNew->BaseObject.hHmgr; 01762 PALETTE_UnlockPalette(ppalNew); 01763 01764 return hpal; 01765 } 01766 01767 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure, 01768 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */ 01769 BITMAPINFO* 01770 FASTCALL 01771 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage) 01772 { 01773 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi; 01774 BITMAPINFO* pNewBmi ; 01775 UINT numColors = 0, ColorsSize = 0; 01776 01777 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi; 01778 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL; 01779 01780 if(pbmci->bmciHeader.bcBitCount <= 8) 01781 { 01782 numColors = 1 << pbmci->bmciHeader.bcBitCount; 01783 if(Usage == DIB_PAL_COLORS) 01784 { 01785 ColorsSize = numColors * sizeof(WORD); 01786 } 01787 else 01788 { 01789 ColorsSize = numColors * sizeof(RGBQUAD); 01790 } 01791 } 01792 else if (Usage == DIB_PAL_COLORS) 01793 { 01794 /* Invalid at high-res */ 01795 return NULL; 01796 } 01797 01798 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB); 01799 if(!pNewBmi) return NULL; 01800 01801 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize); 01802 01803 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 01804 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount; 01805 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth; 01806 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight; 01807 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes; 01808 pNewBmi->bmiHeader.biCompression = BI_RGB ; 01809 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth, 01810 pNewBmi->bmiHeader.biHeight, 01811 pNewBmi->bmiHeader.biBitCount); 01812 01813 if(Usage == DIB_PAL_COLORS) 01814 { 01815 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize); 01816 } 01817 else 01818 { 01819 UINT i; 01820 for(i=0; i<numColors; i++) 01821 { 01822 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed; 01823 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen; 01824 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue; 01825 } 01826 } 01827 01828 return pNewBmi ; 01829 } 01830 01831 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */ 01832 VOID 01833 FASTCALL 01834 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig) 01835 { 01836 if(converted != orig) 01837 ExFreePoolWithTag(converted, TAG_DIB); 01838 } 01839 01840 /* EOF */ Generated on Sun May 27 2012 04:38:25 for ReactOS by
1.7.6.1
|