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