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