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