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