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