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