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