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