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