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