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