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