[WIN32K]
[reactos.git] / subsystems / win32 / win32k / objects / dibobj.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <win32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 static const RGBQUAD EGAColorsQuads[16] = {
26 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
27 { 0x00, 0x00, 0x00, 0x00 },
28 { 0x00, 0x00, 0x80, 0x00 },
29 { 0x00, 0x80, 0x00, 0x00 },
30 { 0x00, 0x80, 0x80, 0x00 },
31 { 0x80, 0x00, 0x00, 0x00 },
32 { 0x80, 0x00, 0x80, 0x00 },
33 { 0x80, 0x80, 0x00, 0x00 },
34 { 0x80, 0x80, 0x80, 0x00 },
35 { 0xc0, 0xc0, 0xc0, 0x00 },
36 { 0x00, 0x00, 0xff, 0x00 },
37 { 0x00, 0xff, 0x00, 0x00 },
38 { 0x00, 0xff, 0xff, 0x00 },
39 { 0xff, 0x00, 0x00, 0x00 },
40 { 0xff, 0x00, 0xff, 0x00 },
41 { 0xff, 0xff, 0x00, 0x00 },
42 { 0xff, 0xff, 0xff, 0x00 }
43 };
44
45 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
46 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
47 { 0x00, 0x00, 0x00, 0x00 },
48 { 0x00, 0x00, 0x80, 0x00 },
49 { 0x00, 0x80, 0x00, 0x00 },
50 { 0x00, 0x80, 0x80, 0x00 },
51 { 0x80, 0x00, 0x00, 0x00 },
52 { 0x80, 0x00, 0x80, 0x00 },
53 { 0x80, 0x80, 0x00, 0x00 },
54 { 0xc0, 0xc0, 0xc0, 0x00 },
55 { 0xc0, 0xdc, 0xc0, 0x00 },
56 { 0xf0, 0xca, 0xa6, 0x00 },
57 { 0xf0, 0xfb, 0xff, 0x00 },
58 { 0xa4, 0xa0, 0xa0, 0x00 },
59 { 0x80, 0x80, 0x80, 0x00 },
60 { 0x00, 0x00, 0xf0, 0x00 },
61 { 0x00, 0xff, 0x00, 0x00 },
62 { 0x00, 0xff, 0xff, 0x00 },
63 { 0xff, 0x00, 0x00, 0x00 },
64 { 0xff, 0x00, 0xff, 0x00 },
65 { 0xff, 0xff, 0x00, 0x00 },
66 { 0xff, 0xff, 0xff, 0x00 }
67 };
68
69
70 UINT
71 APIENTRY
72 IntSetDIBColorTable(
73 HDC hDC,
74 UINT StartIndex,
75 UINT Entries,
76 CONST RGBQUAD *Colors)
77 {
78 PDC dc;
79 PSURFACE psurf;
80 PPALETTE PalGDI;
81 UINT Index;
82 ULONG biBitCount;
83
84 if (!(dc = DC_LockDc(hDC))) return 0;
85 if (dc->dctype == DC_TYPE_INFO)
86 {
87 DC_UnlockDc(dc);
88 return 0;
89 }
90
91 psurf = dc->dclevel.pSurface;
92 if (psurf == NULL)
93 {
94 DC_UnlockDc(dc);
95 SetLastWin32Error(ERROR_INVALID_PARAMETER);
96 return 0;
97 }
98
99 if (psurf->hSecure == NULL)
100 {
101 DC_UnlockDc(dc);
102 SetLastWin32Error(ERROR_INVALID_PARAMETER);
103 return 0;
104 }
105
106 biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
107 if (biBitCount <= 8 && StartIndex < (1 << biBitCount))
108 {
109 if (StartIndex + Entries > (1 << biBitCount))
110 Entries = (1 << biBitCount) - StartIndex;
111
112 if (psurf->ppal == NULL)
113 {
114 DC_UnlockDc(dc);
115 SetLastWin32Error(ERROR_INVALID_HANDLE);
116 return 0;
117 }
118
119 PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
120
121 for (Index = StartIndex;
122 Index < StartIndex + Entries && Index < PalGDI->NumColors;
123 Index++)
124 {
125 PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
126 PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
127 PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
128 }
129 PALETTE_UnlockPalette(PalGDI);
130 }
131 else
132 Entries = 0;
133
134 /* Mark the brushes invalid */
135 dc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE|DIRTY_BACKGROUND|DIRTY_TEXT;
136
137 DC_UnlockDc(dc);
138
139 return Entries;
140 }
141
142 UINT
143 APIENTRY
144 IntGetDIBColorTable(
145 HDC hDC,
146 UINT StartIndex,
147 UINT Entries,
148 RGBQUAD *Colors)
149 {
150 PDC dc;
151 PSURFACE psurf;
152 PPALETTE PalGDI;
153 UINT Index, Count = 0;
154 ULONG biBitCount;
155
156 if (!(dc = DC_LockDc(hDC))) return 0;
157 if (dc->dctype == DC_TYPE_INFO)
158 {
159 DC_UnlockDc(dc);
160 return 0;
161 }
162
163 psurf = dc->dclevel.pSurface;
164 if (psurf == NULL)
165 {
166 DC_UnlockDc(dc);
167 SetLastWin32Error(ERROR_INVALID_PARAMETER);
168 return 0;
169 }
170
171 if (psurf->hSecure == NULL)
172 {
173 DC_UnlockDc(dc);
174 SetLastWin32Error(ERROR_INVALID_PARAMETER);
175 return 0;
176 }
177
178 biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
179 if (biBitCount <= 8 &&
180 StartIndex < (1 << biBitCount))
181 {
182 if (StartIndex + Entries > (1 << biBitCount))
183 Entries = (1 << biBitCount) - StartIndex;
184
185 if (psurf->ppal == NULL)
186 {
187 DC_UnlockDc(dc);
188 SetLastWin32Error(ERROR_INVALID_HANDLE);
189 return 0;
190 }
191
192 PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
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 Count++;
203 }
204 PALETTE_UnlockPalette(PalGDI);
205 }
206
207 DC_UnlockDc(dc);
208
209 return Count;
210 }
211
212 // Converts a DIB to a device-dependent bitmap
213 static INT
214 FASTCALL
215 IntSetDIBits(
216 PDC DC,
217 HBITMAP hBitmap,
218 UINT StartScan,
219 UINT ScanLines,
220 CONST VOID *Bits,
221 CONST BITMAPINFO *bmi,
222 UINT ColorUse)
223 {
224 SURFACE *bitmap;
225 HBITMAP SourceBitmap;
226 INT result = 0;
227 BOOL copyBitsResult;
228 SURFOBJ *DestSurf, *SourceSurf;
229 SIZEL SourceSize;
230 POINTL ZeroPoint;
231 RECTL DestRect;
232 EXLATEOBJ exlo;
233 PPALETTE ppalDDB, ppalDIB;
234 //RGBQUAD *lpRGB;
235 HPALETTE DIB_Palette;
236 ULONG DIB_Palette_Type;
237 INT DIBWidth;
238
239 // Check parameters
240 if (!(bitmap = SURFACE_LockSurface(hBitmap)))
241 {
242 return 0;
243 }
244
245 // Get RGB values
246 //if (ColorUse == DIB_PAL_COLORS)
247 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
248 //else
249 // lpRGB = &bmi->bmiColors;
250
251 DestSurf = &bitmap->SurfObj;
252
253 // Create source surface
254 SourceSize.cx = bmi->bmiHeader.biWidth;
255 SourceSize.cy = ScanLines;
256
257 // Determine width of DIB
258 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
259
260 SourceBitmap = EngCreateBitmap(SourceSize,
261 DIBWidth,
262 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
263 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
264 (PVOID) Bits);
265 if (0 == SourceBitmap)
266 {
267 SURFACE_UnlockSurface(bitmap);
268 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
269 return 0;
270 }
271
272 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
273 if (NULL == SourceSurf)
274 {
275 EngDeleteSurface((HSURF)SourceBitmap);
276 SURFACE_UnlockSurface(bitmap);
277 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
278 return 0;
279 }
280
281 if (bitmap->ppal)
282 {
283 ppalDDB = bitmap->ppal;
284 GDIOBJ_IncrementShareCount(&ppalDDB->BaseObject);
285 }
286 else
287 // Destination palette obtained from the hDC
288 ppalDDB = PALETTE_ShareLockPalette(DC->ppdev->devinfo.hpalDefault);
289
290 if (NULL == ppalDDB)
291 {
292 EngUnlockSurface(SourceSurf);
293 EngDeleteSurface((HSURF)SourceBitmap);
294 SURFACE_UnlockSurface(bitmap);
295 SetLastWin32Error(ERROR_INVALID_HANDLE);
296 return 0;
297 }
298
299 // Source palette obtained from the BITMAPINFO
300 DIB_Palette = BuildDIBPalette((PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type);
301 if (NULL == DIB_Palette)
302 {
303 EngUnlockSurface(SourceSurf);
304 EngDeleteSurface((HSURF)SourceBitmap);
305 SURFACE_UnlockSurface(bitmap);
306 PALETTE_ShareUnlockPalette(ppalDDB);
307 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
308 return 0;
309 }
310
311 ppalDIB = PALETTE_LockPalette(DIB_Palette);
312
313 /* Initialize XLATEOBJ for color translation */
314 EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
315
316 // Zero point
317 ZeroPoint.x = 0;
318 ZeroPoint.y = 0;
319
320 // Determine destination rectangle
321 DestRect.left = 0;
322 DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
323 DestRect.right = SourceSize.cx;
324 DestRect.bottom = DestRect.top + ScanLines;
325
326 copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
327
328 // If it succeeded, return number of scanlines copies
329 if (copyBitsResult == TRUE)
330 {
331 result = SourceSize.cy;
332 // or
333 // result = abs(bmi->bmiHeader.biHeight) - StartScan;
334 }
335
336 // Clean up
337 EXLATEOBJ_vCleanup(&exlo);
338 PALETTE_UnlockPalette(ppalDIB);
339 PALETTE_ShareUnlockPalette(ppalDDB);
340 PALETTE_FreePaletteByHandle(DIB_Palette);
341 EngUnlockSurface(SourceSurf);
342 EngDeleteSurface((HSURF)SourceBitmap);
343
344 // if (ColorUse == DIB_PAL_COLORS)
345 // WinFree((LPSTR)lpRGB);
346
347 SURFACE_UnlockSurface(bitmap);
348
349 return result;
350 }
351
352 // FIXME by Removing NtGdiSetDIBits!!!
353 // This is a victim of the Win32k Initialization BUG!!!!!
354 // Converts a DIB to a device-dependent bitmap
355 INT
356 APIENTRY
357 NtGdiSetDIBits(
358 HDC hDC,
359 HBITMAP hBitmap,
360 UINT StartScan,
361 UINT ScanLines,
362 CONST VOID *Bits,
363 CONST BITMAPINFO *bmi,
364 UINT ColorUse)
365 {
366 PDC Dc;
367 INT Ret;
368 NTSTATUS Status = STATUS_SUCCESS;
369 UINT cjBits;
370
371 if (!Bits) return 0;
372
373 _SEH2_TRY
374 { // FYI: We converted from CORE in gdi.
375 ProbeForRead(bmi, sizeof(BITMAPINFO), 1);
376 cjBits = bmi->bmiHeader.biBitCount * bmi->bmiHeader.biPlanes * bmi->bmiHeader.biWidth;
377 cjBits = ((cjBits + 31) & ~31) / 8;
378 cjBits *= ScanLines;
379 ProbeForRead(Bits, cjBits, 1);
380 }
381 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
382 {
383 Status = _SEH2_GetExceptionCode();
384 }
385 _SEH2_END
386
387 if (!NT_SUCCESS(Status))
388 {
389 return 0;
390 }
391
392 Dc = DC_LockDc(hDC);
393 if (NULL == Dc)
394 {
395 SetLastWin32Error(ERROR_INVALID_HANDLE);
396 return 0;
397 }
398 if (Dc->dctype == DC_TYPE_INFO)
399 {
400 DC_UnlockDc(Dc);
401 return 0;
402 }
403
404 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
405
406 DC_UnlockDc(Dc);
407
408 return Ret;
409 }
410
411 W32KAPI
412 INT
413 APIENTRY
414 NtGdiSetDIBitsToDeviceInternal(
415 IN HDC hDC,
416 IN INT XDest,
417 IN INT YDest,
418 IN DWORD Width,
419 IN DWORD Height,
420 IN INT XSrc,
421 IN INT YSrc,
422 IN DWORD StartScan,
423 IN DWORD ScanLines,
424 IN LPBYTE Bits,
425 IN LPBITMAPINFO bmi,
426 IN DWORD ColorUse,
427 IN UINT cjMaxBits,
428 IN UINT cjMaxInfo,
429 IN BOOL bTransformCoordinates,
430 IN OPTIONAL HANDLE hcmXform)
431 {
432 INT ret = 0;
433 NTSTATUS Status = STATUS_SUCCESS;
434 PDC pDC;
435 HBITMAP hSourceBitmap = NULL;
436 SURFOBJ *pDestSurf, *pSourceSurf = NULL;
437 SURFACE *pSurf;
438 RECTL rcDest;
439 POINTL ptSource;
440 INT DIBWidth;
441 SIZEL SourceSize;
442 EXLATEOBJ exlo;
443 PPALETTE ppalDDB = NULL, ppalDIB = NULL;
444 HPALETTE hpalDIB = NULL;
445 ULONG DIBPaletteType;
446
447 if (!Bits) return 0;
448
449 _SEH2_TRY
450 {
451 ProbeForRead(bmi, cjMaxInfo , 1);
452 ProbeForRead(Bits, cjMaxBits, 1);
453 }
454 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
455 {
456 Status = _SEH2_GetExceptionCode();
457 }
458 _SEH2_END
459
460 if (!NT_SUCCESS(Status))
461 {
462 return 0;
463 }
464
465 pDC = DC_LockDc(hDC);
466 if (!pDC)
467 {
468 SetLastWin32Error(ERROR_INVALID_HANDLE);
469 return 0;
470 }
471 if (pDC->dctype == DC_TYPE_INFO)
472 {
473 DC_UnlockDc(pDC);
474 return 0;
475 }
476
477 pSurf = pDC->dclevel.pSurface;
478
479 pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
480
481 ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
482
483 rcDest.left = XDest;
484 rcDest.top = YDest;
485 if (bTransformCoordinates)
486 {
487 CoordLPtoDP(pDC, (LPPOINT)&rcDest);
488 }
489 rcDest.left += pDC->ptlDCOrig.x;
490 rcDest.top += pDC->ptlDCOrig.y;
491 rcDest.right = rcDest.left + Width;
492 rcDest.bottom = rcDest.top + Height;
493 rcDest.top += StartScan;
494
495 ptSource.x = XSrc;
496 ptSource.y = YSrc;
497
498 SourceSize.cx = bmi->bmiHeader.biWidth;
499 SourceSize.cy = ScanLines;
500
501 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
502
503 hSourceBitmap = EngCreateBitmap(SourceSize,
504 DIBWidth,
505 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
506 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
507 (PVOID) Bits);
508 if (!hSourceBitmap)
509 {
510 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
511 Status = STATUS_NO_MEMORY;
512 goto Exit;
513 }
514
515 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
516 if (!pSourceSurf)
517 {
518 Status = STATUS_UNSUCCESSFUL;
519 goto Exit;
520 }
521
522 /* Obtain destination palette */
523 if (pSurf && pSurf->ppal)
524 {
525 ppalDDB = pSurf->ppal;
526 GDIOBJ_IncrementShareCount(&ppalDDB->BaseObject);
527 }
528 else
529 ppalDDB = PALETTE_ShareLockPalette(pDC->ppdev->devinfo.hpalDefault);
530
531 if (!ppalDDB)
532 {
533 SetLastWin32Error(ERROR_INVALID_HANDLE);
534 Status = STATUS_UNSUCCESSFUL;
535 goto Exit;
536 }
537
538 /* Create a palette for the DIB */
539 hpalDIB = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
540 if (!hpalDIB)
541 {
542 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
543 Status = STATUS_NO_MEMORY;
544 goto Exit;
545 }
546
547 /* Lock the DIB palette */
548 ppalDIB = PALETTE_LockPalette(hpalDIB);
549 if (!ppalDIB)
550 {
551 SetLastWin32Error(ERROR_INVALID_HANDLE);
552 Status = STATUS_UNSUCCESSFUL;
553 goto Exit;
554 }
555
556 /* Initialize EXLATEOBJ */
557 EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
558
559 /* Copy the bits */
560 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
561 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
562 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
563 Status = IntEngBitBlt(pDestSurf,
564 pSourceSurf,
565 NULL,
566 pDC->rosdc.CombinedClip,
567 &exlo.xlo,
568 &rcDest,
569 &ptSource,
570 NULL,
571 NULL,
572 NULL,
573 ROP3_TO_ROP4(SRCCOPY));
574
575 /* Cleanup EXLATEOBJ */
576 EXLATEOBJ_vCleanup(&exlo);
577
578 Exit:
579 if (NT_SUCCESS(Status))
580 {
581 ret = ScanLines;
582 }
583
584 if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
585 if (ppalDDB) PALETTE_ShareUnlockPalette(ppalDDB);
586
587 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
588 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
589 if (hpalDIB) PALETTE_FreePaletteByHandle(hpalDIB);
590 DC_UnlockDc(pDC);
591
592 return ret;
593 }
594
595
596 /* Converts a device-dependent bitmap to a DIB */
597 INT
598 APIENTRY
599 NtGdiGetDIBitsInternal(
600 HDC hDC,
601 HBITMAP hBitmap,
602 UINT StartScan,
603 UINT ScanLines,
604 LPBYTE Bits,
605 LPBITMAPINFO Info,
606 UINT Usage,
607 UINT MaxBits,
608 UINT MaxInfo)
609 {
610 PDC Dc;
611 SURFACE *psurf = NULL;
612 HBITMAP hDestBitmap = NULL;
613 HPALETTE hDestPalette = NULL;
614 PPALETTE ppalSrc = NULL;
615 PPALETTE ppalDst = NULL;
616 NTSTATUS Status = STATUS_SUCCESS;
617 ULONG Result = 0;
618 BOOL bPaletteMatch = FALSE;
619 PBYTE ChkBits = Bits;
620 PVOID ColorPtr;
621 RGBQUAD *rgbQuads;
622 ULONG DestPaletteType;
623 ULONG Index;
624
625 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
626
627 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
628 return 0;
629
630 // if ScanLines == 0, no need to copy Bits.
631 if (!ScanLines)
632 ChkBits = NULL;
633
634 _SEH2_TRY
635 {
636 ProbeForRead(&Info->bmiHeader.biSize, sizeof(DWORD), 1);
637
638 ProbeForWrite(Info, Info->bmiHeader.biSize, 1); // Comp for Core.
639 if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
640 }
641 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
642 {
643 Status = _SEH2_GetExceptionCode();
644 }
645 _SEH2_END
646
647 if (!NT_SUCCESS(Status))
648 {
649 return 0;
650 }
651
652 Dc = DC_LockDc(hDC);
653 if (Dc == NULL) return 0;
654 if (Dc->dctype == DC_TYPE_INFO)
655 {
656 DC_UnlockDc(Dc);
657 return 0;
658 }
659
660 /* Get a pointer to the source bitmap object */
661 psurf = SURFACE_LockSurface(hBitmap);
662 if (psurf == NULL)
663 {
664 DC_UnlockDc(Dc);
665 return 0;
666 }
667
668 if (psurf->ppal)
669 {
670 ppalSrc = psurf->ppal;
671 GDIOBJ_IncrementShareCount(&ppalSrc->BaseObject);
672 }
673 else
674 ppalSrc = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
675
676 DC_UnlockDc(Dc);
677
678 ASSERT(ppalSrc != NULL);
679
680 ColorPtr = ((PBYTE)Info + Info->bmiHeader.biSize);
681 rgbQuads = (RGBQUAD *)ColorPtr;
682
683 /* Copy palette information
684 * Always create a palette for 15 & 16 bit. */
685 if ((Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
686 Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16) ||
687 !ChkBits)
688 {
689 ppalDst = ppalSrc;
690 bPaletteMatch = TRUE;
691 }
692 else
693 hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
694
695 if (!bPaletteMatch)
696 {
697 ppalDst = PALETTE_LockPalette(hDestPalette);
698 /* FIXME - ppalDst can be NULL!!!! Don't assert here!!! */
699 DPRINT("ppalDst : %p\n", ppalDst);
700 ASSERT(ppalDst);
701 }
702
703 /* Copy palette. */
704 /* FIXME: This is largely incomplete. ATM no Core!*/
705 switch (Info->bmiHeader.biBitCount)
706 {
707 case 1:
708 case 4:
709 case 8:
710 Info->bmiHeader.biClrUsed = 0;
711 if (psurf->hSecure &&
712 BitsPerFormat(psurf->SurfObj.iBitmapFormat) == Info->bmiHeader.biBitCount)
713 {
714 if (Usage == DIB_RGB_COLORS)
715 {
716 if (ppalDst->NumColors != 1 << Info->bmiHeader.biBitCount)
717 Info->bmiHeader.biClrUsed = ppalDst->NumColors;
718 for (Index = 0;
719 Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
720 Index++)
721 {
722 rgbQuads[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
723 rgbQuads[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
724 rgbQuads[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
725 rgbQuads[Index].rgbReserved = 0;
726 }
727 }
728 else
729 {
730 PWORD Ptr = ColorPtr;
731 for (Index = 0;
732 Index < (1 << Info->bmiHeader.biBitCount);
733 Index++)
734 {
735 Ptr[Index] = (WORD)Index;
736 }
737 }
738 }
739 else
740 {
741 if (Usage == DIB_PAL_COLORS)
742 {
743 PWORD Ptr = ColorPtr;
744 for (Index = 0;
745 Index < (1 << Info->bmiHeader.biBitCount);
746 Index++)
747 {
748 Ptr[Index] = (WORD)Index;
749 }
750 }
751 else if (Info->bmiHeader.biBitCount > 1 && bPaletteMatch)
752 {
753 for (Index = 0;
754 Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
755 Index++)
756 {
757 Info->bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
758 Info->bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
759 Info->bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
760 Info->bmiColors[Index].rgbReserved = 0;
761 }
762 }
763 else
764 {
765 switch (Info->bmiHeader.biBitCount)
766 {
767 case 1:
768 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
769 rgbQuads[0].rgbReserved = 0;
770 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
771 rgbQuads[1].rgbReserved = 0;
772 break;
773 case 4:
774 RtlCopyMemory(ColorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
775 break;
776 case 8:
777 {
778 INT r, g, b;
779 RGBQUAD *color;
780
781 RtlCopyMemory(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
782 RtlCopyMemory(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
783 color = rgbQuads + 10;
784 for (r = 0; r <= 5; r++) /* FIXME */
785 for (g = 0; g <= 5; g++)
786 for (b = 0; b <= 5; b++)
787 {
788 color->rgbRed = (r * 0xff) / 5;
789 color->rgbGreen = (g * 0xff) / 5;
790 color->rgbBlue = (b * 0xff) / 5;
791 color->rgbReserved = 0;
792 color++;
793 }
794 }
795 break;
796 }
797 }
798 }
799
800 case 15:
801 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
802 {
803 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
804 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
805 ((PDWORD)Info->bmiColors)[2] = 0x001f;
806 }
807 break;
808
809 case 16:
810 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
811 {
812 ((PDWORD)Info->bmiColors)[0] = 0xf800;
813 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
814 ((PDWORD)Info->bmiColors)[2] = 0x001f;
815 }
816 break;
817
818 case 24:
819 case 32:
820 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
821 {
822 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
823 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
824 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
825 }
826 break;
827 }
828
829 if (!bPaletteMatch)
830 PALETTE_UnlockPalette(ppalDst);
831
832 /* fill out the BITMAPINFO struct */
833 if (!ChkBits)
834 { // Core or not to Core? We have converted from Core in Gdi~ so?
835 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
836 {
837 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
838 coreheader->bcWidth = psurf->SurfObj.sizlBitmap.cx;
839 coreheader->bcPlanes = 1;
840 coreheader->bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
841 coreheader->bcHeight = psurf->SurfObj.sizlBitmap.cy;
842 if (psurf->SurfObj.lDelta > 0)
843 coreheader->bcHeight = -coreheader->bcHeight;
844 }
845
846 if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
847 {
848 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
849 Info->bmiHeader.biHeight = psurf->SurfObj.sizlBitmap.cy;
850 Info->bmiHeader.biPlanes = 1;
851 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
852 switch (psurf->SurfObj.iBitmapFormat)
853 {
854 /* FIXME: What about BI_BITFIELDS? */
855 case BMF_1BPP:
856 case BMF_4BPP:
857 case BMF_8BPP:
858 case BMF_16BPP:
859 case BMF_24BPP:
860 case BMF_32BPP:
861 Info->bmiHeader.biCompression = BI_RGB;
862 break;
863 case BMF_4RLE:
864 Info->bmiHeader.biCompression = BI_RLE4;
865 break;
866 case BMF_8RLE:
867 Info->bmiHeader.biCompression = BI_RLE8;
868 break;
869 case BMF_JPEG:
870 Info->bmiHeader.biCompression = BI_JPEG;
871 break;
872 case BMF_PNG:
873 Info->bmiHeader.biCompression = BI_PNG;
874 break;
875 }
876 /* Image size has to be calculated */
877 Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth,
878 Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight;
879 Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
880 Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
881 Info->bmiHeader.biClrUsed = 0;
882 Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
883 /* Report negtive height for top-down bitmaps. */
884 if (psurf->SurfObj.lDelta > 0)
885 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
886 }
887 Result = psurf->SurfObj.sizlBitmap.cy;
888 }
889 else
890 {
891 SIZEL DestSize;
892 POINTL SourcePoint;
893
894 //
895 // If we have a good dib pointer, why not just copy bits from there w/o XLATE'ing them.
896 //
897 /* Create the destination bitmap too for the copy operation */
898 if (StartScan > psurf->SurfObj.sizlBitmap.cy)
899 {
900 goto cleanup;
901 }
902 else
903 {
904 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
905 DestSize.cx = psurf->SurfObj.sizlBitmap.cx;
906 DestSize.cy = ScanLines;
907
908 hDestBitmap = NULL;
909
910 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
911 {
912 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
913 hDestBitmap = EngCreateBitmap(DestSize,
914 DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount),
915 BitmapFormat(coreheader->bcBitCount, BI_RGB),
916 0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN,
917 Bits);
918 }
919
920 if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
921 {
922 Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
923 Info->bmiHeader.biBitCount) * DestSize.cy;
924
925 hDestBitmap = EngCreateBitmap(DestSize,
926 DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
927 BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
928 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
929 Bits);
930 }
931
932 if (hDestBitmap == NULL)
933 goto cleanup;
934 }
935
936 if (NT_SUCCESS(Status))
937 {
938 EXLATEOBJ exlo;
939 SURFOBJ *DestSurfObj;
940 RECTL DestRect;
941
942 EXLATEOBJ_vInitialize(&exlo, ppalSrc, ppalDst, 0, 0, 0);
943
944 SourcePoint.x = 0;
945 SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
946
947 /* Determine destination rectangle */
948 DestRect.top = 0;
949 DestRect.left = 0;
950 DestRect.right = DestSize.cx;
951 DestRect.bottom = DestSize.cy;
952
953 DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
954
955 if (IntEngCopyBits(DestSurfObj,
956 &psurf->SurfObj,
957 NULL,
958 &exlo.xlo,
959 &DestRect,
960 &SourcePoint))
961 {
962 DPRINT("GetDIBits %d \n",abs(Info->bmiHeader.biHeight) - StartScan);
963 Result = ScanLines;
964 }
965
966 EXLATEOBJ_vCleanup(&exlo);
967 EngUnlockSurface(DestSurfObj);
968 }
969 }
970 cleanup:
971 PALETTE_ShareUnlockPalette(ppalSrc);
972
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 = GreCreateBitmap(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 = Dc->ppdev->gdiinfo.cBitsPixel;
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 HPALETTE hpal ;
1350
1351 // Fill BITMAP32 structure with DIB data
1352 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1353 INT effHeight;
1354 ULONG totalSize;
1355 BITMAP bm;
1356 SIZEL Size;
1357 RGBQUAD *lpRGB;
1358 HANDLE hSecure;
1359 DWORD dsBitfields[3] = {0};
1360 ULONG ColorCount;
1361
1362 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1363 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1364 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1365
1366 /* CreateDIBSection should fail for compressed formats */
1367 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1368 {
1369 return (HBITMAP)NULL;
1370 }
1371
1372 pdcattr = dc->pdcattr;
1373
1374 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1375 bm.bmType = 0;
1376 bm.bmWidth = bi->biWidth;
1377 bm.bmHeight = effHeight;
1378 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1379
1380 bm.bmPlanes = bi->biPlanes;
1381 bm.bmBitsPixel = bi->biBitCount;
1382 bm.bmBits = NULL;
1383
1384 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1385 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1386 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1387 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1388
1389 if (section)
1390 {
1391 SYSTEM_BASIC_INFORMATION Sbi;
1392 NTSTATUS Status;
1393 DWORD mapOffset;
1394 LARGE_INTEGER SectionOffset;
1395 SIZE_T mapSize;
1396
1397 Status = ZwQuerySystemInformation(SystemBasicInformation,
1398 &Sbi,
1399 sizeof Sbi,
1400 0);
1401 if (!NT_SUCCESS(Status))
1402 {
1403 return NULL;
1404 }
1405
1406 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1407 mapSize = bi->biSizeImage + (offset - mapOffset);
1408
1409 SectionOffset.LowPart = mapOffset;
1410 SectionOffset.HighPart = 0;
1411
1412 Status = ZwMapViewOfSection(section,
1413 NtCurrentProcess(),
1414 &mapBits,
1415 0,
1416 0,
1417 &SectionOffset,
1418 &mapSize,
1419 ViewShare,
1420 0,
1421 PAGE_READWRITE);
1422 if (!NT_SUCCESS(Status))
1423 {
1424 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1425 return NULL;
1426 }
1427
1428 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1429 }
1430 else if (ovr_pitch && offset)
1431 bm.bmBits = (LPVOID) offset;
1432 else
1433 {
1434 offset = 0;
1435 bm.bmBits = EngAllocUserMem(totalSize, 0);
1436 }
1437
1438 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1439 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1440
1441 if (usage == DIB_PAL_COLORS)
1442 {
1443 lpRGB = DIB_MapPaletteColors(dc, bmi);
1444 ColorCount = bi->biClrUsed;
1445 if (ColorCount == 0)
1446 {
1447 ColorCount = 1 << bi->biBitCount;
1448 }
1449 }
1450 else
1451 {
1452 lpRGB = bmi->bmiColors;
1453 ColorCount = 1 << bi->biBitCount;
1454 }
1455
1456 /* Set dsBitfields values */
1457 if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1458 {
1459 dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
1460 }
1461 else if (bi->biCompression == BI_RGB)
1462 {
1463 switch (bi->biBitCount)
1464 {
1465 case 15:
1466 dsBitfields[0] = 0x7c00;
1467 dsBitfields[1] = 0x03e0;
1468 dsBitfields[2] = 0x001f;
1469 break;
1470
1471 case 16:
1472 dsBitfields[0] = 0xF800;
1473 dsBitfields[1] = 0x07e0;
1474 dsBitfields[2] = 0x001f;
1475 break;
1476
1477 case 24:
1478 case 32:
1479 dsBitfields[0] = 0xff0000;
1480 dsBitfields[1] = 0x00ff00;
1481 dsBitfields[2] = 0x0000ff;
1482 break;
1483 }
1484 }
1485 else
1486 {
1487 dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
1488 dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
1489 dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
1490 }
1491
1492 // Create Device Dependent Bitmap and add DIB pointer
1493 Size.cx = bm.bmWidth;
1494 Size.cy = abs(bm.bmHeight);
1495 res = IntCreateBitmap(Size,
1496 bm.bmWidthBytes,
1497 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1498 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1499 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1500 bm.bmBits);
1501 if (!res)
1502 {
1503 if (lpRGB != bmi->bmiColors)
1504 {
1505 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1506 }
1507 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1508 return NULL;
1509 }
1510 bmp = SURFACE_LockSurface(res);
1511 if (NULL == bmp)
1512 {
1513 if (lpRGB != bmi->bmiColors)
1514 {
1515 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1516 }
1517 SetLastWin32Error(ERROR_INVALID_HANDLE);
1518 GreDeleteObject(res);
1519 return NULL;
1520 }
1521
1522 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1523 table between the DIB and the X physical device. Obviously,
1524 this is left out of the ReactOS implementation. Instead,
1525 we call NtGdiSetDIBColorTable. */
1526 if (bi->biBitCount <= 8)
1527 {
1528 bi->biClrUsed = 1 << bi->biBitCount;
1529 }
1530 else
1531 {
1532 bi->biClrUsed = 0;
1533 }
1534
1535 bmp->hDIBSection = section;
1536 bmp->hSecure = hSecure;
1537 bmp->dwOffset = offset;
1538 bmp->flags = API_BITMAP;
1539 bmp->dsBitfields[0] = dsBitfields[0];
1540 bmp->dsBitfields[1] = dsBitfields[1];
1541 bmp->dsBitfields[2] = dsBitfields[2];
1542 bmp->biClrUsed = bi->biClrUsed;
1543 bmp->biClrImportant = bi->biClrImportant;
1544
1545 if (bi->biClrUsed != 0)
1546 {
1547 hpal = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
1548 }
1549 else
1550 {
1551 hpal = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1552 dsBitfields[0],
1553 dsBitfields[1],
1554 dsBitfields[2]);
1555 }
1556
1557 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1558 /* Lazy delete hpal, it will be freed at surface release */
1559 GreDeleteObject(hpal);
1560
1561 // Clean up in case of errors
1562 if (!res || !bmp || !bm.bmBits)
1563 {
1564 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1565 if (bm.bmBits)
1566 {
1567 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1568 if (section)
1569 {
1570 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1571 bm.bmBits = NULL;
1572 }
1573 else
1574 if (!offset)
1575 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1576 }
1577
1578 if (bmp)
1579 bmp = NULL;
1580
1581 if (res)
1582 {
1583 SURFACE_FreeSurfaceByHandle(res);
1584 res = 0;
1585 }
1586 }
1587
1588 if (lpRGB != bmi->bmiColors)
1589 {
1590 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1591 }
1592
1593 if (bmp)
1594 {
1595 SURFACE_UnlockSurface(bmp);
1596 }
1597
1598 // Return BITMAP handle and storage location
1599 if (NULL != bm.bmBits && NULL != bits)
1600 {
1601 *bits = bm.bmBits;
1602 }
1603
1604 if (res) pdcattr->ulDirty_ |= DC_DIBSECTION;
1605
1606 return res;
1607 }
1608
1609 /***********************************************************************
1610 * DIB_GetDIBWidthBytes
1611 *
1612 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1613 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1614 * 11/16/1999 (RJJ) lifted from wine
1615 */
1616 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1617 {
1618 return ((width * depth + 31) & ~31) >> 3;
1619 }
1620
1621 /***********************************************************************
1622 * DIB_GetDIBImageBytes
1623 *
1624 * Return the number of bytes used to hold the image in a DIB bitmap.
1625 * 11/16/1999 (RJJ) lifted from wine
1626 */
1627
1628 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1629 {
1630 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1631 }
1632
1633 /***********************************************************************
1634 * DIB_BitmapInfoSize
1635 *
1636 * Return the size of the bitmap info structure including color table.
1637 * 11/16/1999 (RJJ) lifted from wine
1638 */
1639
1640 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1641 {
1642 int colors;
1643
1644 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1645 {
1646 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1647 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1648 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1649 }
1650 else /* assume BITMAPINFOHEADER */
1651 {
1652 colors = info->bmiHeader.biClrUsed;
1653 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1654 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1655 }
1656 }
1657
1658 RGBQUAD *
1659 FASTCALL
1660 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1661 {
1662 RGBQUAD *lpRGB;
1663 ULONG nNumColors,i;
1664 USHORT *lpIndex;
1665 PPALETTE palGDI;
1666
1667 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
1668
1669 if (NULL == palGDI)
1670 {
1671 return NULL;
1672 }
1673
1674 if (palGDI->Mode != PAL_INDEXED)
1675 {
1676 PALETTE_UnlockPalette(palGDI);
1677 return NULL;
1678 }
1679
1680 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1681 if (lpbmi->bmiHeader.biClrUsed)
1682 {
1683 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1684 }
1685
1686 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1687 if (lpRGB == NULL)
1688 {
1689 PALETTE_UnlockPalette(palGDI);
1690 return NULL;
1691 }
1692
1693 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1694
1695 for (i = 0; i < nNumColors; i++)
1696 {
1697 if (*lpIndex < palGDI->NumColors)
1698 {
1699 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1700 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1701 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1702 }
1703 else
1704 {
1705 lpRGB[i].rgbRed = 0;
1706 lpRGB[i].rgbGreen = 0;
1707 lpRGB[i].rgbBlue = 0;
1708 }
1709 lpRGB[i].rgbReserved = 0;
1710 lpIndex++;
1711 }
1712 PALETTE_UnlockPalette(palGDI);
1713
1714 return lpRGB;
1715 }
1716
1717 HPALETTE
1718 FASTCALL
1719 BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
1720 {
1721 BYTE bits;
1722 ULONG ColorCount;
1723 PALETTEENTRY *palEntries = NULL;
1724 HPALETTE hPal;
1725 ULONG RedMask, GreenMask, BlueMask;
1726
1727 // Determine Bits Per Pixel
1728 bits = bmi->bmiHeader.biBitCount;
1729
1730 // Determine paletteType from Bits Per Pixel
1731 if (bits <= 8)
1732 {
1733 *paletteType = PAL_INDEXED;
1734 RedMask = GreenMask = BlueMask = 0;
1735 }
1736 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1737 {
1738 *paletteType = PAL_BITFIELDS;
1739 RedMask = ((ULONG *)bmi->bmiColors)[0];
1740 GreenMask = ((ULONG *)bmi->bmiColors)[1];
1741 BlueMask = ((ULONG *)bmi->bmiColors)[2];
1742 }
1743 else if (bits == 15)
1744 {
1745 *paletteType = PAL_BITFIELDS;
1746 RedMask = 0x7c00;
1747 GreenMask = 0x03e0;
1748 BlueMask = 0x001f;
1749 }
1750 else if (bits == 16)
1751 {
1752 *paletteType = PAL_BITFIELDS;
1753 RedMask = 0xF800;
1754 GreenMask = 0x07e0;
1755 BlueMask = 0x001f;
1756 }
1757 else
1758 {
1759 *paletteType = PAL_BGR;
1760 RedMask = 0xff0000;
1761 GreenMask = 0x00ff00;
1762 BlueMask = 0x0000ff;
1763 }
1764
1765 if (bmi->bmiHeader.biClrUsed == 0)
1766 {
1767 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1768 }
1769 else
1770 {
1771 ColorCount = bmi->bmiHeader.biClrUsed;
1772 }
1773
1774 if (PAL_INDEXED == *paletteType)
1775 {
1776 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1777 }
1778 else
1779 {
1780 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1781 (ULONG*) palEntries,
1782 RedMask, GreenMask, BlueMask);
1783 }
1784
1785 return hPal;
1786 }
1787
1788 /* EOF */