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