modified include/reactos/probe.h
[reactos.git] / reactos / subsystems / win32 / win32k / objects / dibobj.c
1 /*
2 * $Id$
3 *
4 * ReactOS W32 Subsystem
5 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <w32k.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 UINT APIENTRY
28 IntSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
29 {
30 PDC dc;
31 PBITMAPOBJ BitmapObj;
32 PPALGDI PalGDI;
33 UINT Index;
34
35 if (!(dc = DC_LockDc(hDC))) return 0;
36 if (dc->DC_Type == DC_TYPE_INFO)
37 {
38 DC_UnlockDc(dc);
39 return 0;
40 }
41
42 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
43 if (BitmapObj == NULL)
44 {
45 DC_UnlockDc(dc);
46 SetLastWin32Error(ERROR_INVALID_PARAMETER);
47 return 0;
48 }
49
50 if (BitmapObj->dib == NULL)
51 {
52 BITMAPOBJ_UnlockBitmap(BitmapObj);
53 DC_UnlockDc(dc);
54 SetLastWin32Error(ERROR_INVALID_PARAMETER);
55 return 0;
56 }
57
58 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
59 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
60 {
61 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
62 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
63
64 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
65 if (PalGDI == NULL)
66 {
67 BITMAPOBJ_UnlockBitmap(BitmapObj);
68 DC_UnlockDc(dc);
69 SetLastWin32Error(ERROR_INVALID_HANDLE);
70 return 0;
71 }
72
73 for (Index = StartIndex;
74 Index < StartIndex + Entries && Index < PalGDI->NumColors;
75 Index++)
76 {
77 PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
78 PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
79 PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
80 }
81 PALETTE_UnlockPalette(PalGDI);
82 }
83 else
84 Entries = 0;
85
86 BITMAPOBJ_UnlockBitmap(BitmapObj);
87 DC_UnlockDc(dc);
88
89 return Entries;
90 }
91
92 UINT APIENTRY
93 IntGetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, RGBQUAD *Colors)
94 {
95 PDC dc;
96 PBITMAPOBJ BitmapObj;
97 PPALGDI PalGDI;
98 UINT Index;
99
100 if (!(dc = DC_LockDc(hDC))) return 0;
101 if (dc->DC_Type == DC_TYPE_INFO)
102 {
103 DC_UnlockDc(dc);
104 return 0;
105 }
106
107 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
108 if (BitmapObj == NULL)
109 {
110 DC_UnlockDc(dc);
111 SetLastWin32Error(ERROR_INVALID_PARAMETER);
112 return 0;
113 }
114
115 if (BitmapObj->dib == NULL)
116 {
117 BITMAPOBJ_UnlockBitmap(BitmapObj);
118 DC_UnlockDc(dc);
119 SetLastWin32Error(ERROR_INVALID_PARAMETER);
120 return 0;
121 }
122
123 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
124 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
125 {
126 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
127 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
128
129 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
130 if (PalGDI == NULL)
131 {
132 BITMAPOBJ_UnlockBitmap(BitmapObj);
133 DC_UnlockDc(dc);
134 SetLastWin32Error(ERROR_INVALID_HANDLE);
135 return 0;
136 }
137
138 for (Index = StartIndex;
139 Index < StartIndex + Entries && Index < PalGDI->NumColors;
140 Index++)
141 {
142 Colors[Index - StartIndex].rgbRed = PalGDI->IndexedColors[Index].peRed;
143 Colors[Index - StartIndex].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
144 Colors[Index - StartIndex].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
145 Colors[Index - StartIndex].rgbReserved = 0;
146 }
147 PALETTE_UnlockPalette(PalGDI);
148 }
149 else
150 Entries = 0;
151
152 BITMAPOBJ_UnlockBitmap(BitmapObj);
153 DC_UnlockDc(dc);
154
155 return Entries;
156 }
157
158 // Converts a DIB to a device-dependent bitmap
159 static INT FASTCALL
160 IntSetDIBits(
161 PDC DC,
162 HBITMAP hBitmap,
163 UINT StartScan,
164 UINT ScanLines,
165 CONST VOID *Bits,
166 CONST BITMAPINFO *bmi,
167 UINT ColorUse)
168 {
169 BITMAPOBJ *bitmap;
170 HBITMAP SourceBitmap;
171 INT result = 0;
172 BOOL copyBitsResult;
173 SURFOBJ *DestSurf, *SourceSurf;
174 SIZEL SourceSize;
175 POINTL ZeroPoint;
176 RECTL DestRect;
177 XLATEOBJ *XlateObj;
178 PPALGDI hDCPalette;
179 //RGBQUAD *lpRGB;
180 HPALETTE DDB_Palette, DIB_Palette;
181 ULONG DDB_Palette_Type, DIB_Palette_Type;
182 INT DIBWidth;
183
184 // Check parameters
185 if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
186 {
187 return 0;
188 }
189
190 // Get RGB values
191 //if (ColorUse == DIB_PAL_COLORS)
192 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
193 //else
194 // lpRGB = &bmi->bmiColors;
195
196 DestSurf = &bitmap->SurfObj;
197
198 // Create source surface
199 SourceSize.cx = bmi->bmiHeader.biWidth;
200 SourceSize.cy = ScanLines;
201
202 // Determine width of DIB
203 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
204
205 SourceBitmap = EngCreateBitmap(SourceSize,
206 DIBWidth,
207 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
208 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
209 (PVOID) Bits);
210 if (0 == SourceBitmap)
211 {
212 BITMAPOBJ_UnlockBitmap(bitmap);
213 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
214 return 0;
215 }
216
217 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
218 if (NULL == SourceSurf)
219 {
220 EngDeleteSurface((HSURF)SourceBitmap);
221 BITMAPOBJ_UnlockBitmap(bitmap);
222 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
223 return 0;
224 }
225
226 // Destination palette obtained from the hDC
227 hDCPalette = PALETTE_LockPalette(((GDIDEVICE *)DC->pPDev)->DevInfo.hpalDefault);
228 if (NULL == hDCPalette)
229 {
230 EngUnlockSurface(SourceSurf);
231 EngDeleteSurface((HSURF)SourceBitmap);
232 BITMAPOBJ_UnlockBitmap(bitmap);
233 SetLastWin32Error(ERROR_INVALID_HANDLE);
234 return 0;
235 }
236 DDB_Palette_Type = hDCPalette->Mode;
237 DDB_Palette = ((GDIDEVICE *)DC->pPDev)->DevInfo.hpalDefault;
238 PALETTE_UnlockPalette(hDCPalette);
239
240 // Source palette obtained from the BITMAPINFO
241 DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
242 if (NULL == DIB_Palette)
243 {
244 EngUnlockSurface(SourceSurf);
245 EngDeleteSurface((HSURF)SourceBitmap);
246 BITMAPOBJ_UnlockBitmap(bitmap);
247 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
248 return 0;
249 }
250
251 // Determine XLATEOBJ for color translation
252 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
253 if (NULL == XlateObj)
254 {
255 PALETTE_FreePaletteByHandle(DIB_Palette);
256 EngUnlockSurface(SourceSurf);
257 EngDeleteSurface((HSURF)SourceBitmap);
258 BITMAPOBJ_UnlockBitmap(bitmap);
259 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
260 return 0;
261 }
262
263 // Zero point
264 ZeroPoint.x = 0;
265 ZeroPoint.y = 0;
266
267 // Determine destination rectangle
268 DestRect.left = 0;
269 DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
270 DestRect.right = SourceSize.cx;
271 DestRect.bottom = DestRect.top + ScanLines;
272
273 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
274
275 // If it succeeded, return number of scanlines copies
276 if(copyBitsResult == TRUE)
277 {
278 result = SourceSize.cy;
279 // or
280 // result = abs(bmi->bmiHeader.biHeight) - StartScan;
281 }
282
283 // Clean up
284 EngDeleteXlate(XlateObj);
285 PALETTE_FreePaletteByHandle(DIB_Palette);
286 EngUnlockSurface(SourceSurf);
287 EngDeleteSurface((HSURF)SourceBitmap);
288
289 // if (ColorUse == DIB_PAL_COLORS)
290 // WinFree((LPSTR)lpRGB);
291
292 BITMAPOBJ_UnlockBitmap(bitmap);
293
294 return result;
295 }
296
297 // Converts a DIB to a device-dependent bitmap
298 INT APIENTRY
299 NtGdiSetDIBits(
300 HDC hDC,
301 HBITMAP hBitmap,
302 UINT StartScan,
303 UINT ScanLines,
304 CONST VOID *Bits,
305 CONST BITMAPINFO *bmi,
306 UINT ColorUse)
307 {
308 PDC Dc;
309 INT Ret;
310
311 Dc = DC_LockDc(hDC);
312 if (NULL == Dc)
313 {
314 SetLastWin32Error(ERROR_INVALID_HANDLE);
315 return 0;
316 }
317 if (Dc->DC_Type == DC_TYPE_INFO)
318 {
319 DC_UnlockDc(Dc);
320 return 0;
321 }
322 // Need SEH to check Bits and bmi. BTW bmi was converted in gdi.
323 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
324
325 DC_UnlockDc(Dc);
326
327 return Ret;
328 }
329
330
331
332 W32KAPI
333 INT
334 APIENTRY
335 NtGdiSetDIBitsToDeviceInternal(
336 IN HDC hDC,
337 IN INT XDest,
338 IN INT YDest,
339 IN DWORD Width,
340 IN DWORD Height,
341 IN INT XSrc,
342 IN INT YSrc,
343 IN DWORD StartScan,
344 IN DWORD ScanLines,
345 IN LPBYTE Bits,
346 IN LPBITMAPINFO bmi,
347 IN DWORD ColorUse,
348 IN UINT cjMaxBits,
349 IN UINT cjMaxInfo,
350 IN BOOL bTransformCoordinates,
351 IN OPTIONAL HANDLE hcmXform
352 )
353 {
354 INT ret = 0;
355 NTSTATUS Status = STATUS_SUCCESS;
356 PDC pDC;
357 HBITMAP hSourceBitmap = NULL;
358 SURFOBJ *pDestSurf, *pSourceSurf = NULL;
359 RECTL rcDest;
360 POINTL ptSource;
361 INT DIBWidth;
362 SIZEL SourceSize;
363 XLATEOBJ *XlateObj = NULL;
364 PPALGDI pDCPalette;
365 HPALETTE DDBPalette, DIBPalette = NULL;
366 ULONG DDBPaletteType, DIBPaletteType;
367
368 if (!Bits) return 0;
369
370 pDC = DC_LockDc(hDC);
371 if (!pDC)
372 {
373 SetLastWin32Error(ERROR_INVALID_HANDLE);
374 return 0;
375 }
376 if (pDC->DC_Type == DC_TYPE_INFO)
377 {
378 DC_UnlockDc(pDC);
379 return 0;
380 }
381
382 pDestSurf = EngLockSurface((HSURF)pDC->w.hBitmap);
383 if (!pDestSurf)
384 {
385 /* FIXME: SetLastError ? */
386 DC_UnlockDc(pDC);
387 return 0;
388 }
389
390 rcDest.left = XDest;
391 rcDest.top = YDest;
392 if (bTransformCoordinates)
393 {
394 CoordLPtoDP(pDC, (LPPOINT)&rcDest);
395 }
396 rcDest.left += pDC->ptlDCOrig.x;
397 rcDest.top += pDC->ptlDCOrig.y;
398 rcDest.right = rcDest.left + Width;
399 rcDest.bottom = rcDest.top + Height;
400 ptSource.x = XSrc;
401 ptSource.y = YSrc;
402
403 /* Enter SEH, as the bits are user mode */
404 _SEH2_TRY // Look at NtGdiStretchDIBitsInternal
405 {
406 SourceSize.cx = bmi->bmiHeader.biWidth;
407 SourceSize.cy = ScanLines; // this one --> abs(bmi->bmiHeader.biHeight) - StartScan
408 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
409
410 ProbeForRead(Bits, DIBWidth * abs(bmi->bmiHeader.biHeight), 1);
411 hSourceBitmap = EngCreateBitmap(SourceSize,
412 DIBWidth,
413 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
414 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
415 (PVOID) Bits);
416 if (!hSourceBitmap)
417 {
418 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
419 Status = STATUS_NO_MEMORY;
420 _SEH2_LEAVE;
421 }
422
423 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
424 if (!pSourceSurf)
425 {
426 Status = STATUS_UNSUCCESSFUL;
427 _SEH2_LEAVE;
428 }
429
430
431 /* Obtain destination palette from the DC */
432 pDCPalette = PALETTE_LockPalette(((GDIDEVICE *)pDC->pPDev)->DevInfo.hpalDefault);
433 if (!pDCPalette)
434 {
435 SetLastWin32Error(ERROR_INVALID_HANDLE);
436 Status = STATUS_UNSUCCESSFUL;
437 _SEH2_LEAVE;
438 }
439 DDBPaletteType = pDCPalette->Mode;
440 DDBPalette = ((GDIDEVICE *)pDC->pPDev)->DevInfo.hpalDefault;
441 PALETTE_UnlockPalette(pDCPalette);
442
443 DIBPalette = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
444 if (!DIBPalette)
445 {
446 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
447 Status = STATUS_NO_MEMORY;
448 _SEH2_LEAVE;
449 }
450
451 /* Determine XlateObj */
452 XlateObj = IntEngCreateXlate(DDBPaletteType, DIBPaletteType, DDBPalette, DIBPalette);
453 if (!XlateObj)
454 {
455 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
456 Status = STATUS_NO_MEMORY;
457 _SEH2_LEAVE;
458 }
459
460 /* Copy the bits */
461 Status = IntEngBitBlt(pDestSurf,
462 pSourceSurf,
463 NULL,
464 pDC->CombinedClip,
465 XlateObj,
466 &rcDest,
467 &ptSource,
468 NULL,
469 NULL,
470 NULL,
471 ROP3_TO_ROP4(SRCCOPY));
472
473 }
474 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
475 {
476 Status = _SEH2_GetExceptionCode();
477 }
478 _SEH2_END
479
480 if (NT_SUCCESS(Status))
481 {
482 /* FIXME: Should probably be only the number of lines actually copied */
483 ret = ScanLines; // this one --> abs(Info->bmiHeader.biHeight) - StartScan;
484 }
485
486 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
487 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
488 if (XlateObj) EngDeleteXlate(XlateObj);
489 if (DIBPalette) PALETTE_FreePaletteByHandle(DIBPalette);
490 EngUnlockSurface(pDestSurf);
491 DC_UnlockDc(pDC);
492
493 return ret;
494 }
495
496
497 /* Converts a device-dependent bitmap to a DIB */
498 INT APIENTRY
499 NtGdiGetDIBitsInternal(HDC hDC,
500 HBITMAP hBitmap,
501 UINT StartScan,
502 UINT ScanLines,
503 LPBYTE Bits,
504 LPBITMAPINFO Info,
505 UINT Usage,
506 UINT MaxBits,
507 UINT MaxInfo)
508 {
509 PDC Dc;
510 BITMAPOBJ *BitmapObj = NULL;
511 HBITMAP hDestBitmap = NULL;
512 HPALETTE hSourcePalette = NULL;
513 HPALETTE hDestPalette = NULL;
514 PPALGDI SourcePalette = NULL;
515 PPALGDI DestPalette = NULL;
516 NTSTATUS Status = STATUS_SUCCESS;
517 ULONG Result = 0;
518 BOOL bPaletteMatch = FALSE;
519
520 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
521
522 /* Get handle for the palette in DC. */
523 Dc = DC_LockDc(hDC);
524 if (Dc == NULL) return 0;
525 if (Dc->DC_Type == DC_TYPE_INFO)
526 {
527 DC_UnlockDc(Dc);
528 return 0;
529 }
530 /* Source palette obtained from the windows hdc */
531 hSourcePalette = Dc->DcLevel.hpal;
532 DC_UnlockDc(Dc);
533
534 /* don't do anything if we fail this */
535 if (Usage != DIB_RGB_COLORS && Usage != DIB_PAL_COLORS)
536 return 0;
537
538 /* Get a pointer to the source bitmap object */
539 BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
540 if (BitmapObj == NULL)
541 return 0;
542
543 /* fill out the BITMAPINFO struct */
544 if (Bits == NULL)
545 {
546 _SEH2_TRY // Look at NtGdiStretchDIBitsInternal
547 { // Why check for anything, we converted in gdi!
548 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
549 {
550 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
551
552 ProbeForWrite(Info, sizeof(BITMAPINFO), 1);
553
554 coreheader = (BITMAPCOREHEADER*) Info;
555 coreheader->bcWidth = BitmapObj->SurfObj.sizlBitmap.cx;
556 coreheader->bcPlanes = 1;
557 coreheader->bcBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
558 /* Resulting height may be smaller than original height */ // You think!
559 coreheader->bcHeight = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
560 coreheader->bcSize = DIB_GetDIBWidthBytes(coreheader->bcWidth,
561 coreheader->bcBitCount) * coreheader->bcHeight;
562 if (BitmapObj->SurfObj.lDelta > 0)
563 coreheader->bcHeight = -coreheader->bcHeight;
564 }
565
566 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
567 {
568 ProbeForWrite(Info, sizeof(BITMAPINFO), 1);
569
570 if (!ScanLines) ScanLines = abs(Info->bmiHeader.biHeight) - StartScan;
571
572 Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
573 /* Resulting height may be smaller than original height */
574 Info->bmiHeader.biHeight = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
575 Info->bmiHeader.biPlanes = 1;
576 Info->bmiHeader.biBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
577 switch (BitmapObj->SurfObj.iBitmapFormat)
578 {
579 case BMF_1BPP:
580 case BMF_4BPP:
581 case BMF_8BPP:
582 case BMF_16BPP:
583 case BMF_24BPP:
584 case BMF_32BPP:
585 Info->bmiHeader.biCompression = BI_RGB;
586 break;
587 case BMF_4RLE:
588 Info->bmiHeader.biCompression = BI_RLE4;
589 break;
590 case BMF_8RLE:
591 Info->bmiHeader.biCompression = BI_RLE8;
592 break;
593 case BMF_JPEG:
594 Info->bmiHeader.biCompression = BI_JPEG;
595 break;
596 case BMF_PNG:
597 Info->bmiHeader.biCompression = BI_PNG;
598 break;
599 }
600 /* Image size has to be calculated */
601 Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth,
602 Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight;
603 Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
604 Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
605 Info->bmiHeader.biClrUsed = 0;
606 Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
607 /* Report negtive height for top-down bitmaps. */
608 if (BitmapObj->SurfObj.lDelta > 0)
609 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
610 }
611 }
612 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
613 {
614 Status = _SEH2_GetExceptionCode();
615 }
616 _SEH2_END
617
618 if (NT_SUCCESS(Status))
619 {
620 Result = BitmapObj->SurfObj.sizlBitmap.cy;
621 }
622 }
623 else
624 {
625 SIZEL DestSize;
626 ULONG SourcePaletteType = 0;
627 ULONG DestPaletteType;
628 POINTL SourcePoint;
629 ULONG Index;
630
631 _SEH2_TRY
632 {
633 ProbeForRead(Info, sizeof(BITMAPINFO), 1);
634
635 if (Info->bmiHeader.biBitCount == BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat))
636 {
637 hDestPalette = hSourcePalette;
638 bPaletteMatch = TRUE;
639 }
640 else
641 hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
642
643 SourcePalette = PALETTE_LockPalette(hSourcePalette);
644 /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
645 ASSERT(SourcePalette);
646 SourcePaletteType = SourcePalette->Mode;
647 PALETTE_UnlockPalette(SourcePalette);
648
649 if (bPaletteMatch)
650 {
651 DestPalette = PALETTE_LockPalette(hDestPalette);
652 /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
653 DPRINT("DestPalette : %p\n", DestPalette);
654 ASSERT(DestPalette);
655 DestPaletteType = DestPalette->Mode;
656 }
657 else
658 {
659 DestPalette = SourcePalette;
660 }
661
662 /* Copy palette. */
663 /* FIXME: This is largely incomplete. */
664 if (Info->bmiHeader.biBitCount <= 8)
665 {
666 if (Usage == DIB_RGB_COLORS)
667 {
668 for (Index = 0;
669 Index < (1 << Info->bmiHeader.biBitCount) && Index < DestPalette->NumColors;
670 Index++)
671 {
672 Info->bmiColors[Index].rgbRed = DestPalette->IndexedColors[Index].peRed;
673 Info->bmiColors[Index].rgbGreen = DestPalette->IndexedColors[Index].peGreen;
674 Info->bmiColors[Index].rgbBlue = DestPalette->IndexedColors[Index].peBlue;
675 Info->bmiColors[Index].rgbReserved = 0;
676 }
677 }
678
679 if (Usage == DIB_PAL_COLORS)
680 {
681 DPRINT1("GetDIBits with DIB_PAL_COLORS isn't implemented yet\n");
682 }
683 }
684
685 if (bPaletteMatch)
686 PALETTE_UnlockPalette(DestPalette);
687
688 if (!ScanLines) ScanLines = abs(Info->bmiHeader.biHeight) - StartScan;
689
690 /* Create the destination bitmap to for the copy operation */
691 if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
692 {
693 _SEH2_YIELD(goto cleanup);
694 }
695 else
696 { // Here again! ScanLine can be zero!
697 ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
698 DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
699 DestSize.cy = ScanLines; // this one ---> abs(Info->bmiHeader.biHeight) - StartScan;
700
701 hDestBitmap = NULL;
702
703 ProbeForWrite(Bits, BitmapObj->SurfObj.cjBits, 1);
704
705 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
706 {
707 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
708 coreheader->bcSize = DIB_GetDIBWidthBytes(DestSize.cx,
709 coreheader->bcBitCount) * DestSize.cy;
710
711 hDestBitmap = EngCreateBitmap(DestSize,
712 DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount),
713 BitmapFormat(coreheader->bcBitCount, BI_RGB),
714 0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN,
715 Bits);
716 }
717
718 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
719 {
720 Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
721 Info->bmiHeader.biBitCount) * DestSize.cy;
722
723 hDestBitmap = EngCreateBitmap(DestSize,
724 DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
725 BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
726 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
727 Bits);
728 }
729
730 if (hDestBitmap == NULL)
731 _SEH2_YIELD(goto cleanup);
732 }
733 }
734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
735 {
736 Status = _SEH2_GetExceptionCode();
737 }
738 _SEH2_END
739
740 if (NT_SUCCESS(Status))
741 {
742 XLATEOBJ *XlateObj;
743 SURFOBJ *DestSurfObj;
744 RECTL DestRect;
745
746 XlateObj = IntEngCreateXlate(DestPaletteType,
747 SourcePaletteType,
748 hDestPalette,
749 hSourcePalette);
750
751 SourcePoint.x = 0;
752 SourcePoint.y = BitmapObj->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
753
754 /* Determine destination rectangle */
755 DestRect.top = 0;
756 DestRect.left = 0;
757 DestRect.right = DestSize.cx;
758 DestRect.bottom = DestSize.cy;
759
760 DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
761
762 if (EngCopyBits(DestSurfObj,
763 &BitmapObj->SurfObj,
764 NULL,
765 XlateObj,
766 &DestRect,
767 &SourcePoint))
768 {
769 DPRINT("GetDIBits %d \n",abs(Info->bmiHeader.biHeight) - StartScan);
770 // Result = abs(Info->bmiHeader.biHeight) - StartScan;
771 Result = ScanLines;
772 }
773
774 EngDeleteXlate(XlateObj);
775 EngUnlockSurface(DestSurfObj);
776 }
777 }
778
779 cleanup:
780 if (hDestBitmap != NULL)
781 EngDeleteSurface((HSURF)hDestBitmap);
782
783 if (hDestPalette != NULL && bPaletteMatch == FALSE)
784 PALETTE_FreePaletteByHandle(hDestPalette);
785
786 BITMAPOBJ_UnlockBitmap(BitmapObj);
787
788 DPRINT("leaving NtGdiGetDIBitsInternal\n");
789
790 return Result;
791 }
792
793 INT
794 APIENTRY
795 NtGdiStretchDIBitsInternal(
796 HDC hDC,
797 INT XDest,
798 INT YDest,
799 INT DestWidth,
800 INT DestHeight,
801 INT XSrc,
802 INT YSrc,
803 INT SrcWidth,
804 INT SrcHeight,
805 LPBYTE Bits,
806 LPBITMAPINFO BitsInfo,
807 DWORD Usage,
808 DWORD ROP,
809 UINT cjMaxInfo,
810 UINT cjMaxBits,
811 HANDLE hcmXform)
812 {
813 HBITMAP hBitmap, hOldBitmap = NULL;
814 HDC hdcMem;
815 HPALETTE hPal = NULL;
816 PDC pDC;
817 BOOL Hit = FALSE;
818
819 if (!Bits || !BitsInfo)
820 {
821 SetLastWin32Error(ERROR_INVALID_PARAMETER);
822 return 0;
823 }
824
825 _SEH2_TRY
826 {
827 ProbeForRead(BitsInfo, cjMaxInfo, 1);
828 ProbeForRead(Bits, cjMaxBits, 1);
829 }
830 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
831 {
832 Hit = TRUE;
833 }
834 _SEH2_END
835
836 if (Hit)
837 {
838 DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
839 return 0;
840 }
841
842 hdcMem = NtGdiCreateCompatibleDC(hDC);
843 if (hdcMem == NULL)
844 {
845 DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
846 return 0;
847 }
848
849 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
850 BitsInfo->bmiHeader.biHeight);
851 if (hBitmap == NULL)
852 {
853 DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
854 DPRINT1("hDC : 0x%08x \n", hDC);
855 DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
856 DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
857 return 0;
858 }
859
860 /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
861 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
862
863 if(Usage == DIB_PAL_COLORS)
864 {
865 hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
866 hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
867 }
868
869 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
870 BitsInfo->bmiHeader.biCompression == BI_RLE8)
871 {
872 /* copy existing bitmap from destination dc */
873 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
874 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
875 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
876 else
877 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
878 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
879 ROP, 0);
880 }
881
882 pDC = DC_LockDc(hdcMem);
883 if (pDC != NULL)
884 {
885 /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
886 * if it negitve we getting to many scanline for scanline is UINT not
887 * a INT, so we need make the negtive value to positve and that make the
888 * count correct for negtive bitmap, TODO : we need testcase for this api */
889 IntSetDIBits(pDC, hBitmap, 0, abs(BitsInfo->bmiHeader.biHeight), Bits,
890 BitsInfo, Usage);
891
892 DC_UnlockDc(pDC);
893 }
894
895
896 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
897 left (negative biHeight) */
898 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
899 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
900 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
901 ROP, 0, 0);
902 else
903 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
904 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
905 SrcWidth, SrcHeight, ROP, 0);
906
907 /* cleanup */
908 if(hPal)
909 GdiSelectPalette(hdcMem, hPal, FALSE);
910
911 if (hOldBitmap)
912 NtGdiSelectBitmap(hdcMem, hOldBitmap);
913
914 NtGdiDeleteObjectApp(hdcMem);
915
916 NtGdiDeleteObject(hBitmap);
917
918 return SrcHeight;
919 }
920
921
922 HBITMAP
923 FASTCALL
924 IntCreateDIBitmap(PDC Dc,
925 INT width,
926 INT height,
927 UINT bpp,
928 DWORD init,
929 LPBYTE bits,
930 PBITMAPINFO data,
931 DWORD coloruse)
932 {
933 HBITMAP handle;
934 BOOL fColor;
935
936 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
937 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
938
939 if (bpp != 1) fColor = TRUE;
940 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
941 else
942 {
943 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
944 {
945 const RGBQUAD *rgb = data->bmiColors;
946 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
947
948 // Check if the first color of the colormap is black
949 if ((col == RGB(0, 0, 0)))
950 {
951 rgb++;
952 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
953
954 // If the second color is white, create a monochrome bitmap
955 fColor = (col != RGB(0xff,0xff,0xff));
956 }
957 else fColor = TRUE;
958 }
959 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
960 {
961 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
962 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
963
964 if ((col == RGB(0,0,0)))
965 {
966 rgb++;
967 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
968 fColor = (col != RGB(0xff,0xff,0xff));
969 }
970 else fColor = TRUE;
971 }
972 else
973 {
974 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
975 return 0;
976 }
977 }
978
979 // Now create the bitmap
980 if (fColor)
981 {
982 handle = IntCreateCompatibleBitmap(Dc, width, height);
983 }
984 else
985 {
986 handle = IntGdiCreateBitmap(width,
987 height,
988 1,
989 1,
990 NULL);
991 }
992
993 if (height < 0)
994 height = -height;
995
996 if (NULL != handle && CBM_INIT == init)
997 {
998 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
999 }
1000
1001 return handle;
1002 }
1003
1004 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1005 // The DDB that is created will be whatever bit depth your reference DC is
1006 HBITMAP
1007 APIENTRY
1008 NtGdiCreateDIBitmapInternal(IN HDC hDc,
1009 IN INT cx,
1010 IN INT cy,
1011 IN DWORD fInit,
1012 IN OPTIONAL LPBYTE pjInit,
1013 IN OPTIONAL LPBITMAPINFO pbmi,
1014 IN DWORD iUsage,
1015 IN UINT cjMaxInitInfo,
1016 IN UINT cjMaxBits,
1017 IN FLONG fl,
1018 IN HANDLE hcmXform)
1019 {
1020 PDC Dc;
1021 HBITMAP Bmp;
1022 UINT bpp;
1023
1024 if (!hDc) // CreateBitmap
1025 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1026 hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
1027 if (!hDc)
1028 {
1029 SetLastWin32Error(ERROR_INVALID_HANDLE);
1030 return NULL;
1031 }
1032
1033 Dc = DC_LockDc(hDc);
1034 if (!Dc)
1035 {
1036 NtGdiDeleteObjectApp(hDc);
1037 SetLastWin32Error(ERROR_INVALID_HANDLE);
1038 return NULL;
1039 }
1040 bpp = 1;
1041 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1042
1043 DC_UnlockDc(Dc);
1044 NtGdiDeleteObjectApp(hDc);
1045 }
1046 else // CreateCompatibleBitmap
1047 {
1048 Dc = DC_LockDc(hDc);
1049 if (!Dc)
1050 {
1051 SetLastWin32Error(ERROR_INVALID_HANDLE);
1052 return NULL;
1053 }
1054 /* pbmi == null
1055 First create an un-initialised bitmap. The depth of the bitmap
1056 should match that of the hdc and not that supplied in bmih.
1057 */
1058 if (pbmi)
1059 bpp = pbmi->bmiHeader.biBitCount;
1060 else
1061 {
1062 if (Dc->DC_Type != DC_TYPE_MEMORY )
1063 bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL);
1064 else
1065 {
1066 DIBSECTION dibs;
1067 INT Count;
1068 BITMAPOBJ *BitmapObject = BITMAPOBJ_LockBitmap(Dc->w.hBitmap);
1069 Count = BITMAP_GetObject(BitmapObject, sizeof(dibs), &dibs);
1070 if (!Count)
1071 bpp = 1;
1072 else
1073 {
1074 if (Count == sizeof(BITMAP))
1075 /* A device-dependent bitmap is selected in the DC */
1076 bpp = dibs.dsBm.bmBitsPixel;
1077 else
1078 /* A DIB section is selected in the DC */
1079 bpp = dibs.dsBmih.biBitCount;
1080 }
1081 BITMAPOBJ_UnlockBitmap(BitmapObject);
1082 }
1083 }
1084 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1085 DC_UnlockDc(Dc);
1086 }
1087 return Bmp;
1088 }
1089
1090
1091 HBITMAP APIENTRY NtGdiCreateDIBSection(HDC hDC,
1092 IN OPTIONAL HANDLE hSection,
1093 IN DWORD dwOffset,
1094 IN LPBITMAPINFO bmi,
1095 DWORD Usage,
1096 IN UINT cjHeader,
1097 IN FLONG fl,
1098 IN ULONG_PTR dwColorSpace,
1099 PVOID *Bits)
1100 {
1101 HBITMAP hbitmap = 0;
1102 DC *dc;
1103 BOOL bDesktopDC = FALSE;
1104
1105 if (!bmi) return hbitmap; // Make sure.
1106
1107 // If the reference hdc is null, take the desktop dc
1108 if (hDC == 0)
1109 {
1110 hDC = NtGdiCreateCompatibleDC(0);
1111 bDesktopDC = TRUE;
1112 }
1113
1114 if ((dc = DC_LockDc(hDC)))
1115 {
1116 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
1117 hSection, dwOffset, 0);
1118 DC_UnlockDc(dc);
1119 }
1120 else
1121 {
1122 SetLastWin32Error(ERROR_INVALID_HANDLE);
1123 }
1124
1125 if (bDesktopDC)
1126 NtGdiDeleteObjectApp(hDC);
1127
1128 return hbitmap;
1129 }
1130
1131 HBITMAP APIENTRY
1132 DIB_CreateDIBSection(
1133 PDC dc, BITMAPINFO *bmi, UINT usage,
1134 LPVOID *bits, HANDLE section,
1135 DWORD offset, DWORD ovr_pitch)
1136 {
1137 HBITMAP res = 0;
1138 BITMAPOBJ *bmp = NULL;
1139 DIBSECTION *dib = NULL;
1140 void *mapBits = NULL;
1141
1142 // Fill BITMAP32 structure with DIB data
1143 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1144 INT effHeight;
1145 ULONG totalSize;
1146 BITMAP bm;
1147 SIZEL Size;
1148 RGBQUAD *lpRGB;
1149
1150 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1151 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1152 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1153
1154 /* CreateDIBSection should fail for compressed formats */
1155 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1156 {
1157 return (HBITMAP)NULL;
1158 }
1159
1160 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1161 bm.bmType = 0;
1162 bm.bmWidth = bi->biWidth;
1163 bm.bmHeight = effHeight;
1164 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1165
1166 bm.bmPlanes = bi->biPlanes;
1167 bm.bmBitsPixel = bi->biBitCount;
1168 bm.bmBits = NULL;
1169
1170 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1171 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1172 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1173 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
1174
1175 if (section)
1176 {
1177 SYSTEM_BASIC_INFORMATION Sbi;
1178 NTSTATUS Status;
1179 DWORD mapOffset;
1180 LARGE_INTEGER SectionOffset;
1181 SIZE_T mapSize;
1182
1183 Status = ZwQuerySystemInformation ( SystemBasicInformation,
1184 &Sbi,
1185 sizeof Sbi,
1186 0);
1187 if (!NT_SUCCESS(Status))
1188 {
1189 return NULL;
1190 }
1191
1192 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1193 mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1194
1195 SectionOffset.LowPart = mapOffset;
1196 SectionOffset.HighPart = 0;
1197
1198 Status = ZwMapViewOfSection ( section,
1199 NtCurrentProcess(),
1200 &mapBits,
1201 0,
1202 0,
1203 &SectionOffset,
1204 &mapSize,
1205 ViewShare,
1206 0,
1207 PAGE_READWRITE);
1208 if (!NT_SUCCESS(Status))
1209 {
1210 return NULL;
1211 }
1212
1213 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1214 }
1215 else if (ovr_pitch && offset)
1216 bm.bmBits = (LPVOID) offset;
1217 else
1218 {
1219 offset = 0;
1220 bm.bmBits = EngAllocUserMem( totalSize, 0 );
1221 }
1222
1223 if(usage == DIB_PAL_COLORS)
1224 lpRGB = DIB_MapPaletteColors(dc, bmi);
1225 else
1226 lpRGB = bmi->bmiColors;
1227
1228 // Allocate Memory for DIB and fill structure
1229 if (bm.bmBits)
1230 {
1231 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
1232 if (dib != NULL) RtlZeroMemory(dib, sizeof(DIBSECTION));
1233 }
1234
1235 if (dib)
1236 {
1237 dib->dsBm = bm;
1238 /* Set dsBitfields values */
1239 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1240 {
1241 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1242 }
1243 else switch(bi->biBitCount)
1244 {
1245 case 15:
1246 case 16:
1247 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00;
1248 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
1249 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f;
1250 break;
1251
1252 case 24:
1253 case 32:
1254 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000;
1255 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
1256 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
1257 break;
1258 }
1259 dib->dshSection = section;
1260 dib->dsOffset = offset;
1261
1262 // Create Device Dependent Bitmap and add DIB pointer
1263 Size.cx = bm.bmWidth;
1264 Size.cy = abs(bm.bmHeight);
1265 res = IntCreateBitmap( Size,
1266 bm.bmWidthBytes,
1267 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1268 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1269 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1270 bm.bmBits);
1271 if ( !res )
1272 {
1273 if (lpRGB != bmi->bmiColors)
1274 {
1275 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1276 }
1277 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1278 return NULL;
1279 }
1280 bmp = BITMAPOBJ_LockBitmap(res);
1281 if (NULL == bmp)
1282 {
1283 if (lpRGB != bmi->bmiColors)
1284 {
1285 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1286 }
1287 SetLastWin32Error(ERROR_INVALID_HANDLE);
1288 NtGdiDeleteObject(bmp);
1289 return NULL;
1290 }
1291 bmp->dib = (DIBSECTION *) dib;
1292 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
1293
1294 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1295 table between the DIB and the X physical device. Obviously,
1296 this is left out of the ReactOS implementation. Instead,
1297 we call NtGdiSetDIBColorTable. */
1298 bi->biClrUsed = 0;
1299 /* set number of entries in bmi.bmiColors table */
1300 if(bi->biBitCount == 1) { bi->biClrUsed = 2; } else
1301 if(bi->biBitCount == 4) { bi->biClrUsed = 16; } else
1302 if(bi->biBitCount == 8) { bi->biClrUsed = 256; }
1303
1304 if (bi->biClrUsed != 0)
1305 bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(bi->biClrUsed, lpRGB);
1306 else
1307 bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1308 dib->dsBitfields[0],
1309 dib->dsBitfields[1],
1310 dib->dsBitfields[2]);
1311
1312 dib->dsBmih = *bi;
1313 dib->dsBmih.biSizeImage = totalSize;
1314 }
1315
1316 // Clean up in case of errors
1317 if (!res || !bmp || !dib || !bm.bmBits)
1318 {
1319 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
1320 if (bm.bmBits)
1321 {
1322 if (section)
1323 {
1324 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1325 bm.bmBits = NULL;
1326 }
1327 else
1328 if (!offset)
1329 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1330 }
1331
1332 if (dib) { ExFreePoolWithTag(dib, TAG_DIB); dib = NULL; }
1333 if (bmp) { bmp = NULL; }
1334 if (res) { BITMAPOBJ_FreeBitmapByHandle(res); res = 0; }
1335 }
1336
1337 if (lpRGB != bmi->bmiColors)
1338 {
1339 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1340 }
1341
1342 if (bmp)
1343 {
1344 BITMAPOBJ_UnlockBitmap(bmp);
1345 }
1346
1347 // Return BITMAP handle and storage location
1348 if (NULL != bm.bmBits && NULL != bits)
1349 {
1350 *bits = bm.bmBits;
1351 }
1352
1353 return res;
1354 }
1355
1356 /***********************************************************************
1357 * DIB_GetDIBWidthBytes
1358 *
1359 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1360 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1361 * 11/16/1999 (RJJ) lifted from wine
1362 */
1363 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
1364 {
1365 return ((width * depth + 31) & ~31) >> 3;
1366 }
1367
1368 /***********************************************************************
1369 * DIB_GetDIBImageBytes
1370 *
1371 * Return the number of bytes used to hold the image in a DIB bitmap.
1372 * 11/16/1999 (RJJ) lifted from wine
1373 */
1374
1375 INT APIENTRY DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1376 {
1377 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1378 }
1379
1380 /***********************************************************************
1381 * DIB_BitmapInfoSize
1382 *
1383 * Return the size of the bitmap info structure including color table.
1384 * 11/16/1999 (RJJ) lifted from wine
1385 */
1386
1387 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1388 {
1389 int colors;
1390
1391 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1392 {
1393 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1394 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1395 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1396 }
1397 else /* assume BITMAPINFOHEADER */
1398 {
1399 colors = info->bmiHeader.biClrUsed;
1400 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1401 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1402 }
1403 }
1404
1405 RGBQUAD * FASTCALL
1406 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1407 {
1408 RGBQUAD *lpRGB;
1409 ULONG nNumColors,i;
1410 USHORT *lpIndex;
1411 PPALGDI palGDI;
1412
1413 palGDI = PALETTE_LockPalette(dc->DcLevel.hpal);
1414
1415 if (NULL == palGDI)
1416 {
1417 return NULL;
1418 }
1419
1420 if (palGDI->Mode != PAL_INDEXED)
1421 {
1422 PALETTE_UnlockPalette(palGDI);
1423 return NULL;
1424 }
1425
1426 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1427 if (lpbmi->bmiHeader.biClrUsed)
1428 {
1429 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1430 }
1431
1432 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1433 if (lpRGB == NULL)
1434 {
1435 PALETTE_UnlockPalette(palGDI);
1436 return NULL;
1437 }
1438
1439 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1440
1441 for (i = 0; i < nNumColors; i++)
1442 {
1443 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1444 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1445 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1446 lpRGB[i].rgbReserved = 0;
1447 lpIndex++;
1448 }
1449 PALETTE_UnlockPalette(palGDI);
1450
1451 return lpRGB;
1452 }
1453
1454 HPALETTE FASTCALL
1455 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
1456 {
1457 BYTE bits;
1458 ULONG ColorCount;
1459 PALETTEENTRY *palEntries = NULL;
1460 HPALETTE hPal;
1461 ULONG RedMask, GreenMask, BlueMask;
1462
1463 // Determine Bits Per Pixel
1464 bits = bmi->bmiHeader.biBitCount;
1465
1466 // Determine paletteType from Bits Per Pixel
1467 if (bits <= 8)
1468 {
1469 *paletteType = PAL_INDEXED;
1470 RedMask = GreenMask = BlueMask = 0;
1471 }
1472 else if(bmi->bmiHeader.biCompression == BI_BITFIELDS)
1473 {
1474 *paletteType = PAL_BITFIELDS;
1475 RedMask = ((ULONG *)bmi->bmiColors)[0];
1476 GreenMask = ((ULONG *)bmi->bmiColors)[1];
1477 BlueMask = ((ULONG *)bmi->bmiColors)[2];
1478 }
1479 else if(bits < 24)
1480 {
1481 *paletteType = PAL_BITFIELDS;
1482 RedMask = 0x7c00;
1483 GreenMask = 0x03e0;
1484 BlueMask = 0x001f;
1485 }
1486 else
1487 {
1488 *paletteType = PAL_BGR;
1489 RedMask = 0xff0000;
1490 GreenMask = 0x00ff00;
1491 BlueMask = 0x0000ff;
1492 }
1493
1494 if (bmi->bmiHeader.biClrUsed == 0)
1495 {
1496 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1497 }
1498 else
1499 {
1500 ColorCount = bmi->bmiHeader.biClrUsed;
1501 }
1502
1503 if (PAL_INDEXED == *paletteType)
1504 {
1505 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1506 }
1507 else
1508 {
1509 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1510 (ULONG*) palEntries,
1511 RedMask, GreenMask, BlueMask );
1512 }
1513
1514 return hPal;
1515 }
1516
1517 /* EOF */