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