[WIN32K]
[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 = psurf->SurfObj.sizlBitmap.cy;
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, hOldDest = NULL, hOldSrc = NULL;
901 HDC hdcDest = NULL, hdcSrc;
902 BOOL ret ;
903
904 if (StartScan > psurf->SurfObj.sizlBitmap.cy)
905 {
906 ScanLines = 0;
907 goto done;
908 }
909 else
910 {
911 ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
912 }
913
914 hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
915
916 if(!hBmpDest)
917 {
918 DPRINT1("Unable to create a DIB Section!\n");
919 SetLastWin32Error(ERROR_INVALID_PARAMETER);
920 ScanLines = 0;
921 goto done ;
922 }
923
924 if(psurf->hdc)
925 hdcSrc = psurf->hdc;
926 else
927 {
928 hdcSrc = NtGdiCreateCompatibleDC(0);
929 if(!hdcSrc)
930 {
931 DPRINT1("Error: could not create HDC!\n");
932 ScanLines = 0;
933 goto cleanup_blt;
934 }
935 hOldSrc = NtGdiSelectBitmap(hdcSrc, hBitmap);
936 if(!hOldSrc)
937 {
938 DPRINT1("Error : Could not Select bitmap\n");
939 ScanLines = 0;
940 goto cleanup_blt;
941 }
942 }
943
944 hdcDest = NtGdiCreateCompatibleDC(0);
945 if(!hdcDest)
946 {
947 DPRINT1("Error: could not create HDC!\n");
948 ScanLines = 0;
949 goto cleanup_blt;
950 }
951 hOldDest = NtGdiSelectBitmap(hdcDest, hBmpDest);
952 if(!hOldDest)
953 {
954 DPRINT1("Error : Could not Select bitmap\n");
955 ScanLines = 0;
956 goto cleanup_blt;
957 }
958
959 ret = GreStretchBltMask(hdcDest,
960 0,
961 0,
962 width,
963 height,
964 hdcSrc,
965 0,
966 StartScan,
967 psurf->SurfObj.sizlBitmap.cx,
968 ScanLines,
969 SRCCOPY,
970 0,
971 NULL,
972 0,
973 0);
974
975 if(!ret)
976 ScanLines = 0;
977 else
978 {
979 Status = STATUS_SUCCESS;
980 _SEH2_TRY
981 {
982 RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, height, bpp));
983 }
984 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
985 {
986 Status = _SEH2_GetExceptionCode();
987 }
988 _SEH2_END
989
990 if(!NT_SUCCESS(Status))
991 {
992 DPRINT1("Unable to copy bits to the user provided pointer\n");
993 ScanLines = 0;
994 }
995 }
996
997 cleanup_blt:
998 if(hdcSrc && (hdcSrc != psurf->hdc))
999 {
1000 if(hOldSrc) NtGdiSelectBitmap(hdcSrc, hOldSrc);
1001 NtGdiDeleteObjectApp(hdcSrc);
1002 }
1003 if(hdcSrc)
1004 {
1005 if(hOldDest) NtGdiSelectBitmap(hdcDest, hOldDest);
1006 NtGdiDeleteObjectApp(hdcDest);
1007 }
1008 GreDeleteObject(hBmpDest);
1009 }
1010
1011 done:
1012
1013 if(pDC) DC_UnlockDc(pDC);
1014 if(psurf) SURFACE_UnlockSurface(psurf);
1015 if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
1016
1017 return ScanLines;
1018 }
1019
1020
1021 INT
1022 APIENTRY
1023 NtGdiStretchDIBitsInternal(
1024 HDC hDC,
1025 INT XDest,
1026 INT YDest,
1027 INT DestWidth,
1028 INT DestHeight,
1029 INT XSrc,
1030 INT YSrc,
1031 INT SrcWidth,
1032 INT SrcHeight,
1033 LPBYTE Bits,
1034 LPBITMAPINFO BitsInfo,
1035 DWORD Usage,
1036 DWORD ROP,
1037 UINT cjMaxInfo,
1038 UINT cjMaxBits,
1039 HANDLE hcmXform)
1040 {
1041 HBITMAP hBitmap, hOldBitmap = NULL;
1042 HDC hdcMem = NULL;
1043 NTSTATUS Status = STATUS_SUCCESS;
1044 PVOID pvDIBits;
1045 INT Ret = 0;
1046
1047 if (!Bits || !BitsInfo)
1048 {
1049 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1050 return 0;
1051 }
1052
1053 /* Create a DIB Section, data will be probed there */
1054 hBitmap = NtGdiCreateDIBSection(hDC,
1055 NULL,
1056 0,
1057 BitsInfo,
1058 Usage,
1059 0,
1060 0,
1061 0,
1062 &pvDIBits);
1063
1064 if(!hBitmap)
1065 {
1066 DPRINT1("Failed to create a DIB.\n");
1067 return 0;
1068 }
1069
1070 _SEH2_TRY
1071 {
1072 ProbeForRead(Bits, cjMaxBits, 1);
1073 RtlCopyMemory(pvDIBits, Bits, DIB_GetDIBImageBytes(BitsInfo->bmiHeader.biWidth,
1074 BitsInfo->bmiHeader.biHeight,
1075 BitsInfo->bmiHeader.biBitCount));
1076 }
1077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1078 {
1079 Status = _SEH2_GetExceptionCode();
1080 }
1081 _SEH2_END
1082
1083 if(!NT_SUCCESS(Status))
1084 {
1085 DPRINT1("Error : Could not read DIB bits\n");
1086 SetLastNtError(Status);
1087 goto cleanup;
1088 }
1089
1090 hdcMem = NtGdiCreateCompatibleDC(0);
1091 if(!hdcMem)
1092 {
1093 DPRINT1("Failed to create a memory DC!");
1094 goto cleanup;
1095 }
1096
1097 hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
1098 if(!hOldBitmap)
1099 {
1100 DPRINT1("Could not select the DIB into the memory DC\n");
1101 goto cleanup;
1102 }
1103
1104 /* Do we want to stretch ? */
1105 if((SrcWidth == DestWidth) && (SrcHeight == DestHeight))
1106 {
1107 Ret = NtGdiBitBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight,
1108 hdcMem, XSrc, YSrc, ROP, 0, 0);
1109 }
1110 else
1111 {
1112 Ret = NtGdiStretchBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight,
1113 hdcMem, XSrc, YSrc, XSrc + SrcWidth, YSrc + SrcHeight,
1114 ROP, 0);
1115 }
1116
1117 if(Ret)
1118 Ret = SrcHeight ;
1119
1120 cleanup:
1121 if(hdcMem)
1122 {
1123 if(hOldBitmap) NtGdiSelectBitmap(hdcMem, hOldBitmap);
1124 NtGdiDeleteObjectApp(hdcMem);
1125 }
1126 GreDeleteObject(hBitmap);
1127
1128 return Ret;
1129 }
1130
1131
1132 HBITMAP
1133 FASTCALL
1134 IntCreateDIBitmap(
1135 PDC Dc,
1136 INT width,
1137 INT height,
1138 UINT bpp,
1139 DWORD init,
1140 LPBYTE bits,
1141 PBITMAPINFO data,
1142 DWORD coloruse)
1143 {
1144 HBITMAP handle;
1145 BOOL fColor;
1146
1147 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
1148 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
1149
1150 if (bpp != 1) fColor = TRUE;
1151 else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
1152 else
1153 {
1154 const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
1155 DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1156
1157 // Check if the first color of the colormap is black
1158 if ((col == RGB(0, 0, 0)))
1159 {
1160 rgb++;
1161 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
1162
1163 // If the second color is white, create a monochrome bitmap
1164 fColor = (col != RGB(0xff,0xff,0xff));
1165 }
1166 else fColor = TRUE;
1167 }
1168
1169 // Now create the bitmap
1170 if (fColor)
1171 {
1172 handle = IntCreateCompatibleBitmap(Dc, width, height);
1173 }
1174 else
1175 {
1176 handle = GreCreateBitmap(width,
1177 height,
1178 1,
1179 1,
1180 NULL);
1181 }
1182
1183 if (height < 0)
1184 height = -height;
1185
1186 if (NULL != handle && CBM_INIT == init)
1187 {
1188 IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
1189 }
1190
1191 return handle;
1192 }
1193
1194 // The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
1195 // The DDB that is created will be whatever bit depth your reference DC is
1196 HBITMAP
1197 APIENTRY
1198 NtGdiCreateDIBitmapInternal(
1199 IN HDC hDc,
1200 IN INT cx,
1201 IN INT cy,
1202 IN DWORD fInit,
1203 IN OPTIONAL LPBYTE pjInit,
1204 IN OPTIONAL LPBITMAPINFO pbmi,
1205 IN DWORD iUsage,
1206 IN UINT cjMaxInitInfo,
1207 IN UINT cjMaxBits,
1208 IN FLONG fl,
1209 IN HANDLE hcmXform)
1210 {
1211 NTSTATUS Status = STATUS_SUCCESS;
1212
1213 _SEH2_TRY
1214 {
1215 if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
1216 if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
1217 }
1218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1219 {
1220 Status = _SEH2_GetExceptionCode();
1221 }
1222 _SEH2_END
1223
1224 if(!NT_SUCCESS(Status))
1225 {
1226 SetLastNtError(Status);
1227 return NULL;
1228 }
1229
1230 return GreCreateDIBitmapInternal(hDc,
1231 cx,
1232 cy,
1233 fInit,
1234 pjInit,
1235 pbmi,
1236 iUsage,
1237 fl,
1238 hcmXform);
1239 }
1240
1241 HBITMAP
1242 FASTCALL
1243 GreCreateDIBitmapInternal(
1244 IN HDC hDc,
1245 IN INT cx,
1246 IN INT cy,
1247 IN DWORD fInit,
1248 IN OPTIONAL LPBYTE pjInit,
1249 IN OPTIONAL PBITMAPINFO pbmi,
1250 IN DWORD iUsage,
1251 IN FLONG fl,
1252 IN HANDLE hcmXform)
1253 {
1254 PDC Dc;
1255 HBITMAP Bmp;
1256 WORD bpp;
1257 HDC hdcDest;
1258
1259 if (!hDc) /* 1bpp monochrome bitmap */
1260 { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
1261 hdcDest = NtGdiCreateCompatibleDC(0);
1262 if(!hdcDest)
1263 {
1264 return NULL;
1265 }
1266 }
1267 else
1268 {
1269 hdcDest = hDc;
1270 }
1271
1272 Dc = DC_LockDc(hdcDest);
1273 if (!Dc)
1274 {
1275 SetLastWin32Error(ERROR_INVALID_HANDLE);
1276 return NULL;
1277 }
1278 /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
1279 * if bpp != 1 and ignore the real value that was passed */
1280 if (pbmi)
1281 bpp = pbmi->bmiHeader.biBitCount;
1282 else
1283 bpp = 0;
1284 Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
1285 DC_UnlockDc(Dc);
1286
1287 if(!hDc)
1288 {
1289 NtGdiDeleteObjectApp(hdcDest);
1290 }
1291 return Bmp;
1292 }
1293
1294
1295 HBITMAP
1296 APIENTRY
1297 NtGdiCreateDIBSection(
1298 IN HDC hDC,
1299 IN OPTIONAL HANDLE hSection,
1300 IN DWORD dwOffset,
1301 IN BITMAPINFO* bmi,
1302 IN DWORD Usage,
1303 IN UINT cjHeader,
1304 IN FLONG fl,
1305 IN ULONG_PTR dwColorSpace,
1306 OUT PVOID *Bits)
1307 {
1308 HBITMAP hbitmap = 0;
1309 DC *dc;
1310 BOOL bDesktopDC = FALSE;
1311 NTSTATUS Status = STATUS_SUCCESS;
1312
1313 if (!bmi) return hbitmap; // Make sure.
1314
1315 _SEH2_TRY
1316 {
1317 ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
1318 ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
1319 ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
1320 }
1321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1322 {
1323 Status = _SEH2_GetExceptionCode();
1324 }
1325 _SEH2_END
1326
1327 if(!NT_SUCCESS(Status))
1328 {
1329 SetLastNtError(Status);
1330 return NULL;
1331 }
1332
1333 // If the reference hdc is null, take the desktop dc
1334 if (hDC == 0)
1335 {
1336 hDC = NtGdiCreateCompatibleDC(0);
1337 bDesktopDC = TRUE;
1338 }
1339
1340 if ((dc = DC_LockDc(hDC)))
1341 {
1342 hbitmap = DIB_CreateDIBSection(dc,
1343 bmi,
1344 Usage,
1345 Bits,
1346 hSection,
1347 dwOffset,
1348 0);
1349 DC_UnlockDc(dc);
1350 }
1351 else
1352 {
1353 SetLastWin32Error(ERROR_INVALID_HANDLE);
1354 }
1355
1356 if (bDesktopDC)
1357 NtGdiDeleteObjectApp(hDC);
1358
1359 return hbitmap;
1360 }
1361
1362 HBITMAP
1363 APIENTRY
1364 DIB_CreateDIBSection(
1365 PDC dc,
1366 CONST BITMAPINFO *bmi,
1367 UINT usage,
1368 LPVOID *bits,
1369 HANDLE section,
1370 DWORD offset,
1371 DWORD ovr_pitch)
1372 {
1373 HBITMAP res = 0;
1374 SURFACE *bmp = NULL;
1375 void *mapBits = NULL;
1376 HPALETTE hpal ;
1377
1378 // Fill BITMAP32 structure with DIB data
1379 CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
1380 INT effHeight;
1381 ULONG totalSize;
1382 BITMAP bm;
1383 SIZEL Size;
1384 HANDLE hSecure;
1385
1386 DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
1387 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
1388 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1389
1390 /* CreateDIBSection should fail for compressed formats */
1391 if (bi->biCompression == BI_RLE4 || bi->biCompression == BI_RLE8)
1392 {
1393 return (HBITMAP)NULL;
1394 }
1395
1396 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
1397 bm.bmType = 0;
1398 bm.bmWidth = bi->biWidth;
1399 bm.bmHeight = effHeight;
1400 bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
1401
1402 bm.bmPlanes = bi->biPlanes;
1403 bm.bmBitsPixel = bi->biBitCount;
1404 bm.bmBits = NULL;
1405
1406 // Get storage location for DIB bits. Only use biSizeImage if it's valid and
1407 // we're dealing with a compressed bitmap. Otherwise, use width * height.
1408 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
1409 ? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
1410
1411 if (section)
1412 {
1413 SYSTEM_BASIC_INFORMATION Sbi;
1414 NTSTATUS Status;
1415 DWORD mapOffset;
1416 LARGE_INTEGER SectionOffset;
1417 SIZE_T mapSize;
1418
1419 Status = ZwQuerySystemInformation(SystemBasicInformation,
1420 &Sbi,
1421 sizeof Sbi,
1422 0);
1423 if (!NT_SUCCESS(Status))
1424 {
1425 return NULL;
1426 }
1427
1428 mapOffset = offset - (offset % Sbi.AllocationGranularity);
1429 mapSize = bi->biSizeImage + (offset - mapOffset);
1430
1431 SectionOffset.LowPart = mapOffset;
1432 SectionOffset.HighPart = 0;
1433
1434 Status = ZwMapViewOfSection(section,
1435 NtCurrentProcess(),
1436 &mapBits,
1437 0,
1438 0,
1439 &SectionOffset,
1440 &mapSize,
1441 ViewShare,
1442 0,
1443 PAGE_READWRITE);
1444 if (!NT_SUCCESS(Status))
1445 {
1446 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1447 return NULL;
1448 }
1449
1450 if (mapBits) bm.bmBits = (char *)mapBits + (offset - mapOffset);
1451 }
1452 else if (ovr_pitch && offset)
1453 bm.bmBits = (LPVOID) offset;
1454 else
1455 {
1456 offset = 0;
1457 bm.bmBits = EngAllocUserMem(totalSize, 0);
1458 if(!bm.bmBits) goto cleanup;
1459 }
1460
1461 // hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
1462 hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
1463
1464 if (usage == DIB_PAL_COLORS)
1465 {
1466 if(dc)
1467 {
1468 PPALETTE pdcPal ;
1469 pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
1470 hpal = DIB_MapPaletteColors(pdcPal, bmi);
1471 PALETTE_UnlockPalette(pdcPal);
1472 }
1473 else
1474 {
1475 /* For DIB Brushes */
1476 DPRINT1("FIXME : Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
1477 /* HACK */
1478 hpal = (HPALETTE) 0xFFFFFFFF;
1479 }
1480 }
1481 else
1482 {
1483 hpal = BuildDIBPalette(bmi);
1484 }
1485
1486 if(!hpal)
1487 {
1488 DPRINT1("Error : Could not create a palette for the DIB.\n");
1489 goto cleanup;
1490 }
1491
1492 // Create Device Dependent Bitmap and add DIB pointer
1493 Size.cx = bm.bmWidth;
1494 Size.cy = abs(bm.bmHeight);
1495 res = GreCreateBitmapEx(bm.bmWidth,
1496 abs(bm.bmHeight),
1497 bm.bmWidthBytes,
1498 BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
1499 BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
1500 (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
1501 bi->biSizeImage,
1502 bm.bmBits,
1503 0);
1504 if (!res)
1505 {
1506 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1507 goto cleanup;
1508 }
1509 bmp = SURFACE_LockSurface(res);
1510 if (NULL == bmp)
1511 {
1512 SetLastWin32Error(ERROR_INVALID_HANDLE);
1513 goto cleanup;
1514 }
1515
1516 /* WINE NOTE: WINE makes use of a colormap, which is a color translation
1517 table between the DIB and the X physical device. Obviously,
1518 this is left out of the ReactOS implementation. Instead,
1519 we call NtGdiSetDIBColorTable. */
1520 bmp->hDIBSection = section;
1521 bmp->hSecure = hSecure;
1522 bmp->dwOffset = offset;
1523 bmp->flags = API_BITMAP;
1524 bmp->biClrImportant = bi->biClrImportant;
1525
1526 /* HACK */
1527 if(hpal != (HPALETTE)0xFFFFFFFF)
1528 {
1529 bmp->ppal = PALETTE_ShareLockPalette(hpal);
1530 /* Lazy delete hpal, it will be freed at surface release */
1531 GreDeleteObject(hpal);
1532 }
1533
1534 // Clean up in case of errors
1535 cleanup:
1536 if (!res || !bmp || !bm.bmBits)
1537 {
1538 DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
1539 if (bm.bmBits)
1540 {
1541 // MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
1542 if (section)
1543 {
1544 ZwUnmapViewOfSection(NtCurrentProcess(), mapBits);
1545 bm.bmBits = NULL;
1546 }
1547 else
1548 if (!offset)
1549 EngFreeUserMem(bm.bmBits), bm.bmBits = NULL;
1550 }
1551
1552 if (bmp)
1553 bmp = NULL;
1554
1555 if (res)
1556 {
1557 SURFACE_FreeSurfaceByHandle(res);
1558 res = 0;
1559 }
1560 }
1561
1562 if (bmp)
1563 {
1564 SURFACE_UnlockSurface(bmp);
1565 }
1566
1567 // Return BITMAP handle and storage location
1568 if (NULL != bm.bmBits && NULL != bits)
1569 {
1570 *bits = bm.bmBits;
1571 }
1572
1573 return res;
1574 }
1575
1576 /***********************************************************************
1577 * DIB_GetBitmapInfo
1578 *
1579 * Get the info from a bitmap header.
1580 * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
1581 */
1582 int
1583 FASTCALL
1584 DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
1585 LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
1586 {
1587 if (header->biSize == sizeof(BITMAPCOREHEADER))
1588 {
1589 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
1590 *width = core->bcWidth;
1591 *height = core->bcHeight;
1592 *planes = core->bcPlanes;
1593 *bpp = core->bcBitCount;
1594 *compr = 0;
1595 *size = 0;
1596 return 0;
1597 }
1598 if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
1599 {
1600 *width = header->biWidth;
1601 *height = header->biHeight;
1602 *planes = header->biPlanes;
1603 *bpp = header->biBitCount;
1604 *compr = header->biCompression;
1605 *size = header->biSizeImage;
1606 return 1;
1607 }
1608 DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
1609 return -1;
1610 }
1611
1612 /***********************************************************************
1613 * DIB_GetDIBWidthBytes
1614 *
1615 * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1616 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
1617 * 11/16/1999 (RJJ) lifted from wine
1618 */
1619 INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
1620 {
1621 return ((width * depth + 31) & ~31) >> 3;
1622 }
1623
1624 /***********************************************************************
1625 * DIB_GetDIBImageBytes
1626 *
1627 * Return the number of bytes used to hold the image in a DIB bitmap.
1628 * 11/16/1999 (RJJ) lifted from wine
1629 */
1630
1631 INT APIENTRY DIB_GetDIBImageBytes(INT width, INT height, INT depth)
1632 {
1633 return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
1634 }
1635
1636 /***********************************************************************
1637 * DIB_BitmapInfoSize
1638 *
1639 * Return the size of the bitmap info structure including color table.
1640 * 11/16/1999 (RJJ) lifted from wine
1641 */
1642
1643 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
1644 {
1645 unsigned int colors, size, masks = 0;
1646
1647 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
1648 {
1649 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
1650 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
1651 return sizeof(BITMAPCOREHEADER) + colors *
1652 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
1653 }
1654 else /* assume BITMAPINFOHEADER */
1655 {
1656 colors = info->bmiHeader.biClrUsed;
1657 if (colors > 256) colors = 256;
1658 if (!colors && (info->bmiHeader.biBitCount <= 8))
1659 colors = 1 << info->bmiHeader.biBitCount;
1660 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
1661 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
1662 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
1663 }
1664 }
1665
1666 HPALETTE
1667 FASTCALL
1668 DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
1669 {
1670 PALETTEENTRY* ppalEntries;
1671 ULONG nNumColors,i;
1672 USHORT *lpIndex;
1673 HPALETTE hpal;
1674
1675 if (ppal->Mode != PAL_INDEXED)
1676 {
1677 return NULL;
1678 }
1679
1680 nNumColors = 1 << lpbmi->bmiHeader.biBitCount;
1681 if (lpbmi->bmiHeader.biClrUsed)
1682 {
1683 nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
1684 }
1685
1686 /* Don't have more colors than we need */
1687 nNumColors = min(ppal->NumColors, nNumColors);
1688
1689 ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
1690 if (ppalEntries == NULL)
1691 {
1692 DPRINT1("Could not allocate palette entries\n");
1693 return NULL;
1694 }
1695
1696 lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
1697
1698 for (i = 0; i < nNumColors; i++)
1699 {
1700 if (*lpIndex < ppal->NumColors)
1701 {
1702 ppalEntries[i] = ppal->IndexedColors[*lpIndex];
1703 }
1704 else
1705 {
1706 ppalEntries[i].peRed = 0;
1707 ppalEntries[i].peGreen = 0;
1708 ppalEntries[i].peBlue = 0;
1709 ppalEntries[i].peFlags = 0;
1710 }
1711
1712 lpIndex++;
1713 }
1714
1715 hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
1716
1717 ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
1718
1719 return hpal;
1720 }
1721
1722 HPALETTE
1723 FASTCALL
1724 BuildDIBPalette(CONST BITMAPINFO *bmi)
1725 {
1726 BYTE bits;
1727 ULONG ColorCount;
1728 HPALETTE hPal;
1729 ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
1730 PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
1731 INT paletteType;
1732
1733 // Determine Bits Per Pixel
1734 bits = bmi->bmiHeader.biBitCount;
1735
1736 // Determine paletteType from Bits Per Pixel
1737 if (bits <= 8)
1738 {
1739 paletteType = PAL_INDEXED;
1740 RedMask = GreenMask = BlueMask = 0;
1741 }
1742 else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
1743 {
1744 paletteType = PAL_BITFIELDS;
1745 RedMask = pdwColors[0];
1746 GreenMask = pdwColors[1];
1747 BlueMask = pdwColors[2];
1748 }
1749 else if (bits == 15)
1750 {
1751 paletteType = PAL_RGB16_555;
1752 }
1753 else if (bits == 16)
1754 {
1755 paletteType = PAL_RGB16_565;
1756 }
1757 else
1758 {
1759 paletteType = PAL_BGR;
1760 }
1761
1762 if (bmi->bmiHeader.biClrUsed == 0)
1763 {
1764 ColorCount = 1 << bmi->bmiHeader.biBitCount;
1765 }
1766 else
1767 {
1768 ColorCount = bmi->bmiHeader.biClrUsed;
1769 }
1770
1771 if (PAL_INDEXED == paletteType)
1772 {
1773 hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
1774 }
1775 else
1776 {
1777 hPal = PALETTE_AllocPalette(paletteType, 0,
1778 NULL,
1779 RedMask, GreenMask, BlueMask);
1780 }
1781
1782 return hPal;
1783 }
1784
1785 /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
1786 * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
1787 BITMAPINFO*
1788 FASTCALL
1789 DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
1790 {
1791 CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
1792 BITMAPINFO* pNewBmi ;
1793 UINT numColors = 0, ColorsSize = 0;
1794
1795 if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
1796 if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
1797
1798 if(pbmci->bmciHeader.bcBitCount <= 8)
1799 {
1800 numColors = 1 << pbmci->bmciHeader.bcBitCount;
1801 if(Usage == DIB_PAL_COLORS)
1802 {
1803 ColorsSize = numColors * sizeof(WORD);
1804 }
1805 else
1806 {
1807 ColorsSize = numColors * sizeof(RGBQUAD);
1808 }
1809 }
1810 else if (Usage == DIB_PAL_COLORS)
1811 {
1812 /* Invalid at high Res */
1813 return NULL;
1814 }
1815
1816 pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
1817 if(!pNewBmi) return NULL;
1818
1819 RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
1820
1821 pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1822 pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
1823 pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
1824 pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
1825 pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
1826 pNewBmi->bmiHeader.biCompression = BI_RGB ;
1827 pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
1828 pNewBmi->bmiHeader.biHeight,
1829 pNewBmi->bmiHeader.biBitCount);
1830
1831 if(Usage == DIB_PAL_COLORS)
1832 {
1833 RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
1834 }
1835 else
1836 {
1837 UINT i;
1838 for(i=0; i<numColors; i++)
1839 {
1840 pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
1841 pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
1842 pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
1843 }
1844 }
1845
1846 return pNewBmi ;
1847 }
1848
1849 /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
1850 VOID
1851 FASTCALL
1852 DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
1853 {
1854 if(converted != orig)
1855 ExFreePoolWithTag(converted, TAG_DIB);
1856 }
1857
1858
1859
1860
1861
1862
1863 /* EOF */