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