0bae35a10589abd7675cd147bc245fc22f977e5d
[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 index = NtGdiGetNearestPaletteIndex(pdc->dclevel.hpal, *Color);
681 if (IntGetPaletteEntries(pdc->dclevel.hpal, index, 1, &palEntry) == 1)
682 {
683 *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
684 }
685 DC_UnlockDc(pdc);
686 break;
687 case 0x01: /* PALETTEINDEX */
688 pdc = DC_LockDc(hDC);
689 if (IntGetPaletteEntries(pdc->dclevel.hpal, LOWORD(*Color), 1, &palEntry) == 1)
690 {
691 *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
692 }
693 DC_UnlockDc(pdc);
694 break;
695 default:
696 DPRINT("Unsupported color type %d passed\n", *Color >> 24);
697 break;
698 }
699 }
700
701 BOOL APIENTRY
702 GdiSetPixelV(
703 HDC hDC,
704 INT X,
705 INT Y,
706 COLORREF Color)
707 {
708 HBRUSH hBrush;
709 HGDIOBJ OldBrush;
710
711 if ((Color & 0xFF000000) != 0)
712 {
713 IntHandleSpecialColorType(hDC, &Color);
714 }
715
716 hBrush = NtGdiCreateSolidBrush(Color, NULL);
717 if (hBrush == NULL)
718 return FALSE;
719
720 OldBrush = NtGdiSelectBrush(hDC, hBrush);
721 if (OldBrush == NULL)
722 {
723 GreDeleteObject(hBrush);
724 return FALSE;
725 }
726
727 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
728 NtGdiSelectBrush(hDC, OldBrush);
729 GreDeleteObject(hBrush);
730
731 return TRUE;
732 }
733
734 COLORREF APIENTRY
735 NtGdiSetPixel(
736 HDC hDC,
737 INT X,
738 INT Y,
739 COLORREF Color)
740 {
741 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
742
743 if (GdiSetPixelV(hDC,X,Y,Color))
744 {
745 Color = NtGdiGetPixel(hDC,X,Y);
746 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
747 return Color;
748 }
749
750 Color = (COLORREF)CLR_INVALID;
751 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
752 return Color;
753 }
754
755
756 /* Internal Functions */
757
758 UINT FASTCALL
759 BITMAP_GetRealBitsPixel(UINT nBitsPixel)
760 {
761 if (nBitsPixel <= 1)
762 return 1;
763 if (nBitsPixel <= 4)
764 return 4;
765 if (nBitsPixel <= 8)
766 return 8;
767 if (nBitsPixel <= 16)
768 return 16;
769 if (nBitsPixel <= 24)
770 return 24;
771 if (nBitsPixel <= 32)
772 return 32;
773
774 return 0;
775 }
776
777 INT FASTCALL
778 BITMAP_GetWidthBytes(INT bmWidth, INT bpp)
779 {
780 #if 0
781 switch (bpp)
782 {
783 case 1:
784 return 2 * ((bmWidth+15) >> 4);
785
786 case 24:
787 bmWidth *= 3; /* fall through */
788 case 8:
789 return bmWidth + (bmWidth & 1);
790
791 case 32:
792 return bmWidth * 4;
793
794 case 16:
795 case 15:
796 return bmWidth * 2;
797
798 case 4:
799 return 2 * ((bmWidth+3) >> 2);
800
801 default:
802 DPRINT ("stub");
803 }
804
805 return -1;
806 #endif
807
808 return ((bmWidth * bpp + 15) & ~15) >> 3;
809 }
810
811 HBITMAP FASTCALL
812 BITMAP_CopyBitmap(HBITMAP hBitmap)
813 {
814 HBITMAP res;
815 BITMAP bm;
816 SURFACE *Bitmap, *resBitmap;
817 SIZEL Size;
818
819 if (hBitmap == NULL)
820 {
821 return 0;
822 }
823
824 Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
825 if (Bitmap == NULL)
826 {
827 return 0;
828 }
829
830 BITMAP_GetObject(Bitmap, sizeof(BITMAP), (PVOID)&bm);
831 bm.bmBits = NULL;
832 if (Bitmap->SurfObj.lDelta >= 0)
833 bm.bmHeight = -bm.bmHeight;
834
835 Size.cx = abs(bm.bmWidth);
836 Size.cy = abs(bm.bmHeight);
837 res = IntCreateBitmap(Size,
838 bm.bmWidthBytes,
839 BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
840 (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
841 NULL);
842
843 if (res)
844 {
845 PBYTE buf;
846
847 resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
848 if (resBitmap)
849 {
850 buf = ExAllocatePoolWithTag(PagedPool,
851 bm.bmWidthBytes * abs(bm.bmHeight),
852 TAG_BITMAP);
853 if (buf == NULL)
854 {
855 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
856 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
857 GreDeleteObject(res);
858 return 0;
859 }
860 IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
861 IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
862 ExFreePoolWithTag(buf,TAG_BITMAP);
863 resBitmap->flFlags = Bitmap->flFlags;
864 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
865 }
866 else
867 {
868 GreDeleteObject(res);
869 res = NULL;
870 }
871 }
872
873 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
874
875 return res;
876 }
877
878 INT APIENTRY
879 BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
880 {
881 PBITMAP pBitmap;
882
883 if (!buffer) return sizeof(BITMAP);
884 if ((UINT)Count < sizeof(BITMAP)) return 0;
885
886 /* always fill a basic BITMAP structure */
887 pBitmap = buffer;
888 pBitmap->bmType = 0;
889 pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
890 pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
891 pBitmap->bmWidthBytes = abs(psurf->SurfObj.lDelta);
892 pBitmap->bmPlanes = 1;
893 pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
894
895 /* Check for DIB section */
896 if (psurf->hSecure)
897 {
898 /* Set bmBits in this case */
899 pBitmap->bmBits = psurf->SurfObj.pvBits;
900
901 if (Count >= sizeof(DIBSECTION))
902 {
903 /* Fill rest of DIBSECTION */
904 PDIBSECTION pds = buffer;
905
906 pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
907 pds->dsBmih.biWidth = pds->dsBm.bmWidth;
908 pds->dsBmih.biHeight = pds->dsBm.bmHeight;
909 pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
910 pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
911 switch (psurf->SurfObj.iBitmapFormat)
912 {
913 /* FIXME: What about BI_BITFIELDS? */
914 case BMF_1BPP:
915 case BMF_4BPP:
916 case BMF_8BPP:
917 case BMF_16BPP:
918 case BMF_24BPP:
919 case BMF_32BPP:
920 pds->dsBmih.biCompression = BI_RGB;
921 break;
922 case BMF_4RLE:
923 pds->dsBmih.biCompression = BI_RLE4;
924 break;
925 case BMF_8RLE:
926 pds->dsBmih.biCompression = BI_RLE8;
927 break;
928 case BMF_JPEG:
929 pds->dsBmih.biCompression = BI_JPEG;
930 break;
931 case BMF_PNG:
932 pds->dsBmih.biCompression = BI_PNG;
933 break;
934 }
935 pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
936 pds->dsBmih.biXPelsPerMeter = 0;
937 pds->dsBmih.biYPelsPerMeter = 0;
938 pds->dsBmih.biClrUsed = psurf->biClrUsed;
939 pds->dsBmih.biClrImportant = psurf->biClrImportant;
940 pds->dsBitfields[0] = psurf->dsBitfields[0];
941 pds->dsBitfields[1] = psurf->dsBitfields[1];
942 pds->dsBitfields[2] = psurf->dsBitfields[2];
943 pds->dshSection = psurf->hDIBSection;
944 pds->dsOffset = psurf->dwOffset;
945
946 return sizeof(DIBSECTION);
947 }
948 }
949 else
950 {
951 /* not set according to wine test, confirmed in win2k */
952 pBitmap->bmBits = NULL;
953 }
954
955 return sizeof(BITMAP);
956 }
957
958 /*
959 * @implemented
960 */
961 HDC
962 APIENTRY
963 NtGdiGetDCforBitmap(
964 IN HBITMAP hsurf)
965 {
966 HDC hDC = NULL;
967 PSURFACE psurf = SURFACE_LockSurface(hsurf);
968 if (psurf)
969 {
970 hDC = psurf->hDC;
971 SURFACE_UnlockSurface(psurf);
972 }
973 return hDC;
974 }
975
976 /* EOF */