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