[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / dibobj.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/dibobj.c
5 * PURPOSE: Dib object functions
6 * PROGRAMMER:
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static const RGBQUAD EGAColorsQuads[16] =
15 {
16 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
17 { 0x00, 0x00, 0x00, 0x00 },
18 { 0x00, 0x00, 0x80, 0x00 },
19 { 0x00, 0x80, 0x00, 0x00 },
20 { 0x00, 0x80, 0x80, 0x00 },
21 { 0x80, 0x00, 0x00, 0x00 },
22 { 0x80, 0x00, 0x80, 0x00 },
23 { 0x80, 0x80, 0x00, 0x00 },
24 { 0x80, 0x80, 0x80, 0x00 },
25 { 0xc0, 0xc0, 0xc0, 0x00 },
26 { 0x00, 0x00, 0xff, 0x00 },
27 { 0x00, 0xff, 0x00, 0x00 },
28 { 0x00, 0xff, 0xff, 0x00 },
29 { 0xff, 0x00, 0x00, 0x00 },
30 { 0xff, 0x00, 0xff, 0x00 },
31 { 0xff, 0xff, 0x00, 0x00 },
32 { 0xff, 0xff, 0xff, 0x00 }
33 };
34
35 static const RGBTRIPLE EGAColorsTriples[16] =
36 {
37 /* rgbBlue, rgbGreen, rgbRed */
38 { 0x00, 0x00, 0x00 },
39 { 0x00, 0x00, 0x80 },
40 { 0x00, 0x80, 0x00 },
41 { 0x00, 0x80, 0x80 },
42 { 0x80, 0x00, 0x00 },
43 { 0x80, 0x00, 0x80 },
44 { 0x80, 0x80, 0x00 },
45 { 0x80, 0x80, 0x80 },
46 { 0xc0, 0xc0, 0xc0 },
47 { 0x00, 0x00, 0xff },
48 { 0x00, 0xff, 0x00 },
49 { 0x00, 0xff, 0xff },
50 { 0xff, 0x00, 0x00 },
51 { 0xff, 0x00, 0xff },
52 { 0xff, 0xff, 0x00 },
53 { 0xff, 0xff, 0xff }
54 };
55
56 static const RGBQUAD DefLogPaletteQuads[20] = /* Copy of Default Logical Palette */
57 {
58 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
59 { 0x00, 0x00, 0x00, 0x00 },
60 { 0x00, 0x00, 0x80, 0x00 },
61 { 0x00, 0x80, 0x00, 0x00 },
62 { 0x00, 0x80, 0x80, 0x00 },
63 { 0x80, 0x00, 0x00, 0x00 },
64 { 0x80, 0x00, 0x80, 0x00 },
65 { 0x80, 0x80, 0x00, 0x00 },
66 { 0xc0, 0xc0, 0xc0, 0x00 },
67 { 0xc0, 0xdc, 0xc0, 0x00 },
68 { 0xf0, 0xca, 0xa6, 0x00 },
69 { 0xf0, 0xfb, 0xff, 0x00 },
70 { 0xa4, 0xa0, 0xa0, 0x00 },
71 { 0x80, 0x80, 0x80, 0x00 },
72 { 0x00, 0x00, 0xf0, 0x00 },
73 { 0x00, 0xff, 0x00, 0x00 },
74 { 0x00, 0xff, 0xff, 0x00 },
75 { 0xff, 0x00, 0x00, 0x00 },
76 { 0xff, 0x00, 0xff, 0x00 },
77 { 0xff, 0xff, 0x00, 0x00 },
78 { 0xff, 0xff, 0xff, 0x00 }
79 };
80
81 static const RGBQUAD DefLogPaletteTriples[20] = /* Copy of Default Logical Palette */
82 {
83 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
84 { 0x00, 0x00, 0x00 },
85 { 0x00, 0x00, 0x80 },
86 { 0x00, 0x80, 0x00 },
87 { 0x00, 0x80, 0x80 },
88 { 0x80, 0x00, 0x00 },
89 { 0x80, 0x00, 0x80 },
90 { 0x80, 0x80, 0x00 },
91 { 0xc0, 0xc0, 0xc0 },
92 { 0xc0, 0xdc, 0xc0 },
93 { 0xf0, 0xca, 0xa6 },
94 { 0xf0, 0xfb, 0xff },
95 { 0xa4, 0xa0, 0xa0 },
96 { 0x80, 0x80, 0x80 },
97 { 0x00, 0x00, 0xf0 },
98 { 0x00, 0xff, 0x00 },
99 { 0x00, 0xff, 0xff },
100 { 0xff, 0x00, 0x00 },
101 { 0xff, 0x00, 0xff },
102 { 0xff, 0xff, 0x00 },
103 { 0xff, 0xff, 0xff }
104 };
105
106 PPALETTE
107 NTAPI
108 CreateDIBPalette(
109 _In_ const BITMAPINFO *pbmi,
110 _In_ PDC pdc,
111 _In_ ULONG iUsage)
112 {
113 PPALETTE ppal;
114 ULONG i, cBitsPixel, cColors;
115
116 if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
117 {
118 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
119 cBitsPixel = pbci->bmciHeader.bcBitCount;
120 }
121 else
122 {
123 cBitsPixel = pbmi->bmiHeader.biBitCount;
124 }
125
126 /* Check if the colors are indexed */
127 if (cBitsPixel <= 8)
128 {
129 /* We create a "full" palette */
130 cColors = 1 << cBitsPixel;
131
132 /* Allocate the palette */
133 ppal = PALETTE_AllocPalette(PAL_INDEXED,
134 cColors,
135 NULL,
136 0,
137 0,
138 0);
139
140 /* Check if the BITMAPINFO specifies how many colors to use */
141 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
142 (pbmi->bmiHeader.biClrUsed != 0))
143 {
144 /* This is how many colors we can actually process */
145 cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
146 }
147
148 /* Check how to use the colors */
149 if (iUsage == DIB_PAL_COLORS)
150 {
151 COLORREF crColor;
152
153 /* The colors are an array of WORD indices into the DC palette */
154 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
155
156 /* Use the DCs palette or, if no DC is given, the default one */
157 PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
158
159 /* Loop all color indices in the DIB */
160 for (i = 0; i < cColors; i++)
161 {
162 /* Get the palette index and handle wraparound when exceeding
163 the number of colors in the DC palette */
164 WORD wIndex = pwColors[i] % ppalDC->NumColors;
165
166 /* USe the RGB value from the DC palette */
167 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
168 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
169 }
170 }
171 else if (iUsage == DIB_PAL_BRUSHHACK)
172 {
173 /* The colors are an array of WORD indices into the DC palette */
174 PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
175
176 /* Loop all color indices in the DIB */
177 for (i = 0; i < cColors; i++)
178 {
179 /* Set the index directly as the RGB color, the real palette
180 containing RGB values will be calculated when the brush is
181 realized */
182 PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
183 }
184
185 /* Mark the palette as a brush hack palette */
186 ppal->flFlags |= PAL_BRUSHHACK;
187 }
188 // else if (iUsage == 2)
189 // {
190 // FIXME: this one is undocumented
191 // ASSERT(FALSE);
192 // }
193 else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
194 {
195 /* The colors are an array of RGBQUAD values */
196 RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
197
198 // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
199
200 /* Loop all color indices in the DIB */
201 for (i = 0; i < cColors; i++)
202 {
203 /* Get the color value and translate it to a COLORREF */
204 RGBQUAD rgb = prgb[i];
205 COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
206
207 /* Set the RGB value in the palette */
208 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
209 }
210 }
211 else
212 {
213 /* The colors are an array of RGBTRIPLE values */
214 RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
215
216 /* Loop all color indices in the DIB */
217 for (i = 0; i < cColors; i++)
218 {
219 /* Get the color value and translate it to a COLORREF */
220 RGBTRIPLE rgb = prgb[i];
221 COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
222
223 /* Set the RGB value in the palette */
224 PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
225 }
226 }
227 }
228 else
229 {
230 /* This is a bitfield / RGB palette */
231 ULONG flRedMask, flGreenMask, flBlueMask;
232
233 /* Check if the DIB contains bitfield values */
234 if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
235 (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
236 {
237 /* Check if we have a v4/v5 header */
238 if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
239 {
240 /* The masks are dedicated fields in the header */
241 PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
242 flRedMask = pbmV4Header->bV4RedMask;
243 flGreenMask = pbmV4Header->bV4GreenMask;
244 flBlueMask = pbmV4Header->bV4BlueMask;
245 }
246 else
247 {
248 /* The masks are the first 3 values in the DIB color table */
249 PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
250 flRedMask = pdwColors[0];
251 flGreenMask = pdwColors[1];
252 flBlueMask = pdwColors[2];
253 }
254 }
255 else
256 {
257 /* Check what bit depth we have. Note: optimization flags are
258 calculated in PALETTE_AllocPalette() */
259 if (cBitsPixel == 16)
260 {
261 /* This is an RGB 555 palette */
262 flRedMask = 0x7C00;
263 flGreenMask = 0x03E0;
264 flBlueMask = 0x001F;
265 }
266 else
267 {
268 /* This is an RGB 888 palette */
269 flRedMask = 0xFF0000;
270 flGreenMask = 0x00FF00;
271 flBlueMask = 0x0000FF;
272 }
273 }
274
275 /* Allocate the bitfield palette */
276 ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
277 0,
278 NULL,
279 flRedMask,
280 flGreenMask,
281 flBlueMask);
282 }
283
284 /* We're done, return the palette */
285 return ppal;
286 }
287
288 // Converts a DIB to a device-dependent bitmap
289 static INT
290 FASTCALL
291 IntSetDIBits(
292 PDC DC,
293 HBITMAP hBitmap,
294 UINT StartScan,
295 UINT ScanLines,
296 CONST VOID *Bits,
297 CONST BITMAPINFO *bmi,
298 UINT ColorUse)
299 {
300 HBITMAP SourceBitmap;
301 PSURFACE psurfDst, psurfSrc;
302 INT result = 0;
303 RECT rcDst;
304 POINTL ptSrc;
305 EXLATEOBJ exlo;
306 PPALETTE ppalDIB = 0;
307
308 if (!bmi) return 0;
309
310 SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
311 ScanLines,
312 0,
313 BitmapFormat(bmi->bmiHeader.biBitCount,
314 bmi->bmiHeader.biCompression),
315 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
316 bmi->bmiHeader.biSizeImage,
317 (PVOID)Bits,
318 0);
319 if (!SourceBitmap)
320 {
321 DPRINT1("Error: Could not create a bitmap.\n");
322 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
323 return 0;
324 }
325
326 psurfDst = SURFACE_ShareLockSurface(hBitmap);
327 psurfSrc = SURFACE_ShareLockSurface(SourceBitmap);
328
329 if(!(psurfSrc && psurfDst))
330 {
331 DPRINT1("Error: Could not lock surfaces\n");
332 goto cleanup;
333 }
334
335 /* Create a palette for the DIB */
336 ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
337 if (!ppalDIB)
338 {
339 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
340 goto cleanup;
341 }
342
343 /* Initialize EXLATEOBJ */
344 EXLATEOBJ_vInitialize(&exlo,
345 ppalDIB,
346 psurfDst->ppal,
347 RGB(0xff, 0xff, 0xff),
348 RGB(0xff, 0xff, 0xff), //DC->pdcattr->crBackgroundClr,
349 0); // DC->pdcattr->crForegroundClr);
350
351 rcDst.top = StartScan;
352 rcDst.left = 0;
353 rcDst.bottom = rcDst.top + ScanLines;
354 rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
355 ptSrc.x = 0;
356 ptSrc.y = 0;
357
358 result = IntEngCopyBits(&psurfDst->SurfObj,
359 &psurfSrc->SurfObj,
360 NULL,
361 &exlo.xlo,
362 &rcDst,
363 &ptSrc);
364 if(result)
365 result = ScanLines;
366
367 EXLATEOBJ_vCleanup(&exlo);
368
369 cleanup:
370 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
371 if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
372 if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
373 GreDeleteObject(SourceBitmap);
374
375 return result;
376 }
377
378 W32KAPI
379 INT
380 APIENTRY
381 NtGdiSetDIBitsToDeviceInternal(
382 IN HDC hDC,
383 IN INT XDest,
384 IN INT YDest,
385 IN DWORD Width,
386 IN DWORD Height,
387 IN INT XSrc,
388 IN INT YSrc,
389 IN DWORD StartScan,
390 IN DWORD ScanLines,
391 IN LPBYTE Bits,
392 IN LPBITMAPINFO bmi,
393 IN DWORD ColorUse,
394 IN UINT cjMaxBits,
395 IN UINT cjMaxInfo,
396 IN BOOL bTransformCoordinates,
397 IN OPTIONAL HANDLE hcmXform)
398 {
399 INT ret = 0;
400 NTSTATUS Status = STATUS_SUCCESS;
401 PDC pDC;
402 HBITMAP hSourceBitmap = NULL;
403 SURFOBJ *pDestSurf, *pSourceSurf = NULL;
404 SURFACE *pSurf;
405 RECTL rcDest;
406 POINTL ptSource;
407 //INT DIBWidth;
408 SIZEL SourceSize;
409 EXLATEOBJ exlo;
410 PPALETTE ppalDIB = NULL;
411 LPBITMAPINFO pbmiSafe;
412
413 if (!Bits) return 0;
414
415 pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'pmTG');
416 if (!pbmiSafe) return 0;
417
418 _SEH2_TRY
419 {
420 ProbeForRead(bmi, cjMaxInfo, 1);
421 ProbeForRead(Bits, cjMaxBits, 1);
422 RtlCopyMemory(pbmiSafe, bmi, cjMaxInfo);
423 bmi = pbmiSafe;
424 }
425 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
426 {
427 Status = _SEH2_GetExceptionCode();
428 }
429 _SEH2_END
430
431 if (!NT_SUCCESS(Status))
432 {
433 goto Exit2;
434 }
435
436 ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
437
438 pDC = DC_LockDc(hDC);
439 if (!pDC)
440 {
441 EngSetLastError(ERROR_INVALID_HANDLE);
442 goto Exit2;
443 }
444
445 if (pDC->dctype == DC_TYPE_INFO)
446 {
447 DC_UnlockDc(pDC);
448 goto Exit;
449 }
450
451 rcDest.left = XDest;
452 rcDest.top = YDest;
453 if (bTransformCoordinates)
454 {
455 IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
456 }
457 rcDest.left += pDC->ptlDCOrig.x;
458 rcDest.top += pDC->ptlDCOrig.y;
459 rcDest.right = rcDest.left + Width;
460 rcDest.bottom = rcDest.top + Height;
461 rcDest.top += StartScan;
462
463 ptSource.x = XSrc;
464 ptSource.y = YSrc;
465
466 SourceSize.cx = bmi->bmiHeader.biWidth;
467 SourceSize.cy = ScanLines;
468
469 //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
470
471 hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
472 ScanLines,
473 0,
474 BitmapFormat(bmi->bmiHeader.biBitCount,
475 bmi->bmiHeader.biCompression),
476 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
477 bmi->bmiHeader.biSizeImage,
478 Bits,
479 0);
480
481 if (!hSourceBitmap)
482 {
483 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
484 Status = STATUS_NO_MEMORY;
485 goto Exit;
486 }
487
488 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
489 if (!pSourceSurf)
490 {
491 Status = STATUS_UNSUCCESSFUL;
492 goto Exit;
493 }
494
495 /* Create a palette for the DIB */
496 ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
497 if (!ppalDIB)
498 {
499 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
500 Status = STATUS_NO_MEMORY;
501 goto Exit;
502 }
503
504 /* This is actually a blit */
505 DC_vPrepareDCsForBlit(pDC, rcDest, NULL, rcDest);
506 pSurf = pDC->dclevel.pSurface;
507 if (!pSurf)
508 {
509 DC_vFinishBlit(pDC, NULL);
510 ret = ScanLines;
511 goto Exit;
512 }
513
514 ASSERT(pSurf->ppal);
515
516 /* Initialize EXLATEOBJ */
517 EXLATEOBJ_vInitialize(&exlo,
518 ppalDIB,
519 pSurf->ppal,
520 RGB(0xff, 0xff, 0xff),
521 pDC->pdcattr->crBackgroundClr,
522 pDC->pdcattr->crForegroundClr);
523
524 pDestSurf = &pSurf->SurfObj;
525
526 /* Copy the bits */
527 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
528 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
529 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
530 Status = IntEngBitBlt(pDestSurf,
531 pSourceSurf,
532 NULL,
533 pDC->rosdc.CombinedClip,
534 &exlo.xlo,
535 &rcDest,
536 &ptSource,
537 NULL,
538 NULL,
539 NULL,
540 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
541
542 /* Cleanup EXLATEOBJ */
543 EXLATEOBJ_vCleanup(&exlo);
544
545 /* We're done */
546 DC_vFinishBlit(pDC, NULL);
547
548 Exit:
549 if (NT_SUCCESS(Status))
550 {
551 ret = ScanLines;
552 }
553
554 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
555
556 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
557 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
558 DC_UnlockDc(pDC);
559 Exit2:
560 ExFreePool(pbmiSafe);
561 return ret;
562 }
563
564
565 /* Converts a device-dependent bitmap to a DIB */
566 INT
567 APIENTRY
568 NtGdiGetDIBitsInternal(
569 HDC hDC,
570 HBITMAP hBitmap,
571 UINT StartScan,
572 UINT ScanLines,
573 LPBYTE Bits,
574 LPBITMAPINFO Info,
575 UINT Usage,
576 UINT MaxBits,
577 UINT MaxInfo)
578 {
579 BITMAPCOREINFO* pbmci = NULL;
580 PSURFACE psurf = NULL;
581 PDC pDC;
582 LONG width, height;
583 WORD planes, bpp;
584 DWORD compr, size ;
585 USHORT i;
586 int bitmap_type;
587 RGBTRIPLE* rgbTriples;
588 RGBQUAD* rgbQuads;
589 VOID* colorPtr;
590 NTSTATUS Status = STATUS_SUCCESS;
591
592 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
593
594 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
595 return 0;
596
597 _SEH2_TRY
598 {
599 /* Probe for read and write */
600 ProbeForRead(Info, MaxInfo, 1);
601 ProbeForWrite(Info, MaxInfo, 1);
602 if (Bits) ProbeForWrite(Bits, MaxBits, 1);
603 }
604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
605 {
606 Status = _SEH2_GetExceptionCode();
607 }
608 _SEH2_END
609
610 if (!NT_SUCCESS(Status))
611 {
612 return 0;
613 }
614
615 colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
616 rgbTriples = colorPtr;
617 rgbQuads = colorPtr;
618
619 bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
620 &width,
621 &height,
622 &planes,
623 &bpp,
624 &compr,
625 &size);
626 if(bitmap_type == -1)
627 {
628 DPRINT("Wrong bitmap format\n");
629 EngSetLastError(ERROR_INVALID_PARAMETER);
630 return 0;
631 }
632 else if(bitmap_type == 0)
633 {
634 /* We need a BITMAPINFO to create a DIB, but we have to fill
635 * the BITMAPCOREINFO we're provided */
636 pbmci = (BITMAPCOREINFO*)Info;
637 Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
638 if(Info == NULL)
639 {
640 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
641 return 0;
642 }
643 rgbQuads = Info->bmiColors;
644 }
645
646 pDC = DC_LockDc(hDC);
647 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
648 {
649 ScanLines = 0;
650 goto done;
651 }
652
653 /* Get a pointer to the source bitmap object */
654 psurf = SURFACE_ShareLockSurface(hBitmap);
655 if (psurf == NULL)
656 {
657 ScanLines = 0;
658 goto done;
659 }
660
661 /* Fill in the structure */
662 switch(bpp)
663 {
664 case 0: /* Only info */
665 if(pbmci)
666 {
667 pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx;
668 pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
669 -psurf->SurfObj.sizlBitmap.cy :
670 psurf->SurfObj.sizlBitmap.cy);
671 pbmci->bmciHeader.bcPlanes = 1;
672 pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
673 }
674 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
675 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
676 -psurf->SurfObj.sizlBitmap.cy :
677 psurf->SurfObj.sizlBitmap.cy;;
678 Info->bmiHeader.biPlanes = 1;
679 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
680 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
681 Info->bmiHeader.biHeight,
682 Info->bmiHeader.biBitCount);
683 if(psurf->hSecure)
684 {
685 switch(Info->bmiHeader.biBitCount)
686 {
687 case 16:
688 case 32:
689 Info->bmiHeader.biCompression = BI_BITFIELDS;
690 break;
691 default:
692 Info->bmiHeader.biCompression = BI_RGB;
693 break;
694 }
695 }
696 else if(Info->bmiHeader.biBitCount > 8)
697 {
698 Info->bmiHeader.biCompression = BI_BITFIELDS;
699 }
700 else
701 {
702 Info->bmiHeader.biCompression = BI_RGB;
703 }
704 Info->bmiHeader.biXPelsPerMeter = 0;
705 Info->bmiHeader.biYPelsPerMeter = 0;
706 Info->bmiHeader.biClrUsed = 0;
707 Info->bmiHeader.biClrImportant = 0;
708 ScanLines = abs(Info->bmiHeader.biHeight);
709 goto done;
710
711 case 1:
712 case 4:
713 case 8:
714 Info->bmiHeader.biClrUsed = 0;
715
716 /* If the bitmap if a DIB section and has the same format than what
717 * we're asked, go ahead! */
718 if((psurf->hSecure) &&
719 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
720 {
721 if(Usage == DIB_RGB_COLORS)
722 {
723 ULONG colors = min(psurf->ppal->NumColors, 256);
724
725 if(pbmci)
726 {
727 for(i = 0; i < colors; i++)
728 {
729 rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
730 rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
731 rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
732 }
733 }
734 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
735 for(i = 0; i < colors; i++)
736 {
737 rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
738 rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
739 rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
740 }
741 }
742 else
743 {
744 for(i = 0; i < 256; i++)
745 {
746 if(pbmci) ((WORD*)rgbTriples)[i] = i;
747 ((WORD*)rgbQuads)[i] = i;
748 }
749 }
750 }
751 else
752 {
753 if(Usage == DIB_PAL_COLORS)
754 {
755 for(i = 0; i < 256; i++)
756 {
757 if(pbmci) ((WORD*)rgbTriples)[i] = i;
758 ((WORD*)rgbQuads)[i] = i;
759 }
760 }
761 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
762 {
763 /* For color DDBs in native depth (mono DDBs always have
764 a black/white palette):
765 Generate the color map from the selected palette */
766 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
767 if(!pDcPal)
768 {
769 ScanLines = 0 ;
770 goto done ;
771 }
772 for (i = 0; i < pDcPal->NumColors; i++)
773 {
774 if (pbmci)
775 {
776 rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed;
777 rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
778 rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue;
779 }
780
781 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
782 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
783 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
784 rgbQuads[i].rgbReserved = 0;
785 }
786 PALETTE_ShareUnlockPalette(pDcPal);
787 }
788 else
789 {
790 switch (bpp)
791 {
792 case 1:
793 if (pbmci)
794 {
795 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
796 rgbTriples[0].rgbtBlue = 0;
797 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
798 rgbTriples[1].rgbtBlue = 0xff;
799 }
800 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
801 rgbQuads[0].rgbBlue = 0;
802 rgbQuads[0].rgbReserved = 0;
803 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
804 rgbQuads[1].rgbBlue = 0xff;
805 rgbQuads[1].rgbReserved = 0;
806 break;
807
808 case 4:
809 if (pbmci)
810 RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
811 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
812
813 break;
814
815 case 8:
816 {
817 INT r, g, b;
818 RGBQUAD *color;
819 if (pbmci)
820 {
821 RGBTRIPLE *colorTriple;
822
823 RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
824 10 * sizeof(RGBTRIPLE));
825 RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
826 10 * sizeof(RGBTRIPLE));
827 colorTriple = rgbTriples + 10;
828 for(r = 0; r <= 5; r++) /* FIXME */
829 {
830 for(g = 0; g <= 5; g++)
831 {
832 for(b = 0; b <= 5; b++)
833 {
834 colorTriple->rgbtRed = (r * 0xff) / 5;
835 colorTriple->rgbtGreen = (g * 0xff) / 5;
836 colorTriple->rgbtBlue = (b * 0xff) / 5;
837 color++;
838 }
839 }
840 }
841 }
842 memcpy(rgbQuads, DefLogPaletteQuads,
843 10 * sizeof(RGBQUAD));
844 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
845 10 * sizeof(RGBQUAD));
846 color = rgbQuads + 10;
847 for(r = 0; r <= 5; r++) /* FIXME */
848 {
849 for(g = 0; g <= 5; g++)
850 {
851 for(b = 0; b <= 5; b++)
852 {
853 color->rgbRed = (r * 0xff) / 5;
854 color->rgbGreen = (g * 0xff) / 5;
855 color->rgbBlue = (b * 0xff) / 5;
856 color->rgbReserved = 0;
857 color++;
858 }
859 }
860 }
861 }
862 }
863 }
864 }
865 break;
866
867 case 15:
868 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
869 {
870 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
871 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
872 ((PDWORD)Info->bmiColors)[2] = 0x001f;
873 }
874 break;
875
876 case 16:
877 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
878 {
879 if (psurf->hSecure)
880 {
881 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
882 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
883 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
884 }
885 else
886 {
887 ((PDWORD)Info->bmiColors)[0] = 0xf800;
888 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
889 ((PDWORD)Info->bmiColors)[2] = 0x001f;
890 }
891 }
892 break;
893
894 case 24:
895 case 32:
896 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
897 {
898 if (psurf->hSecure)
899 {
900 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
901 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
902 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
903 }
904 else
905 {
906 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
907 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
908 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
909 }
910 }
911 break;
912 }
913 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
914
915 if(Bits && ScanLines)
916 {
917 /* Create a DIBSECTION, blt it, profit */
918 PVOID pDIBits ;
919 HBITMAP hBmpDest;
920 PSURFACE psurfDest;
921 EXLATEOBJ exlo;
922 RECT rcDest;
923 POINTL srcPoint;
924 BOOL ret ;
925
926 if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy)
927 {
928 ScanLines = 0;
929 goto done;
930 }
931 else
932 {
933 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
934 }
935
936 /* Fixup values */
937 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
938 Info->bmiHeader.biHeight = (height < 0) ?
939 -(LONG)ScanLines : ScanLines;
940 /* Create the DIB */
941 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
942 /* Restore them */
943 Info->bmiHeader.biWidth = width;
944 Info->bmiHeader.biHeight = height;
945
946 if(!hBmpDest)
947 {
948 DPRINT1("Unable to create a DIB Section!\n");
949 EngSetLastError(ERROR_INVALID_PARAMETER);
950 ScanLines = 0;
951 goto done ;
952 }
953
954 psurfDest = SURFACE_ShareLockSurface(hBmpDest);
955
956 rcDest.left = 0;
957 rcDest.top = 0;
958 rcDest.bottom = ScanLines;
959 rcDest.right = psurf->SurfObj.sizlBitmap.cx;
960
961 srcPoint.x = 0;
962
963 if(height < 0)
964 {
965 srcPoint.y = 0;
966
967 if(ScanLines <= StartScan)
968 {
969 ScanLines = 1;
970 SURFACE_ShareUnlockSurface(psurfDest);
971 GreDeleteObject(hBmpDest);
972 goto done;
973 }
974
975 ScanLines -= StartScan;
976 }
977 else
978 {
979 srcPoint.y = StartScan;
980 }
981
982 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
983
984 ret = IntEngCopyBits(&psurfDest->SurfObj,
985 &psurf->SurfObj,
986 NULL,
987 &exlo.xlo,
988 &rcDest,
989 &srcPoint);
990
991 SURFACE_ShareUnlockSurface(psurfDest);
992
993 if(!ret)
994 ScanLines = 0;
995 else
996 {
997 Status = STATUS_SUCCESS;
998 _SEH2_TRY
999 {
1000 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
1001 }
1002 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1003 {
1004 Status = _SEH2_GetExceptionCode();
1005 }
1006 _SEH2_END
1007
1008 if(!NT_SUCCESS(Status))
1009 {
1010 DPRINT1("Unable to copy bits to the user provided pointer\n");
1011 ScanLines = 0;
1012 }
1013 }
1014
1015 GreDeleteObject(hBmpDest);
1016 EXLATEOBJ_vCleanup(&exlo);
1017 }
1018 else ScanLines = abs(height);
1019
1020 done:
1021
1022 if(pDC) DC_UnlockDc(pDC);
1023 if(psurf) SURFACE_ShareUnlockSurface(psurf);
1024 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
1025
1026 return ScanLines;
1027 }
1028
1029 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
1030
1031 W32KAPI
1032 INT
1033 APIENTRY
1034 NtGdiStretchDIBitsInternal(
1035 IN HDC hdc,
1036 IN INT xDst,
1037 IN INT yDst,
1038 IN INT cxDst,
1039 IN INT cyDst,
1040 IN INT xSrc,
1041 IN INT ySrc,
1042 IN INT cxSrc,
1043 IN INT cySrc,
1044 IN OPTIONAL LPBYTE pjInit,
1045 IN LPBITMAPINFO pbmi,
1046 IN DWORD dwUsage,
1047 IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
1048 IN UINT cjMaxInfo,
1049 IN UINT cjMaxBits,
1050 IN HANDLE hcmXform)
1051 {
1052 BOOL bResult = FALSE;
1053 SIZEL sizel;
1054 RECTL rcSrc, rcDst;
1055 PDC pdc;
1056 HBITMAP hbmTmp = 0;
1057 PSURFACE psurfTmp = 0, psurfDst = 0;
1058 PPALETTE ppalDIB = 0;
1059 EXLATEOBJ exlo;
1060 PVOID pvBits;
1061
1062 if (!(pdc = DC_LockDc(hdc)))
1063 {
1064 EngSetLastError(ERROR_INVALID_HANDLE);
1065 return 0;
1066 }
1067
1068 /* Transform dest size */
1069 sizel.cx = cxDst;
1070 sizel.cy = cyDst;
1071 IntLPtoDP(pdc, (POINTL*)&sizel, 1);
1072 DC_UnlockDc(pdc);
1073
1074 /* Check if we can use NtGdiSetDIBitsToDeviceInternal */
1075 if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
1076 {
1077 /* Yes, we can! */
1078 return NtGdiSetDIBitsToDeviceInternal(hdc,
1079 xDst,
1080 yDst,
1081 cxDst,
1082 cyDst,
1083 xSrc,
1084 ySrc,
1085 0,
1086 cySrc,
1087 pjInit,
1088 pbmi,
1089 dwUsage,
1090 cjMaxBits,
1091 cjMaxInfo,
1092 TRUE,
1093 hcmXform);
1094 }
1095
1096 pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
1097 if (!pvBits)
1098 {
1099 return 0;
1100 }
1101
1102 _SEH2_TRY
1103 {
1104 ProbeForRead(pjInit, cjMaxBits, 1);
1105 RtlCopyMemory(pvBits, pjInit, cjMaxBits);
1106 }
1107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1108 {
1109 _SEH2_YIELD(return 0);
1110 }
1111 _SEH2_END
1112
1113 /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
1114 if (!(pdc = DC_LockDc(hdc)))
1115 {
1116 DPRINT1("Could not lock dc\n");
1117 EngSetLastError(ERROR_INVALID_HANDLE);
1118 goto cleanup;
1119 }
1120
1121 /* Calculate source and destination rect */
1122 rcSrc.left = xSrc;
1123 rcSrc.top = ySrc;
1124 rcSrc.right = xSrc + abs(cxSrc);
1125 rcSrc.bottom = ySrc + abs(cySrc);
1126 rcDst.left = xDst;
1127 rcDst.top = yDst;
1128 rcDst.right = rcDst.left + cxDst;
1129 rcDst.bottom = rcDst.top + cyDst;
1130 IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
1131 RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
1132
1133 hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
1134 pbmi->bmiHeader.biHeight,
1135 0,
1136 BitmapFormat(pbmi->bmiHeader.biBitCount,
1137 pbmi->bmiHeader.biCompression),
1138 pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
1139 pbmi->bmiHeader.biSizeImage,
1140 pvBits,
1141 0);
1142
1143 if (!hbmTmp)
1144 {
1145 bResult = FALSE;
1146 goto cleanup;
1147 }
1148
1149 psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
1150 if (!psurfTmp)
1151 {
1152 bResult = FALSE;
1153 goto cleanup;
1154 }
1155
1156 /* Create a palette for the DIB */
1157 ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
1158 if (!ppalDIB)
1159 {
1160 bResult = FALSE;
1161 goto cleanup;
1162 }
1163
1164 /* Prepare DC for blit */
1165 DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
1166
1167 psurfDst = pdc->dclevel.pSurface;
1168 if (!psurfDst)
1169 {
1170 DC_vFinishBlit(pdc, NULL);
1171 // CHECKME
1172 bResult = TRUE;
1173 goto cleanup;
1174 }
1175
1176 /* Initialize XLATEOBJ */
1177 EXLATEOBJ_vInitialize(&exlo,
1178 ppalDIB,
1179 psurfDst->ppal,
1180 RGB(0xff, 0xff, 0xff),
1181 pdc->pdcattr->crBackgroundClr,
1182 pdc->pdcattr->crForegroundClr);
1183
1184 /* Perform the stretch operation */
1185 bResult = IntEngStretchBlt(&psurfDst->SurfObj,
1186 &psurfTmp->SurfObj,
1187 NULL,
1188 pdc->rosdc.CombinedClip,
1189 &exlo.xlo,
1190 &pdc->dclevel.ca,
1191 &rcDst,
1192 &rcSrc,
1193 NULL,
1194 &pdc->eboFill.BrushObject,
1195 NULL,
1196 ROP_TO_ROP4(dwRop));
1197
1198 /* Cleanup */
1199 DC_vFinishBlit(pdc, NULL);
1200 EXLATEOBJ_vCleanup(&exlo);
1201 cleanup:
1202 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
1203 if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
1204 if (hbmTmp) GreDeleteObject(hbmTmp);
1205 if (pdc) DC_UnlockDc(pdc);
1206 ExFreePoolWithTag(pvBits, 'pmeT');
1207
1208 return bResult;
1209 }
1210
1211
1212 HBITMAP
1213 FASTCALL
1214 IntCreateDIBitmap(
1215 PDC Dc,
1216 INT width,
1217 INT height,
1218 UINT bpp,
1219 DWORD init,
1220 LPBYTE bits,
1221 PBITMAPINFO data,
1222 DWORD coloruse)
1223 {
1224 HBITMAP handle;
1225 BOOL fColor;
1226
1227 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1228 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1229
1230 if (bpp != 1) fColor = TRUE;
1231 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1232 else
1233 {
1234 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1235 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1236
1237 // Check if the first color of the colormap is black
1238 if ((col == RGB(0, 0, 0)))
1239 {
1240 rgb++;
1241 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1242
1243 // If the second color is white, create a monochrome bitmap
1244 fColor = (col != RGB(0xff,0xff,0xff));
1245 }
1246 else fColor = TRUE;
1247 }
1248
1249 // Now create the bitmap
1250 if (fColor)
1251 {
1252 handle = IntCreateCompatibleBitmap(Dc, width, height);
1253 }
1254 else
1255 {
1256 handle = GreCreateBitmap(width,
1257 height,
1258 1,
1259 1,
1260 NULL);
1261 }
1262
1263 if (height < 0)
1264 height = -height;
1265
1266 if (NULL != handle && CBM_INIT == init)
1267 {
1268 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1269 }
1270
1271 return handle;
1272 }
1273
1274 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1275 // The DDB that is created will be whatever bit depth your reference DC is
1276 HBITMAP
1277 APIENTRY
1278 NtGdiCreateDIBitmapInternal(
1279 IN HDC hDc,
1280 IN INT cx,
1281 IN INT cy,
1282 IN DWORD fInit,
1283 IN OPTIONAL LPBYTE pjInit,
1284 IN OPTIONAL LPBITMAPINFO pbmi,
1285 IN DWORD iUsage,
1286 IN UINT cjMaxInitInfo,
1287 IN UINT cjMaxBits,
1288 IN FLONG fl,
1289 IN HANDLE hcmXform)
1290 {
1291 NTSTATUS Status = STATUS_SUCCESS;
1292 PBYTE safeBits = NULL;
1293 HBITMAP hbmResult = NULL;
1294
1295 if(pjInit && (fInit == CBM_INIT))
1296 {
1297 if (cjMaxBits == 0) return NULL;
1298 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1299 if(!safeBits)
1300 {
1301 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1302 return NULL;
1303 }
1304 }
1305
1306 _SEH2_TRY
1307 {
1308 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1309 if(pjInit && (fInit == CBM_INIT))
1310 {
1311 ProbeForRead(pjInit, cjMaxBits, 1);
1312 RtlCopyMemory(safeBits, pjInit, cjMaxBits);
1313 }
1314 }
1315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1316 {
1317 Status = _SEH2_GetExceptionCode();
1318 }
1319 _SEH2_END
1320
1321 if(!NT_SUCCESS(Status))
1322 {
1323 SetLastNtError(Status);
1324 goto cleanup;
1325 }
1326
1327 hbmResult = GreCreateDIBitmapInternal(hDc,
1328 cx,
1329 cy,
1330 fInit,
1331 safeBits,
1332 pbmi,
1333 iUsage,
1334 fl,
1335 cjMaxBits,
1336 hcmXform);
1337
1338 cleanup:
1339 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1340 return hbmResult;
1341 }
1342
1343 HBITMAP
1344 NTAPI
1345 GreCreateDIBitmapInternal(
1346 IN HDC hDc,
1347 IN INT cx,
1348 IN INT cy,
1349 IN DWORD fInit,
1350 IN OPTIONAL LPBYTE pjInit,
1351 IN OPTIONAL PBITMAPINFO pbmi,
1352 IN DWORD iUsage,
1353 IN FLONG fl,
1354 IN UINT cjMaxBits,
1355 IN HANDLE hcmXform)
1356 {
1357 PDC Dc;
1358 HBITMAP Bmp;
1359 WORD bpp;
1360 HDC hdcDest;
1361
1362 if (!hDc) /* 1bpp monochrome bitmap */
1363 {
1364 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1365 hdcDest = NtGdiCreateCompatibleDC(0);
1366 if(!hdcDest)
1367 {
1368 return NULL;
1369 }
1370 }
1371 else
1372 {
1373 hdcDest = hDc;
1374 }
1375
1376 Dc = DC_LockDc(hdcDest);
1377 if (!Dc)
1378 {
1379 EngSetLastError(ERROR_INVALID_HANDLE);
1380 return NULL;
1381 }
1382 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1383 * if bpp != 1 and ignore the real value that was passed */
1384 if (pbmi)
1385 bpp = pbmi->bmiHeader.biBitCount;
1386 else
1387 bpp = 0;
1388 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1389 DC_UnlockDc(Dc);
1390
1391 if(!hDc)
1392 {
1393 NtGdiDeleteObjectApp(hdcDest);
1394 }
1395 return Bmp;
1396 }
1397
1398
1399 HBITMAP
1400 APIENTRY
1401 NtGdiCreateDIBSection(
1402 IN HDC hDC,
1403 IN OPTIONAL HANDLE hSection,
1404 IN DWORD dwOffset,
1405 IN BITMAPINFO* bmi,
1406 IN DWORD Usage,
1407 IN UINT cjHeader,
1408 IN FLONG fl,
1409 IN ULONG_PTR dwColorSpace,
1410 OUT PVOID *Bits)
1411 {
1412 HBITMAP hbitmap = 0;
1413 DC *dc;
1414 BOOL bDesktopDC = FALSE;
1415 NTSTATUS Status = STATUS_SUCCESS;
1416
1417 if (!bmi) return hbitmap; // Make sure.
1418
1419 _SEH2_TRY
1420 {
1421 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1422 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1423 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
1424 }
1425 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1426 {
1427 Status = _SEH2_GetExceptionCode();
1428 }
1429 _SEH2_END
1430
1431 if(!NT_SUCCESS(Status))
1432 {
1433 SetLastNtError(Status);
1434 return NULL;
1435 }
1436
1437 // If the reference hdc is null, take the desktop dc
1438 if (hDC == 0)
1439 {
1440 hDC = NtGdiCreateCompatibleDC(0);
1441 bDesktopDC = TRUE;
1442 }
1443
1444 if ((dc = DC_LockDc(hDC)))
1445 {
1446 hbitmap = DIB_CreateDIBSection(dc,
1447 bmi,
1448 Usage,
1449 Bits,
1450 hSection,
1451 dwOffset,
1452 0);
1453 DC_UnlockDc(dc);
1454 }
1455 else
1456 {
1457 EngSetLastError(ERROR_INVALID_HANDLE);
1458 }
1459
1460 if (bDesktopDC)
1461 NtGdiDeleteObjectApp(hDC);
1462
1463 return hbitmap;
1464 }
1465
1466 HBITMAP
1467 APIENTRY
1468 DIB_CreateDIBSection(
1469 PDC dc,
1470 CONST BITMAPINFO *bmi,
1471 UINT usage,
1472 LPVOID *bits,
1473 HANDLE section,
1474 DWORD offset,
1475 DWORD ovr_pitch)
1476 {
1477 HBITMAP res = 0;
1478 SURFACE *bmp = NULL;
1479 void *mapBits = NULL;
1480 PPALETTE ppalDIB;
1481
1482 // Fill BITMAP32 structure with DIB data
1483 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1484 INT effHeight;
1485 ULONG totalSize;
1486 BITMAP bm;
1487 //SIZEL Size;
1488 HANDLE hSecure;
1489
1490 DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
1491 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1492 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1493
1494 /* CreateDIBSection should fail for compressed formats */
1495 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1496 {
1497 DPRINT1("no compressed format allowed\n");
1498 return (HBITMAP)NULL;
1499 }
1500
1501 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1502 bm.bmType = 0;
1503 bm.bmWidth = bi->biWidth;
1504 bm.bmHeight = effHeight;
1505 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1506
1507 bm.bmPlanes = bi->biPlanes;
1508 bm.bmBitsPixel = bi->biBitCount;
1509 bm.bmBits = NULL;
1510
1511 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1512 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1513 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1514 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1515
1516 if (section)
1517 {
1518 SYSTEM_BASIC_INFORMATION Sbi;
1519 NTSTATUS Status;
1520 DWORD mapOffset;
1521 LARGE_INTEGER SectionOffset;
1522 SIZE_T mapSize;
1523
1524 Status = ZwQuerySystemInformation(SystemBasicInformation,
1525 &Sbi,
1526 sizeof Sbi,
1527 0);
1528 if (!NT_SUCCESS(Status))
1529 {
1530 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
1531 return NULL;
1532 }
1533
1534 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1535 mapSize = bi->biSizeImage + (offset - mapOffset);
1536
1537 SectionOffset.LowPart = mapOffset;
1538 SectionOffset.HighPart = 0;
1539
1540 Status = ZwMapViewOfSection(section,
1541 NtCurrentProcess(),
1542 &mapBits,
1543 0,
1544 0,
1545 &SectionOffset,
1546 &mapSize,
1547 ViewShare,
1548 0,
1549 PAGE_READWRITE);
1550 if (!NT_SUCCESS(Status))
1551 {
1552 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
1553 EngSetLastError(ERROR_INVALID_PARAMETER);
1554 return NULL;
1555 }
1556
1557 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1558 }
1559 else if (ovr_pitch && offset)
1560 bm.bmBits = (LPVOID) offset;
1561 else
1562 {
1563 offset = 0;
1564 bm.bmBits = EngAllocUserMem(totalSize, 0);
1565 if(!bm.bmBits)
1566 {
1567 DPRINT1("Failed to allocate memory\n");
1568 goto cleanup;
1569 }
1570 }
1571
1572 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1573 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1574
1575
1576 // Create Device Dependent Bitmap and add DIB pointer
1577 //Size.cx = bm.bmWidth;
1578 //Size.cy = abs(bm.bmHeight);
1579 res = GreCreateBitmapEx(bm.bmWidth,
1580 abs(bm.bmHeight),
1581 bm.bmWidthBytes,
1582 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1583 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1584 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
1585 bi->biSizeImage,
1586 bm.bmBits,
1587 0);
1588 if (!res)
1589 {
1590 DPRINT1("GreCreateBitmapEx failed\n");
1591 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1592 goto cleanup;
1593 }
1594 bmp = SURFACE_ShareLockSurface(res); // HACK
1595 if (NULL == bmp)
1596 {
1597 DPRINT1("SURFACE_LockSurface failed\n");
1598 EngSetLastError(ERROR_INVALID_HANDLE);
1599 goto cleanup;
1600 }
1601
1602 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1603 table between the DIB and the X physical device. Obviously,
1604 this is left out of the ReactOS implementation. Instead,
1605 we call NtGdiSetDIBColorTable. */
1606 bmp->hDIBSection = section;
1607 bmp->hSecure = hSecure;
1608 bmp->dwOffset = offset;
1609 bmp->flags = API_BITMAP;
1610 bmp->biClrImportant = bi->biClrImportant;
1611
1612 /* Create a palette for the DIB */
1613 ppalDIB = CreateDIBPalette(bmi, dc, usage);
1614 if (ppalDIB)
1615 {
1616 SURFACE_vSetPalette(bmp, ppalDIB);
1617 PALETTE_ShareUnlockPalette(ppalDIB);
1618 }
1619
1620 // Clean up in case of errors
1621 cleanup:
1622 if (!res || !bmp || !bm.bmBits)
1623 {
1624 DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1625 if (bm.bmBits)
1626 {
1627 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1628 if (section)
1629 {
1630 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1631 bm.bmBits = NULL;
1632 }
1633 else if (!offset)
1634 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1635 }
1636
1637 if (bmp)
1638 bmp = NULL;
1639
1640 if (res)
1641 {
1642 GreDeleteObject(res);
1643 res = 0;
1644 }
1645 }
1646
1647 if (bmp)
1648 {
1649 SURFACE_ShareUnlockSurface(bmp);
1650 }
1651
1652 // Return BITMAP handle and storage location
1653 if (NULL != bm.bmBits && NULL != bits)
1654 {
1655 *bits = bm.bmBits;
1656 }
1657
1658 return res;
1659 }
1660
1661 /***********************************************************************
1662 * DIB_GetBitmapInfo
1663 *
1664 * Get the info from a bitmap header.
1665 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1666 */
1667 int
1668 FASTCALL
1669 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1670 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1671 {
1672 if (header->biSize == sizeof(BITMAPCOREHEADER))
1673 {
1674 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1675 *width = core->bcWidth;
1676 *height = core->bcHeight;
1677 *planes = core->bcPlanes;
1678 *bpp = core->bcBitCount;
1679 *compr = BI_RGB;
1680 *size = 0;
1681 return 0;
1682 }
1683 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
1684 {
1685 *width = header->biWidth;
1686 *height = header->biHeight;
1687 *planes = header->biPlanes;
1688 *bpp = header->biBitCount;
1689 *compr = header->biCompression;
1690 *size = header->biSizeImage;
1691 return 1;
1692 }
1693 DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
1694 return -1;
1695 }
1696
1697 /***********************************************************************
1698 * DIB_GetDIBImageBytes
1699 *
1700 * Return the number of bytes used to hold the image in a DIB bitmap.
1701 * 11/16/1999 (RJJ) lifted from wine
1702 */
1703
1704 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1705 {
1706 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1707 }
1708
1709 /***********************************************************************
1710 * DIB_BitmapInfoSize
1711 *
1712 * Return the size of the bitmap info structure including color table.
1713 * 11/16/1999 (RJJ) lifted from wine
1714 */
1715
1716 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1717 {
1718 unsigned int colors, size, masks = 0;
1719
1720 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1721 {
1722 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1723 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1724 return sizeof(BITMAPCOREHEADER) + colors *
1725 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1726 }
1727 else /* Assume BITMAPINFOHEADER */
1728 {
1729 colors = info->bmiHeader.biClrUsed;
1730 if (colors > 256) colors = 256;
1731 if (!colors && (info->bmiHeader.biBitCount <= 8))
1732 colors = 1 << info->bmiHeader.biBitCount;
1733 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1734 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1735 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1736 }
1737 }
1738
1739 HPALETTE
1740 FASTCALL
1741 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
1742 {
1743 PPALETTE ppalNew;
1744 ULONG nNumColors,i;
1745 USHORT *lpIndex;
1746 HPALETTE hpal;
1747
1748 if (!(ppalDc->flFlags & PAL_INDEXED))
1749 {
1750 return NULL;
1751 }
1752
1753 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1754 if (lpbmi->bmiHeader.biClrUsed)
1755 {
1756 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1757 }
1758
1759 ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
1760 if (ppalNew == NULL)
1761 {
1762 DPRINT1("Could not allocate palette\n");
1763 return NULL;
1764 }
1765
1766 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1767
1768 for (i = 0; i < nNumColors; i++)
1769 {
1770 ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
1771 ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
1772 lpIndex++;
1773 }
1774
1775 hpal = ppalNew->BaseObject.hHmgr;
1776 PALETTE_UnlockPalette(ppalNew);
1777
1778 return hpal;
1779 }
1780
1781 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1782 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1783 BITMAPINFO*
1784 FASTCALL
1785 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1786 {
1787 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1788 BITMAPINFO* pNewBmi ;
1789 UINT numColors = 0, ColorsSize = 0;
1790
1791 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1792 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1793
1794 if(pbmci->bmciHeader.bcBitCount <= 8)
1795 {
1796 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1797 if(Usage == DIB_PAL_COLORS)
1798 {
1799 ColorsSize = numColors * sizeof(WORD);
1800 }
1801 else
1802 {
1803 ColorsSize = numColors * sizeof(RGBQUAD);
1804 }
1805 }
1806 else if (Usage == DIB_PAL_COLORS)
1807 {
1808 /* Invalid at high-res */
1809 return NULL;
1810 }
1811
1812 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1813 if(!pNewBmi) return NULL;
1814
1815 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1816
1817 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1818 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1819 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1820 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1821 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1822 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1823 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1824 pNewBmi->bmiHeader.biHeight,
1825 pNewBmi->bmiHeader.biBitCount);
1826
1827 if(Usage == DIB_PAL_COLORS)
1828 {
1829 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1830 }
1831 else
1832 {
1833 UINT i;
1834 for(i=0; i<numColors; i++)
1835 {
1836 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1837 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1838 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1839 }
1840 }
1841
1842 return pNewBmi ;
1843 }
1844
1845 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
1846 VOID
1847 FASTCALL
1848 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
1849 {
1850 if(converted != orig)
1851 ExFreePoolWithTag(converted, TAG_DIB);
1852 }
1853
1854 /* EOF */