[WIN32SS]
[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 hcmXform);
1298
1299 cleanup:
1300 if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
1301 return hbmResult;
1302 }
1303
1304 HBITMAP
1305 FASTCALL
1306 GreCreateDIBitmapInternal(
1307 IN HDC hDc,
1308 IN INT cx,
1309 IN INT cy,
1310 IN DWORD fInit,
1311 IN OPTIONAL LPBYTE pjInit,
1312 IN OPTIONAL PBITMAPINFO pbmi,
1313 IN DWORD iUsage,
1314 IN FLONG fl,
1315 IN HANDLE hcmXform)
1316 {
1317 PDC Dc;
1318 HBITMAP Bmp;
1319 WORD bpp;
1320 HDC hdcDest;
1321
1322 if (!hDc) /* 1bpp monochrome bitmap */
1323 {
1324 // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1325 hdcDest = NtGdiCreateCompatibleDC(0);
1326 if(!hdcDest)
1327 {
1328 return NULL;
1329 }
1330 }
1331 else
1332 {
1333 hdcDest = hDc;
1334 }
1335
1336 Dc = DC_LockDc(hdcDest);
1337 if (!Dc)
1338 {
1339 EngSetLastError(ERROR_INVALID_HANDLE);
1340 return NULL;
1341 }
1342 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1343 * if bpp != 1 and ignore the real value that was passed */
1344 if (pbmi)
1345 bpp = pbmi->bmiHeader.biBitCount;
1346 else
1347 bpp = 0;
1348 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1349 DC_UnlockDc(Dc);
1350
1351 if(!hDc)
1352 {
1353 NtGdiDeleteObjectApp(hdcDest);
1354 }
1355 return Bmp;
1356 }
1357
1358
1359 HBITMAP
1360 APIENTRY
1361 NtGdiCreateDIBSection(
1362 IN HDC hDC,
1363 IN OPTIONAL HANDLE hSection,
1364 IN DWORD dwOffset,
1365 IN BITMAPINFO* bmi,
1366 IN DWORD Usage,
1367 IN UINT cjHeader,
1368 IN FLONG fl,
1369 IN ULONG_PTR dwColorSpace,
1370 OUT PVOID *Bits)
1371 {
1372 HBITMAP hbitmap = 0;
1373 DC *dc;
1374 BOOL bDesktopDC = FALSE;
1375 NTSTATUS Status = STATUS_SUCCESS;
1376
1377 if (!bmi) return hbitmap; // Make sure.
1378
1379 _SEH2_TRY
1380 {
1381 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1382 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1383 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, (WORD)Usage), 1);
1384 }
1385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1386 {
1387 Status = _SEH2_GetExceptionCode();
1388 }
1389 _SEH2_END
1390
1391 if(!NT_SUCCESS(Status))
1392 {
1393 SetLastNtError(Status);
1394 return NULL;
1395 }
1396
1397 // If the reference hdc is null, take the desktop dc
1398 if (hDC == 0)
1399 {
1400 hDC = NtGdiCreateCompatibleDC(0);
1401 bDesktopDC = TRUE;
1402 }
1403
1404 if ((dc = DC_LockDc(hDC)))
1405 {
1406 hbitmap = DIB_CreateDIBSection(dc,
1407 bmi,
1408 Usage,
1409 Bits,
1410 hSection,
1411 dwOffset,
1412 0);
1413 DC_UnlockDc(dc);
1414 }
1415 else
1416 {
1417 EngSetLastError(ERROR_INVALID_HANDLE);
1418 }
1419
1420 if (bDesktopDC)
1421 NtGdiDeleteObjectApp(hDC);
1422
1423 return hbitmap;
1424 }
1425
1426 HBITMAP
1427 APIENTRY
1428 DIB_CreateDIBSection(
1429 PDC dc,
1430 CONST BITMAPINFO *bmi,
1431 UINT usage,
1432 LPVOID *bits,
1433 HANDLE section,
1434 DWORD offset,
1435 DWORD ovr_pitch)
1436 {
1437 HBITMAP res = 0;
1438 SURFACE *bmp = NULL;
1439 void *mapBits = NULL;
1440 HPALETTE hpal ;
1441
1442 // Fill BITMAP32 structure with DIB data
1443 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1444 INT effHeight;
1445 ULONG totalSize;
1446 BITMAP bm;
1447 //SIZEL Size;
1448 HANDLE hSecure;
1449
1450 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1451 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1452 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1453
1454 /* CreateDIBSection should fail for compressed formats */
1455 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1456 {
1457 DPRINT1("no compressed format allowed\n");
1458 return (HBITMAP)NULL;
1459 }
1460
1461 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1462 bm.bmType = 0;
1463 bm.bmWidth = bi->biWidth;
1464 bm.bmHeight = effHeight;
1465 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
1466
1467 bm.bmPlanes = bi->biPlanes;
1468 bm.bmBitsPixel = bi->biBitCount;
1469 bm.bmBits = NULL;
1470
1471 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1472 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1473 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
1474 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1475
1476 if (section)
1477 {
1478 SYSTEM_BASIC_INFORMATION Sbi;
1479 NTSTATUS Status;
1480 DWORD mapOffset;
1481 LARGE_INTEGER SectionOffset;
1482 SIZE_T mapSize;
1483
1484 Status = ZwQuerySystemInformation(SystemBasicInformation,
1485 &Sbi,
1486 sizeof Sbi,
1487 0);
1488 if (!NT_SUCCESS(Status))
1489 {
1490 DPRINT1("ZwQuerySystemInformation failed (0x%lx)\n", Status);
1491 return NULL;
1492 }
1493
1494 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1495 mapSize = bi->biSizeImage + (offset - mapOffset);
1496
1497 SectionOffset.LowPart = mapOffset;
1498 SectionOffset.HighPart = 0;
1499
1500 Status = ZwMapViewOfSection(section,
1501 NtCurrentProcess(),
1502 &mapBits,
1503 0,
1504 0,
1505 &SectionOffset,
1506 &mapSize,
1507 ViewShare,
1508 0,
1509 PAGE_READWRITE);
1510 if (!NT_SUCCESS(Status))
1511 {
1512 DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status);
1513 EngSetLastError(ERROR_INVALID_PARAMETER);
1514 return NULL;
1515 }
1516
1517 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1518 }
1519 else if (ovr_pitch && offset)
1520 bm.bmBits = (LPVOID) offset;
1521 else
1522 {
1523 offset = 0;
1524 bm.bmBits = EngAllocUserMem(totalSize, 0);
1525 if(!bm.bmBits)
1526 {
1527 DPRINT1("Failed to allocate memory\n");
1528 goto cleanup;
1529 }
1530 }
1531
1532 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1533 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1534
1535 if (usage == DIB_PAL_COLORS)
1536 {
1537 if(dc)
1538 {
1539 PPALETTE ppalDc;
1540 ppalDc = PALETTE_ShareLockPalette(dc->dclevel.hpal);
1541 hpal = DIB_MapPaletteColors(ppalDc, bmi);
1542 PALETTE_ShareUnlockPalette(ppalDc);
1543 }
1544 else
1545 {
1546 /* For DIB Brushes */
1547 DPRINT1("FIXME: Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
1548 /* HACK */
1549 hpal = (HPALETTE) 0xFFFFFFFF;
1550 }
1551 }
1552 else
1553 {
1554 hpal = BuildDIBPalette(bmi);
1555 }
1556
1557 if(!hpal)
1558 {
1559 DPRINT1("Error: Could not create a palette for the DIB.\n");
1560 goto cleanup;
1561 }
1562
1563 // Create Device Dependent Bitmap and add DIB pointer
1564 //Size.cx = bm.bmWidth;
1565 //Size.cy = abs(bm.bmHeight);
1566 res = GreCreateBitmapEx(bm.bmWidth,
1567 abs(bm.bmHeight),
1568 bm.bmWidthBytes,
1569 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1570 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1571 ((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
1572 bi->biSizeImage,
1573 bm.bmBits,
1574 0);
1575 if (!res)
1576 {
1577 DPRINT1("GreCreateBitmapEx failed\n");
1578 EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
1579 goto cleanup;
1580 }
1581 bmp = SURFACE_ShareLockSurface(res); // HACK
1582 if (NULL == bmp)
1583 {
1584 DPRINT1("SURFACE_LockSurface failed\n");
1585 EngSetLastError(ERROR_INVALID_HANDLE);
1586 goto cleanup;
1587 }
1588
1589 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1590 table between the DIB and the X physical device. Obviously,
1591 this is left out of the ReactOS implementation. Instead,
1592 we call NtGdiSetDIBColorTable. */
1593 bmp->hDIBSection = section;
1594 bmp->hSecure = hSecure;
1595 bmp->dwOffset = offset;
1596 bmp->flags = API_BITMAP;
1597 bmp->biClrImportant = bi->biClrImportant;
1598 bmp->SurfObj.fjBitmap &= ~BMF_DONT_FREE;
1599
1600 /* HACK */
1601 if(hpal != (HPALETTE)0xFFFFFFFF)
1602 {
1603 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1604 /* Lazy delete hpal, it will be freed at surface release */
1605 GreDeleteObject(hpal);
1606 }
1607
1608 // Clean up in case of errors
1609 cleanup:
1610 if (!res || !bmp || !bm.bmBits)
1611 {
1612 DPRINT("Got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1613 if (bm.bmBits)
1614 {
1615 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1616 if (section)
1617 {
1618 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1619 bm.bmBits = NULL;
1620 }
1621 else if (!offset)
1622 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1623 }
1624
1625 if (bmp)
1626 bmp = NULL;
1627
1628 if (res)
1629 {
1630 GreDeleteObject(res);
1631 res = 0;
1632 }
1633 }
1634
1635 if (bmp)
1636 {
1637 SURFACE_ShareUnlockSurface(bmp);
1638 }
1639
1640 // Return BITMAP handle and storage location
1641 if (NULL != bm.bmBits && NULL != bits)
1642 {
1643 *bits = bm.bmBits;
1644 }
1645
1646 return res;
1647 }
1648
1649 /***********************************************************************
1650 * DIB_GetBitmapInfo
1651 *
1652 * Get the info from a bitmap header.
1653 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1654 */
1655 int
1656 FASTCALL
1657 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1658 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1659 {
1660 if (header->biSize == sizeof(BITMAPCOREHEADER))
1661 {
1662 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1663 *width = core->bcWidth;
1664 *height = core->bcHeight;
1665 *planes = core->bcPlanes;
1666 *bpp = core->bcBitCount;
1667 *compr = BI_RGB;
1668 *size = 0;
1669 return 0;
1670 }
1671 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* Assume BITMAPINFOHEADER */
1672 {
1673 *width = header->biWidth;
1674 *height = header->biHeight;
1675 *planes = header->biPlanes;
1676 *bpp = header->biBitCount;
1677 *compr = header->biCompression;
1678 *size = header->biSizeImage;
1679 return 1;
1680 }
1681 DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
1682 return -1;
1683 }
1684
1685 /***********************************************************************
1686 * DIB_GetDIBImageBytes
1687 *
1688 * Return the number of bytes used to hold the image in a DIB bitmap.
1689 * 11/16/1999 (RJJ) lifted from wine
1690 */
1691
1692 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1693 {
1694 return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
1695 }
1696
1697 /***********************************************************************
1698 * DIB_BitmapInfoSize
1699 *
1700 * Return the size of the bitmap info structure including color table.
1701 * 11/16/1999 (RJJ) lifted from wine
1702 */
1703
1704 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1705 {
1706 unsigned int colors, size, masks = 0;
1707
1708 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1709 {
1710 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1711 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1712 return sizeof(BITMAPCOREHEADER) + colors *
1713 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1714 }
1715 else /* Assume BITMAPINFOHEADER */
1716 {
1717 colors = info->bmiHeader.biClrUsed;
1718 if (colors > 256) colors = 256;
1719 if (!colors && (info->bmiHeader.biBitCount <= 8))
1720 colors = 1 << info->bmiHeader.biBitCount;
1721 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1722 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1723 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1724 }
1725 }
1726
1727 HPALETTE
1728 FASTCALL
1729 DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
1730 {
1731 PALETTEENTRY* ppalEntries;
1732 ULONG nNumColors,i;
1733 USHORT *lpIndex;
1734 HPALETTE hpal;
1735
1736 if (!(ppal->flFlags & PAL_INDEXED))
1737 {
1738 return NULL;
1739 }
1740
1741 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1742 if (lpbmi->bmiHeader.biClrUsed)
1743 {
1744 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1745 }
1746
1747 /* Don't have more colors than we need */
1748 nNumColors = min(ppal->NumColors, nNumColors);
1749
1750 ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
1751 if (ppalEntries == NULL)
1752 {
1753 DPRINT1("Could not allocate palette entries\n");
1754 return NULL;
1755 }
1756
1757 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1758
1759 for (i = 0; i < nNumColors; i++)
1760 {
1761 if (*lpIndex < ppal->NumColors)
1762 {
1763 ppalEntries[i] = ppal->IndexedColors[*lpIndex];
1764 }
1765 else
1766 {
1767 ppalEntries[i].peRed = 0;
1768 ppalEntries[i].peGreen = 0;
1769 ppalEntries[i].peBlue = 0;
1770 ppalEntries[i].peFlags = 0;
1771 }
1772
1773 lpIndex++;
1774 }
1775
1776 hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
1777
1778 ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
1779
1780 return hpal;
1781 }
1782
1783 HPALETTE
1784 FASTCALL
1785 BuildDIBPalette(CONST BITMAPINFO *bmi)
1786 {
1787 WORD bits;
1788 ULONG ColorCount;
1789 HPALETTE hPal;
1790 ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
1791 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1792 INT paletteType;
1793
1794 // Determine Bits Per Pixel
1795 bits = bmi->bmiHeader.biBitCount;
1796
1797 // Determine paletteType from Bits Per Pixel
1798 if (bits <= 8)
1799 {
1800 paletteType = PAL_INDEXED;
1801 RedMask = GreenMask = BlueMask = 0;
1802 }
1803 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1804 {
1805 paletteType = PAL_BITFIELDS;
1806 if (bmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
1807 {
1808 PBITMAPV4HEADER pV4Header = (PBITMAPV4HEADER)&bmi->bmiHeader;
1809 RedMask = pV4Header->bV4RedMask;
1810 GreenMask = pV4Header->bV4GreenMask;
1811 BlueMask = pV4Header->bV4BlueMask;
1812 }
1813 else
1814 {
1815 RedMask = pdwColors[0];
1816 GreenMask = pdwColors[1];
1817 BlueMask = pdwColors[2];
1818 }
1819 }
1820 else
1821 {
1822 paletteType = PAL_BITFIELDS;
1823 switch (bits)
1824 {
1825 case 16:
1826 paletteType |= PAL_RGB16_555;
1827 RedMask = 0x7C00;
1828 GreenMask = 0x03E0;
1829 BlueMask = 0x001F;
1830 break;
1831
1832 case 24:
1833 case 32:
1834 paletteType |= PAL_BGR;
1835 RedMask = 0xFF0000;
1836 GreenMask = 0x00FF00;
1837 BlueMask = 0x0000FF;
1838 break;
1839 }
1840 }
1841
1842 if (bmi->bmiHeader.biClrUsed == 0)
1843 {
1844 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1845 }
1846 else
1847 {
1848 ColorCount = bmi->bmiHeader.biClrUsed;
1849 }
1850
1851 if (PAL_INDEXED == paletteType)
1852 {
1853 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1854 }
1855 else
1856 {
1857 hPal = PALETTE_AllocPalette(paletteType, 0,
1858 NULL,
1859 RedMask, GreenMask, BlueMask);
1860 }
1861
1862 return hPal;
1863 }
1864
1865 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1866 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1867 BITMAPINFO*
1868 FASTCALL
1869 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1870 {
1871 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1872 BITMAPINFO* pNewBmi ;
1873 UINT numColors = 0, ColorsSize = 0;
1874
1875 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1876 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1877
1878 if(pbmci->bmciHeader.bcBitCount <= 8)
1879 {
1880 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1881 if(Usage == DIB_PAL_COLORS)
1882 {
1883 ColorsSize = numColors * sizeof(WORD);
1884 }
1885 else
1886 {
1887 ColorsSize = numColors * sizeof(RGBQUAD);
1888 }
1889 }
1890 else if (Usage == DIB_PAL_COLORS)
1891 {
1892 /* Invalid at high-res */
1893 return NULL;
1894 }
1895
1896 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1897 if(!pNewBmi) return NULL;
1898
1899 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1900
1901 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1902 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1903 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1904 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1905 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1906 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1907 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1908 pNewBmi->bmiHeader.biHeight,
1909 pNewBmi->bmiHeader.biBitCount);
1910
1911 if(Usage == DIB_PAL_COLORS)
1912 {
1913 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1914 }
1915 else
1916 {
1917 UINT i;
1918 for(i=0; i<numColors; i++)
1919 {
1920 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1921 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1922 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1923 }
1924 }
1925
1926 return pNewBmi ;
1927 }
1928
1929 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
1930 VOID
1931 FASTCALL
1932 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
1933 {
1934 if(converted != orig)
1935 ExFreePoolWithTag(converted, TAG_DIB);
1936 }
1937
1938 /* EOF */