[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 Exit2;
449 }
450
451 pSurf = pDC->dclevel.pSurface;
452 if (!pSurf)
453 {
454 DC_UnlockDc(pDC);
455 ret = ScanLines;
456 goto Exit2;
457 }
458
459 pDestSurf = &pSurf->SurfObj;
460
461 rcDest.left = XDest;
462 rcDest.top = YDest;
463 if (bTransformCoordinates)
464 {
465 IntLPtoDP(pDC, (LPPOINT)&rcDest, 2);
466 }
467 rcDest.left += pDC->ptlDCOrig.x;
468 rcDest.top += pDC->ptlDCOrig.y;
469 rcDest.right = rcDest.left + Width;
470 rcDest.bottom = rcDest.top + Height;
471 rcDest.top += StartScan;
472
473 ptSource.x = XSrc;
474 ptSource.y = YSrc;
475
476 SourceSize.cx = bmi->bmiHeader.biWidth;
477 SourceSize.cy = ScanLines;
478
479 //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
480
481 hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
482 ScanLines,
483 0,
484 BitmapFormat(bmi->bmiHeader.biBitCount,
485 bmi->bmiHeader.biCompression),
486 bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
487 bmi->bmiHeader.biSizeImage,
488 Bits,
489 0);
490
491 if (!hSourceBitmap)
492 {
493 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
494 Status = STATUS_NO_MEMORY;
495 goto Exit;
496 }
497
498 pSourceSurf = EngLockSurface((HSURF)hSourceBitmap);
499 if (!pSourceSurf)
500 {
501 Status = STATUS_UNSUCCESSFUL;
502 goto Exit;
503 }
504
505 ASSERT(pSurf->ppal);
506
507 /* Create a palette for the DIB */
508 ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
509 if (!ppalDIB)
510 {
511 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
512 Status = STATUS_NO_MEMORY;
513 goto Exit;
514 }
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 /* Copy the bits */
525 DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
526 rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
527 ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
528 Status = IntEngBitBlt(pDestSurf,
529 pSourceSurf,
530 NULL,
531 pDC->rosdc.CombinedClip,
532 &exlo.xlo,
533 &rcDest,
534 &ptSource,
535 NULL,
536 NULL,
537 NULL,
538 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
539
540 /* Cleanup EXLATEOBJ */
541 EXLATEOBJ_vCleanup(&exlo);
542
543 Exit:
544 if (NT_SUCCESS(Status))
545 {
546 ret = ScanLines;
547 }
548
549 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
550
551 if (pSourceSurf) EngUnlockSurface(pSourceSurf);
552 if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
553 DC_UnlockDc(pDC);
554 Exit2:
555 ExFreePool(pbmiSafe);
556 return ret;
557 }
558
559
560 /* Converts a device-dependent bitmap to a DIB */
561 INT
562 APIENTRY
563 NtGdiGetDIBitsInternal(
564 HDC hDC,
565 HBITMAP hBitmap,
566 UINT StartScan,
567 UINT ScanLines,
568 LPBYTE Bits,
569 LPBITMAPINFO Info,
570 UINT Usage,
571 UINT MaxBits,
572 UINT MaxInfo)
573 {
574 BITMAPCOREINFO* pbmci = NULL;
575 PSURFACE psurf = NULL;
576 PDC pDC;
577 LONG width, height;
578 WORD planes, bpp;
579 DWORD compr, size ;
580 USHORT i;
581 int bitmap_type;
582 RGBTRIPLE* rgbTriples;
583 RGBQUAD* rgbQuads;
584 VOID* colorPtr;
585 NTSTATUS Status = STATUS_SUCCESS;
586
587 DPRINT("Entered NtGdiGetDIBitsInternal()\n");
588
589 if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
590 return 0;
591
592 _SEH2_TRY
593 {
594 /* Probe for read and write */
595 ProbeForRead(Info, MaxInfo, 1);
596 ProbeForWrite(Info, MaxInfo, 1);
597 if (Bits) ProbeForWrite(Bits, MaxBits, 1);
598 }
599 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
600 {
601 Status = _SEH2_GetExceptionCode();
602 }
603 _SEH2_END
604
605 if (!NT_SUCCESS(Status))
606 {
607 return 0;
608 }
609
610 colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
611 rgbTriples = colorPtr;
612 rgbQuads = colorPtr;
613
614 bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
615 &width,
616 &height,
617 &planes,
618 &bpp,
619 &compr,
620 &size);
621 if(bitmap_type == -1)
622 {
623 DPRINT("Wrong bitmap format\n");
624 EngSetLastError(ERROR_INVALID_PARAMETER);
625 return 0;
626 }
627 else if(bitmap_type == 0)
628 {
629 /* We need a BITMAPINFO to create a DIB, but we have to fill
630 * the BITMAPCOREINFO we're provided */
631 pbmci = (BITMAPCOREINFO*)Info;
632 Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
633 if(Info == NULL)
634 {
635 DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
636 return 0;
637 }
638 rgbQuads = Info->bmiColors;
639 }
640
641 pDC = DC_LockDc(hDC);
642 if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
643 {
644 ScanLines = 0;
645 goto done;
646 }
647
648 /* Get a pointer to the source bitmap object */
649 psurf = SURFACE_ShareLockSurface(hBitmap);
650 if (psurf == NULL)
651 {
652 ScanLines = 0;
653 goto done;
654 }
655
656 /* Fill in the structure */
657 switch(bpp)
658 {
659 case 0: /* Only info */
660 if(pbmci)
661 {
662 pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx;
663 pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
664 -psurf->SurfObj.sizlBitmap.cy :
665 psurf->SurfObj.sizlBitmap.cy);
666 pbmci->bmciHeader.bcPlanes = 1;
667 pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
668 }
669 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
670 Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
671 -psurf->SurfObj.sizlBitmap.cy :
672 psurf->SurfObj.sizlBitmap.cy;;
673 Info->bmiHeader.biPlanes = 1;
674 Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
675 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
676 Info->bmiHeader.biHeight,
677 Info->bmiHeader.biBitCount);
678 if(psurf->hSecure)
679 {
680 switch(Info->bmiHeader.biBitCount)
681 {
682 case 16:
683 case 32:
684 Info->bmiHeader.biCompression = BI_BITFIELDS;
685 break;
686 default:
687 Info->bmiHeader.biCompression = BI_RGB;
688 break;
689 }
690 }
691 else if(Info->bmiHeader.biBitCount > 8)
692 {
693 Info->bmiHeader.biCompression = BI_BITFIELDS;
694 }
695 else
696 {
697 Info->bmiHeader.biCompression = BI_RGB;
698 }
699 Info->bmiHeader.biXPelsPerMeter = 0;
700 Info->bmiHeader.biYPelsPerMeter = 0;
701 Info->bmiHeader.biClrUsed = 0;
702 Info->bmiHeader.biClrImportant = 0;
703 ScanLines = abs(Info->bmiHeader.biHeight);
704 goto done;
705
706 case 1:
707 case 4:
708 case 8:
709 Info->bmiHeader.biClrUsed = 0;
710
711 /* If the bitmap if a DIB section and has the same format than what
712 * we're asked, go ahead! */
713 if((psurf->hSecure) &&
714 (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
715 {
716 if(Usage == DIB_RGB_COLORS)
717 {
718 ULONG colors = min(psurf->ppal->NumColors, 256);
719
720 if(pbmci)
721 {
722 for(i = 0; i < colors; i++)
723 {
724 rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
725 rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
726 rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
727 }
728 }
729 if(colors != 256) Info->bmiHeader.biClrUsed = colors;
730 for(i = 0; i < colors; i++)
731 {
732 rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
733 rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
734 rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
735 }
736 }
737 else
738 {
739 for(i = 0; i < 256; i++)
740 {
741 if(pbmci) ((WORD*)rgbTriples)[i] = i;
742 ((WORD*)rgbQuads)[i] = i;
743 }
744 }
745 }
746 else
747 {
748 if(Usage == DIB_PAL_COLORS)
749 {
750 for(i = 0; i < 256; i++)
751 {
752 if(pbmci) ((WORD*)rgbTriples)[i] = i;
753 ((WORD*)rgbQuads)[i] = i;
754 }
755 }
756 else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat))
757 {
758 /* For color DDBs in native depth (mono DDBs always have
759 a black/white palette):
760 Generate the color map from the selected palette */
761 PPALETTE pDcPal = PALETTE_ShareLockPalette(pDC->dclevel.hpal);
762 if(!pDcPal)
763 {
764 ScanLines = 0 ;
765 goto done ;
766 }
767 for (i = 0; i < pDcPal->NumColors; i++)
768 {
769 if (pbmci)
770 {
771 rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed;
772 rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
773 rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue;
774 }
775
776 rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
777 rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
778 rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
779 rgbQuads[i].rgbReserved = 0;
780 }
781 PALETTE_ShareUnlockPalette(pDcPal);
782 }
783 else
784 {
785 switch (bpp)
786 {
787 case 1:
788 if (pbmci)
789 {
790 rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
791 rgbTriples[0].rgbtBlue = 0;
792 rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
793 rgbTriples[1].rgbtBlue = 0xff;
794 }
795 rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
796 rgbQuads[0].rgbBlue = 0;
797 rgbQuads[0].rgbReserved = 0;
798 rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
799 rgbQuads[1].rgbBlue = 0xff;
800 rgbQuads[1].rgbReserved = 0;
801 break;
802
803 case 4:
804 if (pbmci)
805 RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
806 RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
807
808 break;
809
810 case 8:
811 {
812 INT r, g, b;
813 RGBQUAD *color;
814 if (pbmci)
815 {
816 RGBTRIPLE *colorTriple;
817
818 RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
819 10 * sizeof(RGBTRIPLE));
820 RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
821 10 * sizeof(RGBTRIPLE));
822 colorTriple = rgbTriples + 10;
823 for(r = 0; r <= 5; r++) /* FIXME */
824 {
825 for(g = 0; g <= 5; g++)
826 {
827 for(b = 0; b <= 5; b++)
828 {
829 colorTriple->rgbtRed = (r * 0xff) / 5;
830 colorTriple->rgbtGreen = (g * 0xff) / 5;
831 colorTriple->rgbtBlue = (b * 0xff) / 5;
832 color++;
833 }
834 }
835 }
836 }
837 memcpy(rgbQuads, DefLogPaletteQuads,
838 10 * sizeof(RGBQUAD));
839 memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
840 10 * sizeof(RGBQUAD));
841 color = rgbQuads + 10;
842 for(r = 0; r <= 5; r++) /* FIXME */
843 {
844 for(g = 0; g <= 5; g++)
845 {
846 for(b = 0; b <= 5; b++)
847 {
848 color->rgbRed = (r * 0xff) / 5;
849 color->rgbGreen = (g * 0xff) / 5;
850 color->rgbBlue = (b * 0xff) / 5;
851 color->rgbReserved = 0;
852 color++;
853 }
854 }
855 }
856 }
857 }
858 }
859 }
860 break;
861
862 case 15:
863 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
864 {
865 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
866 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
867 ((PDWORD)Info->bmiColors)[2] = 0x001f;
868 }
869 break;
870
871 case 16:
872 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
873 {
874 if (psurf->hSecure)
875 {
876 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
877 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
878 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
879 }
880 else
881 {
882 ((PDWORD)Info->bmiColors)[0] = 0xf800;
883 ((PDWORD)Info->bmiColors)[1] = 0x07e0;
884 ((PDWORD)Info->bmiColors)[2] = 0x001f;
885 }
886 }
887 break;
888
889 case 24:
890 case 32:
891 if (Info->bmiHeader.biCompression == BI_BITFIELDS)
892 {
893 if (psurf->hSecure)
894 {
895 ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
896 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
897 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
898 }
899 else
900 {
901 ((PDWORD)Info->bmiColors)[0] = 0xff0000;
902 ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
903 ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
904 }
905 }
906 break;
907 }
908 Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
909
910 if(Bits && ScanLines)
911 {
912 /* Create a DIBSECTION, blt it, profit */
913 PVOID pDIBits ;
914 HBITMAP hBmpDest;
915 PSURFACE psurfDest;
916 EXLATEOBJ exlo;
917 RECT rcDest;
918 POINTL srcPoint;
919 BOOL ret ;
920
921 if (StartScan > (ULONG)psurf->SurfObj.sizlBitmap.cy)
922 {
923 ScanLines = 0;
924 goto done;
925 }
926 else
927 {
928 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
929 }
930
931 /* Fixup values */
932 Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
933 Info->bmiHeader.biHeight = (height < 0) ?
934 -(LONG)ScanLines : ScanLines;
935 /* Create the DIB */
936 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
937 /* Restore them */
938 Info->bmiHeader.biWidth = width;
939 Info->bmiHeader.biHeight = height;
940
941 if(!hBmpDest)
942 {
943 DPRINT1("Unable to create a DIB Section!\n");
944 EngSetLastError(ERROR_INVALID_PARAMETER);
945 ScanLines = 0;
946 goto done ;
947 }
948
949 psurfDest = SURFACE_ShareLockSurface(hBmpDest);
950
951 rcDest.left = 0;
952 rcDest.top = 0;
953 rcDest.bottom = ScanLines;
954 rcDest.right = psurf->SurfObj.sizlBitmap.cx;
955
956 srcPoint.x = 0;
957
958 if(height < 0)
959 {
960 srcPoint.y = 0;
961
962 if(ScanLines <= StartScan)
963 {
964 ScanLines = 1;
965 SURFACE_ShareUnlockSurface(psurfDest);
966 GreDeleteObject(hBmpDest);
967 goto done;
968 }
969
970 ScanLines -= StartScan;
971 }
972 else
973 {
974 srcPoint.y = StartScan;
975 }
976
977 EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xffffff, 0xffffff, 0);
978
979 ret = IntEngCopyBits(&psurfDest->SurfObj,
980 &psurf->SurfObj,
981 NULL,
982 &exlo.xlo,
983 &rcDest,
984 &srcPoint);
985
986 SURFACE_ShareUnlockSurface(psurfDest);
987
988 if(!ret)
989 ScanLines = 0;
990 else
991 {
992 Status = STATUS_SUCCESS;
993 _SEH2_TRY
994 {
995 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
996 }
997 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
998 {
999 Status = _SEH2_GetExceptionCode();
1000 }
1001 _SEH2_END
1002
1003 if(!NT_SUCCESS(Status))
1004 {
1005 DPRINT1("Unable to copy bits to the user provided pointer\n");
1006 ScanLines = 0;
1007 }
1008 }
1009
1010 GreDeleteObject(hBmpDest);
1011 EXLATEOBJ_vCleanup(&exlo);
1012 }
1013 else ScanLines = abs(height);
1014
1015 done:
1016
1017 if(pDC) DC_UnlockDc(pDC);
1018 if(psurf) SURFACE_ShareUnlockSurface(psurf);
1019 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
1020
1021 return ScanLines;
1022 }
1023
1024 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
1025
1026 W32KAPI
1027 INT
1028 APIENTRY
1029 NtGdiStretchDIBitsInternal(
1030 IN HDC hdc,
1031 IN INT xDst,
1032 IN INT yDst,
1033 IN INT cxDst,
1034 IN INT cyDst,
1035 IN INT xSrc,
1036 IN INT ySrc,
1037 IN INT cxSrc,
1038 IN INT cySrc,
1039 IN OPTIONAL LPBYTE pjInit,
1040 IN LPBITMAPINFO pbmi,
1041 IN DWORD dwUsage,
1042 IN DWORD dwRop, // MS ntgdi.h says dwRop4(?)
1043 IN UINT cjMaxInfo,
1044 IN UINT cjMaxBits,
1045 IN HANDLE hcmXform)
1046 {
1047 BOOL bResult = FALSE;
1048 SIZEL sizel;
1049 RECTL rcSrc, rcDst;
1050 PDC pdc;
1051 HBITMAP hbmTmp = 0;
1052 PSURFACE psurfTmp = 0, psurfDst = 0;
1053 PPALETTE ppalDIB = 0;
1054 EXLATEOBJ exlo;
1055 PVOID pvBits;
1056
1057 if (!(pdc = DC_LockDc(hdc)))
1058 {
1059 EngSetLastError(ERROR_INVALID_HANDLE);
1060 return 0;
1061 }
1062
1063 /* Transform dest size */
1064 sizel.cx = cxDst;
1065 sizel.cy = cyDst;
1066 IntLPtoDP(pdc, (POINTL*)&sizel, 1);
1067 DC_UnlockDc(pdc);
1068
1069 /* Check if we can use NtGdiSetDIBitsToDeviceInternal */
1070 if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
1071 {
1072 /* Yes, we can! */
1073 return NtGdiSetDIBitsToDeviceInternal(hdc,
1074 xDst,
1075 yDst,
1076 cxDst,
1077 cyDst,
1078 xSrc,
1079 ySrc,
1080 0,
1081 cySrc,
1082 pjInit,
1083 pbmi,
1084 dwUsage,
1085 cjMaxBits,
1086 cjMaxInfo,
1087 TRUE,
1088 hcmXform);
1089 }
1090
1091 pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
1092 if (!pvBits)
1093 {
1094 return 0;
1095 }
1096
1097 _SEH2_TRY
1098 {
1099 ProbeForRead(pjInit, cjMaxBits, 1);
1100 RtlCopyMemory(pvBits, pjInit, cjMaxBits);
1101 }
1102 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1103 {
1104 _SEH2_YIELD(return 0);
1105 }
1106 _SEH2_END
1107
1108 /* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
1109 if (!(pdc = DC_LockDc(hdc)))
1110 {
1111 DPRINT1("Could not lock dc\n");
1112 EngSetLastError(ERROR_INVALID_HANDLE);
1113 goto cleanup;
1114 }
1115
1116 psurfDst = pdc->dclevel.pSurface;
1117 if (!psurfDst)
1118 {
1119 // CHECKME
1120 bResult = TRUE;
1121 goto cleanup;
1122 }
1123
1124 /* Calculate source and destination rect */
1125 rcSrc.left = xSrc;
1126 rcSrc.top = ySrc;
1127 rcSrc.right = xSrc + abs(cxSrc);
1128 rcSrc.bottom = ySrc + abs(cySrc);
1129 rcDst.left = xDst;
1130 rcDst.top = yDst;
1131 rcDst.right = rcDst.left + cxDst;
1132 rcDst.bottom = rcDst.top + cyDst;
1133 IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
1134 RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
1135
1136 hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
1137 pbmi->bmiHeader.biHeight,
1138 0,
1139 BitmapFormat(pbmi->bmiHeader.biBitCount,
1140 pbmi->bmiHeader.biCompression),
1141 pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
1142 pbmi->bmiHeader.biSizeImage,
1143 pvBits,
1144 0);
1145
1146 if (!hbmTmp)
1147 {
1148 bResult = FALSE;
1149 goto cleanup;
1150 }
1151
1152 psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
1153 if (!psurfTmp)
1154 {
1155 bResult = FALSE;
1156 goto cleanup;
1157 }
1158
1159 /* Create a palette for the DIB */
1160 ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
1161 if (!ppalDIB)
1162 {
1163 bResult = FALSE;
1164 goto cleanup;
1165 }
1166
1167 /* Initialize XLATEOBJ */
1168 EXLATEOBJ_vInitialize(&exlo,
1169 ppalDIB,
1170 psurfDst->ppal,
1171 RGB(0xff, 0xff, 0xff),
1172 pdc->pdcattr->crBackgroundClr,
1173 pdc->pdcattr->crForegroundClr);
1174
1175 /* Prepare DC for blit */
1176 DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
1177
1178 /* Perform the stretch operation */
1179 bResult = IntEngStretchBlt(&psurfDst->SurfObj,
1180 &psurfTmp->SurfObj,
1181 NULL,
1182 pdc->rosdc.CombinedClip,
1183 &exlo.xlo,
1184 &pdc->dclevel.ca,
1185 &rcDst,
1186 &rcSrc,
1187 NULL,
1188 &pdc->eboFill.BrushObject,
1189 NULL,
1190 ROP_TO_ROP4(dwRop));
1191
1192 /* Cleanup */
1193 DC_vFinishBlit(pdc, NULL);
1194 EXLATEOBJ_vCleanup(&exlo);
1195 cleanup:
1196 if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
1197 if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
1198 if (hbmTmp) GreDeleteObject(hbmTmp);
1199 if (pdc) DC_UnlockDc(pdc);
1200 ExFreePoolWithTag(pvBits, 'pmeT');
1201
1202 return bResult;
1203 }
1204
1205
1206 HBITMAP
1207 FASTCALL
1208 IntCreateDIBitmap(
1209 PDC Dc,
1210 INT width,
1211 INT height,
1212 UINT bpp,
1213 DWORD init,
1214 LPBYTE bits,
1215 PBITMAPINFO data,
1216 DWORD coloruse)
1217 {
1218 HBITMAP handle;
1219 BOOL fColor;
1220
1221 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1222 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1223
1224 if (bpp != 1) fColor = TRUE;
1225 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1226 else
1227 {
1228 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1229 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1230
1231 // Check if the first color of the colormap is black
1232 if ((col == RGB(0, 0, 0)))
1233 {
1234 rgb++;
1235 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1236
1237 // If the second color is white, create a monochrome bitmap
1238 fColor = (col != RGB(0xff,0xff,0xff));
1239 }
1240 else fColor = TRUE;
1241 }
1242
1243 // Now create the bitmap
1244 if (fColor)
1245 {
1246 handle = IntCreateCompatibleBitmap(Dc, width, height);
1247 }
1248 else
1249 {
1250 handle = GreCreateBitmap(width,
1251 height,
1252 1,
1253 1,
1254 NULL);
1255 }
1256
1257 if (height < 0)
1258 height = -height;
1259
1260 if (NULL != handle && CBM_INIT == init)
1261 {
1262 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1263 }
1264
1265 return handle;
1266 }
1267
1268 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1269 // The DDB that is created will be whatever bit depth your reference DC is
1270 HBITMAP
1271 APIENTRY
1272 NtGdiCreateDIBitmapInternal(
1273 IN HDC hDc,
1274 IN INT cx,
1275 IN INT cy,
1276 IN DWORD fInit,
1277 IN OPTIONAL LPBYTE pjInit,
1278 IN OPTIONAL LPBITMAPINFO pbmi,
1279 IN DWORD iUsage,
1280 IN UINT cjMaxInitInfo,
1281 IN UINT cjMaxBits,
1282 IN FLONG fl,
1283 IN HANDLE hcmXform)
1284 {
1285 NTSTATUS Status = STATUS_SUCCESS;
1286 PBYTE safeBits = NULL;
1287 HBITMAP hbmResult = NULL;
1288
1289 if(pjInit && (fInit == CBM_INIT))
1290 {
1291 if (cjMaxBits == 0) return NULL;
1292 safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
1293 if(!safeBits)
1294 {
1295 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1296 return NULL;
1297 }
1298 }
1299
1300 _SEH2_TRY
1301 {
1302 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1303 if(pjInit && (fInit == CBM_INIT))
1304 {
1305 ProbeForRead(pjInit, cjMaxBits, 1);
1306 RtlCopyMemory(safeBits, pjInit, cjMaxBits);
1307 }
1308 }
1309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1310 {
1311 Status = _SEH2_GetExceptionCode();
1312 }
1313 _SEH2_END
1314
1315 if(!NT_SUCCESS(Status))
1316 {
1317 SetLastNtError(Status);
1318 goto cleanup;
1319 }
1320
1321 hbmResult = GreCreateDIBitmapInternal(hDc,
1322 cx,
1323 cy,
1324 fInit,
1325 safeBits,
1326 pbmi,
1327 iUsage,
1328 fl,
1329 cjMaxBits,
1330 hcmXform);
1331
1332 cleanup:
1333 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1334 return hbmResult;
1335 }
1336
1337 HBITMAP
1338 NTAPI
1339 GreCreateDIBitmapInternal(
1340 IN HDC hDc,
1341 IN INT cx,
1342 IN INT cy,
1343 IN DWORD fInit,
1344 IN OPTIONAL LPBYTE pjInit,
1345 IN OPTIONAL PBITMAPINFO pbmi,
1346 IN DWORD iUsage,
1347 IN FLONG fl,
1348 IN UINT cjMaxBits,
1349 IN HANDLE hcmXform)
1350 {
1351 PDC Dc;
1352 HBITMAP Bmp;
1353 WORD bpp;
1354 HDC hdcDest;
1355
1356 if (!hDc) /* 1bpp monochrome bitmap */
1357 {
1358 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1359 hdcDest = NtGdiCreateCompatibleDC(0);
1360 if(!hdcDest)
1361 {
1362 return NULL;
1363 }
1364 }
1365 else
1366 {
1367 hdcDest = hDc;
1368 }
1369
1370 Dc = DC_LockDc(hdcDest);
1371 if (!Dc)
1372 {
1373 EngSetLastError(ERROR_INVALID_HANDLE);
1374 return NULL;
1375 }
1376 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1377 * if bpp != 1 and ignore the real value that was passed */
1378 if (pbmi)
1379 bpp = pbmi->bmiHeader.biBitCount;
1380 else
1381 bpp = 0;
1382 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1383 DC_UnlockDc(Dc);
1384
1385 if(!hDc)
1386 {
1387 NtGdiDeleteObjectApp(hdcDest);
1388 }
1389 return Bmp;
1390 }
1391
1392
1393 HBITMAP
1394 APIENTRY
1395 NtGdiCreateDIBSection(
1396 IN HDC hDC,
1397 IN OPTIONAL HANDLE hSection,
1398 IN DWORD dwOffset,
1399 IN BITMAPINFO* bmi,
1400 IN DWORD Usage,
1401 IN UINT cjHeader,
1402 IN FLONG fl,
1403 IN ULONG_PTR dwColorSpace,
1404 OUT PVOID *Bits)
1405 {
1406 HBITMAP hbitmap = 0;
1407 DC *dc;
1408 BOOL bDesktopDC = FALSE;
1409 NTSTATUS Status = STATUS_SUCCESS;
1410
1411 if (!bmi) return hbitmap; // Make sure.
1412
1413 _SEH2_TRY
1414 {
1415 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1416 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1417 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
1418 }
1419 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1420 {
1421 Status = _SEH2_GetExceptionCode();
1422 }
1423 _SEH2_END
1424
1425 if(!NT_SUCCESS(Status))
1426 {
1427 SetLastNtError(Status);
1428 return NULL;
1429 }
1430
1431 // If the reference hdc is null, take the desktop dc
1432 if (hDC == 0)
1433 {
1434 hDC = NtGdiCreateCompatibleDC(0);
1435 bDesktopDC = TRUE;
1436 }
1437
1438 if ((dc = DC_LockDc(hDC)))
1439 {
1440 hbitmap = DIB_CreateDIBSection(dc,
1441 bmi,
1442 Usage,
1443 Bits,
1444 hSection,
1445 dwOffset,
1446 0);
1447 DC_UnlockDc(dc);
1448 }
1449 else
1450 {
1451 EngSetLastError(ERROR_INVALID_HANDLE);
1452 }
1453
1454 if (bDesktopDC)
1455 NtGdiDeleteObjectApp(hDC);
1456
1457 return hbitmap;
1458 }
1459
1460 HBITMAP
1461 APIENTRY
1462 DIB_CreateDIBSection(
1463 PDC dc,
1464 CONST BITMAPINFO *bmi,
1465 UINT usage,
1466 LPVOID *bits,
1467 HANDLE section,
1468 DWORD offset,
1469 DWORD ovr_pitch)
1470 {
1471 HBITMAP res = 0;
1472 SURFACE *bmp = NULL;
1473 void *mapBits = NULL;
1474 PPALETTE ppalDIB;
1475
1476 // Fill BITMAP32 structure with DIB data
1477 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1478 INT effHeight;
1479 ULONG totalSize;
1480 BITMAP bm;
1481 //SIZEL Size;
1482 HANDLE hSecure;
1483
1484 DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
1485 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1486 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1487
1488 /* CreateDIBSection should fail for compressed formats */
1489 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1490 {
1491 DPRINT1("no compressed format allowed\n");
1492 return (HBITMAP)NULL;
1493 }
1494
1495 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1496 bm.bmType = 0;
1497 bm.bmWidth = bi->biWidth;
1498 bm.bmHeight = effHeight;
1499 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1500
1501 bm.bmPlanes = bi->biPlanes;
1502 bm.bmBitsPixel = bi->biBitCount;
1503 bm.bmBits = NULL;
1504
1505 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1506 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1507 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1508 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1509
1510 if (section)
1511 {
1512 SYSTEM_BASIC_INFORMATION Sbi;
1513 NTSTATUS Status;
1514 DWORD mapOffset;
1515 LARGE_INTEGER SectionOffset;
1516 SIZE_T mapSize;
1517
1518 Status = ZwQuerySystemInformation(SystemBasicInformation,
1519 &Sbi,
1520 sizeof Sbi,
1521 0);
1522 if (!NT_SUCCESS(Status))
1523 {
1524 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
1525 return NULL;
1526 }
1527
1528 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1529 mapSize = bi->biSizeImage + (offset - mapOffset);
1530
1531 SectionOffset.LowPart = mapOffset;
1532 SectionOffset.HighPart = 0;
1533
1534 Status = ZwMapViewOfSection(section,
1535 NtCurrentProcess(),
1536 &mapBits,
1537 0,
1538 0,
1539 &SectionOffset,
1540 &mapSize,
1541 ViewShare,
1542 0,
1543 PAGE_READWRITE);
1544 if (!NT_SUCCESS(Status))
1545 {
1546 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
1547 EngSetLastError(ERROR_INVALID_PARAMETER);
1548 return NULL;
1549 }
1550
1551 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1552 }
1553 else if (ovr_pitch && offset)
1554 bm.bmBits = (LPVOID) offset;
1555 else
1556 {
1557 offset = 0;
1558 bm.bmBits = EngAllocUserMem(totalSize, 0);
1559 if(!bm.bmBits)
1560 {
1561 DPRINT1("Failed to allocate memory\n");
1562 goto cleanup;
1563 }
1564 }
1565
1566 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1567 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1568
1569
1570 // Create Device Dependent Bitmap and add DIB pointer
1571 //Size.cx = bm.bmWidth;
1572 //Size.cy = abs(bm.bmHeight);
1573 res = GreCreateBitmapEx(bm.bmWidth,
1574 abs(bm.bmHeight),
1575 bm.bmWidthBytes,
1576 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1577 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1578 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
1579 bi->biSizeImage,
1580 bm.bmBits,
1581 0);
1582 if (!res)
1583 {
1584 DPRINT1("GreCreateBitmapEx failed\n");
1585 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1586 goto cleanup;
1587 }
1588 bmp = SURFACE_ShareLockSurface(res); // HACK
1589 if (NULL == bmp)
1590 {
1591 DPRINT1("SURFACE_LockSurface failed\n");
1592 EngSetLastError(ERROR_INVALID_HANDLE);
1593 goto cleanup;
1594 }
1595
1596 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1597 table between the DIB and the X physical device. Obviously,
1598 this is left out of the ReactOS implementation. Instead,
1599 we call NtGdiSetDIBColorTable. */
1600 bmp->hDIBSection = section;
1601 bmp->hSecure = hSecure;
1602 bmp->dwOffset = offset;
1603 bmp->flags = API_BITMAP;
1604 bmp->biClrImportant = bi->biClrImportant;
1605
1606 /* Create a palette for the DIB */
1607 ppalDIB = CreateDIBPalette(bmi, dc, usage);
1608 if (ppalDIB)
1609 {
1610 SURFACE_vSetPalette(bmp, ppalDIB);
1611 PALETTE_ShareUnlockPalette(ppalDIB);
1612 }
1613
1614 // Clean up in case of errors
1615 cleanup:
1616 if (!res || !bmp || !bm.bmBits)
1617 {
1618 DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1619 if (bm.bmBits)
1620 {
1621 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1622 if (section)
1623 {
1624 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1625 bm.bmBits = NULL;
1626 }
1627 else if (!offset)
1628 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1629 }
1630
1631 if (bmp)
1632 bmp = NULL;
1633
1634 if (res)
1635 {
1636 GreDeleteObject(res);
1637 res = 0;
1638 }
1639 }
1640
1641 if (bmp)
1642 {
1643 SURFACE_ShareUnlockSurface(bmp);
1644 }
1645
1646 // Return BITMAP handle and storage location
1647 if (NULL != bm.bmBits && NULL != bits)
1648 {
1649 *bits = bm.bmBits;
1650 }
1651
1652 return res;
1653 }
1654
1655 /***********************************************************************
1656 * DIB_GetBitmapInfo
1657 *
1658 * Get the info from a bitmap header.
1659 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1660 */
1661 int
1662 FASTCALL
1663 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1664 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1665 {
1666 if (header->biSize == sizeof(BITMAPCOREHEADER))
1667 {
1668 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1669 *width = core->bcWidth;
1670 *height = core->bcHeight;
1671 *planes = core->bcPlanes;
1672 *bpp = core->bcBitCount;
1673 *compr = BI_RGB;
1674 *size = 0;
1675 return 0;
1676 }
1677 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
1678 {
1679 *width = header->biWidth;
1680 *height = header->biHeight;
1681 *planes = header->biPlanes;
1682 *bpp = header->biBitCount;
1683 *compr = header->biCompression;
1684 *size = header->biSizeImage;
1685 return 1;
1686 }
1687 DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
1688 return -1;
1689 }
1690
1691 /***********************************************************************
1692 * DIB_GetDIBImageBytes
1693 *
1694 * Return the number of bytes used to hold the image in a DIB bitmap.
1695 * 11/16/1999 (RJJ) lifted from wine
1696 */
1697
1698 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1699 {
1700 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1701 }
1702
1703 /***********************************************************************
1704 * DIB_BitmapInfoSize
1705 *
1706 * Return the size of the bitmap info structure including color table.
1707 * 11/16/1999 (RJJ) lifted from wine
1708 */
1709
1710 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1711 {
1712 unsigned int colors, size, masks = 0;
1713
1714 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1715 {
1716 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1717 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1718 return sizeof(BITMAPCOREHEADER) + colors *
1719 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1720 }
1721 else /* Assume BITMAPINFOHEADER */
1722 {
1723 colors = info->bmiHeader.biClrUsed;
1724 if (colors > 256) colors = 256;
1725 if (!colors && (info->bmiHeader.biBitCount <= 8))
1726 colors = 1 << info->bmiHeader.biBitCount;
1727 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1728 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1729 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1730 }
1731 }
1732
1733 HPALETTE
1734 FASTCALL
1735 DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
1736 {
1737 PPALETTE ppalNew;
1738 ULONG nNumColors,i;
1739 USHORT *lpIndex;
1740 HPALETTE hpal;
1741
1742 if (!(ppalDc->flFlags & PAL_INDEXED))
1743 {
1744 return NULL;
1745 }
1746
1747 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1748 if (lpbmi->bmiHeader.biClrUsed)
1749 {
1750 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1751 }
1752
1753 ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
1754 if (ppalNew == NULL)
1755 {
1756 DPRINT1("Could not allocate palette\n");
1757 return NULL;
1758 }
1759
1760 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1761
1762 for (i = 0; i < nNumColors; i++)
1763 {
1764 ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
1765 ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
1766 lpIndex++;
1767 }
1768
1769 hpal = ppalNew->BaseObject.hHmgr;
1770 PALETTE_UnlockPalette(ppalNew);
1771
1772 return hpal;
1773 }
1774
1775 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1776 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1777 BITMAPINFO*
1778 FASTCALL
1779 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1780 {
1781 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1782 BITMAPINFO* pNewBmi ;
1783 UINT numColors = 0, ColorsSize = 0;
1784
1785 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1786 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1787
1788 if(pbmci->bmciHeader.bcBitCount <= 8)
1789 {
1790 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1791 if(Usage == DIB_PAL_COLORS)
1792 {
1793 ColorsSize = numColors * sizeof(WORD);
1794 }
1795 else
1796 {
1797 ColorsSize = numColors * sizeof(RGBQUAD);
1798 }
1799 }
1800 else if (Usage == DIB_PAL_COLORS)
1801 {
1802 /* Invalid at high-res */
1803 return NULL;
1804 }
1805
1806 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1807 if(!pNewBmi) return NULL;
1808
1809 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1810
1811 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1812 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1813 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1814 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1815 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1816 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1817 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1818 pNewBmi->bmiHeader.biHeight,
1819 pNewBmi->bmiHeader.biBitCount);
1820
1821 if(Usage == DIB_PAL_COLORS)
1822 {
1823 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1824 }
1825 else
1826 {
1827 UINT i;
1828 for(i=0; i<numColors; i++)
1829 {
1830 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1831 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1832 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1833 }
1834 }
1835
1836 return pNewBmi ;
1837 }
1838
1839 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
1840 VOID
1841 FASTCALL
1842 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
1843 {
1844 if(converted != orig)
1845 ExFreePoolWithTag(converted, TAG_DIB);
1846 }
1847
1848 /* EOF */