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