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