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