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