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