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