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