WIN32K: little work on Set/GetPixel (I don't know how to actually get/set a pixel...
[reactos.git] / reactos / subsys / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: bitmaps.c,v 1.35 2003/08/20 20:45:28 ea Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <win32k/gdiobj.h>
24 #include <win32k/bitmaps.h>
25 //#include <win32k/debug.h>
26 #include "../eng/handle.h"
27 #include <include/inteng.h>
28 #include <include/eng.h>
29 #include <include/surface.h>
30
31 #define NDEBUG
32 #include <win32k/debug1.h>
33
34 //FIXME: where should CLR_INVALID be defined?
35 #define CLR_INVALID 0xffffffff
36
37 BOOL STDCALL NtGdiBitBlt(HDC hDCDest,
38 INT XDest,
39 INT YDest,
40 INT Width,
41 INT Height,
42 HDC hDCSrc,
43 INT XSrc,
44 INT YSrc,
45 DWORD ROP)
46 {
47 GDIMULTILOCK Lock[2] = {{hDCDest, 0, GDI_OBJECT_TYPE_DC}, {hDCSrc, 0, GDI_OBJECT_TYPE_DC}};
48 PDC DCDest = NULL;
49 PDC DCSrc = NULL;
50 PSURFOBJ SurfDest, SurfSrc;
51 PSURFGDI SurfGDIDest, SurfGDISrc;
52 RECTL DestRect;
53 POINTL SourcePoint;
54 //PBITMAPOBJ DestBitmapObj;
55 //PBITMAPOBJ SrcBitmapObj;
56 BOOL Status, SurfDestAlloc, SurfSrcAlloc, XlateAlloc;
57 PPALOBJ DCLogPal;
58 PPALGDI PalDestGDI, PalSourceGDI;
59 PXLATEOBJ XlateObj = NULL;
60 HPALETTE SourcePalette, DestPalette;
61
62 if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) )
63 {
64 DPRINT1("GDIOBJ_LockMultipleObj() failed\n" );
65 return STATUS_INVALID_PARAMETER;
66 }
67
68 DCDest = Lock[0].pObj;
69 DCSrc = Lock[1].pObj;
70
71 if ( !DCDest || !DCSrc )
72 return STATUS_INVALID_PARAMETER;
73
74 /* Offset the destination and source by the origin of their DCs. */
75 XDest += DCDest->w.DCOrgX;
76 YDest += DCDest->w.DCOrgY;
77 XSrc += DCSrc->w.DCOrgX;
78 YSrc += DCSrc->w.DCOrgY;
79
80 DestRect.left = XDest;
81 DestRect.top = YDest;
82 DestRect.right = XDest+Width;
83 DestRect.bottom = YDest+Height;
84
85 SourcePoint.x = XSrc;
86 SourcePoint.y = YSrc;
87
88 SurfDestAlloc = FALSE;
89 SurfSrcAlloc = FALSE;
90 XlateAlloc = FALSE;
91
92 // Determine surfaces to be used in the bitblt
93 SurfDest = (PSURFOBJ)AccessUserObject((ULONG)DCDest->Surface);
94 SurfSrc = (PSURFOBJ)AccessUserObject((ULONG)DCSrc->Surface);
95
96 SurfGDIDest = (PSURFGDI)AccessInternalObjectFromUserObject(SurfDest);
97 SurfGDISrc = (PSURFGDI)AccessInternalObjectFromUserObject(SurfSrc);
98
99 // Retrieve the logical palette of the destination DC
100 DCLogPal = (PPALOBJ)AccessUserObject((ULONG)DCDest->w.hPalette);
101
102 if(DCLogPal)
103 if(DCLogPal->logicalToSystem)
104 XlateObj = DCLogPal->logicalToSystem;
105
106 // If the source and destination formats differ, create an XlateObj [what if we already have one??]
107 if((BitsPerFormat(SurfDest->iBitmapFormat) != BitsPerFormat(SurfSrc->iBitmapFormat)) && (XlateObj == NULL))
108 {
109 if(DCDest->w.hPalette != 0)
110 DestPalette = DCDest->w.hPalette;
111 else
112 DestPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
113
114 if(DCSrc->w.hPalette != 0)
115 SourcePalette = DCSrc->w.hPalette;
116 else
117 SourcePalette = NtGdiGetStockObject(DEFAULT_PALETTE);
118
119 PalDestGDI = (PPALGDI)AccessInternalObject((ULONG)DestPalette);
120 PalSourceGDI = (PPALGDI)AccessInternalObject((ULONG)SourcePalette);
121
122 XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalDestGDI->Mode, PalSourceGDI->Mode, DestPalette, SourcePalette);
123 XlateAlloc = TRUE;
124 }
125
126 // Perform the bitblt operation
127
128 Status = IntEngBitBlt(SurfDest, SurfSrc, NULL, DCDest->CombinedClip, XlateObj, &DestRect, &SourcePoint, NULL, NULL, NULL, ROP);
129
130 if (XlateAlloc) EngDeleteXlate(XlateObj);
131 if (SurfDestAlloc) ExFreePool(SurfDest);
132 if (SurfSrcAlloc) ExFreePool(SurfSrc);
133
134 GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0]));
135
136 return Status;
137 }
138
139 HBITMAP STDCALL NtGdiCreateBitmap(INT Width,
140 INT Height,
141 UINT Planes,
142 UINT BitsPerPel,
143 CONST VOID *Bits)
144 {
145 PBITMAPOBJ bmp;
146 HBITMAP hBitmap;
147
148 Planes = (BYTE) Planes;
149 BitsPerPel = (BYTE) BitsPerPel;
150
151 /* Check parameters */
152 if (!Height || !Width)
153 {
154 return 0;
155 }
156 if (Planes != 1)
157 {
158 UNIMPLEMENTED;
159 return 0;
160 }
161 if (Height < 0)
162 {
163 Height = -Height;
164 }
165 if (Width < 0)
166 {
167 Width = -Width;
168 }
169
170 /* Create the BITMAPOBJ */
171 hBitmap = BITMAPOBJ_AllocBitmap ();
172 if (!hBitmap)
173 {
174 DPRINT("NtGdiCreateBitmap: BITMAPOBJ_AllocBitmap returned 0\n");
175 return 0;
176 }
177
178 bmp = BITMAPOBJ_LockBitmap( hBitmap );
179
180 DPRINT("NtGdiCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width, Height,
181 1 << (Planes * BitsPerPel), BitsPerPel, bmp);
182
183 bmp->size.cx = Width;
184 bmp->size.cy = Height;
185 bmp->bitmap.bmType = 0;
186 bmp->bitmap.bmWidth = Width;
187 bmp->bitmap.bmHeight = Height;
188 bmp->bitmap.bmPlanes = Planes;
189 bmp->bitmap.bmBitsPixel = BitsPerPel;
190 bmp->bitmap.bmWidthBytes = BITMAPOBJ_GetWidthBytes (Width, BitsPerPel);
191 bmp->bitmap.bmBits = NULL;
192 bmp->DDBitmap = NULL;
193 bmp->dib = NULL;
194
195 // Allocate memory for bitmap bits
196 bmp->bitmap.bmBits = ExAllocatePool(PagedPool, bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight);
197
198 if (Bits) /* Set bitmap bits */
199 {
200 NtGdiSetBitmapBits(hBitmap, Height * bmp->bitmap.bmWidthBytes, Bits);
201 }
202
203 BITMAPOBJ_UnlockBitmap( hBitmap );
204
205 return hBitmap;
206 }
207
208 BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp )
209 {
210 ASSERT( pBmp );
211
212 if (NULL != pBmp->bitmap.bmBits)
213 {
214 if (NULL != pBmp->dib)
215 {
216 if (NULL == pBmp->dib->dshSection)
217 {
218 EngFreeUserMem(pBmp->bitmap.bmBits);
219 }
220 else
221 {
222 /* This is a file-mapped section */
223 UNIMPLEMENTED;
224 }
225 }
226 else
227 {
228 ExFreePool(pBmp->bitmap.bmBits);
229 }
230 }
231
232 return TRUE;
233 }
234
235
236 HBITMAP STDCALL NtGdiCreateCompatibleBitmap(HDC hDC,
237 INT Width,
238 INT Height)
239 {
240 HBITMAP hbmpRet;
241 PDC dc;
242
243 hbmpRet = 0;
244 dc = DC_LockDc(hDC);
245
246 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, dc->w.bitsPerPixel);
247
248 if (!dc)
249 {
250 return 0;
251 }
252 if ((Width >= 0x10000) || (Height >= 0x10000))
253 {
254 DPRINT("got bad width %d or height %d, please look for reason\n", Width, Height);
255 }
256 else
257 {
258 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
259 if (!Width || !Height)
260 {
261 hbmpRet = NtGdiCreateBitmap (1, 1, 1, 1, NULL);
262 }
263 else
264 {
265 hbmpRet = NtGdiCreateBitmap(Width, Height, 1, dc->w.bitsPerPixel, NULL);
266 }
267 }
268 DPRINT ("\t\t%04x\n", hbmpRet);
269 DC_UnlockDc( hDC );
270 return hbmpRet;
271 }
272
273 HBITMAP STDCALL NtGdiCreateBitmapIndirect(CONST BITMAP *BM)
274 {
275 return NtGdiCreateBitmap (BM->bmWidth,
276 BM->bmHeight,
277 BM->bmPlanes,
278 BM->bmBitsPixel,
279 BM->bmBits);
280 }
281
282 HBITMAP STDCALL NtGdiCreateDiscardableBitmap(HDC hDC,
283 INT Width,
284 INT Height)
285 {
286 /* FIXME: this probably should do something else */
287 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
288 }
289
290 BOOL STDCALL NtGdiExtFloodFill(HDC hDC,
291 INT XStart,
292 INT YStart,
293 COLORREF Color,
294 UINT FillType)
295 {
296 UNIMPLEMENTED;
297 }
298
299 BOOL STDCALL NtGdiFloodFill(HDC hDC,
300 INT XStart,
301 INT YStart,
302 COLORREF Fill)
303 {
304 UNIMPLEMENTED;
305 }
306
307 BOOL STDCALL NtGdiGetBitmapDimensionEx(HBITMAP hBitmap,
308 LPSIZE Dimension)
309 {
310 PBITMAPOBJ bmp;
311
312 bmp = BITMAPOBJ_LockBitmap(hBitmap);
313 if (bmp == NULL)
314 {
315 return FALSE;
316 }
317
318 *Dimension = bmp->size;
319
320 BITMAPOBJ_UnlockBitmap(hBitmap);
321
322 return TRUE;
323 }
324
325 COLORREF STDCALL NtGdiGetPixel(HDC hDC,
326 INT XPos,
327 INT YPos)
328 {
329 PDC dc = NULL;
330 COLORREF cr = (COLORREF) 0;
331
332 dc = DC_LockDc (hDC);
333 if (NULL == dc)
334 {
335 return (COLORREF) CLR_INVALID;
336 }
337 //FIXME: get actual pixel RGB value
338 DC_UnlockDc (hDC);
339 return cr;
340 }
341
342 BOOL STDCALL NtGdiMaskBlt(HDC hDCDest,
343 INT XDest,
344 INT YDest,
345 INT Width,
346 INT Height,
347 HDC hDCSrc,
348 INT XSrc,
349 INT YSrc,
350 HBITMAP hMaskBitmap,
351 INT xMask,
352 INT yMask,
353 DWORD ROP)
354 {
355 UNIMPLEMENTED;
356 }
357
358 BOOL STDCALL NtGdiPlgBlt(HDC hDCDest,
359 CONST POINT *Point,
360 HDC hDCSrc,
361 INT XSrc,
362 INT YSrc,
363 INT Width,
364 INT Height,
365 HBITMAP hMaskBitmap,
366 INT xMask,
367 INT yMask)
368 {
369 UNIMPLEMENTED;
370 }
371
372 LONG STDCALL NtGdiSetBitmapBits(HBITMAP hBitmap,
373 DWORD Bytes,
374 CONST VOID *Bits)
375 {
376 LONG height, ret;
377 PBITMAPOBJ bmp;
378
379 bmp = BITMAPOBJ_LockBitmap(hBitmap);
380 if (bmp == NULL || Bits == NULL)
381 {
382 return 0;
383 }
384
385 if (Bytes < 0)
386 {
387 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes );
388 Bytes = -Bytes;
389 }
390
391 /* Only get entire lines */
392 height = Bytes / bmp->bitmap.bmWidthBytes;
393 if (height > bmp->bitmap.bmHeight)
394 {
395 height = bmp->bitmap.bmHeight;
396 }
397 Bytes = height * bmp->bitmap.bmWidthBytes;
398 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
399 hBitmap,
400 Bytes,
401 Bits,
402 bmp->bitmap.bmWidth,
403 bmp->bitmap.bmHeight,
404 1 << bmp->bitmap.bmBitsPixel,
405 height);
406
407 #if 0
408 /* FIXME: call DDI specific function here if available */
409 if(bmp->DDBitmap)
410 {
411 DPRINT ("Calling device specific BitmapBits\n");
412 if (bmp->DDBitmap->funcs->pBitmapBits)
413 {
414 ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET);
415 }
416 else
417 {
418 DPRINT ("BitmapBits == NULL??\n");
419 ret = 0;
420 }
421 }
422 else
423 #endif
424 {
425 /* FIXME: Alloc enough for entire bitmap */
426 if (bmp->bitmap.bmBits == NULL)
427 {
428 bmp->bitmap.bmBits = ExAllocatePool (PagedPool, Bytes);
429 }
430 if(!bmp->bitmap.bmBits)
431 {
432 DPRINT ("Unable to allocate bit buffer\n");
433 ret = 0;
434 }
435 else
436 {
437 memcpy(bmp->bitmap.bmBits, Bits, Bytes);
438 ret = Bytes;
439 }
440 }
441
442 return ret;
443 }
444
445 BOOL STDCALL NtGdiSetBitmapDimensionEx(HBITMAP hBitmap,
446 INT Width,
447 INT Height,
448 LPSIZE Size)
449 {
450 PBITMAPOBJ bmp;
451
452 bmp = BITMAPOBJ_LockBitmap(hBitmap);
453 if (bmp == NULL)
454 {
455 return FALSE;
456 }
457
458 if (Size)
459 {
460 *Size = bmp->size;
461 }
462 bmp->size.cx = Width;
463 bmp->size.cy = Height;
464
465 BITMAPOBJ_UnlockBitmap (hBitmap);
466
467 return TRUE;
468 }
469
470 COLORREF STDCALL NtGdiSetPixel(HDC hDC,
471 INT X,
472 INT Y,
473 COLORREF Color)
474 {
475 if(NtGdiSetPixelV(hDC,X,Y,Color))
476 {
477 COLORREF cr = NtGdiGetPixel(hDC,X,Y);
478 if(CLR_INVALID != cr) return(cr);
479 }
480 return ((COLORREF) -1);
481 }
482
483 BOOL STDCALL NtGdiSetPixelV(HDC hDC,
484 INT X,
485 INT Y,
486 COLORREF Color)
487 {
488 PDC dc = NULL;
489 PBITMAPOBJ bmp = NULL;
490 BITMAP bm;
491
492 dc = DC_LockDc (hDC);
493 if(NULL == dc)
494 {
495 return(FALSE);
496 }
497 bmp = BITMAPOBJ_LockBitmap (dc->w.hBitmap);
498 if(NULL == bmp)
499 {
500 DC_UnlockDc (hDC);
501 return(FALSE);
502 }
503 bm = bmp->bitmap;
504 //FIXME: set the actual pixel value
505 BITMAPOBJ_UnlockBitmap (bmp);
506 DC_UnlockDc (hDC);
507 return(TRUE);
508 }
509
510 BOOL STDCALL NtGdiStretchBlt(HDC hDCDest,
511 INT XOriginDest,
512 INT YOriginDest,
513 INT WidthDest,
514 INT HeightDest,
515 HDC hDCSrc,
516 INT XOriginSrc,
517 INT YOriginSrc,
518 INT WidthSrc,
519 INT HeightSrc,
520 DWORD ROP)
521 {
522 UNIMPLEMENTED;
523 }
524
525 /* Internal Functions */
526
527 INT FASTCALL
528 BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
529 {
530 #if 0
531 switch(bpp)
532 {
533 case 1:
534 return 2 * ((bmWidth+15) >> 4);
535
536 case 24:
537 bmWidth *= 3; /* fall through */
538 case 8:
539 return bmWidth + (bmWidth & 1);
540
541 case 32:
542 return bmWidth * 4;
543
544 case 16:
545 case 15:
546 return bmWidth * 2;
547
548 case 4:
549 return 2 * ((bmWidth+3) >> 2);
550
551 default:
552 DPRINT ("stub");
553 }
554
555 return -1;
556 #endif
557
558 return ((bmWidth * bpp + 31) & ~31) >> 3;
559 }
560
561 HBITMAP FASTCALL BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
562 {
563 PBITMAPOBJ bmp;
564 HBITMAP res;
565 BITMAP bm;
566
567 bmp = BITMAPOBJ_LockBitmap(hBitmap);
568 if (bmp == NULL)
569 {
570 return 0;
571 }
572 res = 0;
573
574 bm = bmp->bitmap;
575 bm.bmBits = NULL;
576 res = NtGdiCreateBitmapIndirect(&bm);
577 if(res)
578 {
579 char *buf;
580
581 buf = ExAllocatePool (NonPagedPool, bm.bmWidthBytes * bm.bmHeight);
582 NtGdiGetBitmapBits (hBitmap, bm.bmWidthBytes * bm.bmHeight, buf);
583 NtGdiSetBitmapBits (res, bm.bmWidthBytes * bm.bmHeight, buf);
584 ExFreePool (buf);
585 }
586
587 return res;
588 }
589
590 INT STDCALL BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer)
591 {
592 if(bmp->dib)
593 {
594 if(count < (INT) sizeof(DIBSECTION))
595 {
596 if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
597 }
598 else
599 {
600 if (count > (INT) sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
601 }
602 memcpy(buffer, bmp->dib, count);
603 return count;
604 }
605 else
606 {
607 if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
608 memcpy(buffer, &bmp->bitmap, count);
609 return count;
610 }
611 }
612 /* EOF */