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