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