- Fixed clipping code in NtGdiGetPixel. Patch by James Pritchard.
[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.54 2004/02/12 21:50:19 navaraf Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <win32k/color.h>
24 #include <win32k/gdiobj.h>
25 #include <win32k/bitmaps.h>
26 #include <win32k/brush.h>
27 #include <win32k/region.h>
28 //#include <win32k/debug.h>
29 #include "../eng/handle.h"
30 #include <include/inteng.h>
31 #include <include/eng.h>
32 #include <include/error.h>
33 #include <include/surface.h>
34 #include <include/palette.h>
35
36 #define NDEBUG
37 #include <win32k/debug1.h>
38
39 BOOL STDCALL NtGdiBitBlt(HDC hDCDest,
40 INT XDest,
41 INT YDest,
42 INT Width,
43 INT Height,
44 HDC hDCSrc,
45 INT XSrc,
46 INT YSrc,
47 DWORD ROP)
48 {
49 PDC DCDest = NULL;
50 PDC DCSrc = NULL;
51 PSURFOBJ SurfDest, SurfSrc;
52 PSURFGDI SurfGDIDest, SurfGDISrc;
53 RECTL DestRect;
54 POINTL SourcePoint;
55 BOOL Status;
56 PPALGDI PalDestGDI, PalSourceGDI;
57 PXLATEOBJ XlateObj = NULL;
58 HPALETTE SourcePalette, DestPalette;
59 ULONG SourceMode, DestMode;
60 PBRUSHOBJ BrushObj;
61 BOOL UsesSource = ((ROP & 0xCC0000) >> 2) != (ROP & 0x330000);
62 BOOL UsesPattern = TRUE;//((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
63
64 DCDest = DC_LockDc(hDCDest);
65 if (NULL == DCDest)
66 {
67 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
68 SetLastWin32Error(ERROR_INVALID_HANDLE);
69 return FALSE;
70 }
71
72 if (UsesSource)
73 {
74 if (hDCSrc != hDCDest)
75 {
76 DCSrc = DC_LockDc(hDCSrc);
77 if (NULL == DCSrc)
78 {
79 DC_UnlockDc(hDCDest);
80 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
81 SetLastWin32Error(ERROR_INVALID_HANDLE);
82 return FALSE;
83 }
84 }
85 else
86 {
87 DCSrc = DCDest;
88 }
89 }
90 else
91 {
92 DCSrc = NULL;
93 }
94
95 /* Offset the destination and source by the origin of their DCs. */
96 XDest += DCDest->w.DCOrgX;
97 YDest += DCDest->w.DCOrgY;
98 if (UsesSource)
99 {
100 XSrc += DCSrc->w.DCOrgX;
101 YSrc += DCSrc->w.DCOrgY;
102 }
103
104 DestRect.left = XDest;
105 DestRect.top = YDest;
106 DestRect.right = XDest+Width;
107 DestRect.bottom = YDest+Height;
108
109 SourcePoint.x = XSrc;
110 SourcePoint.y = YSrc;
111
112 /* Determine surfaces to be used in the bitblt */
113 SurfDest = (PSURFOBJ)AccessUserObject((ULONG)DCDest->Surface);
114 SurfGDIDest = (PSURFGDI)AccessInternalObjectFromUserObject(SurfDest);
115 if (UsesSource)
116 {
117 SurfSrc = (PSURFOBJ)AccessUserObject((ULONG)DCSrc->Surface);
118 SurfGDISrc = (PSURFGDI)AccessInternalObjectFromUserObject(SurfSrc);
119 }
120 else
121 {
122 SurfSrc = NULL;
123 SurfGDISrc = NULL;
124 }
125
126 if (UsesPattern)
127 {
128 BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
129 if (NULL == BrushObj)
130 {
131 if (UsesSource && hDCSrc != hDCDest)
132 {
133 DC_UnlockDc(hDCSrc);
134 }
135 DC_UnlockDc(hDCDest);
136 SetLastWin32Error(ERROR_INVALID_HANDLE);
137 return FALSE;
138 }
139 }
140 else
141 {
142 BrushObj = NULL;
143 }
144
145 if (DCDest->w.hPalette != 0)
146 {
147 DestPalette = DCDest->w.hPalette;
148 }
149 else
150 {
151 DestPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
152 }
153
154 if (UsesSource && DCSrc->w.hPalette != 0)
155 {
156 SourcePalette = DCSrc->w.hPalette;
157 }
158 else
159 {
160 SourcePalette = NtGdiGetStockObject(DEFAULT_PALETTE);
161 }
162
163 PalSourceGDI = PALETTE_LockPalette(SourcePalette);
164 if (NULL == PalSourceGDI)
165 {
166 if (UsesSource && hDCSrc != hDCDest)
167 {
168 DC_UnlockDc(hDCSrc);
169 }
170 DC_UnlockDc(hDCDest);
171 SetLastWin32Error(ERROR_INVALID_HANDLE);
172 return FALSE;
173 }
174 SourceMode = PalSourceGDI->Mode;
175 PALETTE_UnlockPalette(SourcePalette);
176
177 if (DestPalette == SourcePalette)
178 {
179 DestMode = SourceMode;
180 }
181 else
182 {
183 PalDestGDI = PALETTE_LockPalette(DestPalette);
184 if (NULL == PalDestGDI)
185 {
186 if (UsesSource && hDCSrc != hDCDest)
187 {
188 DC_UnlockDc(hDCSrc);
189 }
190 DC_UnlockDc(hDCDest);
191 SetLastWin32Error(ERROR_INVALID_HANDLE);
192 return FALSE;
193 }
194 DestMode = PalDestGDI->Mode;
195 PALETTE_UnlockPalette(DestPalette);
196 }
197
198 if (DCDest->w.bitsPerPixel == 1)
199 {
200 XlateObj = (PXLATEOBJ)IntEngCreateMonoXlate(SourceMode, DestPalette,
201 SourcePalette, DCSrc->w.backgroundColor);
202 }
203 else
204 {
205 XlateObj = (PXLATEOBJ)IntEngCreateXlate(DestMode, SourceMode, DestPalette, SourcePalette);
206 }
207 if (NULL == XlateObj)
208 {
209 if (UsesSource && hDCSrc != hDCDest)
210 {
211 DC_UnlockDc(hDCSrc);
212 }
213 DC_UnlockDc(hDCDest);
214 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
215 return FALSE;
216 }
217
218 /* Perform the bitblt operation */
219 Status = IntEngBitBlt(SurfDest, SurfSrc, NULL, DCDest->CombinedClip, XlateObj,
220 &DestRect, &SourcePoint, NULL, BrushObj, NULL, ROP);
221
222 EngDeleteXlate(XlateObj);
223 if (UsesPattern)
224 {
225 BRUSHOBJ_UnlockBrush(DCDest->w.hBrush);
226 }
227 if (UsesSource && hDCSrc != hDCDest)
228 {
229 DC_UnlockDc(hDCSrc);
230 }
231 DC_UnlockDc(hDCDest);
232
233 return Status;
234 }
235
236 HBITMAP STDCALL NtGdiCreateBitmap(INT Width,
237 INT Height,
238 UINT Planes,
239 UINT BitsPerPel,
240 CONST VOID *Bits)
241 {
242 PBITMAPOBJ bmp;
243 HBITMAP hBitmap;
244
245 Planes = (BYTE) Planes;
246 BitsPerPel = (BYTE) BitsPerPel;
247
248 /* Check parameters */
249 if (!Height || !Width)
250 {
251 return 0;
252 }
253 if (Planes != 1)
254 {
255 UNIMPLEMENTED;
256 return 0;
257 }
258 if (Height < 0)
259 {
260 Height = -Height;
261 }
262 if (Width < 0)
263 {
264 Width = -Width;
265 }
266
267 /* Create the BITMAPOBJ */
268 hBitmap = BITMAPOBJ_AllocBitmap ();
269 if (!hBitmap)
270 {
271 DPRINT("NtGdiCreateBitmap: BITMAPOBJ_AllocBitmap returned 0\n");
272 return 0;
273 }
274
275 bmp = BITMAPOBJ_LockBitmap( hBitmap );
276
277 DPRINT("NtGdiCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width, Height,
278 1 << (Planes * BitsPerPel), BitsPerPel, bmp);
279
280 bmp->dimension.cx = 0;
281 bmp->dimension.cy = 0;
282 bmp->bitmap.bmType = 0;
283 bmp->bitmap.bmWidth = Width;
284 bmp->bitmap.bmHeight = Height;
285 bmp->bitmap.bmPlanes = Planes;
286 bmp->bitmap.bmBitsPixel = BitsPerPel;
287 bmp->bitmap.bmWidthBytes = BITMAPOBJ_GetWidthBytes (Width, BitsPerPel);
288 bmp->bitmap.bmBits = NULL;
289 bmp->DDBitmap = NULL;
290 bmp->dib = NULL;
291
292 // Allocate memory for bitmap bits
293 bmp->bitmap.bmBits = ExAllocatePool(PagedPool, bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight);
294
295 BITMAPOBJ_UnlockBitmap( hBitmap );
296
297 if (Bits) /* Set bitmap bits */
298 {
299 NtGdiSetBitmapBits(hBitmap, Height * bmp->bitmap.bmWidthBytes, Bits);
300 }
301
302 return hBitmap;
303 }
304
305 BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp )
306 {
307 ASSERT( pBmp );
308
309 if (NULL != pBmp->bitmap.bmBits)
310 {
311 if (NULL != pBmp->dib)
312 {
313 if (NULL == pBmp->dib->dshSection)
314 {
315 EngFreeUserMem(pBmp->bitmap.bmBits);
316 }
317 else
318 {
319 /* This is a file-mapped section */
320 UNIMPLEMENTED;
321 }
322 }
323 else
324 {
325 ExFreePool(pBmp->bitmap.bmBits);
326 }
327 }
328
329 return TRUE;
330 }
331
332
333 HBITMAP STDCALL NtGdiCreateCompatibleBitmap(HDC hDC,
334 INT Width,
335 INT Height)
336 {
337 HBITMAP hbmpRet;
338 PDC dc;
339
340 hbmpRet = 0;
341 dc = DC_LockDc(hDC);
342
343 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, dc->w.bitsPerPixel);
344
345 if (!dc)
346 {
347 return 0;
348 }
349 if ((Width >= 0x10000) || (Height >= 0x10000))
350 {
351 DPRINT("got bad width %d or height %d, please look for reason\n", Width, Height);
352 }
353 else
354 {
355 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
356 if (!Width || !Height)
357 {
358 hbmpRet = NtGdiCreateBitmap (1, 1, 1, 1, NULL);
359 }
360 else
361 {
362 hbmpRet = NtGdiCreateBitmap(Width, Height, 1, dc->w.bitsPerPixel, NULL);
363 }
364 }
365 DPRINT ("\t\t%04x\n", hbmpRet);
366 DC_UnlockDc( hDC );
367 return hbmpRet;
368 }
369
370 HBITMAP STDCALL NtGdiCreateBitmapIndirect(CONST BITMAP *BM)
371 {
372 return NtGdiCreateBitmap (BM->bmWidth,
373 BM->bmHeight,
374 BM->bmPlanes,
375 BM->bmBitsPixel,
376 BM->bmBits);
377 }
378
379 HBITMAP STDCALL NtGdiCreateDiscardableBitmap(HDC hDC,
380 INT Width,
381 INT Height)
382 {
383 /* FIXME: this probably should do something else */
384 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
385 }
386
387 BOOL STDCALL NtGdiExtFloodFill(HDC hDC,
388 INT XStart,
389 INT YStart,
390 COLORREF Color,
391 UINT FillType)
392 {
393 UNIMPLEMENTED;
394 }
395
396 BOOL STDCALL NtGdiFloodFill(HDC hDC,
397 INT XStart,
398 INT YStart,
399 COLORREF Fill)
400 {
401 return NtGdiExtFloodFill(hDC, XStart, YStart, Fill, FLOODFILLBORDER );
402 }
403
404 BOOL STDCALL NtGdiGetBitmapDimensionEx(HBITMAP hBitmap,
405 LPSIZE Dimension)
406 {
407 PBITMAPOBJ bmp;
408
409 bmp = BITMAPOBJ_LockBitmap(hBitmap);
410 if (bmp == NULL)
411 {
412 return FALSE;
413 }
414
415 *Dimension = bmp->dimension;
416
417 BITMAPOBJ_UnlockBitmap(hBitmap);
418
419 return TRUE;
420 }
421
422 COLORREF STDCALL NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
423 {
424 PDC dc = NULL;
425 COLORREF Result = (COLORREF) 0;
426 PSURFGDI Surface;
427 PSURFOBJ SurfaceObject;
428
429 dc = DC_LockDc (hDC);
430 if (dc == NULL)
431 {
432 return (COLORREF)CLR_INVALID;
433 }
434 if (XPos < dc->CombinedClip->rclBounds.left ||
435 XPos > dc->CombinedClip->rclBounds.right ||
436 YPos < dc->CombinedClip->rclBounds.top ||
437 YPos > dc->CombinedClip->rclBounds.bottom)
438 {
439 DC_UnlockDc(hDC);
440 return (COLORREF)CLR_INVALID;
441 }
442 SurfaceObject = (PSURFOBJ)AccessUserObject((ULONG)dc->Surface);
443 Surface = (PSURFGDI)AccessInternalObjectFromUserObject(SurfaceObject);
444 if (Surface == NULL || Surface->DIB_GetPixel == NULL)
445 {
446 DC_UnlockDc(hDC);
447 return (COLORREF)CLR_INVALID;
448 }
449 Result = Surface->DIB_GetPixel(SurfaceObject, XPos, YPos);
450 DC_UnlockDc(hDC);
451 return Result;
452 }
453
454 /***********************************************************************
455 * MaskBlt
456 * Ported from WINE by sedwards 11-4-03
457 *
458 * Someone thought it would be faster to do it here and then switch back
459 * to GDI32. I dunno. Write a test and let me know.
460 */
461
462 static inline BYTE SwapROP3_SrcDst(BYTE bRop3)
463 {
464 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
465 }
466
467 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
468 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
469 #define DSTCOPY 0x00AA0029
470 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
471
472 BOOL STDCALL NtGdiMaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
473 INT nWidth, INT nHeight, HDC hdcSrc,
474 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
475 INT xMask, INT yMask, DWORD dwRop)
476 {
477 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
478 HDC hDCMask, hDC1, hDC2;
479 static const DWORD ROP3Table[256] =
480 {
481 0x00000042, 0x00010289,
482 0x00020C89, 0x000300AA,
483 0x00040C88, 0x000500A9,
484 0x00060865, 0x000702C5,
485 0x00080F08, 0x00090245,
486 0x000A0329, 0x000B0B2A,
487 0x000C0324, 0x000D0B25,
488 0x000E08A5, 0x000F0001,
489 0x00100C85, 0x001100A6,
490 0x00120868, 0x001302C8,
491 0x00140869, 0x001502C9,
492 0x00165CCA, 0x00171D54,
493 0x00180D59, 0x00191CC8,
494 0x001A06C5, 0x001B0768,
495 0x001C06CA, 0x001D0766,
496 0x001E01A5, 0x001F0385,
497 0x00200F09, 0x00210248,
498 0x00220326, 0x00230B24,
499 0x00240D55, 0x00251CC5,
500 0x002606C8, 0x00271868,
501 0x00280369, 0x002916CA,
502 0x002A0CC9, 0x002B1D58,
503 0x002C0784, 0x002D060A,
504 0x002E064A, 0x002F0E2A,
505 0x0030032A, 0x00310B28,
506 0x00320688, 0x00330008,
507 0x003406C4, 0x00351864,
508 0x003601A8, 0x00370388,
509 0x0038078A, 0x00390604,
510 0x003A0644, 0x003B0E24,
511 0x003C004A, 0x003D18A4,
512 0x003E1B24, 0x003F00EA,
513 0x00400F0A, 0x00410249,
514 0x00420D5D, 0x00431CC4,
515 0x00440328, 0x00450B29,
516 0x004606C6, 0x0047076A,
517 0x00480368, 0x004916C5,
518 0x004A0789, 0x004B0605,
519 0x004C0CC8, 0x004D1954,
520 0x004E0645, 0x004F0E25,
521 0x00500325, 0x00510B26,
522 0x005206C9, 0x00530764,
523 0x005408A9, 0x00550009,
524 0x005601A9, 0x00570389,
525 0x00580785, 0x00590609,
526 0x005A0049, 0x005B18A9,
527 0x005C0649, 0x005D0E29,
528 0x005E1B29, 0x005F00E9,
529 0x00600365, 0x006116C6,
530 0x00620786, 0x00630608,
531 0x00640788, 0x00650606,
532 0x00660046, 0x006718A8,
533 0x006858A6, 0x00690145,
534 0x006A01E9, 0x006B178A,
535 0x006C01E8, 0x006D1785,
536 0x006E1E28, 0x006F0C65,
537 0x00700CC5, 0x00711D5C,
538 0x00720648, 0x00730E28,
539 0x00740646, 0x00750E26,
540 0x00761B28, 0x007700E6,
541 0x007801E5, 0x00791786,
542 0x007A1E29, 0x007B0C68,
543 0x007C1E24, 0x007D0C69,
544 0x007E0955, 0x007F03C9,
545 0x008003E9, 0x00810975,
546 0x00820C49, 0x00831E04,
547 0x00840C48, 0x00851E05,
548 0x008617A6, 0x008701C5,
549 0x008800C6, 0x00891B08,
550 0x008A0E06, 0x008B0666,
551 0x008C0E08, 0x008D0668,
552 0x008E1D7C, 0x008F0CE5,
553 0x00900C45, 0x00911E08,
554 0x009217A9, 0x009301C4,
555 0x009417AA, 0x009501C9,
556 0x00960169, 0x0097588A,
557 0x00981888, 0x00990066,
558 0x009A0709, 0x009B07A8,
559 0x009C0704, 0x009D07A6,
560 0x009E16E6, 0x009F0345,
561 0x00A000C9, 0x00A11B05,
562 0x00A20E09, 0x00A30669,
563 0x00A41885, 0x00A50065,
564 0x00A60706, 0x00A707A5,
565 0x00A803A9, 0x00A90189,
566 0x00AA0029, 0x00AB0889,
567 0x00AC0744, 0x00AD06E9,
568 0x00AE0B06, 0x00AF0229,
569 0x00B00E05, 0x00B10665,
570 0x00B21974, 0x00B30CE8,
571 0x00B4070A, 0x00B507A9,
572 0x00B616E9, 0x00B70348,
573 0x00B8074A, 0x00B906E6,
574 0x00BA0B09, 0x00BB0226,
575 0x00BC1CE4, 0x00BD0D7D,
576 0x00BE0269, 0x00BF08C9,
577 0x00C000CA, 0x00C11B04,
578 0x00C21884, 0x00C3006A,
579 0x00C40E04, 0x00C50664,
580 0x00C60708, 0x00C707AA,
581 0x00C803A8, 0x00C90184,
582 0x00CA0749, 0x00CB06E4,
583 0x00CC0020, 0x00CD0888,
584 0x00CE0B08, 0x00CF0224,
585 0x00D00E0A, 0x00D1066A,
586 0x00D20705, 0x00D307A4,
587 0x00D41D78, 0x00D50CE9,
588 0x00D616EA, 0x00D70349,
589 0x00D80745, 0x00D906E8,
590 0x00DA1CE9, 0x00DB0D75,
591 0x00DC0B04, 0x00DD0228,
592 0x00DE0268, 0x00DF08C8,
593 0x00E003A5, 0x00E10185,
594 0x00E20746, 0x00E306EA,
595 0x00E40748, 0x00E506E5,
596 0x00E61CE8, 0x00E70D79,
597 0x00E81D74, 0x00E95CE6,
598 0x00EA02E9, 0x00EB0849,
599 0x00EC02E8, 0x00ED0848,
600 0x00EE0086, 0x00EF0A08,
601 0x00F00021, 0x00F10885,
602 0x00F20B05, 0x00F3022A,
603 0x00F40B0A, 0x00F50225,
604 0x00F60265, 0x00F708C5,
605 0x00F802E5, 0x00F90845,
606 0x00FA0089, 0x00FB0A09,
607 0x00FC008A, 0x00FD0A0A,
608 0x00FE02A9, 0x00FF0062,
609 };
610
611 if (!hbmMask)
612 return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
613
614 /* 1. make mask bitmap's dc */
615 hDCMask = NtGdiCreateCompatableDC(hdcDest);
616 hOldMaskBitmap = (HBITMAP)NtGdiSelectObject(hDCMask, hbmMask);
617
618 /* 2. make masked Background bitmap */
619
620 /* 2.1 make bitmap */
621 hDC1 = NtGdiCreateCompatableDC(hdcDest);
622 hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
623 hOldBitmap2 = (HBITMAP)NtGdiSelectObject(hDC1, hBitmap2);
624
625 /* 2.2 draw dest bitmap and mask */
626 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
627 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop));
628 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE);
629
630 /* 3. make masked Foreground bitmap */
631
632 /* 3.1 make bitmap */
633 hDC2 = NtGdiCreateCompatableDC(hdcDest);
634 hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
635 hOldBitmap3 = (HBITMAP)NtGdiSelectObject(hDC2, hBitmap3);
636
637 /* 3.2 draw src bitmap and mask */
638 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
639 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
640 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND);
641
642 /* 4. combine two bitmap and copy it to hdcDest */
643 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT);
644 NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY);
645
646 /* 5. restore all object */
647 NtGdiSelectObject(hDCMask, hOldMaskBitmap);
648 NtGdiSelectObject(hDC1, hOldBitmap2);
649 NtGdiSelectObject(hDC2, hOldBitmap3);
650
651 /* 6. delete all temp object */
652 NtGdiDeleteObject(hBitmap2);
653 NtGdiDeleteObject(hBitmap3);
654
655 NtGdiDeleteDC(hDC1);
656 NtGdiDeleteDC(hDC2);
657 NtGdiDeleteDC(hDCMask);
658
659 return TRUE;
660 }
661
662 BOOL STDCALL NtGdiPlgBlt(HDC hDCDest,
663 CONST POINT *Point,
664 HDC hDCSrc,
665 INT XSrc,
666 INT YSrc,
667 INT Width,
668 INT Height,
669 HBITMAP hMaskBitmap,
670 INT xMask,
671 INT yMask)
672 {
673 UNIMPLEMENTED;
674 }
675
676 LONG STDCALL NtGdiSetBitmapBits(HBITMAP hBitmap,
677 DWORD Bytes,
678 CONST VOID *Bits)
679 {
680 LONG height, ret;
681 PBITMAPOBJ bmp;
682
683 bmp = BITMAPOBJ_LockBitmap(hBitmap);
684 if (bmp == NULL || Bits == NULL)
685 {
686 return 0;
687 }
688
689 if (Bytes < 0)
690 {
691 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes );
692 Bytes = -Bytes;
693 }
694
695 /* Only get entire lines */
696 height = Bytes / bmp->bitmap.bmWidthBytes;
697 if (height > bmp->bitmap.bmHeight)
698 {
699 height = bmp->bitmap.bmHeight;
700 }
701 Bytes = height * bmp->bitmap.bmWidthBytes;
702 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
703 hBitmap,
704 Bytes,
705 Bits,
706 bmp->bitmap.bmWidth,
707 bmp->bitmap.bmHeight,
708 1 << bmp->bitmap.bmBitsPixel,
709 height);
710
711 #if 0
712 /* FIXME: call DDI specific function here if available */
713 if(bmp->DDBitmap)
714 {
715 DPRINT ("Calling device specific BitmapBits\n");
716 if (bmp->DDBitmap->funcs->pBitmapBits)
717 {
718 ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET);
719 }
720 else
721 {
722 DPRINT ("BitmapBits == NULL??\n");
723 ret = 0;
724 }
725 }
726 else
727 #endif
728 {
729 /* FIXME: Alloc enough for entire bitmap */
730 if (bmp->bitmap.bmBits == NULL)
731 {
732 bmp->bitmap.bmBits = ExAllocatePool (PagedPool, Bytes);
733 }
734 if(!bmp->bitmap.bmBits)
735 {
736 DPRINT ("Unable to allocate bit buffer\n");
737 ret = 0;
738 }
739 else
740 {
741 memcpy(bmp->bitmap.bmBits, Bits, Bytes);
742 ret = Bytes;
743 }
744 }
745
746 BITMAPOBJ_UnlockBitmap(hBitmap);
747
748 return ret;
749 }
750
751 BOOL STDCALL NtGdiSetBitmapDimensionEx(HBITMAP hBitmap,
752 INT Width,
753 INT Height,
754 LPSIZE Size)
755 {
756 PBITMAPOBJ bmp;
757
758 bmp = BITMAPOBJ_LockBitmap(hBitmap);
759 if (bmp == NULL)
760 {
761 return FALSE;
762 }
763
764 if (Size)
765 {
766 *Size = bmp->dimension;
767 }
768 bmp->dimension.cx = Width;
769 bmp->dimension.cy = Height;
770
771 BITMAPOBJ_UnlockBitmap (hBitmap);
772
773 return TRUE;
774 }
775
776 COLORREF STDCALL NtGdiSetPixel(HDC hDC,
777 INT X,
778 INT Y,
779 COLORREF Color)
780 {
781 COLORREF cr = NtGdiGetPixel(hDC,X,Y);
782 if(cr != CLR_INVALID && NtGdiSetPixelV(hDC,X,Y,Color))
783 {
784 return(cr);
785 }
786 return ((COLORREF) -1);
787 }
788
789 BOOL STDCALL NtGdiSetPixelV(HDC hDC,
790 INT X,
791 INT Y,
792 COLORREF Color)
793 {
794 HBRUSH NewBrush = NtGdiCreateSolidBrush(Color);
795 HGDIOBJ OldBrush;
796
797 if (NewBrush == NULL)
798 return(FALSE);
799 OldBrush = NtGdiSelectObject(hDC, NewBrush);
800 if (OldBrush == NULL)
801 return(FALSE);
802 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
803 NtGdiSelectObject(hDC, OldBrush);
804 NtGdiDeleteObject(NewBrush);
805 return TRUE;
806 }
807
808 BOOL STDCALL NtGdiStretchBlt(HDC hDCDest,
809 INT XOriginDest,
810 INT YOriginDest,
811 INT WidthDest,
812 INT HeightDest,
813 HDC hDCSrc,
814 INT XOriginSrc,
815 INT YOriginSrc,
816 INT WidthSrc,
817 INT HeightSrc,
818 DWORD ROP)
819 {
820 PDC DCDest = NULL;
821 PDC DCSrc = NULL;
822 PSURFOBJ SurfDest, SurfSrc;
823 PSURFGDI SurfGDIDest, SurfGDISrc;
824 RECTL DestRect;
825 RECTL SourceRect;
826 BOOL Status;
827 PPALGDI PalDestGDI, PalSourceGDI;
828 PXLATEOBJ XlateObj = NULL;
829 HPALETTE SourcePalette, DestPalette;
830 ULONG SourceMode, DestMode;
831 PBRUSHOBJ BrushObj;
832 BOOL UsesSource = ((ROP & 0xCC0000) >> 2) != (ROP & 0x330000);
833 BOOL UsesPattern = ((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
834
835 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
836 {
837 SetLastWin32Error(ERROR_INVALID_PARAMETER);
838 return FALSE;
839 }
840 DCDest = DC_LockDc(hDCDest);
841 if (NULL == DCDest)
842 {
843 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
844 SetLastWin32Error(ERROR_INVALID_HANDLE);
845 return FALSE;
846 }
847
848 if (UsesSource)
849 {
850 if (hDCSrc != hDCDest)
851 {
852 DCSrc = DC_LockDc(hDCSrc);
853 if (NULL == DCSrc)
854 {
855 DC_UnlockDc(hDCDest);
856 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
857 SetLastWin32Error(ERROR_INVALID_HANDLE);
858 return FALSE;
859 }
860 }
861 else
862 {
863 DCSrc = DCDest;
864 }
865 }
866 else
867 {
868 DCSrc = NULL;
869 }
870
871 /* Offset the destination and source by the origin of their DCs. */
872 XOriginDest += DCDest->w.DCOrgX;
873 YOriginDest += DCDest->w.DCOrgY;
874 if (UsesSource)
875 {
876 XOriginSrc += DCSrc->w.DCOrgX;
877 YOriginSrc += DCSrc->w.DCOrgY;
878 }
879
880 DestRect.left = XOriginDest;
881 DestRect.top = YOriginDest;
882 DestRect.right = XOriginDest+WidthDest;
883 DestRect.bottom = YOriginDest+HeightDest;
884
885 SourceRect.left = XOriginSrc;
886 SourceRect.top = YOriginSrc;
887 SourceRect.right = XOriginSrc+WidthSrc;
888 SourceRect.bottom = YOriginSrc+HeightSrc;
889
890 /* Determine surfaces to be used in the bitblt */
891 SurfDest = (PSURFOBJ)AccessUserObject((ULONG)DCDest->Surface);
892 SurfGDIDest = (PSURFGDI)AccessInternalObjectFromUserObject(SurfDest);
893 if (UsesSource)
894 {
895 SurfSrc = (PSURFOBJ)AccessUserObject((ULONG)DCSrc->Surface);
896 SurfGDISrc = (PSURFGDI)AccessInternalObjectFromUserObject(SurfSrc);
897 }
898 else
899 {
900 SurfSrc = NULL;
901 SurfGDISrc = NULL;
902 }
903
904 if (UsesPattern)
905 {
906 BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
907 if (NULL == BrushObj)
908 {
909 if (UsesSource && hDCSrc != hDCDest)
910 {
911 DC_UnlockDc(hDCSrc);
912 }
913 DC_UnlockDc(hDCDest);
914 SetLastWin32Error(ERROR_INVALID_HANDLE);
915 return FALSE;
916 }
917 }
918 else
919 {
920 BrushObj = NULL;
921 }
922
923 if (DCDest->w.hPalette != 0)
924 {
925 DestPalette = DCDest->w.hPalette;
926 }
927 else
928 {
929 DestPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
930 }
931
932 if (UsesSource && DCSrc->w.hPalette != 0)
933 {
934 SourcePalette = DCSrc->w.hPalette;
935 }
936 else
937 {
938 SourcePalette = NtGdiGetStockObject(DEFAULT_PALETTE);
939 }
940
941 PalSourceGDI = PALETTE_LockPalette(SourcePalette);
942 if (NULL == PalSourceGDI)
943 {
944 if (UsesSource && hDCSrc != hDCDest)
945 {
946 DC_UnlockDc(hDCSrc);
947 }
948 DC_UnlockDc(hDCDest);
949 SetLastWin32Error(ERROR_INVALID_HANDLE);
950 return FALSE;
951 }
952 SourceMode = PalSourceGDI->Mode;
953 PALETTE_UnlockPalette(SourcePalette);
954
955 if (DestPalette == SourcePalette)
956 {
957 DestMode = SourceMode;
958 }
959 else
960 {
961 PalDestGDI = PALETTE_LockPalette(DestPalette);
962 if (NULL == PalDestGDI)
963 {
964 if (UsesSource && hDCSrc != hDCDest)
965 {
966 DC_UnlockDc(hDCSrc);
967 }
968 DC_UnlockDc(hDCDest);
969 SetLastWin32Error(ERROR_INVALID_HANDLE);
970 return FALSE;
971 }
972 DestMode = PalDestGDI->Mode;
973 PALETTE_UnlockPalette(DestPalette);
974 }
975
976 XlateObj = (PXLATEOBJ)IntEngCreateXlate(DestMode, SourceMode, DestPalette, SourcePalette);
977 if (NULL == XlateObj)
978 {
979 if (UsesSource && hDCSrc != hDCDest)
980 {
981 DC_UnlockDc(hDCSrc);
982 }
983 DC_UnlockDc(hDCDest);
984 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
985 return FALSE;
986 }
987
988 /* Perform the bitblt operation */
989 Status = IntEngStretchBlt(SurfDest, SurfSrc, NULL, DCDest->CombinedClip,
990 XlateObj, &DestRect, &SourceRect, NULL, NULL, NULL, COLORONCOLOR);
991
992 EngDeleteXlate(XlateObj);
993 if (UsesPattern)
994 {
995 BRUSHOBJ_UnlockBrush(DCDest->w.hBrush);
996 }
997 if (UsesSource && hDCSrc != hDCDest)
998 {
999 DC_UnlockDc(hDCSrc);
1000 }
1001 DC_UnlockDc(hDCDest);
1002
1003 return Status;
1004 }
1005
1006 /* Internal Functions */
1007
1008 INT FASTCALL
1009 BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
1010 {
1011 #if 0
1012 switch(bpp)
1013 {
1014 case 1:
1015 return 2 * ((bmWidth+15) >> 4);
1016
1017 case 24:
1018 bmWidth *= 3; /* fall through */
1019 case 8:
1020 return bmWidth + (bmWidth & 1);
1021
1022 case 32:
1023 return bmWidth * 4;
1024
1025 case 16:
1026 case 15:
1027 return bmWidth * 2;
1028
1029 case 4:
1030 return 2 * ((bmWidth+3) >> 2);
1031
1032 default:
1033 DPRINT ("stub");
1034 }
1035
1036 return -1;
1037 #endif
1038
1039 return ((bmWidth * bpp + 31) & ~31) >> 3;
1040 }
1041
1042 HBITMAP FASTCALL BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
1043 {
1044 PBITMAPOBJ bmp;
1045 HBITMAP res;
1046 BITMAP bm;
1047
1048 bmp = BITMAPOBJ_LockBitmap(hBitmap);
1049 if (bmp == NULL)
1050 {
1051 return 0;
1052 }
1053 res = 0;
1054
1055 bm = bmp->bitmap;
1056 bm.bmBits = NULL;
1057 BITMAPOBJ_UnlockBitmap(hBitmap);
1058 res = NtGdiCreateBitmapIndirect(&bm);
1059 if(res)
1060 {
1061 char *buf;
1062
1063 buf = ExAllocatePool (NonPagedPool, bm.bmWidthBytes * bm.bmHeight);
1064 NtGdiGetBitmapBits (hBitmap, bm.bmWidthBytes * bm.bmHeight, buf);
1065 NtGdiSetBitmapBits (res, bm.bmWidthBytes * bm.bmHeight, buf);
1066 ExFreePool (buf);
1067 }
1068
1069 return res;
1070 }
1071
1072 INT STDCALL BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer)
1073 {
1074 if(bmp->dib)
1075 {
1076 if(count < (INT) sizeof(DIBSECTION))
1077 {
1078 if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
1079 }
1080 else
1081 {
1082 if (count > (INT) sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
1083 }
1084 memcpy(buffer, bmp->dib, count);
1085 return count;
1086 }
1087 else
1088 {
1089 if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
1090 memcpy(buffer, &bmp->bitmap, count);
1091 return count;
1092 }
1093 }
1094 /* EOF */