[ZLIB]
[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 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 ASSERT(bitmap->ppal);
282
283 // Source palette obtained from the BITMAPINFO
284 DIB_Palette = BuildDIBPalette(bmi, (PINT)&DIB_Palette_Type);
285 if (NULL == DIB_Palette)
286 {
287 EngUnlockSurface(SourceSurf);
288 EngDeleteSurface((HSURF)SourceBitmap);
289 SURFACE_UnlockSurface(bitmap);
290 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
291 return 0;
292 }
293
294 ppalDIB = PALETTE_LockPalette(DIB_Palette);
295
296 /* Initialize XLATEOBJ for color translation */
297 EXLATEOBJ_vInitialize(&exlo, ppalDIB, bitmap->ppal, 0, 0, 0);
298
299 // Zero point
300 ZeroPoint.x = 0;
301 ZeroPoint.y = 0;
302
303 // Determine destination rectangle
304 DestRect.left = 0;
305 DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
306 DestRect.right = SourceSize.cx;
307 DestRect.bottom = DestRect.top + ScanLines;
308
309 copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
310
311 // If it succeeded, return number of scanlines copies
312 if (copyBitsResult == TRUE)
313 {
314 result = SourceSize.cy;
315 // or
316 // result = abs(bmi->bmiHeader.biHeight) - StartScan;
317 }
318
319 // Clean up
320 EXLATEOBJ_vCleanup(&exlo);
321 PALETTE_UnlockPalette(ppalDIB);
322 PALETTE_FreePaletteByHandle(DIB_Palette);
323 EngUnlockSurface(SourceSurf);
324 EngDeleteSurface((HSURF)SourceBitmap);
325
326 // if (ColorUse == DIB_PAL_COLORS)
327 // WinFree((LPSTR)lpRGB);
328
329 SURFACE_UnlockSurface(bitmap);
330
331 return result;
332 }
333
334 // FIXME by Removing NtGdiSetDIBits!!!
335 // This is a victim of the Win32k Initialization BUG!!!!!
336 // Converts a DIB to a device-dependent bitmap
337 INT
338 APIENTRY
339 NtGdiSetDIBits(
340 HDC hDC,
341 HBITMAP hBitmap,
342 UINT StartScan,
343 UINT ScanLines,
344 CONST VOID *Bits,
345 CONST BITMAPINFO *bmi,
346 UINT ColorUse)
347 {
348 PDC Dc;
349 INT Ret;
350 NTSTATUS Status = STATUS_SUCCESS;
351 BITMAPV5INFO bmiLocal;
352
353 if (!Bits) return 0;
354
355 _SEH2_TRY
356 {
357 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, 0);
358 ProbeForRead(Bits, bmiLocal.bmiHeader.bV5SizeImage, 1);
359 }
360 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
361 {
362 Status = _SEH2_GetExceptionCode();
363 }
364 _SEH2_END
365
366 if (!NT_SUCCESS(Status))
367 {
368 return 0;
369 }
370
371 Dc = DC_LockDc(hDC);
372 if (NULL == Dc)
373 {
374 SetLastWin32Error(ERROR_INVALID_HANDLE);
375 return 0;
376 }
377 if (Dc->dctype == DC_TYPE_INFO)
378 {
379 DC_UnlockDc(Dc);
380 return 0;
381 }
382
383 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, (PBITMAPINFO)&bmiLocal, ColorUse);
384
385 DC_UnlockDc(Dc);
386
387 return Ret;
388 }
389
390 W32KAPI
391 INT
392 APIENTRY
393 NtGdiSetDIBitsToDeviceInternal(
394 IN HDC hDC,
395 IN INT XDest,
396 IN INT YDest,
397 IN DWORD Width,
398 IN DWORD Height,
399 IN INT XSrc,
400 IN INT YSrc,
401 IN DWORD StartScan,
402 IN DWORD ScanLines,
403 IN LPBYTE Bits,
404 IN LPBITMAPINFO bmi,
405 IN DWORD ColorUse,
406 IN UINT cjMaxBits,
407 IN UINT cjMaxInfo,
408 IN BOOL bTransformCoordinates,
409 IN OPTIONAL HANDLE hcmXform)
410 {
411 INT ret = 0;
412 NTSTATUS Status = STATUS_SUCCESS;
413 PDC pDC;
414 HBITMAP hSourceBitmap = NULL;
415 SURFOBJ *pDestSurf, *pSourceSurf = NULL;
416 SURFACE *pSurf;
417 RECTL rcDest;
418 POINTL ptSource;
419 INT DIBWidth;
420 SIZEL SourceSize;
421 EXLATEOBJ exlo;
422 PPALETTE ppalDIB = NULL;
423 HPALETTE hpalDIB = NULL;
424 ULONG DIBPaletteType;
425 BITMAPV5INFO bmiLocal ;
426
427 if (!Bits) return 0;
428
429 _SEH2_TRY
430 {
431 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, cjMaxInfo);
432 ProbeForRead(Bits, cjMaxBits, 1);
433 }
434 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
435 {
436 Status = _SEH2_GetExceptionCode();
437 }
438 _SEH2_END
439
440 if (!NT_SUCCESS(Status))
441 {
442 return 0;
443 }
444
445 pDC = DC_LockDc(hDC);
446 if (!pDC)
447 {
448 SetLastWin32Error(ERROR_INVALID_HANDLE);
449 return 0;
450 }
451 if (pDC->dctype == DC_TYPE_INFO)
452 {
453 DC_UnlockDc(pDC);
454 return 0;
455 }
456
457 pSurf = pDC->dclevel.pSurface;
458
459 pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
460
461 ScanLines = min(ScanLines, abs(bmiLocal.bmiHeader.bV5Height) - StartScan);
462
463 rcDest.left = XDest;
464 rcDest.top = YDest;
465 if (bTransformCoordinates)
466 {
467 CoordLPtoDP(pDC, (LPPOINT)&rcDest);
468 }
469 rcDest.left += pDC->ptlDCOrig.x;
470 rcDest.top += pDC->ptlDCOrig.y;
471 rcDest.right = rcDest.left + Width;
472 rcDest.bottom = rcDest.top + Height;
473 rcDest.top += StartScan;
474
475 ptSource.x = XSrc;
476 ptSource.y = YSrc;
477
478 SourceSize.cx = bmiLocal.bmiHeader.bV5Width;
479 SourceSize.cy = ScanLines;
480
481 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmiLocal.bmiHeader.bV5BitCount);
482
483 hSourceBitmap = EngCreateBitmap(SourceSize,
484 DIBWidth,
485 BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
486 bmiLocal.bmiHeader.bV5Compression),
487 bmiLocal.bmiHeader.bV5Height < 0 ? BMF_TOPDOWN : 0,
488 (PVOID) Bits);
489 if (!hSourceBitmap)
490 {
491 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
492 Status = STATUS_NO_MEMORY;
493 goto Exit;
494 }
495
496 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
497 if (!pSourceSurf)
498 {
499 Status = STATUS_UNSUCCESSFUL;
500 goto Exit;
501 }
502
503 ASSERT(pSurf->ppal);
504
505 /* Create a palette for the DIB */
506 hpalDIB = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DIBPaletteType);
507 if (!hpalDIB)
508 {
509 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
510 Status = STATUS_NO_MEMORY;
511 goto Exit;
512 }
513
514 /* Lock the DIB palette */
515 ppalDIB = PALETTE_LockPalette(hpalDIB);
516 if (!ppalDIB)
517 {
518 SetLastWin32Error(ERROR_INVALID_HANDLE);
519 Status = STATUS_UNSUCCESSFUL;
520 goto Exit;
521 }
522
523 /* Initialize EXLATEOBJ */
524 EXLATEOBJ_vInitialize(&exlo, ppalDIB, pSurf->ppal, 0, 0, 0);
525
526 /* Copy the bits */
527 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
528 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
529 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
530 Status = IntEngBitBlt(pDestSurf,
531 pSourceSurf,
532 NULL,
533 pDC->rosdc.CombinedClip,
534 &exlo.xlo,
535 &rcDest,
536 &ptSource,
537 NULL,
538 NULL,
539 NULL,
540 ROP3_TO_ROP4(SRCCOPY));
541
542 /* Cleanup EXLATEOBJ */
543 EXLATEOBJ_vCleanup(&exlo);
544
545 Exit:
546 if (NT_SUCCESS(Status))
547 {
548 ret = ScanLines;
549 }
550
551 if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
552
553 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
554 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
555 if (hpalDIB) PALETTE_FreePaletteByHandle(hpalDIB);
556 DC_UnlockDc(pDC);
557
558 return ret;
559 }
560
561
562 /* Converts a device-dependent bitmap to a DIB */
563 INT
564 APIENTRY
565 NtGdiGetDIBitsInternal(
566 HDC hDC,
567 HBITMAP hBitmap,
568 UINT StartScan,
569 UINT ScanLines,
570 LPBYTE Bits,
571 LPBITMAPINFO Info,
572 UINT Usage,
573 UINT MaxBits,
574 UINT MaxInfo)
575 {
576 PDC Dc;
577 SURFACE *psurf = NULL;
578 HBITMAP hDestBitmap = NULL;
579 HPALETTE hDestPalette = NULL;
580 BITMAPV5INFO bmiLocal ;
581 PPALETTE ppalDst = NULL;
582 NTSTATUS Status = STATUS_SUCCESS;
583 ULONG Result = 0;
584 BOOL bPaletteMatch = FALSE;
585 PBYTE ChkBits = Bits;
586 ULONG DestPaletteType;
587 ULONG Index;
588
589 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
590
591 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
592 return 0;
593
594 // if ScanLines == 0, no need to copy Bits.
595 if (!ScanLines)
596 ChkBits = NULL;
597
598 _SEH2_TRY
599 {
600 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage, MaxInfo);
601 if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
602 }
603 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
604 {
605 Status = _SEH2_GetExceptionCode();
606 }
607 _SEH2_END
608
609 if (!NT_SUCCESS(Status))
610 {
611 return 0;
612 }
613
614 Dc = DC_LockDc(hDC);
615 if (Dc == NULL) return 0;
616 if (Dc->dctype == DC_TYPE_INFO)
617 {
618 DC_UnlockDc(Dc);
619 return 0;
620 }
621
622 /* Get a pointer to the source bitmap object */
623 psurf = SURFACE_LockSurface(hBitmap);
624 if (psurf == NULL)
625 {
626 DC_UnlockDc(Dc);
627 return 0;
628 }
629
630 ASSERT(psurf->ppal);
631
632 DC_UnlockDc(Dc);
633
634 /* Copy palette information
635 * Always create a palette for 15 & 16 bit. */
636 if ((bmiLocal.bmiHeader.bV5BitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
637 bmiLocal.bmiHeader.bV5BitCount != 15 && bmiLocal.bmiHeader.bV5BitCount != 16) ||
638 !ChkBits)
639 {
640 ppalDst = psurf->ppal;
641 bPaletteMatch = TRUE;
642 }
643 else
644 {
645 hDestPalette = BuildDIBPalette((PBITMAPINFO)&bmiLocal, (PINT)&DestPaletteType);
646 ppalDst = PALETTE_LockPalette(hDestPalette);
647 }
648
649 DPRINT("ppalDst : %p\n", ppalDst);
650 ASSERT(ppalDst);
651
652 /* Copy palette. */
653 switch (bmiLocal.bmiHeader.bV5BitCount)
654 {
655 case 1:
656 case 4:
657 case 8:
658 bmiLocal.bmiHeader.bV5ClrUsed = 0;
659 if (psurf->hSecure &&
660 BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bmiLocal.bmiHeader.bV5BitCount)
661 {
662 if (Usage == DIB_RGB_COLORS)
663 {
664 if (ppalDst->NumColors != 1 << bmiLocal.bmiHeader.bV5BitCount)
665 bmiLocal.bmiHeader.bV5ClrUsed = ppalDst->NumColors;
666 for (Index = 0;
667 Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors;
668 Index++)
669 {
670 bmiLocal.bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
671 bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
672 bmiLocal.bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
673 bmiLocal.bmiColors[Index].rgbReserved = 0;
674 }
675 }
676 else
677 {
678 for (Index = 0;
679 Index < (1 << bmiLocal.bmiHeader.bV5BitCount);
680 Index++)
681 {
682 ((WORD*)bmiLocal.bmiColors)[Index] = Index;
683 }
684 }
685 }
686 else
687 {
688 if (Usage == DIB_PAL_COLORS)
689 {
690 for (Index = 0;
691 Index < (1 << bmiLocal.bmiHeader.bV5BitCount);
692 Index++)
693 {
694 ((WORD*)bmiLocal.bmiColors)[Index] = (WORD)Index;
695 }
696 }
697 else if (bmiLocal.bmiHeader.bV5BitCount > 1 && bPaletteMatch)
698 {
699 for (Index = 0;
700 Index < (1 << bmiLocal.bmiHeader.bV5BitCount) && Index < ppalDst->NumColors;
701 Index++)
702 {
703 bmiLocal.bmiColors[Index].rgbRed = ppalDst->IndexedColors[Index].peRed;
704 bmiLocal.bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
705 bmiLocal.bmiColors[Index].rgbBlue = ppalDst->IndexedColors[Index].peBlue;
706 bmiLocal.bmiColors[Index].rgbReserved = 0;
707 }
708 }
709 else
710 {
711 switch (bmiLocal.bmiHeader.bV5BitCount)
712 {
713 case 1:
714 bmiLocal.bmiColors[0].rgbRed =0 ;
715 bmiLocal.bmiColors[0].rgbGreen = 0;
716 bmiLocal.bmiColors[0].rgbBlue = 0;
717 bmiLocal.bmiColors[0].rgbReserved = 0;
718 bmiLocal.bmiColors[1].rgbRed =0xFF ;
719 bmiLocal.bmiColors[1].rgbGreen = 0xFF;
720 bmiLocal.bmiColors[1].rgbBlue = 0xFF;
721 bmiLocal.bmiColors[1].rgbReserved = 0;
722 break;
723 case 4:
724 RtlCopyMemory(bmiLocal.bmiColors, EGAColorsQuads, sizeof(EGAColorsQuads));
725 break;
726 case 8:
727 {
728 INT r, g, b;
729 RGBQUAD *color;
730
731 RtlCopyMemory(bmiLocal.bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
732 RtlCopyMemory(bmiLocal.bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
733 color = bmiLocal.bmiColors + 10;
734 for (r = 0; r <= 5; r++) /* FIXME */
735 for (g = 0; g <= 5; g++)
736 for (b = 0; b <= 5; b++)
737 {
738 color->rgbRed = (r * 0xff) / 5;
739 color->rgbGreen = (g * 0xff) / 5;
740 color->rgbBlue = (b * 0xff) / 5;
741 color->rgbReserved = 0;
742 color++;
743 }
744 }
745 break;
746 }
747 }
748 }
749
750 case 15:
751 if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
752 {
753 bmiLocal.bmiHeader.bV5RedMask = 0x7c00;
754 bmiLocal.bmiHeader.bV5GreenMask = 0x03e0;
755 bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
756 }
757 break;
758
759 case 16:
760 if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
761 {
762 bmiLocal.bmiHeader.bV5RedMask = 0xf800;
763 bmiLocal.bmiHeader.bV5GreenMask = 0x07e0;
764 bmiLocal.bmiHeader.bV5BlueMask = 0x001f;
765 }
766 break;
767
768 case 24:
769 case 32:
770 if (bmiLocal.bmiHeader.bV5Compression == BI_BITFIELDS)
771 {
772 bmiLocal.bmiHeader.bV5RedMask = 0xff0000;
773 bmiLocal.bmiHeader.bV5GreenMask = 0x00ff00;
774 bmiLocal.bmiHeader.bV5BlueMask = 0x0000ff;
775 }
776 break;
777 }
778
779 /* fill out the BITMAPINFO struct */
780 if (!ChkBits)
781 {
782 bmiLocal.bmiHeader.bV5Width = psurf->SurfObj.sizlBitmap.cx;
783 /* Report negative height for top-down bitmaps. */
784 if (psurf->SurfObj.fjBitmap & BMF_TOPDOWN)
785 bmiLocal.bmiHeader.bV5Height = - psurf->SurfObj.sizlBitmap.cy;
786 else
787 bmiLocal.bmiHeader.bV5Height = psurf->SurfObj.sizlBitmap.cy;
788 bmiLocal.bmiHeader.bV5Planes = 1;
789 bmiLocal.bmiHeader.bV5BitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
790 switch (psurf->SurfObj.iBitmapFormat)
791 {
792 /* FIXME: What about BI_BITFIELDS? */
793 case BMF_1BPP:
794 case BMF_4BPP:
795 case BMF_8BPP:
796 case BMF_16BPP:
797 case BMF_24BPP:
798 case BMF_32BPP:
799 bmiLocal.bmiHeader.bV5Compression = BI_RGB;
800 break;
801 case BMF_4RLE:
802 bmiLocal.bmiHeader.bV5Compression = BI_RLE4;
803 break;
804 case BMF_8RLE:
805 bmiLocal.bmiHeader.bV5Compression = BI_RLE8;
806 break;
807 case BMF_JPEG:
808 bmiLocal.bmiHeader.bV5Compression = BI_JPEG;
809 break;
810 case BMF_PNG:
811 bmiLocal.bmiHeader.bV5Compression = BI_PNG;
812 break;
813 }
814
815 bmiLocal.bmiHeader.bV5SizeImage = psurf->SurfObj.cjBits;
816 bmiLocal.bmiHeader.bV5XPelsPerMeter = psurf->sizlDim.cx; /* FIXME */
817 bmiLocal.bmiHeader.bV5YPelsPerMeter = psurf->sizlDim.cy; /* FIXME */
818 bmiLocal.bmiHeader.bV5ClrUsed = 0;
819 bmiLocal.bmiHeader.bV5ClrImportant = 1 << bmiLocal.bmiHeader.bV5BitCount; /* FIXME */
820 Result = psurf->SurfObj.sizlBitmap.cy;
821 }
822 else
823 {
824 SIZEL DestSize;
825 POINTL SourcePoint;
826
827 //
828 // If we have a good dib pointer, why not just copy bits from there w/o XLATE'ing them.
829 //
830 /* Create the destination bitmap too for the copy operation */
831 if (StartScan > psurf->SurfObj.sizlBitmap.cy)
832 {
833 goto cleanup;
834 }
835 else
836 {
837 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
838 DestSize.cx = psurf->SurfObj.sizlBitmap.cx;
839 DestSize.cy = ScanLines;
840
841 hDestBitmap = NULL;
842
843 bmiLocal.bmiHeader.bV5SizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
844 bmiLocal.bmiHeader.bV5BitCount) * DestSize.cy;
845
846 hDestBitmap = EngCreateBitmap(DestSize,
847 DIB_GetDIBWidthBytes(DestSize.cx,
848 bmiLocal.bmiHeader.bV5BitCount),
849 BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
850 bmiLocal.bmiHeader.bV5Compression),
851 bmiLocal.bmiHeader.bV5Height > 0 ? 0 : BMF_TOPDOWN,
852 Bits);
853
854 if (hDestBitmap == NULL)
855 goto cleanup;
856 }
857
858 if (NT_SUCCESS(Status))
859 {
860 EXLATEOBJ exlo;
861 SURFOBJ *DestSurfObj;
862 RECTL DestRect;
863
864 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, ppalDst, 0, 0, 0);
865
866 SourcePoint.x = 0;
867 SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
868
869 /* Determine destination rectangle */
870 DestRect.top = 0;
871 DestRect.left = 0;
872 DestRect.right = DestSize.cx;
873 DestRect.bottom = DestSize.cy;
874
875 DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
876
877 if (IntEngCopyBits(DestSurfObj,
878 &psurf->SurfObj,
879 NULL,
880 &exlo.xlo,
881 &DestRect,
882 &SourcePoint))
883 {
884 DPRINT("GetDIBits %d \n",abs(bmiLocal.bmiHeader.bV5Height) - StartScan);
885 Result = ScanLines;
886 }
887
888 EXLATEOBJ_vCleanup(&exlo);
889 EngUnlockSurface(DestSurfObj);
890 }
891 }
892
893 /* Now that everything is over, get back the information to caller */
894 _SEH2_TRY
895 {
896 /* Note : Info has already been probed */
897 GetBMIFromBitmapV5Info(&bmiLocal, Info, Usage);
898 }
899 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
900 {
901 /* FIXME: fail or something */
902 }
903 _SEH2_END
904
905 cleanup:
906
907 if (hDestBitmap != NULL)
908 EngDeleteSurface((HSURF)hDestBitmap);
909
910 if (hDestPalette != NULL && !bPaletteMatch)
911 {
912 PALETTE_UnlockPalette(ppalDst);
913 PALETTE_FreePaletteByHandle(hDestPalette);
914 }
915
916 SURFACE_UnlockSurface(psurf);
917
918 DPRINT("leaving NtGdiGetDIBitsInternal\n");
919
920 return Result;
921 }
922
923 INT
924 APIENTRY
925 NtGdiStretchDIBitsInternal(
926 HDC hDC,
927 INT XDest,
928 INT YDest,
929 INT DestWidth,
930 INT DestHeight,
931 INT XSrc,
932 INT YSrc,
933 INT SrcWidth,
934 INT SrcHeight,
935 LPBYTE Bits,
936 LPBITMAPINFO BitsInfo,
937 DWORD Usage,
938 DWORD ROP,
939 UINT cjMaxInfo,
940 UINT cjMaxBits,
941 HANDLE hcmXform)
942 {
943 HBITMAP hBitmap, hOldBitmap = NULL;
944 HDC hdcMem;
945 HPALETTE hPal = NULL;
946 PDC pDC;
947 NTSTATUS Status;
948 BITMAPV5INFO bmiLocal ;
949
950 if (!Bits || !BitsInfo)
951 {
952 SetLastWin32Error(ERROR_INVALID_PARAMETER);
953 return 0;
954 }
955
956 _SEH2_TRY
957 {
958 Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, BitsInfo, Usage, cjMaxInfo);
959 ProbeForRead(Bits, cjMaxBits, 1);
960 }
961 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
962 {
963 Status = _SEH2_GetExceptionCode();
964 }
965 _SEH2_END
966
967 if (!NT_SUCCESS(Status))
968 {
969 DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
970 return 0;
971 }
972
973 hdcMem = NtGdiCreateCompatibleDC(hDC);
974 if (hdcMem == NULL)
975 {
976 DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
977 return 0;
978 }
979
980 hBitmap = NtGdiCreateCompatibleBitmap(hDC,
981 abs(bmiLocal.bmiHeader.bV5Width),
982 abs(bmiLocal.bmiHeader.bV5Height));
983 if (hBitmap == NULL)
984 {
985 DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
986 DPRINT1("hDC : 0x%08x \n", hDC);
987 DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
988 DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
989 return 0;
990 }
991
992 /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
993 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
994
995 if (Usage == DIB_PAL_COLORS)
996 {
997 hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
998 hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
999 }
1000
1001 if (bmiLocal.bmiHeader.bV5Compression == BI_RLE4 ||
1002 bmiLocal.bmiHeader.bV5Compression == BI_RLE8)
1003 {
1004 /* copy existing bitmap from destination dc */
1005 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
1006 NtGdiBitBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1007 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
1008 else
1009 NtGdiStretchBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1010 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
1011 ROP, 0);
1012 }
1013
1014 pDC = DC_LockDc(hdcMem);
1015 if (pDC != NULL)
1016 {
1017 /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
1018 * if it negitve we getting to many scanline for scanline is UINT not
1019 * a INT, so we need make the negtive value to positve and that make the
1020 * count correct for negtive bitmap, TODO : we need testcase for this api */
1021 IntSetDIBits(pDC, hBitmap, 0, abs(bmiLocal.bmiHeader.bV5Height), Bits,
1022 (PBITMAPINFO)&bmiLocal, Usage);
1023
1024 DC_UnlockDc(pDC);
1025 }
1026
1027
1028 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
1029 left (negative biHeight) */
1030 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
1031 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1032 hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1033 ROP, 0, 0);
1034 else
1035 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
1036 hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
1037 SrcWidth, SrcHeight, ROP, 0);
1038
1039 /* cleanup */
1040 if (hPal)
1041 GdiSelectPalette(hdcMem, hPal, FALSE);
1042
1043 if (hOldBitmap)
1044 NtGdiSelectBitmap(hdcMem, hOldBitmap);
1045
1046 NtGdiDeleteObjectApp(hdcMem);
1047
1048 GreDeleteObject(hBitmap);
1049
1050 return SrcHeight;
1051 }
1052
1053
1054 HBITMAP
1055 FASTCALL
1056 IntCreateDIBitmap(
1057 PDC Dc,
1058 INT width,
1059 INT height,
1060 UINT bpp,
1061 DWORD init,
1062 LPBYTE bits,
1063 PBITMAPV5INFO data,
1064 DWORD coloruse)
1065 {
1066 HBITMAP handle;
1067 BOOL fColor;
1068
1069 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1070 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1071
1072 if (bpp != 1) fColor = TRUE;
1073 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1074 else
1075 {
1076 const RGBQUAD *rgb = data->bmiColors;
1077 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1078
1079 // Check if the first color of the colormap is black
1080 if ((col == RGB(0, 0, 0)))
1081 {
1082 rgb++;
1083 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1084
1085 // If the second color is white, create a monochrome bitmap
1086 fColor = (col != RGB(0xff,0xff,0xff));
1087 }
1088 else fColor = TRUE;
1089 }
1090
1091 // Now create the bitmap
1092 if (fColor)
1093 {
1094 handle = IntCreateCompatibleBitmap(Dc, width, height);
1095 }
1096 else
1097 {
1098 handle = GreCreateBitmap(width,
1099 height,
1100 1,
1101 1,
1102 NULL);
1103 }
1104
1105 if (height < 0)
1106 height = -height;
1107
1108 if (NULL != handle && CBM_INIT == init)
1109 {
1110 IntSetDIBits(Dc, handle, 0, height, bits, (BITMAPINFO*)data, coloruse);
1111 }
1112
1113 return handle;
1114 }
1115
1116 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1117 // The DDB that is created will be whatever bit depth your reference DC is
1118 HBITMAP
1119 APIENTRY
1120 NtGdiCreateDIBitmapInternal(
1121 IN HDC hDc,
1122 IN INT cx,
1123 IN INT cy,
1124 IN DWORD fInit,
1125 IN OPTIONAL LPBYTE pjInit,
1126 IN OPTIONAL LPBITMAPINFO pbmi,
1127 IN DWORD iUsage,
1128 IN UINT cjMaxInitInfo,
1129 IN UINT cjMaxBits,
1130 IN FLONG fl,
1131 IN HANDLE hcmXform)
1132 {
1133 BITMAPV5INFO bmiLocal ;
1134 NTSTATUS Status = STATUS_SUCCESS;
1135
1136 _SEH2_TRY
1137 {
1138 if(pbmi) Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, pbmi, iUsage, cjMaxInitInfo);
1139 if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
1140 }
1141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1142 {
1143 Status = _SEH2_GetExceptionCode();
1144 }
1145 _SEH2_END
1146
1147 if(!NT_SUCCESS(Status))
1148 {
1149 SetLastNtError(Status);
1150 return NULL;
1151 }
1152
1153 return GreCreateDIBitmapInternal(hDc,
1154 cx,
1155 cy,
1156 fInit,
1157 pjInit,
1158 pbmi ? &bmiLocal : NULL,
1159 iUsage,
1160 fl,
1161 hcmXform);
1162 }
1163
1164 HBITMAP
1165 FASTCALL
1166 GreCreateDIBitmapInternal(
1167 IN HDC hDc,
1168 IN INT cx,
1169 IN INT cy,
1170 IN DWORD fInit,
1171 IN OPTIONAL LPBYTE pjInit,
1172 IN OPTIONAL PBITMAPV5INFO pbmi,
1173 IN DWORD iUsage,
1174 IN FLONG fl,
1175 IN HANDLE hcmXform)
1176 {
1177 PDC Dc;
1178 HBITMAP Bmp;
1179 WORD bpp;
1180 HDC hdcDest;
1181
1182 if (!hDc) /* 1bpp monochrome bitmap */
1183 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1184 hdcDest = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
1185 if(!hdcDest)
1186 {
1187 return NULL;
1188 }
1189 }
1190 else
1191 {
1192 hdcDest = hDc;
1193 }
1194
1195 Dc = DC_LockDc(hdcDest);
1196 if (!Dc)
1197 {
1198 SetLastWin32Error(ERROR_INVALID_HANDLE);
1199 return NULL;
1200 }
1201 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1202 * if bpp != 1 and ignore the real value that was passed */
1203 if (pbmi)
1204 bpp = pbmi->bmiHeader.bV5BitCount;
1205 else
1206 bpp = 0;
1207 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1208 DC_UnlockDc(Dc);
1209
1210 if(!hDc)
1211 {
1212 NtGdiDeleteObjectApp(hdcDest);
1213 }
1214 return Bmp;
1215 }
1216
1217
1218 HBITMAP
1219 APIENTRY
1220 NtGdiCreateDIBSection(
1221 IN HDC hDC,
1222 IN OPTIONAL HANDLE hSection,
1223 IN DWORD dwOffset,
1224 IN LPBITMAPINFO bmi,
1225 IN DWORD Usage,
1226 IN UINT cjHeader,
1227 IN FLONG fl,
1228 IN ULONG_PTR dwColorSpace,
1229 OUT PVOID *Bits)
1230 {
1231 HBITMAP hbitmap = 0;
1232 DC *dc;
1233 BOOL bDesktopDC = FALSE;
1234
1235 if (!bmi) return hbitmap; // Make sure.
1236
1237 // If the reference hdc is null, take the desktop dc
1238 if (hDC == 0)
1239 {
1240 hDC = NtGdiCreateCompatibleDC(0);
1241 bDesktopDC = TRUE;
1242 }
1243
1244 if ((dc = DC_LockDc(hDC)))
1245 {
1246 hbitmap = DIB_CreateDIBSection(dc,
1247 (BITMAPINFO*)bmi,
1248 Usage,
1249 Bits,
1250 hSection,
1251 dwOffset,
1252 0);
1253 DC_UnlockDc(dc);
1254 }
1255 else
1256 {
1257 SetLastWin32Error(ERROR_INVALID_HANDLE);
1258 }
1259
1260 if (bDesktopDC)
1261 NtGdiDeleteObjectApp(hDC);
1262
1263 return hbitmap;
1264 }
1265
1266 HBITMAP
1267 APIENTRY
1268 DIB_CreateDIBSection(
1269 PDC dc,
1270 BITMAPINFO *bmi,
1271 UINT usage,
1272 LPVOID *bits,
1273 HANDLE section,
1274 DWORD offset,
1275 DWORD ovr_pitch)
1276 {
1277 HBITMAP res = 0;
1278 SURFACE *bmp = NULL;
1279 void *mapBits = NULL;
1280 PDC_ATTR pdcattr;
1281 HPALETTE hpal ;
1282
1283 // Fill BITMAP32 structure with DIB data
1284 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1285 INT effHeight;
1286 ULONG totalSize;
1287 BITMAP bm;
1288 SIZEL Size;
1289 RGBQUAD *lpRGB;
1290 HANDLE hSecure;
1291 DWORD dsBitfields[3] = {0};
1292 ULONG ColorCount;
1293
1294 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1295 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1296 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1297
1298 /* CreateDIBSection should fail for compressed formats */
1299 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1300 {
1301 return (HBITMAP)NULL;
1302 }
1303
1304 pdcattr = dc->pdcattr;
1305
1306 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1307 bm.bmType = 0;
1308 bm.bmWidth = bi->biWidth;
1309 bm.bmHeight = effHeight;
1310 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1311
1312 bm.bmPlanes = bi->biPlanes;
1313 bm.bmBitsPixel = bi->biBitCount;
1314 bm.bmBits = NULL;
1315
1316 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1317 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1318 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1319 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1320
1321 if (section)
1322 {
1323 SYSTEM_BASIC_INFORMATION Sbi;
1324 NTSTATUS Status;
1325 DWORD mapOffset;
1326 LARGE_INTEGER SectionOffset;
1327 SIZE_T mapSize;
1328
1329 Status = ZwQuerySystemInformation(SystemBasicInformation,
1330 &Sbi,
1331 sizeof Sbi,
1332 0);
1333 if (!NT_SUCCESS(Status))
1334 {
1335 return NULL;
1336 }
1337
1338 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1339 mapSize = bi->biSizeImage + (offset - mapOffset);
1340
1341 SectionOffset.LowPart = mapOffset;
1342 SectionOffset.HighPart = 0;
1343
1344 Status = ZwMapViewOfSection(section,
1345 NtCurrentProcess(),
1346 &mapBits,
1347 0,
1348 0,
1349 &SectionOffset,
1350 &mapSize,
1351 ViewShare,
1352 0,
1353 PAGE_READWRITE);
1354 if (!NT_SUCCESS(Status))
1355 {
1356 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1357 return NULL;
1358 }
1359
1360 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1361 }
1362 else if (ovr_pitch && offset)
1363 bm.bmBits = (LPVOID) offset;
1364 else
1365 {
1366 offset = 0;
1367 bm.bmBits = EngAllocUserMem(totalSize, 0);
1368 }
1369
1370 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1371 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1372
1373 if (usage == DIB_PAL_COLORS)
1374 {
1375 lpRGB = DIB_MapPaletteColors(dc, bmi);
1376 ColorCount = bi->biClrUsed;
1377 if (ColorCount == 0)
1378 {
1379 ColorCount = 1 << bi->biBitCount;
1380 }
1381 }
1382 else
1383 {
1384 lpRGB = bmi->bmiColors;
1385 ColorCount = 1 << bi->biBitCount;
1386 }
1387
1388 /* Set dsBitfields values */
1389 if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
1390 {
1391 dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
1392 }
1393 else if (bi->biCompression == BI_RGB)
1394 {
1395 switch (bi->biBitCount)
1396 {
1397 case 15:
1398 dsBitfields[0] = 0x7c00;
1399 dsBitfields[1] = 0x03e0;
1400 dsBitfields[2] = 0x001f;
1401 break;
1402
1403 case 16:
1404 dsBitfields[0] = 0xF800;
1405 dsBitfields[1] = 0x07e0;
1406 dsBitfields[2] = 0x001f;
1407 break;
1408
1409 case 24:
1410 case 32:
1411 dsBitfields[0] = 0xff0000;
1412 dsBitfields[1] = 0x00ff00;
1413 dsBitfields[2] = 0x0000ff;
1414 break;
1415 }
1416 }
1417 else
1418 {
1419 dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
1420 dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
1421 dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
1422 }
1423
1424 // Create Device Dependent Bitmap and add DIB pointer
1425 Size.cx = bm.bmWidth;
1426 Size.cy = abs(bm.bmHeight);
1427 res = GreCreateBitmapEx(bm.bmWidth,
1428 abs(bm.bmHeight),
1429 bm.bmWidthBytes,
1430 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1431 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1432 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1433 bi->biSizeImage,
1434 bm.bmBits);
1435 if (!res)
1436 {
1437 if (lpRGB != bmi->bmiColors)
1438 {
1439 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1440 }
1441 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1442 return NULL;
1443 }
1444 bmp = SURFACE_LockSurface(res);
1445 if (NULL == bmp)
1446 {
1447 if (lpRGB != bmi->bmiColors)
1448 {
1449 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1450 }
1451 SetLastWin32Error(ERROR_INVALID_HANDLE);
1452 GreDeleteObject(res);
1453 return NULL;
1454 }
1455
1456 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1457 table between the DIB and the X physical device. Obviously,
1458 this is left out of the ReactOS implementation. Instead,
1459 we call NtGdiSetDIBColorTable. */
1460 if (bi->biBitCount <= 8)
1461 {
1462 bi->biClrUsed = 1 << bi->biBitCount;
1463 }
1464 else
1465 {
1466 bi->biClrUsed = 0;
1467 }
1468
1469 bmp->hDIBSection = section;
1470 bmp->hSecure = hSecure;
1471 bmp->dwOffset = offset;
1472 bmp->flags = API_BITMAP;
1473 bmp->dsBitfields[0] = dsBitfields[0];
1474 bmp->dsBitfields[1] = dsBitfields[1];
1475 bmp->dsBitfields[2] = dsBitfields[2];
1476 bmp->biClrUsed = bi->biClrUsed;
1477 bmp->biClrImportant = bi->biClrImportant;
1478
1479 if (bi->biClrUsed != 0)
1480 {
1481 hpal = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
1482 }
1483 else
1484 {
1485 hpal = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
1486 dsBitfields[0],
1487 dsBitfields[1],
1488 dsBitfields[2]);
1489 }
1490
1491 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1492 /* Lazy delete hpal, it will be freed at surface release */
1493 GreDeleteObject(hpal);
1494
1495 // Clean up in case of errors
1496 if (!res || !bmp || !bm.bmBits)
1497 {
1498 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1499 if (bm.bmBits)
1500 {
1501 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1502 if (section)
1503 {
1504 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1505 bm.bmBits = NULL;
1506 }
1507 else
1508 if (!offset)
1509 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1510 }
1511
1512 if (bmp)
1513 bmp = NULL;
1514
1515 if (res)
1516 {
1517 SURFACE_FreeSurfaceByHandle(res);
1518 res = 0;
1519 }
1520 }
1521
1522 if (lpRGB != bmi->bmiColors)
1523 {
1524 ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
1525 }
1526
1527 if (bmp)
1528 {
1529 SURFACE_UnlockSurface(bmp);
1530 }
1531
1532 // Return BITMAP handle and storage location
1533 if (NULL != bm.bmBits && NULL != bits)
1534 {
1535 *bits = bm.bmBits;
1536 }
1537
1538 if (res) pdcattr->ulDirty_ |= DC_DIBSECTION;
1539
1540 return res;
1541 }
1542
1543 /***********************************************************************
1544 * DIB_GetDIBWidthBytes
1545 *
1546 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1547 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1548 * 11/16/1999 (RJJ) lifted from wine
1549 */
1550 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1551 {
1552 return ((width * depth + 31) & ~31) >> 3;
1553 }
1554
1555 /***********************************************************************
1556 * DIB_GetDIBImageBytes
1557 *
1558 * Return the number of bytes used to hold the image in a DIB bitmap.
1559 * 11/16/1999 (RJJ) lifted from wine
1560 */
1561
1562 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1563 {
1564 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1565 }
1566
1567 /***********************************************************************
1568 * DIB_BitmapInfoSize
1569 *
1570 * Return the size of the bitmap info structure including color table.
1571 * 11/16/1999 (RJJ) lifted from wine
1572 */
1573
1574 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1575 {
1576 int colors;
1577
1578 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1579 {
1580 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1581 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1582 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1583 }
1584 else /* assume BITMAPINFOHEADER */
1585 {
1586 colors = info->bmiHeader.biClrUsed;
1587 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1588 return info->bmiHeader.biSize + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1589 }
1590 }
1591
1592 RGBQUAD *
1593 FASTCALL
1594 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1595 {
1596 RGBQUAD *lpRGB;
1597 ULONG nNumColors,i;
1598 USHORT *lpIndex;
1599 PPALETTE palGDI;
1600
1601 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
1602
1603 if (NULL == palGDI)
1604 {
1605 return NULL;
1606 }
1607
1608 if (palGDI->Mode != PAL_INDEXED)
1609 {
1610 PALETTE_UnlockPalette(palGDI);
1611 return NULL;
1612 }
1613
1614 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1615 if (lpbmi->bmiHeader.biClrUsed)
1616 {
1617 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1618 }
1619
1620 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1621 if (lpRGB == NULL)
1622 {
1623 PALETTE_UnlockPalette(palGDI);
1624 return NULL;
1625 }
1626
1627 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1628
1629 for (i = 0; i < nNumColors; i++)
1630 {
1631 if (*lpIndex < palGDI->NumColors)
1632 {
1633 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1634 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1635 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1636 }
1637 else
1638 {
1639 lpRGB[i].rgbRed = 0;
1640 lpRGB[i].rgbGreen = 0;
1641 lpRGB[i].rgbBlue = 0;
1642 }
1643 lpRGB[i].rgbReserved = 0;
1644 lpIndex++;
1645 }
1646 PALETTE_UnlockPalette(palGDI);
1647
1648 return lpRGB;
1649 }
1650
1651 HPALETTE
1652 FASTCALL
1653 BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
1654 {
1655 BYTE bits;
1656 ULONG ColorCount;
1657 HPALETTE hPal;
1658 ULONG RedMask, GreenMask, BlueMask;
1659 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1660
1661 // Determine Bits Per Pixel
1662 bits = bmi->bmiHeader.biBitCount;
1663
1664 // Determine paletteType from Bits Per Pixel
1665 if (bits <= 8)
1666 {
1667 *paletteType = PAL_INDEXED;
1668 RedMask = GreenMask = BlueMask = 0;
1669 }
1670 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1671 {
1672 *paletteType = PAL_BITFIELDS;
1673 RedMask = pdwColors[0];
1674 GreenMask = pdwColors[1];
1675 BlueMask = pdwColors[2];
1676 }
1677 else if (bits == 15)
1678 {
1679 *paletteType = PAL_BITFIELDS;
1680 RedMask = 0x7c00;
1681 GreenMask = 0x03e0;
1682 BlueMask = 0x001f;
1683 }
1684 else if (bits == 16)
1685 {
1686 *paletteType = PAL_BITFIELDS;
1687 RedMask = 0xF800;
1688 GreenMask = 0x07e0;
1689 BlueMask = 0x001f;
1690 }
1691 else
1692 {
1693 *paletteType = PAL_BGR;
1694 RedMask = 0xff0000;
1695 GreenMask = 0x00ff00;
1696 BlueMask = 0x0000ff;
1697 }
1698
1699 if (bmi->bmiHeader.biClrUsed == 0)
1700 {
1701 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1702 }
1703 else
1704 {
1705 ColorCount = bmi->bmiHeader.biClrUsed;
1706 }
1707
1708 if (PAL_INDEXED == *paletteType)
1709 {
1710 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1711 }
1712 else
1713 {
1714 hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
1715 NULL,
1716 RedMask, GreenMask, BlueMask);
1717 }
1718
1719 return hPal;
1720 }
1721
1722 FORCEINLINE
1723 DWORD
1724 GetBMIColor(CONST BITMAPINFO* pbmi, INT i)
1725 {
1726 DWORD dwRet = 0;
1727 INT size;
1728 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1729 {
1730 /* BITMAPCOREINFO holds RGBTRIPLE values */
1731 size = sizeof(RGBTRIPLE);
1732 }
1733 else
1734 {
1735 size = sizeof(RGBQUAD);
1736 }
1737 memcpy(&dwRet, (PBYTE)pbmi + pbmi->bmiHeader.biSize + i*size, size);
1738 return dwRet;
1739 }
1740
1741 FORCEINLINE
1742 VOID
1743 SetBMIColor(CONST BITMAPINFO* pbmi, DWORD* color, INT i)
1744 {
1745 PVOID pvColors = ((PBYTE)pbmi + pbmi->bmiHeader.biSize);
1746 if(pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1747 {
1748 RGBTRIPLE *pColor = pvColors;
1749 pColor[i] = *(RGBTRIPLE*)color;
1750 }
1751 else
1752 {
1753 RGBQUAD *pColor = pvColors;
1754 pColor[i] = *(RGBQUAD*)color;
1755 }
1756 }
1757
1758 NTSTATUS
1759 FASTCALL
1760 ProbeAndConvertToBitmapV5Info(
1761 OUT PBITMAPV5INFO pbmiDst,
1762 IN CONST BITMAPINFO* pbmiUnsafe,
1763 IN DWORD dwColorUse,
1764 IN UINT MaxSize)
1765 {
1766 DWORD dwSize;
1767 ULONG ulWidthBytes;
1768 PBITMAPV5HEADER pbmhDst = &pbmiDst->bmiHeader;
1769
1770 /* Get the size and probe */
1771 ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
1772 dwSize = pbmiUnsafe->bmiHeader.biSize;
1773 /* At least dwSize bytes must be valids */
1774 ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 1);
1775
1776 /* Check the size */
1777 // FIXME: are intermediate sizes allowed? As what are they interpreted?
1778 // make sure we don't use a too big dwSize later
1779 if (dwSize != sizeof(BITMAPCOREHEADER) &&
1780 dwSize != sizeof(BITMAPINFOHEADER) &&
1781 dwSize != sizeof(BITMAPV4HEADER) &&
1782 dwSize != sizeof(BITMAPV5HEADER))
1783 {
1784 return STATUS_INVALID_PARAMETER;
1785 }
1786
1787 if (dwSize == sizeof(BITMAPCOREHEADER))
1788 {
1789 PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
1790
1791 /* Manually copy the fields that are present */
1792 pbmhDst->bV5Width = pbch->bcWidth;
1793 pbmhDst->bV5Height = pbch->bcHeight;
1794 pbmhDst->bV5Planes = pbch->bcPlanes;
1795 pbmhDst->bV5BitCount = pbch->bcBitCount;
1796
1797 /* Set some default values */
1798 pbmhDst->bV5Compression = BI_RGB;
1799 pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbch->bcWidth,
1800 pbch->bcHeight,
1801 pbch->bcPlanes*pbch->bcBitCount) ;
1802 pbmhDst->bV5XPelsPerMeter = 72;
1803 pbmhDst->bV5YPelsPerMeter = 72;
1804 pbmhDst->bV5ClrUsed = 0;
1805 pbmhDst->bV5ClrImportant = 0;
1806 }
1807 else
1808 {
1809 /* Copy valid fields */
1810 memcpy(pbmiDst, pbmiUnsafe, dwSize);
1811 if(!pbmhDst->bV5SizeImage)
1812 pbmhDst->bV5SizeImage = DIB_GetDIBImageBytes(pbmhDst->bV5Width,
1813 pbmhDst->bV5Height,
1814 pbmhDst->bV5Planes*pbmhDst->bV5BitCount) ;
1815
1816 if(dwSize < sizeof(BITMAPV5HEADER))
1817 {
1818 /* Zero out the rest of the V5 header */
1819 memset((char*)pbmiDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
1820 }
1821 }
1822 pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
1823
1824
1825 if (dwSize < sizeof(BITMAPV4HEADER))
1826 {
1827 if (pbmhDst->bV5Compression == BI_BITFIELDS)
1828 {
1829 pbmhDst->bV5RedMask = GetBMIColor(pbmiUnsafe, 0);
1830 pbmhDst->bV5GreenMask = GetBMIColor(pbmiUnsafe, 1);
1831 pbmhDst->bV5BlueMask = GetBMIColor(pbmiUnsafe, 2);
1832 pbmhDst->bV5AlphaMask = 0;
1833 pbmhDst->bV5ClrUsed = 0;
1834 }
1835
1836 // pbmhDst->bV5CSType;
1837 // pbmhDst->bV5Endpoints;
1838 // pbmhDst->bV5GammaRed;
1839 // pbmhDst->bV5GammaGreen;
1840 // pbmhDst->bV5GammaBlue;
1841 }
1842
1843 if (dwSize < sizeof(BITMAPV5HEADER))
1844 {
1845 // pbmhDst->bV5Intent;
1846 // pbmhDst->bV5ProfileData;
1847 // pbmhDst->bV5ProfileSize;
1848 // pbmhDst->bV5Reserved;
1849 }
1850
1851 ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
1852 pbmhDst->bV5BitCount + 31) & ~31) / 8;
1853
1854 if (pbmhDst->bV5SizeImage == 0)
1855 pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
1856
1857 if (pbmhDst->bV5ClrUsed == 0)
1858 {
1859 switch(pbmhDst->bV5BitCount)
1860 {
1861 case 1:
1862 pbmhDst->bV5ClrUsed = 2;
1863 break;
1864 case 4:
1865 pbmhDst->bV5ClrUsed = 16;
1866 break;
1867 case 8:
1868 pbmhDst->bV5ClrUsed = 256;
1869 break;
1870 default:
1871 pbmhDst->bV5ClrUsed = 0;
1872 break;
1873 }
1874 }
1875
1876 if (pbmhDst->bV5Planes != 1)
1877 {
1878 return STATUS_INVALID_PARAMETER;
1879 }
1880
1881 if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
1882 pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
1883 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
1884 pbmhDst->bV5BitCount != 32)
1885 {
1886 DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
1887 return STATUS_INVALID_PARAMETER;
1888 }
1889
1890 if ((pbmhDst->bV5BitCount == 0 &&
1891 pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
1892 {
1893 DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
1894 return STATUS_INVALID_PARAMETER;
1895 }
1896
1897 if (pbmhDst->bV5Compression == BI_BITFIELDS &&
1898 pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
1899 {
1900 DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
1901 return STATUS_INVALID_PARAMETER;
1902 }
1903
1904 /* Copy Colors */
1905 if(pbmhDst->bV5ClrUsed)
1906 {
1907 INT i;
1908 if(dwColorUse == DIB_PAL_COLORS)
1909 {
1910 RtlCopyMemory(pbmiDst->bmiColors,
1911 pbmiUnsafe->bmiColors,
1912 pbmhDst->bV5ClrUsed * sizeof(WORD));
1913 }
1914 else
1915 {
1916 for(i = 0; i < pbmhDst->bV5ClrUsed; i++)
1917 {
1918 ((DWORD*)pbmiDst->bmiColors)[i] = GetBMIColor(pbmiUnsafe, i);
1919 }
1920 }
1921 }
1922
1923 return STATUS_SUCCESS;
1924 }
1925
1926 VOID
1927 FASTCALL
1928 GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc,
1929 OUT PBITMAPINFO pbmiDst,
1930 IN DWORD dwColorUse)
1931 {
1932 if(pbmiDst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1933 {
1934 /* Manually set value */
1935 BITMAPCOREHEADER* pbmhCore = (BITMAPCOREHEADER*)&pbmiDst->bmiHeader;
1936 pbmhCore->bcWidth = pbmiSrc->bmiHeader.bV5Width;
1937 pbmhCore->bcHeight = pbmiSrc->bmiHeader.bV5Height;
1938 pbmhCore->bcPlanes = pbmiSrc->bmiHeader.bV5Planes;
1939 pbmhCore->bcBitCount = pbmiSrc->bmiHeader.bV5BitCount;
1940 }
1941 else
1942 {
1943 /* Copy valid Fields, keep bmiHeader.biSize safe */
1944 RtlCopyMemory(&pbmiDst->bmiHeader.biWidth,
1945 &pbmiSrc->bmiHeader.bV5Width,
1946 pbmiDst->bmiHeader.biSize - sizeof(DWORD));
1947 }
1948 if((pbmiDst->bmiHeader.biSize < sizeof(BITMAPV4HEADER)) &&
1949 (pbmiSrc->bmiHeader.bV5Compression == BI_BITFIELDS))
1950 {
1951 /* Masks are already set in V4 and V5 headers */
1952 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5RedMask, 0);
1953 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5GreenMask, 1);
1954 SetBMIColor(pbmiDst, &pbmiSrc->bmiHeader.bV5BlueMask, 2);
1955 }
1956 else
1957 {
1958 INT i;
1959 ULONG cColorsUsed;
1960
1961 cColorsUsed = pbmiSrc->bmiHeader.bV5ClrUsed;
1962 if (cColorsUsed == 0 && pbmiSrc->bmiHeader.bV5BitCount <= 8)
1963 cColorsUsed = (1 << pbmiSrc->bmiHeader.bV5BitCount);
1964
1965 if(dwColorUse == DIB_PAL_COLORS)
1966 {
1967 RtlCopyMemory(pbmiDst->bmiColors,
1968 pbmiSrc->bmiColors,
1969 cColorsUsed * sizeof(WORD));
1970 }
1971 else
1972 {
1973 for(i = 0; i < cColorsUsed; i++)
1974 {
1975 SetBMIColor(pbmiDst, (DWORD*)pbmiSrc->bmiColors + i, i);
1976 }
1977 }
1978 }
1979 }
1980
1981 /* EOF */