c4bb3857cc8ea616b3c8e5df161372acb03bb286
[reactos.git] / subsystems / win32 / win32k / objects / bitmaps.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <win32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 HBITMAP APIENTRY
26 IntGdiCreateBitmap(
27 INT Width,
28 INT Height,
29 UINT Planes,
30 UINT BitsPixel,
31 IN OPTIONAL LPBYTE pBits)
32 {
33 HBITMAP hBitmap;
34 SIZEL Size;
35 LONG WidthBytes;
36 PSURFACE psurfBmp;
37
38 /* NOTE: Windows also doesn't store nr. of planes separately! */
39 BitsPixel = BITMAP_GetRealBitsPixel(BitsPixel * Planes);
40
41 /* Check parameters */
42 if (BitsPixel == 0 || Width <= 0 || Width >= 0x8000000 || Height == 0)
43 {
44 DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
45 Width, Height, BitsPixel);
46 SetLastWin32Error(ERROR_INVALID_PARAMETER);
47 return 0;
48 }
49
50 WidthBytes = BITMAP_GetWidthBytes(Width, BitsPixel);
51
52 Size.cx = Width;
53 Size.cy = abs(Height);
54
55 /* Make sure that cjBits will not overflow */
56 if ((ULONGLONG)WidthBytes * Size.cy >= 0x100000000ULL)
57 {
58 DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
59 Width, Height, BitsPixel);
60 SetLastWin32Error(ERROR_INVALID_PARAMETER);
61 return 0;
62 }
63
64 /* Create the bitmap object. */
65 hBitmap = IntCreateBitmap(Size, WidthBytes,
66 BitmapFormat(BitsPixel, BI_RGB),
67 (Height < 0 ? BMF_TOPDOWN : 0) |
68 (NULL == pBits ? 0 : BMF_NOZEROINIT), NULL);
69 if (!hBitmap)
70 {
71 DPRINT("IntGdiCreateBitmap: returned 0\n");
72 return 0;
73 }
74
75 psurfBmp = SURFACE_LockSurface(hBitmap);
76 if (psurfBmp == NULL)
77 {
78 GreDeleteObject(hBitmap);
79 return NULL;
80 }
81
82 psurfBmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
83 psurfBmp->hDC = NULL; // Fixme
84
85 if (NULL != pBits)
86 {
87 IntSetBitmapBits(psurfBmp, psurfBmp->SurfObj.cjBits, pBits);
88 }
89
90 SURFACE_UnlockSurface(psurfBmp);
91
92 DPRINT("IntGdiCreateBitmap : %dx%d, %d BPP colors, topdown %d, returning %08x\n",
93 Size.cx, Size.cy, BitsPixel, (Height < 0 ? 1 : 0), hBitmap);
94
95 return hBitmap;
96 }
97
98
99 HBITMAP APIENTRY
100 NtGdiCreateBitmap(
101 INT Width,
102 INT Height,
103 UINT Planes,
104 UINT BitsPixel,
105 IN OPTIONAL LPBYTE pUnsafeBits)
106 {
107 if (pUnsafeBits)
108 {
109 BOOL Hit = FALSE;
110 UINT cjBits = BITMAP_GetWidthBytes(Width, BitsPixel) * abs(Height);
111
112 // FIXME: Use MmSecureVirtualMemory
113 _SEH2_TRY
114 {
115 ProbeForRead(pUnsafeBits, cjBits, 1);
116 }
117 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
118 {
119 Hit = TRUE;
120 }
121 _SEH2_END
122
123 if (Hit) return 0;
124 }
125
126 return IntGdiCreateBitmap(Width, Height, Planes, BitsPixel, pUnsafeBits);
127 }
128
129 HBITMAP FASTCALL
130 IntCreateCompatibleBitmap(
131 PDC Dc,
132 INT Width,
133 INT Height)
134 {
135 HBITMAP Bmp = NULL;
136
137 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
138 if (0 == Width || 0 == Height)
139 {
140 Bmp = NtGdiGetStockObject(DEFAULT_BITMAP);
141 }
142 else
143 {
144 if (Dc->dctype != DC_TYPE_MEMORY)
145 {
146 PSURFACE psurf;
147 Bmp = IntGdiCreateBitmap(abs(Width),
148 abs(Height),
149 Dc->ppdev->gdiinfo.cPlanes,
150 Dc->ppdev->gdiinfo.cBitsPixel,
151 NULL);
152 /* Set palette */
153 psurf = SURFACE_LockSurface(Bmp);
154 if(!psurf)
155 {
156 DPRINT1("Could not lock surface?\n");
157 }
158 else
159 {
160 psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
161 SURFACE_UnlockSurface(psurf);
162 }
163 }
164 else
165 {
166 DIBSECTION dibs;
167 INT Count;
168 PSURFACE psurf = Dc->dclevel.pSurface;
169 Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
170
171 if (Count)
172 {
173 if (Count == sizeof(BITMAP))
174 {
175 /* We have a bitmap bug!!! W/O the HACK, we have white icons.
176
177 MSDN Note: When a memory device context is created, it initially
178 has a 1-by-1 monochrome bitmap selected into it. If this memory
179 device context is used in CreateCompatibleBitmap, the bitmap that
180 is created is a monochrome bitmap. To create a color bitmap, use
181 the hDC that was used to create the memory device context, as
182 shown in the following code:
183
184 HDC memDC = CreateCompatibleDC(hDC);
185 HBITMAP memBM = CreateCompatibleBitmap(hDC, nWidth, nHeight);
186 SelectObject(memDC, memBM);
187 */
188 Bmp = IntGdiCreateBitmap(abs(Width),
189 abs(Height),
190 dibs.dsBm.bmPlanes,
191 dibs.dsBm.bmBitsPixel,
192 NULL);
193 }
194 else
195 {
196 /* A DIB section is selected in the DC */
197 BITMAPINFO *bi;
198 PVOID Bits;
199
200 /* Allocate memory for a BITMAPINFOHEADER structure and a
201 color table. The maximum number of colors in a color table
202 is 256 which corresponds to a bitmap with depth 8.
203 Bitmaps with higher depths don't have color tables. */
204 bi = ExAllocatePoolWithTag(PagedPool,
205 sizeof(BITMAPINFOHEADER) +
206 256 * sizeof(RGBQUAD),
207 TAG_TEMP);
208
209 if (bi)
210 {
211 bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
212 bi->bmiHeader.biWidth = Width;
213 bi->bmiHeader.biHeight = Height;
214 bi->bmiHeader.biPlanes = dibs.dsBmih.biPlanes;
215 bi->bmiHeader.biBitCount = dibs.dsBmih.biBitCount;
216 bi->bmiHeader.biCompression = dibs.dsBmih.biCompression;
217 bi->bmiHeader.biSizeImage = 0;
218 bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
219 bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
220 bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed;
221 bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant;
222
223 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
224 {
225 /* Copy the color masks */
226 RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3 * sizeof(DWORD));
227 }
228 else if (bi->bmiHeader.biBitCount <= 8)
229 {
230 /* Copy the color table */
231 UINT Index;
232 PPALETTE PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
233
234 if (!PalGDI)
235 {
236 ExFreePoolWithTag(bi, TAG_TEMP);
237 SetLastWin32Error(ERROR_INVALID_HANDLE);
238 return 0;
239 }
240
241 for (Index = 0;
242 Index < 256 && Index < PalGDI->NumColors;
243 Index++)
244 {
245 bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed;
246 bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
247 bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
248 bi->bmiColors[Index].rgbReserved = 0;
249 }
250 PALETTE_UnlockPalette(PalGDI);
251 }
252
253 Bmp = DIB_CreateDIBSection(Dc,
254 bi,
255 DIB_RGB_COLORS,
256 &Bits,
257 NULL,
258 0,
259 0);
260
261 ExFreePoolWithTag(bi, TAG_TEMP);
262 return Bmp;
263 }
264 }
265 }
266 }
267 }
268 return Bmp;
269 }
270
271 HBITMAP APIENTRY
272 NtGdiCreateCompatibleBitmap(
273 HDC hDC,
274 INT Width,
275 INT Height)
276 {
277 HBITMAP Bmp;
278 PDC Dc;
279
280 if (Width <= 0 || Height <= 0 || (Width * Height) > 0x3FFFFFFF)
281 {
282 SetLastWin32Error(ERROR_INVALID_PARAMETER);
283 return NULL;
284 }
285
286 if (!hDC)
287 return IntGdiCreateBitmap(Width, Height, 1, 1, 0);
288
289 Dc = DC_LockDc(hDC);
290
291 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n",
292 hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel);
293
294 if (NULL == Dc)
295 {
296 SetLastWin32Error(ERROR_INVALID_HANDLE);
297 return NULL;
298 }
299
300 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
301
302 DPRINT("\t\t%04x\n", Bmp);
303 DC_UnlockDc(Dc);
304 return Bmp;
305 }
306
307 BOOL APIENTRY
308 NtGdiGetBitmapDimension(
309 HBITMAP hBitmap,
310 LPSIZE Dimension)
311 {
312 PSURFACE psurfBmp;
313 BOOL Ret = TRUE;
314
315 if (hBitmap == NULL)
316 return FALSE;
317
318 psurfBmp = SURFACE_LockSurface(hBitmap);
319 if (psurfBmp == NULL)
320 {
321 SetLastWin32Error(ERROR_INVALID_HANDLE);
322 return FALSE;
323 }
324
325 _SEH2_TRY
326 {
327 ProbeForWrite(Dimension, sizeof(SIZE), 1);
328 *Dimension = psurfBmp->dimension;
329 }
330 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
331 {
332 Ret = FALSE;
333 }
334 _SEH2_END
335
336 SURFACE_UnlockSurface(psurfBmp);
337
338 return Ret;
339 }
340
341 COLORREF APIENTRY
342 NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
343 {
344 PDC dc = NULL;
345 COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
346 BOOL bInRect = FALSE;
347 SURFACE *psurf;
348 SURFOBJ *pso;
349 PPALETTE ppal;
350 EXLATEOBJ exlo;
351 HBITMAP hBmpTmp;
352
353 dc = DC_LockDc(hDC);
354
355 if (!dc)
356 {
357 SetLastWin32Error(ERROR_INVALID_HANDLE);
358 return Result;
359 }
360
361 if (dc->dctype == DC_TYPE_INFO)
362 {
363 DC_UnlockDc(dc);
364 return Result;
365 }
366
367 XPos += dc->ptlDCOrig.x;
368 YPos += dc->ptlDCOrig.y;
369 if (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos))
370 {
371 bInRect = TRUE;
372 psurf = dc->dclevel.pSurface;
373 if (psurf)
374 {
375 pso = &psurf->SurfObj;
376 if(psurf->hDIBPalette)
377 ppal = PALETTE_ShareLockPalette(psurf->hDIBPalette);
378 else if (psurf->ppal)
379 {
380 ppal = psurf->ppal;
381 GDIOBJ_IncrementShareCount(&ppal->BaseObject);
382 }
383 else
384 ppal = PALETTE_ShareLockPalette(dc->ppdev->devinfo.hpalDefault);
385
386 if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure)
387 {
388 /* FIXME: palette should be gpalMono already ! */
389 EXLATEOBJ_vInitialize(&exlo, &gpalMono, &gpalRGB, 0, 0xffffff, 0);
390 }
391 else
392 {
393 EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, 0xffffff, 0);
394 }
395
396 // check if this DC has a DIB behind it...
397 if (pso->pvScan0) // STYPE_BITMAP == pso->iType
398 {
399 ASSERT(pso->lDelta);
400 Result = XLATEOBJ_iXlate(&exlo.xlo,
401 DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_GetPixel(pso, XPos, YPos));
402 }
403
404 EXLATEOBJ_vCleanup(&exlo);
405 PALETTE_ShareUnlockPalette(ppal);
406 }
407 }
408 DC_UnlockDc(dc);
409
410 // if Result is still CLR_INVALID, then the "quick" method above didn't work
411 if (bInRect && Result == CLR_INVALID)
412 {
413 // FIXME: create a 1x1 32BPP DIB, and blit to it
414 HDC hDCTmp = NtGdiCreateCompatibleDC(hDC);
415 if (hDCTmp)
416 {
417 static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
418 BITMAPINFO bi;
419 RtlMoveMemory(&(bi.bmiHeader), &bih, sizeof(bih));
420 hBmpTmp = NtGdiCreateDIBitmapInternal(hDC,
421 bi.bmiHeader.biWidth,
422 bi.bmiHeader.biHeight,
423 0,
424 NULL,
425 &bi,
426 DIB_RGB_COLORS,
427 bi.bmiHeader.biBitCount,
428 bi.bmiHeader.biSizeImage,
429 0,
430 0);
431
432 //HBITMAP hBmpTmp = IntGdiCreateBitmap(1, 1, 1, 32, NULL);
433 if (hBmpTmp)
434 {
435 HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp);
436 if (hBmpOld)
437 {
438 PSURFACE psurf;
439
440 NtGdiBitBlt(hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0);
441 NtGdiSelectBitmap(hDCTmp, hBmpOld);
442
443 // our bitmap is no longer selected, so we can access it's stuff...
444 psurf = SURFACE_LockSurface(hBmpTmp);
445 if (psurf)
446 {
447 // Dont you need to convert something here?
448 Result = *(COLORREF*)psurf->SurfObj.pvScan0;
449 SURFACE_UnlockSurface(psurf);
450 }
451 }
452 GreDeleteObject(hBmpTmp);
453 }
454 NtGdiDeleteObjectApp(hDCTmp);
455 }
456 }
457
458 return Result;
459 }
460
461
462 LONG APIENTRY
463 IntGetBitmapBits(
464 PSURFACE psurf,
465 DWORD Bytes,
466 OUT PBYTE Bits)
467 {
468 LONG ret;
469
470 ASSERT(Bits);
471
472 /* Don't copy more bytes than the buffer has */
473 Bytes = min(Bytes, psurf->SurfObj.cjBits);
474
475 #if 0
476 /* FIXME: Call DDI CopyBits here if available */
477 if (psurf->DDBitmap)
478 {
479 DPRINT("Calling device specific BitmapBits\n");
480 if (psurf->DDBitmap->funcs->pBitmapBits)
481 {
482 ret = psurf->DDBitmap->funcs->pBitmapBits(hbitmap,
483 bits,
484 count,
485 DDB_GET);
486 }
487 else
488 {
489 ERR_(bitmap)("BitmapBits == NULL??\n");
490 ret = 0;
491 }
492 }
493 else
494 #endif
495 {
496 RtlCopyMemory(Bits, psurf->SurfObj.pvBits, Bytes);
497 ret = Bytes;
498 }
499 return ret;
500 }
501
502 LONG APIENTRY
503 NtGdiGetBitmapBits(
504 HBITMAP hBitmap,
505 ULONG Bytes,
506 OUT OPTIONAL PBYTE pUnsafeBits)
507 {
508 PSURFACE psurf;
509 LONG bmSize, ret;
510
511 if (pUnsafeBits != NULL && Bytes == 0)
512 {
513 return 0;
514 }
515
516 psurf = SURFACE_LockSurface(hBitmap);
517 if (!psurf)
518 {
519 SetLastWin32Error(ERROR_INVALID_HANDLE);
520 return 0;
521 }
522
523 bmSize = BITMAP_GetWidthBytes(psurf->SurfObj.sizlBitmap.cx,
524 BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
525 abs(psurf->SurfObj.sizlBitmap.cy);
526
527 /* If the bits vector is null, the function should return the read size */
528 if (pUnsafeBits == NULL)
529 {
530 SURFACE_UnlockSurface(psurf);
531 return bmSize;
532 }
533
534 /* Don't copy more bytes than the buffer has */
535 Bytes = min(Bytes, bmSize);
536
537 // FIXME: use MmSecureVirtualMemory
538 _SEH2_TRY
539 {
540 ProbeForWrite(pUnsafeBits, Bytes, 1);
541 ret = IntGetBitmapBits(psurf, Bytes, pUnsafeBits);
542 }
543 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
544 {
545 ret = 0;
546 }
547 _SEH2_END
548
549 SURFACE_UnlockSurface(psurf);
550
551 return ret;
552 }
553
554
555 LONG APIENTRY
556 IntSetBitmapBits(
557 PSURFACE psurf,
558 DWORD Bytes,
559 IN PBYTE Bits)
560 {
561 LONG ret;
562
563 /* Don't copy more bytes than the buffer has */
564 Bytes = min(Bytes, psurf->SurfObj.cjBits);
565
566 #if 0
567 /* FIXME: call DDI specific function here if available */
568 if (psurf->DDBitmap)
569 {
570 DPRINT("Calling device specific BitmapBits\n");
571 if (psurf->DDBitmap->funcs->pBitmapBits)
572 {
573 ret = psurf->DDBitmap->funcs->pBitmapBits(hBitmap,
574 (void *)Bits,
575 Bytes,
576 DDB_SET);
577 }
578 else
579 {
580 DPRINT("BitmapBits == NULL??\n");
581 ret = 0;
582 }
583 }
584 else
585 #endif
586 {
587 RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
588 ret = Bytes;
589 }
590
591 return ret;
592 }
593
594
595 LONG APIENTRY
596 NtGdiSetBitmapBits(
597 HBITMAP hBitmap,
598 DWORD Bytes,
599 IN PBYTE pUnsafeBits)
600 {
601 LONG ret;
602 PSURFACE psurf;
603
604 if (pUnsafeBits == NULL || Bytes == 0)
605 {
606 return 0;
607 }
608
609 psurf = SURFACE_LockSurface(hBitmap);
610 if (psurf == NULL)
611 {
612 SetLastWin32Error(ERROR_INVALID_HANDLE);
613 return 0;
614 }
615
616 _SEH2_TRY
617 {
618 ProbeForRead(pUnsafeBits, Bytes, 1);
619 ret = IntSetBitmapBits(psurf, Bytes, pUnsafeBits);
620 }
621 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
622 {
623 ret = 0;
624 }
625 _SEH2_END
626
627 SURFACE_UnlockSurface(psurf);
628
629 return ret;
630 }
631
632 BOOL APIENTRY
633 NtGdiSetBitmapDimension(
634 HBITMAP hBitmap,
635 INT Width,
636 INT Height,
637 LPSIZE Size)
638 {
639 PSURFACE psurf;
640 BOOL Ret = TRUE;
641
642 if (hBitmap == NULL)
643 return FALSE;
644
645 psurf = SURFACE_LockSurface(hBitmap);
646 if (psurf == NULL)
647 {
648 SetLastWin32Error(ERROR_INVALID_HANDLE);
649 return FALSE;
650 }
651
652 if (Size)
653 {
654 _SEH2_TRY
655 {
656 ProbeForWrite(Size, sizeof(SIZE), 1);
657 *Size = psurf->dimension;
658 }
659 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
660 {
661 Ret = FALSE;
662 }
663 _SEH2_END
664 }
665
666 /* The dimension is changed even if writing the old value failed */
667 psurf->dimension.cx = Width;
668 psurf->dimension.cy = Height;
669
670 SURFACE_UnlockSurface(psurf);
671
672 return Ret;
673 }
674
675 VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color)
676 {
677 PDC pdc = NULL;
678 RGBQUAD quad;
679 PALETTEENTRY palEntry;
680 UINT index;
681
682 switch (*Color >> 24)
683 {
684 case 0x10: /* DIBINDEX */
685 if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
686 {
687 *Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
688 }
689 else
690 {
691 /* Out of color table bounds - use black */
692 *Color = RGB(0, 0, 0);
693 }
694 break;
695 case 0x02: /* PALETTERGB */
696 pdc = DC_LockDc(hDC);
697 if (pdc->dclevel.hpal != NtGdiGetStockObject(DEFAULT_PALETTE))
698 {
699 index = NtGdiGetNearestPaletteIndex(pdc->dclevel.hpal, *Color);
700 IntGetPaletteEntries(pdc->dclevel.hpal, index, 1, &palEntry);
701 *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
702 }
703 else
704 {
705 /* Use the pure color */
706 *Color = *Color & 0x00FFFFFF;
707 }
708 DC_UnlockDc(pdc);
709 break;
710 case 0x01: /* PALETTEINDEX */
711 pdc = DC_LockDc(hDC);
712 if (IntGetPaletteEntries(pdc->dclevel.hpal, LOWORD(*Color), 1, &palEntry) == 1)
713 {
714 *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
715 }
716 else
717 {
718 /* Index does not exist, use zero index */
719 IntGetPaletteEntries(pdc->dclevel.hpal, 0, 1, &palEntry);
720 *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
721 }
722 DC_UnlockDc(pdc);
723 break;
724 default:
725 DPRINT("Unsupported color type %d passed\n", *Color >> 24);
726 break;
727 }
728 }
729
730 BOOL APIENTRY
731 GdiSetPixelV(
732 HDC hDC,
733 INT X,
734 INT Y,
735 COLORREF Color)
736 {
737 HBRUSH hBrush;
738 HGDIOBJ OldBrush;
739
740 if ((Color & 0xFF000000) != 0)
741 {
742 IntHandleSpecialColorType(hDC, &Color);
743 }
744
745 hBrush = NtGdiCreateSolidBrush(Color, NULL);
746 if (hBrush == NULL)
747 return FALSE;
748
749 OldBrush = NtGdiSelectBrush(hDC, hBrush);
750 if (OldBrush == NULL)
751 {
752 GreDeleteObject(hBrush);
753 return FALSE;
754 }
755
756 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
757 NtGdiSelectBrush(hDC, OldBrush);
758 GreDeleteObject(hBrush);
759
760 return TRUE;
761 }
762
763 COLORREF APIENTRY
764 NtGdiSetPixel(
765 HDC hDC,
766 INT X,
767 INT Y,
768 COLORREF Color)
769 {
770 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
771
772 if (GdiSetPixelV(hDC,X,Y,Color))
773 {
774 Color = NtGdiGetPixel(hDC,X,Y);
775 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
776 return Color;
777 }
778
779 Color = (COLORREF)CLR_INVALID;
780 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
781 return Color;
782 }
783
784
785 /* Internal Functions */
786
787 UINT FASTCALL
788 BITMAP_GetRealBitsPixel(UINT nBitsPixel)
789 {
790 if (nBitsPixel <= 1)
791 return 1;
792 if (nBitsPixel <= 4)
793 return 4;
794 if (nBitsPixel <= 8)
795 return 8;
796 if (nBitsPixel <= 16)
797 return 16;
798 if (nBitsPixel <= 24)
799 return 24;
800 if (nBitsPixel <= 32)
801 return 32;
802
803 return 0;
804 }
805
806 INT FASTCALL
807 BITMAP_GetWidthBytes(INT bmWidth, INT bpp)
808 {
809 #if 0
810 switch (bpp)
811 {
812 case 1:
813 return 2 * ((bmWidth+15) >> 4);
814
815 case 24:
816 bmWidth *= 3; /* fall through */
817 case 8:
818 return bmWidth + (bmWidth & 1);
819
820 case 32:
821 return bmWidth * 4;
822
823 case 16:
824 case 15:
825 return bmWidth * 2;
826
827 case 4:
828 return 2 * ((bmWidth+3) >> 2);
829
830 default:
831 DPRINT ("stub");
832 }
833
834 return -1;
835 #endif
836
837 return ((bmWidth * bpp + 15) & ~15) >> 3;
838 }
839
840 HBITMAP FASTCALL
841 BITMAP_CopyBitmap(HBITMAP hBitmap)
842 {
843 HBITMAP res;
844 BITMAP bm;
845 SURFACE *Bitmap, *resBitmap;
846 SIZEL Size;
847
848 if (hBitmap == NULL)
849 {
850 return 0;
851 }
852
853 Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
854 if (Bitmap == NULL)
855 {
856 return 0;
857 }
858
859 BITMAP_GetObject(Bitmap, sizeof(BITMAP), (PVOID)&bm);
860 bm.bmBits = NULL;
861 if (Bitmap->SurfObj.lDelta >= 0)
862 bm.bmHeight = -bm.bmHeight;
863
864 Size.cx = abs(bm.bmWidth);
865 Size.cy = abs(bm.bmHeight);
866 res = IntCreateBitmap(Size,
867 bm.bmWidthBytes,
868 BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
869 (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
870 NULL);
871
872 if (res)
873 {
874 PBYTE buf;
875
876 resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
877 if (resBitmap)
878 {
879 buf = ExAllocatePoolWithTag(PagedPool,
880 bm.bmWidthBytes * abs(bm.bmHeight),
881 TAG_BITMAP);
882 if (buf == NULL)
883 {
884 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
885 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
886 GreDeleteObject(res);
887 return 0;
888 }
889 IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
890 IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
891 ExFreePoolWithTag(buf,TAG_BITMAP);
892 resBitmap->flFlags = Bitmap->flFlags;
893 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
894 }
895 else
896 {
897 GreDeleteObject(res);
898 res = NULL;
899 }
900 }
901
902 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
903
904 return res;
905 }
906
907 INT APIENTRY
908 BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
909 {
910 PBITMAP pBitmap;
911
912 if (!buffer) return sizeof(BITMAP);
913 if ((UINT)Count < sizeof(BITMAP)) return 0;
914
915 /* always fill a basic BITMAP structure */
916 pBitmap = buffer;
917 pBitmap->bmType = 0;
918 pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
919 pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
920 pBitmap->bmWidthBytes = abs(psurf->SurfObj.lDelta);
921 pBitmap->bmPlanes = 1;
922 pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
923
924 /* Check for DIB section */
925 if (psurf->hSecure)
926 {
927 /* Set bmBits in this case */
928 pBitmap->bmBits = psurf->SurfObj.pvBits;
929
930 if (Count >= sizeof(DIBSECTION))
931 {
932 /* Fill rest of DIBSECTION */
933 PDIBSECTION pds = buffer;
934
935 pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
936 pds->dsBmih.biWidth = pds->dsBm.bmWidth;
937 pds->dsBmih.biHeight = pds->dsBm.bmHeight;
938 pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
939 pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
940 switch (psurf->SurfObj.iBitmapFormat)
941 {
942 /* FIXME: What about BI_BITFIELDS? */
943 case BMF_1BPP:
944 case BMF_4BPP:
945 case BMF_8BPP:
946 case BMF_16BPP:
947 case BMF_24BPP:
948 case BMF_32BPP:
949 pds->dsBmih.biCompression = BI_RGB;
950 break;
951 case BMF_4RLE:
952 pds->dsBmih.biCompression = BI_RLE4;
953 break;
954 case BMF_8RLE:
955 pds->dsBmih.biCompression = BI_RLE8;
956 break;
957 case BMF_JPEG:
958 pds->dsBmih.biCompression = BI_JPEG;
959 break;
960 case BMF_PNG:
961 pds->dsBmih.biCompression = BI_PNG;
962 break;
963 }
964 pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
965 pds->dsBmih.biXPelsPerMeter = 0;
966 pds->dsBmih.biYPelsPerMeter = 0;
967 pds->dsBmih.biClrUsed = psurf->biClrUsed;
968 pds->dsBmih.biClrImportant = psurf->biClrImportant;
969 pds->dsBitfields[0] = psurf->dsBitfields[0];
970 pds->dsBitfields[1] = psurf->dsBitfields[1];
971 pds->dsBitfields[2] = psurf->dsBitfields[2];
972 pds->dshSection = psurf->hDIBSection;
973 pds->dsOffset = psurf->dwOffset;
974
975 return sizeof(DIBSECTION);
976 }
977 }
978 else
979 {
980 /* not set according to wine test, confirmed in win2k */
981 pBitmap->bmBits = NULL;
982 }
983
984 return sizeof(BITMAP);
985 }
986
987 /*
988 * @implemented
989 */
990 HDC
991 APIENTRY
992 NtGdiGetDCforBitmap(
993 IN HBITMAP hsurf)
994 {
995 HDC hDC = NULL;
996 PSURFACE psurf = SURFACE_LockSurface(hsurf);
997 if (psurf)
998 {
999 hDC = psurf->hDC;
1000 SURFACE_UnlockSurface(psurf);
1001 }
1002 return hDC;
1003 }
1004
1005 /* EOF */