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