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