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