Move the inclusion of <debug.h> to individual files and consolidate the inclusion...
[reactos.git] / reactos / subsys / win32k / objects / dib.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 UINT STDCALL
28 NtGdiSetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, CONST RGBQUAD *Colors)
29 {
30 PDC dc;
31 PBITMAPOBJ BitmapObj;
32 PPALGDI PalGDI;
33 UINT Index;
34
35 if (!(dc = DC_LockDc(hDC))) return 0;
36 if (dc->IsIC)
37 {
38 DC_UnlockDc(dc);
39 return 0;
40 }
41
42 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
43 if (BitmapObj == NULL)
44 {
45 DC_UnlockDc(dc);
46 SetLastWin32Error(ERROR_INVALID_PARAMETER);
47 return 0;
48 }
49
50 if (BitmapObj->dib == NULL)
51 {
52 BITMAPOBJ_UnlockBitmap(BitmapObj);
53 DC_UnlockDc(dc);
54 SetLastWin32Error(ERROR_INVALID_PARAMETER);
55 return 0;
56 }
57
58 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
59 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
60 {
61 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
62 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
63
64 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
65 _SEH_TRY
66 {
67 for (Index = StartIndex;
68 Index < StartIndex + Entries && Index < PalGDI->NumColors;
69 Index++)
70 {
71 PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
72 PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
73 PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
74 }
75 }
76 _SEH_HANDLE
77 {
78 Entries = 0;
79 }
80 _SEH_END
81 PALETTE_UnlockPalette(PalGDI);
82 }
83 else
84 Entries = 0;
85
86 BITMAPOBJ_UnlockBitmap(BitmapObj);
87 DC_UnlockDc(dc);
88
89 return Entries;
90 }
91
92 UINT STDCALL
93 NtGdiGetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, RGBQUAD *Colors)
94 {
95 PDC dc;
96 PBITMAPOBJ BitmapObj;
97 PPALGDI PalGDI;
98 UINT Index;
99
100 if (!(dc = DC_LockDc(hDC))) return 0;
101 if (dc->IsIC)
102 {
103 DC_UnlockDc(dc);
104 return 0;
105 }
106
107 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
108 if (BitmapObj == NULL)
109 {
110 DC_UnlockDc(dc);
111 SetLastWin32Error(ERROR_INVALID_PARAMETER);
112 return 0;
113 }
114
115 if (BitmapObj->dib == NULL)
116 {
117 BITMAPOBJ_UnlockBitmap(BitmapObj);
118 DC_UnlockDc(dc);
119 SetLastWin32Error(ERROR_INVALID_PARAMETER);
120 return 0;
121 }
122
123 if (BitmapObj->dib->dsBmih.biBitCount <= 8 &&
124 StartIndex < (1 << BitmapObj->dib->dsBmih.biBitCount))
125 {
126 if (StartIndex + Entries > (1 << BitmapObj->dib->dsBmih.biBitCount))
127 Entries = (1 << BitmapObj->dib->dsBmih.biBitCount) - StartIndex;
128
129 PalGDI = PALETTE_LockPalette(BitmapObj->hDIBPalette);
130 _SEH_TRY
131 {
132 for (Index = StartIndex;
133 Index < StartIndex + Entries && Index < PalGDI->NumColors;
134 Index++)
135 {
136 Colors[Index - StartIndex].rgbRed = PalGDI->IndexedColors[Index].peRed;
137 Colors[Index - StartIndex].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
138 Colors[Index - StartIndex].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
139 }
140 }
141 _SEH_HANDLE
142 {
143 Entries = 0;
144 }
145 _SEH_END
146 PALETTE_UnlockPalette(PalGDI);
147 }
148 else
149 Entries = 0;
150
151 BITMAPOBJ_UnlockBitmap(BitmapObj);
152 DC_UnlockDc(dc);
153
154 return Entries;
155 }
156
157 // Converts a DIB to a device-dependent bitmap
158 static INT FASTCALL
159 IntSetDIBits(
160 PDC DC,
161 HBITMAP hBitmap,
162 UINT StartScan,
163 UINT ScanLines,
164 CONST VOID *Bits,
165 CONST BITMAPINFO *bmi,
166 UINT ColorUse)
167 {
168 BITMAPOBJ *bitmap;
169 HBITMAP SourceBitmap;
170 INT result = 0;
171 BOOL copyBitsResult;
172 SURFOBJ *DestSurf, *SourceSurf;
173 SIZEL SourceSize;
174 POINTL ZeroPoint;
175 RECTL DestRect;
176 XLATEOBJ *XlateObj;
177 PPALGDI hDCPalette;
178 //RGBQUAD *lpRGB;
179 HPALETTE DDB_Palette, DIB_Palette;
180 ULONG DDB_Palette_Type, DIB_Palette_Type;
181 INT DIBWidth;
182
183 // Check parameters
184 if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
185 {
186 return 0;
187 }
188
189 // Get RGB values
190 //if (ColorUse == DIB_PAL_COLORS)
191 // lpRGB = DIB_MapPaletteColors(hDC, bmi);
192 //else
193 // lpRGB = &bmi->bmiColors[0];
194
195 DestSurf = &bitmap->SurfObj;
196
197 // Create source surface
198 SourceSize.cx = bmi->bmiHeader.biWidth;
199 SourceSize.cy = ScanLines;
200
201 // Determine width of DIB
202 DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
203
204 SourceBitmap = EngCreateBitmap(SourceSize,
205 DIBWidth,
206 BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
207 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
208 (PVOID) Bits);
209 if (0 == SourceBitmap)
210 {
211 BITMAPOBJ_UnlockBitmap(bitmap);
212 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
213 return 0;
214 }
215
216 SourceSurf = EngLockSurface((HSURF)SourceBitmap);
217 if (NULL == SourceSurf)
218 {
219 EngDeleteSurface((HSURF)SourceBitmap);
220 BITMAPOBJ_UnlockBitmap(bitmap);
221 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
222 return 0;
223 }
224
225 // Destination palette obtained from the hDC
226 hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault);
227 if (NULL == hDCPalette)
228 {
229 EngUnlockSurface(SourceSurf);
230 EngDeleteSurface((HSURF)SourceBitmap);
231 BITMAPOBJ_UnlockBitmap(bitmap);
232 SetLastWin32Error(ERROR_INVALID_HANDLE);
233 return 0;
234 }
235 DDB_Palette_Type = hDCPalette->Mode;
236 DDB_Palette = DC->DevInfo->hpalDefault;
237 PALETTE_UnlockPalette(hDCPalette);
238
239 // Source palette obtained from the BITMAPINFO
240 DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
241 if (NULL == DIB_Palette)
242 {
243 EngUnlockSurface(SourceSurf);
244 EngDeleteSurface((HSURF)SourceBitmap);
245 BITMAPOBJ_UnlockBitmap(bitmap);
246 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
247 return 0;
248 }
249
250 // Determine XLATEOBJ for color translation
251 XlateObj = IntEngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette);
252 if (NULL == XlateObj)
253 {
254 PALETTE_FreePalette(DIB_Palette);
255 EngUnlockSurface(SourceSurf);
256 EngDeleteSurface((HSURF)SourceBitmap);
257 BITMAPOBJ_UnlockBitmap(bitmap);
258 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
259 return 0;
260 }
261
262 // Zero point
263 ZeroPoint.x = 0;
264 ZeroPoint.y = 0;
265
266 // Determine destination rectangle
267 DestRect.left = 0;
268 DestRect.top = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
269 DestRect.right = SourceSize.cx;
270 DestRect.bottom = DestRect.top + ScanLines;
271
272 copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
273
274 // If it succeeded, return number of scanlines copies
275 if(copyBitsResult == TRUE)
276 {
277 result = SourceSize.cy - 1;
278 }
279
280 // Clean up
281 EngDeleteXlate(XlateObj);
282 PALETTE_FreePalette(DIB_Palette);
283 EngUnlockSurface(SourceSurf);
284 EngDeleteSurface((HSURF)SourceBitmap);
285
286 // if (ColorUse == DIB_PAL_COLORS)
287 // WinFree((LPSTR)lpRGB);
288
289 BITMAPOBJ_UnlockBitmap(bitmap);
290
291 return result;
292 }
293
294 // Converts a DIB to a device-dependent bitmap
295 INT STDCALL
296 NtGdiSetDIBits(
297 HDC hDC,
298 HBITMAP hBitmap,
299 UINT StartScan,
300 UINT ScanLines,
301 CONST VOID *Bits,
302 CONST BITMAPINFO *bmi,
303 UINT ColorUse)
304 {
305 PDC Dc;
306 INT Ret;
307
308 Dc = DC_LockDc(hDC);
309 if (NULL == Dc)
310 {
311 SetLastWin32Error(ERROR_INVALID_HANDLE);
312 return 0;
313 }
314 if (Dc->IsIC)
315 {
316 DC_UnlockDc(Dc);
317 return 0;
318 }
319
320 Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
321
322 DC_UnlockDc(Dc);
323
324 return Ret;
325 }
326
327 INT STDCALL
328 NtGdiSetDIBitsToDevice(
329 HDC hDC,
330 INT XDest,
331 INT YDest,
332 DWORD Width,
333 DWORD Height,
334 INT XSrc,
335 INT YSrc,
336 UINT StartScan,
337 UINT ScanLines,
338 CONST VOID *Bits,
339 CONST BITMAPINFO *bmi,
340 UINT ColorUse)
341 {
342 UNIMPLEMENTED;
343 return 0;
344 }
345
346 /* Converts a device-dependent bitmap to a DIB */
347 INT STDCALL
348 NtGdiGetDIBits(HDC hDC,
349 HBITMAP hBitmap,
350 UINT StartScan,
351 UINT ScanLines,
352 LPVOID Bits,
353 LPBITMAPINFO Info,
354 UINT Usage)
355 {
356 BITMAPOBJ *BitmapObj;
357 SURFOBJ *DestSurfObj;
358 XLATEOBJ *XlateObj;
359 HBITMAP DestBitmap;
360 SIZEL DestSize;
361 HPALETTE hSourcePalette;
362 HPALETTE hDestPalette;
363 PPALGDI SourcePalette;
364 PPALGDI DestPalette;
365 ULONG SourcePaletteType;
366 ULONG DestPaletteType;
367 PDC Dc;
368 POINTL SourcePoint;
369 RECTL DestRect;
370 ULONG Result = 0;
371 ULONG Index;
372
373 /* Get handle for the palette in DC. */
374 Dc = DC_LockDc(hDC);
375 if (Dc == NULL)
376 {
377 SetLastWin32Error(ERROR_INVALID_HANDLE);
378 return 0;
379 }
380 if (Dc->IsIC)
381 {
382 DC_UnlockDc(Dc);
383 return 0;
384 }
385 hSourcePalette = Dc->w.hPalette;
386 /* FIXME: This is incorrect. hDestPalette should be something other. */
387 hDestPalette = Dc->DevInfo->hpalDefault;
388 DC_UnlockDc(Dc);
389
390 /* Get pointer to the source bitmap object. */
391 BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
392 if (BitmapObj == NULL)
393 {
394 SetLastWin32Error(ERROR_INVALID_HANDLE);
395 return 0;
396 }
397
398 if (Bits == NULL)
399 {
400 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) ||
401 Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
402 {
403 Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
404 Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
405 /* Report negtive height for top-down bitmaps. */
406 if (BitmapObj->SurfObj.lDelta > 0)
407 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
408 Info->bmiHeader.biPlanes = 1;
409 Info->bmiHeader.biBitCount = BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
410 if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
411 {
412 switch (BitmapObj->SurfObj.iBitmapFormat)
413 {
414 case BMF_1BPP: case BMF_4BPP: case BMF_8BPP:
415 case BMF_16BPP: case BMF_24BPP: case BMF_32BPP:
416 Info->bmiHeader.biCompression = BI_RGB;
417 break;
418 case BMF_4RLE:
419 Info->bmiHeader.biCompression = BI_RLE4;
420 break;
421 case BMF_8RLE:
422 Info->bmiHeader.biCompression = BI_RLE8;
423 break;
424 case BMF_JPEG:
425 Info->bmiHeader.biCompression = BI_JPEG;
426 break;
427 case BMF_PNG:
428 Info->bmiHeader.biCompression = BI_PNG;
429 break;
430 }
431 Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
432 Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
433 Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
434 Info->bmiHeader.biClrUsed =
435 Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
436 Result = BitmapObj->SurfObj.sizlBitmap.cy;
437 }
438 }
439 }
440 else
441 {
442 if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
443 {
444 Result = 0;
445 }
446 else
447 {
448 ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
449 DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
450 DestSize.cy = ScanLines;
451 DestBitmap = EngCreateBitmap(
452 DestSize, BitmapObj->SurfObj.lDelta,
453 BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
454 0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
455 Bits);
456 DestSurfObj = EngLockSurface((HSURF)DestBitmap);
457
458 SourcePalette = PALETTE_LockPalette(hSourcePalette);
459 /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
460 ASSERT(SourcePalette);
461 SourcePaletteType = SourcePalette->Mode;
462 PALETTE_UnlockPalette(SourcePalette);
463
464 DestPalette = PALETTE_LockPalette(hDestPalette);
465 /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
466 ASSERT(DestPalette);
467 DestPaletteType = DestPalette->Mode;
468
469 /* Copy palette. */
470 /* FIXME: This is largely incomplete. */
471 if (Info->bmiHeader.biBitCount <= 8)
472 {
473 if (Usage == DIB_RGB_COLORS)
474 {
475 for (Index = 0;
476 Index < (1 << Info->bmiHeader.biBitCount) &&
477 Index < DestPalette->NumColors;
478 Index++)
479 {
480 Info->bmiColors[Index].rgbRed =
481 DestPalette->IndexedColors[Index].peRed;
482 Info->bmiColors[Index].rgbGreen =
483 DestPalette->IndexedColors[Index].peGreen;
484 Info->bmiColors[Index].rgbBlue =
485 DestPalette->IndexedColors[Index].peBlue;
486 }
487 }
488 if (Usage == DIB_PAL_COLORS)
489 {
490 DbgPrint("GetDIBits with DIB_PAL_COLORS isn't implemented yet.");
491 }
492 }
493
494 PALETTE_UnlockPalette(DestPalette);
495
496 XlateObj = IntEngCreateXlate(
497 DestPaletteType, SourcePaletteType, hDestPalette, hSourcePalette);
498
499 SourcePoint.x = 0;
500 SourcePoint.y = StartScan;
501
502 /* Determine destination rectangle */
503 DestRect.top = 0;
504 DestRect.left = 0;
505 DestRect.right = DestSize.cx;
506 DestRect.bottom = DestSize.cy;
507
508 if (EngCopyBits(DestSurfObj, &BitmapObj->SurfObj,
509 NULL, XlateObj, &DestRect, &SourcePoint))
510 {
511 Result = ScanLines;
512 }
513
514 EngDeleteXlate(XlateObj);
515 EngUnlockSurface(DestSurfObj);
516 }
517 }
518
519 BITMAPOBJ_UnlockBitmap(BitmapObj);
520
521 return Result;
522 }
523
524 INT STDCALL NtGdiStretchDIBits(HDC hDC,
525 INT XDest,
526 INT YDest,
527 INT DestWidth,
528 INT DestHeight,
529 INT XSrc,
530 INT YSrc,
531 INT SrcWidth,
532 INT SrcHeight,
533 CONST VOID *Bits,
534 CONST BITMAPINFO *BitsInfo,
535 UINT Usage,
536 DWORD ROP)
537 {
538 HBITMAP hBitmap, hOldBitmap;
539 HDC hdcMem;
540
541 if (!Bits || !BitsInfo)
542 {
543 SetLastWin32Error(ERROR_INVALID_PARAMETER);
544 return 0;
545 }
546
547 hdcMem = NtGdiCreateCompatableDC(hDC);
548 hBitmap = NtGdiCreateCompatibleBitmap(hDC, BitsInfo->bmiHeader.biWidth,
549 BitsInfo->bmiHeader.biHeight);
550 hOldBitmap = NtGdiSelectObject(hdcMem, hBitmap);
551
552 if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
553 BitsInfo->bmiHeader.biCompression == BI_RLE8)
554 {
555 /* copy existing bitmap from destination dc */
556 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
557 NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
558 SrcWidth, SrcHeight, hDC, XDest, YDest, ROP);
559 else
560 NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
561 SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
562 ROP);
563 }
564
565 NtGdiSetDIBits(hdcMem, hBitmap, 0, BitsInfo->bmiHeader.biHeight, Bits,
566 BitsInfo, Usage);
567
568 /* Origin for DIBitmap may be bottom left (positive biHeight) or top
569 left (negative biHeight) */
570 if (SrcWidth == DestWidth && SrcHeight == DestHeight)
571 NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
572 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
573 ROP);
574 else
575 NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
576 hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
577 SrcWidth, SrcHeight, ROP);
578
579 NtGdiSelectObject(hdcMem, hOldBitmap);
580 NtGdiDeleteDC(hdcMem);
581 NtGdiDeleteObject(hBitmap);
582
583 return SrcHeight;
584 }
585
586 LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap,
587 LONG Count,
588 LPVOID Bits)
589 {
590 PBITMAPOBJ bmp;
591 LONG height, ret;
592
593 bmp = BITMAPOBJ_LockBitmap (hBitmap);
594 if (!bmp)
595 {
596 return 0;
597 }
598
599 /* If the bits vector is null, the function should return the read size */
600 if (Bits == NULL)
601 {
602 ret = bmp->SurfObj.cjBits;
603 BITMAPOBJ_UnlockBitmap (bmp);
604 return ret;
605 }
606
607 if (Count < 0)
608 {
609 DPRINT ("(%ld): Negative number of bytes passed???\n", Count);
610 Count = -Count;
611 }
612
613 /* Only get entire lines */
614 height = Count / abs(bmp->SurfObj.lDelta);
615 if (height > bmp->SurfObj.sizlBitmap.cy)
616 {
617 height = bmp->SurfObj.sizlBitmap.cy;
618 }
619 Count = height * abs(bmp->SurfObj.lDelta);
620 if (Count == 0)
621 {
622 DPRINT("Less then one entire line requested\n");
623 BITMAPOBJ_UnlockBitmap (bmp);
624 return 0;
625 }
626
627 DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
628 hBitmap, Count, Bits, bmp->SurfObj.sizlBitmap.cx,
629 bmp->SurfObj.sizlBitmap.cy,
630 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat), height );
631 #if 0
632 /* FIXME: Call DDI CopyBits here if available */
633 if(bmp->DDBitmap)
634 {
635 DPRINT("Calling device specific BitmapBits\n");
636 if(bmp->DDBitmap->funcs->pBitmapBits)
637 {
638 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
639 DDB_GET);
640 }
641 else
642 {
643 ERR_(bitmap)("BitmapBits == NULL??\n");
644 ret = 0;
645 }
646 }
647 else
648 #endif
649 {
650 memcpy(Bits, bmp->SurfObj.pvBits, Count);
651 ret = Count;
652 }
653
654 BITMAPOBJ_UnlockBitmap (bmp);
655
656 return ret;
657 }
658
659 HBITMAP FASTCALL
660 IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
661 DWORD init, LPCVOID bits, const BITMAPINFO *data,
662 UINT coloruse)
663 {
664 HBITMAP handle;
665 BOOL fColor;
666 DWORD width;
667 int height;
668 WORD bpp;
669 WORD compr;
670
671 if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
672
673 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
674 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
675
676 if (bpp != 1) fColor = TRUE;
677 else if ((coloruse != DIB_RGB_COLORS) ||
678 (init != CBM_INIT) || !data) fColor = FALSE;
679 else
680 {
681 if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
682 {
683 RGBQUAD *rgb = data->bmiColors;
684 DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
685
686 // Check if the first color of the colormap is black
687 if ((col == RGB(0, 0, 0)))
688 {
689 rgb++;
690 col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
691
692 // If the second color is white, create a monochrome bitmap
693 fColor = (col != RGB(0xff,0xff,0xff));
694 }
695 else fColor = TRUE;
696 }
697 else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
698 {
699 RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
700 DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
701
702 if ((col == RGB(0,0,0)))
703 {
704 rgb++;
705 col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
706 fColor = (col != RGB(0xff,0xff,0xff));
707 }
708 else fColor = TRUE;
709 }
710 else
711 {
712 DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
713 return 0;
714 }
715 }
716
717 // Now create the bitmap
718 if (fColor)
719 {
720 handle = IntCreateCompatibleBitmap(Dc, width, height);
721 }
722 else
723 {
724 handle = NtGdiCreateBitmap( width, height, 1, 1, NULL);
725 }
726
727 if (height < 0)
728 height = -height;
729
730 if (NULL != handle && CBM_INIT == init)
731 {
732 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
733 }
734
735 return handle;
736 }
737
738 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
739 // The DDB that is created will be whatever bit depth your reference DC is
740 HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
741 DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
742 UINT ColorUse)
743 {
744 PDC Dc;
745 HBITMAP Bmp;
746
747 Dc = DC_LockDc(hDc);
748 if (NULL == Dc)
749 {
750 SetLastWin32Error(ERROR_INVALID_HANDLE);
751 return NULL;
752 }
753
754 Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
755
756 DC_UnlockDc(Dc);
757
758 return Bmp;
759 }
760
761 HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
762 CONST BITMAPINFO *bmi,
763 UINT Usage,
764 VOID *Bits,
765 HANDLE hSection,
766 DWORD dwOffset)
767 {
768 HBITMAP hbitmap = 0;
769 DC *dc;
770 BOOL bDesktopDC = FALSE;
771
772 // If the reference hdc is null, take the desktop dc
773 if (hDC == 0)
774 {
775 hDC = NtGdiCreateCompatableDC(0);
776 bDesktopDC = TRUE;
777 }
778
779 if ((dc = DC_LockDc(hDC)))
780 {
781 hbitmap = DIB_CreateDIBSection ( dc, (BITMAPINFO*)bmi, Usage, Bits,
782 hSection, dwOffset, 0);
783 DC_UnlockDc(dc);
784 }
785 else
786 {
787 SetLastWin32Error(ERROR_INVALID_HANDLE);
788 }
789
790 if (bDesktopDC)
791 NtGdiDeleteDC(hDC);
792
793 return hbitmap;
794 }
795
796 HBITMAP STDCALL
797 DIB_CreateDIBSection(
798 PDC dc, BITMAPINFO *bmi, UINT usage,
799 LPVOID *bits, HANDLE section,
800 DWORD offset, DWORD ovr_pitch)
801 {
802 HBITMAP res = 0;
803 BITMAPOBJ *bmp = NULL;
804 DIBSECTION *dib = NULL;
805
806 // Fill BITMAP32 structure with DIB data
807 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
808 INT effHeight;
809 ULONG totalSize;
810 UINT Entries = 0;
811 BITMAP bm;
812 SIZEL Size;
813
814 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
815 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
816 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
817
818 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
819 bm.bmType = 0;
820 bm.bmWidth = bi->biWidth;
821 bm.bmHeight = effHeight;
822 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
823
824 bm.bmPlanes = bi->biPlanes;
825 bm.bmBitsPixel = bi->biBitCount;
826 bm.bmBits = NULL;
827
828 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
829 // we're dealing with a compressed bitmap. Otherwise, use width * height.
830 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
831 ? bi->biSizeImage : (ULONG) (bm.bmWidthBytes * effHeight);
832
833 if (section)
834 {
835 /* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS,
836 0L, offset, totalSize); */
837 DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n");
838 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
839 return 0;
840 }
841 else if (ovr_pitch && offset)
842 bm.bmBits = (LPVOID) offset;
843 else {
844 offset = 0;
845 bm.bmBits = EngAllocUserMem(totalSize, 0);
846 }
847
848 if(usage == DIB_PAL_COLORS)
849 memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *));
850
851 // Allocate Memory for DIB and fill structure
852 if (bm.bmBits)
853 {
854 dib = ExAllocatePoolWithTag(PagedPool, sizeof(DIBSECTION), TAG_DIB);
855 RtlZeroMemory(dib, sizeof(DIBSECTION));
856 }
857
858 if (dib)
859 {
860 dib->dsBm = bm;
861 dib->dsBmih = *bi;
862 dib->dsBmih.biSizeImage = totalSize;
863
864 /* Set dsBitfields values */
865 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
866 {
867 dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
868 }
869 else switch(bi->biBitCount)
870 {
871 case 16:
872 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
873 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
874 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f; break;
875
876 case 24:
877 dib->dsBitfields[0] = 0xff0000;
878 dib->dsBitfields[1] = 0x00ff00;
879 dib->dsBitfields[2] = 0x0000ff;
880 break;
881
882 case 32:
883 dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
884 dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
885 dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
886 break;
887 }
888 dib->dshSection = section;
889 dib->dsOffset = offset;
890 }
891
892 // Create Device Dependent Bitmap and add DIB pointer
893 if (dib)
894 {
895 Size.cx = bm.bmWidth;
896 Size.cy = abs(bm.bmHeight);
897 res = IntCreateBitmap(Size, bm.bmWidthBytes,
898 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
899 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
900 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
901 bm.bmBits);
902 if (! res)
903 {
904 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
905 return NULL;
906 }
907 bmp = BITMAPOBJ_LockBitmap(res);
908 if (NULL == bmp)
909 {
910 SetLastWin32Error(ERROR_INVALID_HANDLE);
911 NtGdiDeleteObject(bmp);
912 return NULL;
913 }
914 bmp->dib = (DIBSECTION *) dib;
915
916 /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical
917 device. Obviously, this is left out of the ReactOS implementation. Instead, we call
918 NtGdiSetDIBColorTable. */
919 if(bi->biBitCount == 1) { Entries = 2; } else
920 if(bi->biBitCount == 4) { Entries = 16; } else
921 if(bi->biBitCount == 8) { Entries = 256; }
922
923 if (Entries)
924 bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(Entries, bmi->bmiColors);
925 else
926 bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
927 dib->dsBitfields[0],
928 dib->dsBitfields[1],
929 dib->dsBitfields[2]);
930 }
931
932 // Clean up in case of errors
933 if (!res || !bmp || !dib || !bm.bmBits)
934 {
935 DPRINT("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits);
936 /* if (bm.bmBits)
937 {
938 if (section)
939 UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL;
940 else if (!offset)
941 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
942 } */
943
944 if (dib) { ExFreePool(dib); dib = NULL; }
945 if (bmp) { bmp = NULL; }
946 if (res) { BITMAPOBJ_FreeBitmap(res); res = 0; }
947 }
948
949 if (bmp)
950 {
951 BITMAPOBJ_UnlockBitmap(bmp);
952 }
953
954 // Return BITMAP handle and storage location
955 if (NULL != bm.bmBits && NULL != bits)
956 {
957 *bits = bm.bmBits;
958 }
959
960 return res;
961 }
962
963 /***********************************************************************
964 * DIB_GetDIBWidthBytes
965 *
966 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
967 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
968 * 11/16/1999 (RJJ) lifted from wine
969 */
970 INT FASTCALL DIB_GetDIBWidthBytes (INT width, INT depth)
971 {
972 int words;
973
974 switch(depth)
975 {
976 case 1: words = (width + 31) >> 5; break;
977 case 4: words = (width + 7) >> 3; break;
978 case 8: words = (width + 3) >> 2; break;
979 case 15:
980 case 16: words = (width + 1) >> 1; break;
981 case 24: words = (width * 3 + 3) >> 2; break;
982
983 default:
984 DPRINT("(%d): Unsupported depth\n", depth );
985 /* fall through */
986 case 32:
987 words = width;
988 }
989 return words << 2;
990 }
991
992 /***********************************************************************
993 * DIB_GetDIBImageBytes
994 *
995 * Return the number of bytes used to hold the image in a DIB bitmap.
996 * 11/16/1999 (RJJ) lifted from wine
997 */
998
999 INT STDCALL DIB_GetDIBImageBytes (INT width, INT height, INT depth)
1000 {
1001 return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height);
1002 }
1003
1004 /***********************************************************************
1005 * DIB_BitmapInfoSize
1006 *
1007 * Return the size of the bitmap info structure including color table.
1008 * 11/16/1999 (RJJ) lifted from wine
1009 */
1010
1011 INT FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
1012 {
1013 int colors;
1014
1015 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1016 {
1017 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
1018 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1019 return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1020 }
1021 else /* assume BITMAPINFOHEADER */
1022 {
1023 colors = info->bmiHeader.biClrUsed;
1024 if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
1025 return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1026 }
1027 }
1028
1029 INT STDCALL DIB_GetBitmapInfo (const BITMAPINFOHEADER *header,
1030 PDWORD width,
1031 PINT height,
1032 PWORD bpp,
1033 PWORD compr)
1034 {
1035 if (header->biSize == sizeof(BITMAPINFOHEADER))
1036 {
1037 *width = header->biWidth;
1038 *height = header->biHeight;
1039 *bpp = header->biBitCount;
1040 *compr = header->biCompression;
1041 return 1;
1042 }
1043 if (header->biSize == sizeof(BITMAPCOREHEADER))
1044 {
1045 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
1046 *width = core->bcWidth;
1047 *height = core->bcHeight;
1048 *bpp = core->bcBitCount;
1049 *compr = 0;
1050 return 0;
1051 }
1052 DPRINT("(%ld): wrong size for header\n", header->biSize );
1053 return -1;
1054 }
1055
1056 // Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB)
1057 // The specified Device Context (DC) defines what the DIB should be converted to
1058 PBITMAPOBJ FASTCALL DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should
1059 // change to NtGdiSetDIBits
1060 {
1061 HBITMAP hBmp = 0;
1062 PBITMAPOBJ pBmp = NULL;
1063 DIBSECTION *dib;
1064 LPBYTE pbits = NULL;
1065
1066 // Get a pointer to the packed DIB's data
1067 // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
1068 dib = hPackedDIB;
1069
1070 pbits = (LPBYTE)(dib + DIB_BitmapInfoSize((BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS));
1071
1072 // Create a DDB from the DIB
1073 hBmp = NtGdiCreateDIBitmap ( hdc, &dib->dsBmih, CBM_INIT,
1074 (LPVOID)pbits, (BITMAPINFO*)&dib->dsBmih, DIB_RGB_COLORS);
1075
1076 // GlobalUnlock(hPackedDIB);
1077
1078 // Retrieve the internal Pixmap from the DDB
1079 pBmp = BITMAPOBJ_LockBitmap(hBmp);
1080
1081 return pBmp;
1082 }
1083
1084 RGBQUAD * FASTCALL
1085 DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
1086 {
1087 RGBQUAD *lpRGB;
1088 ULONG nNumColors,i;
1089 USHORT *lpIndex;
1090 PPALGDI palGDI;
1091
1092 palGDI = PALETTE_LockPalette(dc->w.hPalette);
1093
1094 if (NULL == palGDI)
1095 {
1096 // RELEASEDCINFO(hDC);
1097 return NULL;
1098 }
1099
1100 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1101 if (lpbmi->bmiHeader.biClrUsed)
1102 {
1103 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1104 }
1105
1106 lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
1107 lpIndex = (USHORT *)&lpbmi->bmiColors[0];
1108
1109 for (i = 0; i < nNumColors; i++)
1110 {
1111 lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
1112 lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
1113 lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
1114 lpIndex++;
1115 }
1116 // RELEASEDCINFO(hDC);
1117 PALETTE_UnlockPalette(palGDI);
1118
1119 return lpRGB;
1120 }
1121
1122 HPALETTE FASTCALL
1123 BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType)
1124 {
1125 BYTE bits;
1126 ULONG ColorCount;
1127 PALETTEENTRY *palEntries = NULL;
1128 HPALETTE hPal;
1129
1130 // Determine Bits Per Pixel
1131 bits = bmi->bmiHeader.biBitCount;
1132
1133 // Determine paletteType from Bits Per Pixel
1134 if (bits <= 8)
1135 {
1136 *paletteType = PAL_INDEXED;
1137 }
1138 else if(bits < 24)
1139 {
1140 *paletteType = PAL_BITFIELDS;
1141 }
1142 else
1143 {
1144 *paletteType = PAL_BGR;
1145 }
1146
1147 if (bmi->bmiHeader.biClrUsed == 0)
1148 {
1149 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1150 }
1151 else
1152 {
1153 ColorCount = bmi->bmiHeader.biClrUsed;
1154 }
1155
1156 if (PAL_INDEXED == *paletteType)
1157 {
1158 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
1159 }
1160 else
1161 {
1162 hPal = PALETTE_AllocPalette( *paletteType, ColorCount, (ULONG*)palEntries, 0, 0, 0 );
1163 }
1164
1165 return hPal;
1166 }
1167
1168 /* EOF */