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