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