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