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