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