{ 0xff, 0xff, 0xff }
};
-
-UINT
-APIENTRY
-IntSetDIBColorTable(
- HDC hDC,
- UINT StartIndex,
- UINT Entries,
- CONST RGBQUAD *Colors)
+PPALETTE
+NTAPI
+CreateDIBPalette(
+ _In_ const BITMAPINFO *pbmi,
+ _In_ PDC pdc,
+ _In_ ULONG iUsage)
{
- PDC dc;
- PSURFACE psurf;
- PPALETTE PalGDI;
- UINT Index;
- ULONG biBitCount;
+ PPALETTE ppal;
+ ULONG i, cBitsPixel, cColors;
- if (!(dc = DC_LockDc(hDC))) return 0;
- if (dc->dctype == DC_TYPE_INFO)
+ if (pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
{
- DC_UnlockDc(dc);
- return 0;
+ PBITMAPCOREINFO pbci = (PBITMAPCOREINFO)pbmi;
+ cBitsPixel = pbci->bmciHeader.bcBitCount;
}
-
- psurf = dc->dclevel.pSurface;
- if (psurf == NULL)
+ else
{
- DC_UnlockDc(dc);
- EngSetLastError(ERROR_INVALID_PARAMETER);
- return 0;
+ cBitsPixel = pbmi->bmiHeader.biBitCount;
}
- if (psurf->hSecure == NULL)
+ /* Check if the colors are indexed */
+ if (cBitsPixel <= 8)
{
- DC_UnlockDc(dc);
- EngSetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
+ /* We create a "full" palette */
+ cColors = 1 << cBitsPixel;
- biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
- if ((biBitCount <= 8) && (StartIndex < (1UL << biBitCount)))
- {
- if (StartIndex + Entries > (1UL << biBitCount))
- Entries = (1 << biBitCount) - StartIndex;
+ /* Allocate the palette */
+ ppal = PALETTE_AllocPalette(PAL_INDEXED,
+ cColors,
+ NULL,
+ 0,
+ 0,
+ 0);
- if (psurf->ppal == NULL)
+ /* Check if the BITMAPINFO specifies how many colors to use */
+ if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
+ (pbmi->bmiHeader.biClrUsed != 0))
{
- DC_UnlockDc(dc);
- EngSetLastError(ERROR_INVALID_HANDLE);
- return 0;
+ /* This is how many colors we can actually process */
+ cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
}
- PalGDI = psurf->ppal;
-
- for (Index = StartIndex;
- Index < StartIndex + Entries && Index < PalGDI->NumColors;
- Index++)
+ /* Check how to use the colors */
+ if (iUsage == DIB_PAL_COLORS)
{
- PalGDI->IndexedColors[Index].peRed = Colors[Index - StartIndex].rgbRed;
- PalGDI->IndexedColors[Index].peGreen = Colors[Index - StartIndex].rgbGreen;
- PalGDI->IndexedColors[Index].peBlue = Colors[Index - StartIndex].rgbBlue;
- }
- }
- else
- Entries = 0;
+ COLORREF crColor;
- /* Mark the brushes invalid */
- dc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE|DIRTY_BACKGROUND|DIRTY_TEXT;
+ /* The colors are an array of WORD indices into the DC palette */
+ PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
- DC_UnlockDc(dc);
+ /* Use the DCs palette or, if no DC is given, the default one */
+ PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
- return Entries;
-}
+ /* Loop all color indices in the DIB */
+ for (i = 0; i < cColors; i++)
+ {
+ /* Get the palette index and handle wraparound when exceeding
+ the number of colors in the DC palette */
+ WORD wIndex = pwColors[i] % ppalDC->NumColors;
-UINT
-APIENTRY
-IntGetDIBColorTable(
- HDC hDC,
- UINT StartIndex,
- UINT Entries,
- RGBQUAD *Colors)
-{
- PDC dc;
- PSURFACE psurf;
- PPALETTE ppal;
- UINT Index, Count = 0;
+ /* USe the RGB value from the DC palette */
+ crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, wIndex);
+ PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
+ }
+ }
+ else if (iUsage == DIB_PAL_BRUSHHACK)
+ {
+ /* The colors are an array of WORD indices into the DC palette */
+ PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
- if (!(dc = DC_LockDc(hDC))) return 0;
- if (dc->dctype == DC_TYPE_INFO)
- {
- DC_UnlockDc(dc);
- return 0;
- }
+ /* Loop all color indices in the DIB */
+ for (i = 0; i < cColors; i++)
+ {
+ /* Set the index directly as the RGB color, the real palette
+ containing RGB values will be calculated when the brush is
+ realized */
+ PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
+ }
- psurf = dc->dclevel.pSurface;
- if (psurf == NULL)
- {
- DC_UnlockDc(dc);
- EngSetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
+ /* Mark the palette as a brush hack palette */
+ ppal->flFlags |= PAL_BRUSHHACK;
+ }
+// else if (iUsage == 2)
+// {
+ // FIXME: this one is undocumented
+// ASSERT(FALSE);
+// }
+ else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
+ {
+ /* The colors are an array of RGBQUAD values */
+ RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
- if (psurf->hSecure == NULL)
- {
- DC_UnlockDc(dc);
- EngSetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
+ // FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
- ppal = psurf->ppal;
- ASSERT(ppal);
+ /* Loop all color indices in the DIB */
+ for (i = 0; i < cColors; i++)
+ {
+ /* Get the color value and translate it to a COLORREF */
+ RGBQUAD rgb = prgb[i];
+ COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
- if (ppal->flFlags & PAL_INDEXED)
+ /* Set the RGB value in the palette */
+ PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
+ }
+ }
+ else
+ {
+ /* The colors are an array of RGBTRIPLE values */
+ RGBTRIPLE *prgb = (RGBTRIPLE*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
+
+ /* Loop all color indices in the DIB */
+ for (i = 0; i < cColors; i++)
+ {
+ /* Get the color value and translate it to a COLORREF */
+ RGBTRIPLE rgb = prgb[i];
+ COLORREF crColor = RGB(rgb.rgbtRed, rgb.rgbtGreen, rgb.rgbtBlue);
+
+ /* Set the RGB value in the palette */
+ PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
+ }
+ }
+ }
+ else
{
+ /* This is a bitfield / RGB palette */
+ ULONG flRedMask, flGreenMask, flBlueMask;
- for (Index = StartIndex;
- Index < StartIndex + Entries && Index < ppal->NumColors;
- Index++)
+ /* Check if the DIB contains bitfield values */
+ if ((pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
+ (pbmi->bmiHeader.biCompression == BI_BITFIELDS))
{
- Colors[Index - StartIndex].rgbRed = ppal->IndexedColors[Index].peRed;
- Colors[Index - StartIndex].rgbGreen = ppal->IndexedColors[Index].peGreen;
- Colors[Index - StartIndex].rgbBlue = ppal->IndexedColors[Index].peBlue;
- Colors[Index - StartIndex].rgbReserved = 0;
- Count++;
+ /* Check if we have a v4/v5 header */
+ if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
+ {
+ /* The masks are dedicated fields in the header */
+ PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
+ flRedMask = pbmV4Header->bV4RedMask;
+ flGreenMask = pbmV4Header->bV4GreenMask;
+ flBlueMask = pbmV4Header->bV4BlueMask;
+ }
+ else
+ {
+ /* The masks are the first 3 values in the DIB color table */
+ PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
+ flRedMask = pdwColors[0];
+ flGreenMask = pdwColors[1];
+ flBlueMask = pdwColors[2];
+ }
+ }
+ else
+ {
+ /* Check what bit depth we have. Note: optimization flags are
+ calculated in PALETTE_AllocPalette() */
+ if (cBitsPixel == 16)
+ {
+ /* This is an RGB 555 palette */
+ flRedMask = 0x7C00;
+ flGreenMask = 0x03E0;
+ flBlueMask = 0x001F;
+ }
+ else
+ {
+ /* This is an RGB 888 palette */
+ flRedMask = 0xFF0000;
+ flGreenMask = 0x00FF00;
+ flBlueMask = 0x0000FF;
+ }
}
- }
- DC_UnlockDc(dc);
+ /* Allocate the bitfield palette */
+ ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
+ 0,
+ NULL,
+ flRedMask,
+ flGreenMask,
+ flBlueMask);
+ }
- return Count;
+ /* We're done, return the palette */
+ return ppal;
}
// Converts a DIB to a device-dependent bitmap
RECT rcDst;
POINTL ptSrc;
EXLATEOBJ exlo;
- HPALETTE hpalDIB = 0;
PPALETTE ppalDIB = 0;
+ if (!bmi) return 0;
+
SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
ScanLines,
0,
}
/* Create a palette for the DIB */
- hpalDIB = BuildDIBPalette(bmi);
- if (!hpalDIB)
- {
- EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
- goto cleanup;
- }
-
- /* Lock the DIB palette */
- ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
+ ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
if (!ppalDIB)
{
- EngSetLastError(ERROR_INVALID_HANDLE);
+ EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
goto cleanup;
}
cleanup:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
- if (hpalDIB) GreDeleteObject(hpalDIB);
if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
GreDeleteObject(SourceBitmap);
return result;
}
+static
+HBITMAP
+IntGdiCreateMaskFromRLE(
+ DWORD Width,
+ DWORD Height,
+ ULONG Compression,
+ const BYTE* Bits,
+ DWORD BitsSize)
+{
+ HBITMAP Mask;
+ DWORD x, y;
+ SURFOBJ* SurfObj;
+ UINT i = 0;
+ BYTE Data, NumPixels, ToSkip;
+
+ ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
+
+ /* Create the bitmap */
+ Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
+ if (!Mask)
+ return NULL;
+
+ SurfObj = EngLockSurface((HSURF)Mask);
+ if (!SurfObj)
+ {
+ GreDeleteObject(Mask);
+ return NULL;
+ }
+ ASSERT(SurfObj->pvBits != NULL);
+
+ x = y = 0;
+
+ while (i < BitsSize)
+ {
+ NumPixels = Bits[i];
+ Data = Bits[i + 1];
+ i += 2;
+
+ if (NumPixels != 0)
+ {
+ if ((x + NumPixels) > Width)
+ NumPixels = Width - x;
+
+ if (NumPixels == 0)
+ continue;
+
+ DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+ x += NumPixels;
+ continue;
+ }
+
+ if (Data < 3)
+ {
+ switch (Data)
+ {
+ case 0:
+ /* End of line */
+ y++;
+ if (y == Height)
+ goto done;
+ x = 0;
+ break;
+ case 1:
+ /* End of file */
+ goto done;
+ case 2:
+ /* Jump */
+ if (i >= (BitsSize - 1))
+ goto done;
+ x += Bits[i];
+ if (x > Width)
+ x = Width;
+ y += Bits[i + 1];
+ if (y >= Height)
+ goto done;
+ i += 2;
+ break;
+ }
+ /* Done for this run */
+ continue;
+ }
+
+ /* Embedded data into the RLE */
+ NumPixels = Data;
+ if (Compression == BI_RLE8)
+ ToSkip = NumPixels;
+ else
+ ToSkip = (NumPixels / 2) + (NumPixels & 1);
+
+ if ((i + ToSkip) > BitsSize)
+ goto done;
+ ToSkip = (ToSkip + 1) & ~1;
+
+ if ((x + NumPixels) > Width)
+ NumPixels = Width - x;
+
+ if (NumPixels != 0)
+ {
+ DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+ x += NumPixels;
+ }
+ i += ToSkip;
+ }
+
+done:
+ EngUnlockSurface(SurfObj);
+ return Mask;
+}
+
W32KAPI
INT
APIENTRY
INT ret = 0;
NTSTATUS Status = STATUS_SUCCESS;
PDC pDC;
- HBITMAP hSourceBitmap = NULL;
- SURFOBJ *pDestSurf, *pSourceSurf = NULL;
+ HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
+ SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
SURFACE *pSurf;
RECTL rcDest;
POINTL ptSource;
SIZEL SourceSize;
EXLATEOBJ exlo;
PPALETTE ppalDIB = NULL;
- HPALETTE hpalDIB = NULL;
LPBITMAPINFO pbmiSafe;
if (!Bits) return 0;
goto Exit2;
}
+ ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
+
pDC = DC_LockDc(hDC);
if (!pDC)
{
EngSetLastError(ERROR_INVALID_HANDLE);
goto Exit2;
}
+
if (pDC->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(pDC);
- goto Exit2;
+ goto Exit;
}
- pSurf = pDC->dclevel.pSurface;
-
- pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
-
- ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
-
rcDest.left = XDest;
rcDest.top = YDest;
if (bTransformCoordinates)
goto Exit;
}
- ASSERT(pSurf->ppal);
+ /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
+ if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
+ {
+ hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
+ ScanLines,
+ bmi->bmiHeader.biCompression,
+ Bits,
+ cjMaxBits);
+ if (!hMaskBitmap)
+ {
+ EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
+ Status = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+ pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
+ if (!pMaskSurf)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+ }
/* Create a palette for the DIB */
- hpalDIB = BuildDIBPalette(bmi);
- if (!hpalDIB)
+ ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
+ if (!ppalDIB)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
Status = STATUS_NO_MEMORY;
goto Exit;
}
- /* Lock the DIB palette */
- ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
- if (!ppalDIB)
+ /* This is actually a blit */
+ DC_vPrepareDCsForBlit(pDC, &rcDest, NULL, NULL);
+ pSurf = pDC->dclevel.pSurface;
+ if (!pSurf)
{
- EngSetLastError(ERROR_INVALID_HANDLE);
- Status = STATUS_UNSUCCESSFUL;
+ DC_vFinishBlit(pDC, NULL);
+ ret = ScanLines;
goto Exit;
}
+ ASSERT(pSurf->ppal);
+
/* Initialize EXLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
pDC->pdcattr->crBackgroundClr,
pDC->pdcattr->crForegroundClr);
+ pDestSurf = &pSurf->SurfObj;
+
/* Copy the bits */
DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
Status = IntEngBitBlt(pDestSurf,
pSourceSurf,
- NULL,
- pDC->rosdc.CombinedClip,
+ pMaskSurf,
+ &pDC->co.ClipObj,
&exlo.xlo,
&rcDest,
&ptSource,
+ pMaskSurf ? &ptSource : NULL,
NULL,
NULL,
- NULL,
- ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
+ pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
/* Cleanup EXLATEOBJ */
EXLATEOBJ_vCleanup(&exlo);
+ /* We're done */
+ DC_vFinishBlit(pDC, NULL);
+
Exit:
if (NT_SUCCESS(Status))
{
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
- if (hpalDIB) GreDeleteObject(hpalDIB);
+ if (pMaskSurf) EngUnlockSurface(pMaskSurf);
+ if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
DC_UnlockDc(pDC);
Exit2:
- ExFreePool(pbmiSafe);
+ ExFreePoolWithTag(pbmiSafe, 'pmTG');
return ret;
}
/* Converts a device-dependent bitmap to a DIB */
INT
APIENTRY
-NtGdiGetDIBitsInternal(
+GreGetDIBitsInternal(
HDC hDC,
HBITMAP hBitmap,
UINT StartScan,
DWORD compr, size ;
USHORT i;
int bitmap_type;
- RGBTRIPLE* rgbTriples;
RGBQUAD* rgbQuads;
VOID* colorPtr;
- NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Entered NtGdiGetDIBitsInternal()\n");
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
return 0;
- _SEH2_TRY
- {
- /* Probe for read and write */
- ProbeForRead(Info, MaxInfo, 1);
- ProbeForWrite(Info, MaxInfo, 1);
- if (Bits) ProbeForWrite(Bits, MaxBits, 1);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END
-
- if (!NT_SUCCESS(Status))
- {
- return 0;
- }
-
colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
- rgbTriples = colorPtr;
rgbQuads = colorPtr;
bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
switch(bpp)
{
case 0: /* Only info */
- if(pbmci)
- {
- pbmci->bmciHeader.bcWidth = (WORD)psurf->SurfObj.sizlBitmap.cx;
- pbmci->bmciHeader.bcHeight = (WORD)((psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
- -psurf->SurfObj.sizlBitmap.cy :
- psurf->SurfObj.sizlBitmap.cy);
- pbmci->bmciHeader.bcPlanes = 1;
- pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
- }
Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
-psurf->SurfObj.sizlBitmap.cy :
if(Usage == DIB_RGB_COLORS)
{
ULONG colors = min(psurf->ppal->NumColors, 256);
-
- if(pbmci)
- {
- for(i = 0; i < colors; i++)
- {
- rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
- rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
- rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
- }
- }
if(colors != 256) Info->bmiHeader.biClrUsed = colors;
for(i = 0; i < colors; i++)
{
rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
+ rgbQuads[i].rgbReserved = 0;
}
}
else
{
for(i = 0; i < 256; i++)
- {
- if(pbmci) ((WORD*)rgbTriples)[i] = i;
((WORD*)rgbQuads)[i] = i;
- }
}
}
else
{
for(i = 0; i < 256; i++)
{
- if(pbmci) ((WORD*)rgbTriples)[i] = i;
((WORD*)rgbQuads)[i] = i;
}
}
}
for (i = 0; i < pDcPal->NumColors; i++)
{
- if (pbmci)
- {
- rgbTriples[i].rgbtRed = pDcPal->IndexedColors[i].peRed;
- rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
- rgbTriples[i].rgbtBlue = pDcPal->IndexedColors[i].peBlue;
- }
-
rgbQuads[i].rgbRed = pDcPal->IndexedColors[i].peRed;
rgbQuads[i].rgbGreen = pDcPal->IndexedColors[i].peGreen;
rgbQuads[i].rgbBlue = pDcPal->IndexedColors[i].peBlue;
switch (bpp)
{
case 1:
- if (pbmci)
- {
- rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
- rgbTriples[0].rgbtBlue = 0;
- rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
- rgbTriples[1].rgbtBlue = 0xff;
- }
- rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
- rgbQuads[0].rgbBlue = 0;
+ rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
rgbQuads[0].rgbReserved = 0;
- rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
- rgbQuads[1].rgbBlue = 0xff;
+ rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
rgbQuads[1].rgbReserved = 0;
break;
case 4:
- if (pbmci)
- RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
-
break;
case 8:
{
INT r, g, b;
RGBQUAD *color;
- if (pbmci)
- {
- RGBTRIPLE *colorTriple;
-
- RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
- 10 * sizeof(RGBTRIPLE));
- RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
- 10 * sizeof(RGBTRIPLE));
- colorTriple = rgbTriples + 10;
- for(r = 0; r <= 5; r++) /* FIXME */
- {
- for(g = 0; g <= 5; g++)
- {
- for(b = 0; b <= 5; b++)
- {
- colorTriple->rgbtRed = (r * 0xff) / 5;
- colorTriple->rgbtGreen = (g * 0xff) / 5;
- colorTriple->rgbtBlue = (b * 0xff) / 5;
- color++;
- }
- }
- }
- }
memcpy(rgbQuads, DefLogPaletteQuads,
10 * sizeof(RGBQUAD));
memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
psurfDest = SURFACE_ShareLockSurface(hBmpDest);
- rcDest.left = 0;
- rcDest.top = 0;
- rcDest.bottom = ScanLines;
- rcDest.right = psurf->SurfObj.sizlBitmap.cx;
+ RECTL_vSetRect(&rcDest, 0, 0, psurf->SurfObj.sizlBitmap.cx, ScanLines);
srcPoint.x = 0;
ScanLines = 0;
else
{
- Status = STATUS_SUCCESS;
- _SEH2_TRY
- {
- RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END
-
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to copy bits to the user provided pointer\n");
- ScanLines = 0;
- }
+ RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
}
GreDeleteObject(hBmpDest);
if(pDC) DC_UnlockDc(pDC);
if(psurf) SURFACE_ShareUnlockSurface(psurf);
- if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
+ if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage);
return ScanLines;
}
+INT
+APIENTRY
+NtGdiGetDIBitsInternal(
+ _In_ HDC hdc,
+ _In_ HBITMAP hbm,
+ _In_ UINT iStartScan,
+ _In_ UINT cScans,
+ _Out_opt_ LPBYTE pjBits,
+ _Inout_ LPBITMAPINFO pbmiUser,
+ _In_ UINT iUsage,
+ _In_ UINT cjMaxBits,
+ _In_ UINT cjMaxInfo)
+{
+ PBITMAPINFO pbmi;
+ HANDLE hSecure = NULL;
+ INT iResult = 0;
+ UINT cjAlloc;
+
+ /* Check for bad iUsage */
+ if (iUsage > 2) return 0;
+
+ /* Check if the size of the bitmap info is large enough */
+ if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
+ {
+ return 0;
+ }
+
+ /* Use maximum size */
+ cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
+
+ // HACK: the underlying code sucks and doesn't care for the size, so we
+ // give it the maximum ever needed
+ cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
+
+ /* Allocate a buffer the bitmapinfo */
+ pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
+ if (!pbmi)
+ {
+ /* Fail */
+ return 0;
+ }
+
+ /* Use SEH */
+ _SEH2_TRY
+ {
+ /* Probe and copy the BITMAPINFO */
+ ProbeForRead(pbmiUser, cjMaxInfo, 1);
+ RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(goto cleanup;)
+ }
+ _SEH2_END;
+
+ /* Check if the header size is large enough */
+ if ((pbmi->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
+ (pbmi->bmiHeader.biSize > cjMaxInfo))
+ {
+ goto cleanup;
+ }
+
+ /* Check if the caller provided bitmap bits */
+ if (pjBits)
+ {
+ /* Secure the user mode memory */
+ hSecure = EngSecureMem(pjBits, cjMaxBits);
+ if (!hSecure)
+ {
+ goto cleanup;
+ }
+ }
+
+ /* Now call the internal function */
+ iResult = GreGetDIBitsInternal(hdc,
+ hbm,
+ iStartScan,
+ cScans,
+ pjBits,
+ pbmi,
+ iUsage,
+ cjMaxBits,
+ cjMaxInfo);
+
+ /* Check for success */
+ if (iResult)
+ {
+ /* Use SEH to copy back to user mode */
+ _SEH2_TRY
+ {
+ /* Copy the data back */
+ ProbeForWrite(pbmiUser, cjMaxInfo, 1);
+ RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Ignore */
+ }
+ _SEH2_END;
+ }
+
+cleanup:
+ if (hSecure) EngUnsecureMem(hSecure);
+ ExFreePoolWithTag(pbmi, 'imBG');
+
+ return iResult;
+}
+
+
#define ROP_TO_ROP4(Rop) ((Rop) >> 16)
W32KAPI
PDC pdc;
HBITMAP hbmTmp = 0;
PSURFACE psurfTmp = 0, psurfDst = 0;
- HPALETTE hpalDIB = 0;
PPALETTE ppalDIB = 0;
EXLATEOBJ exlo;
PVOID pvBits;
return 0;
}
+ /* Check for info / mem DC without surface */
+ if (!pdc->dclevel.pSurface)
+ {
+ DC_UnlockDc(pdc);
+ // CHECKME
+ return TRUE;
+ }
+
/* Transform dest size */
sizel.cx = cxDst;
sizel.cy = cyDst;
hcmXform);
}
- pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
- if (!pvBits)
+ if (pjInit && (cjMaxBits > 0))
{
- return 0;
- }
+ pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
+ if (!pvBits)
+ {
+ return 0;
+ }
- _SEH2_TRY
- {
- ProbeForRead(pjInit, cjMaxBits, 1);
- RtlCopyMemory(pvBits, pjInit, cjMaxBits);
+ _SEH2_TRY
+ {
+ ProbeForRead(pjInit, cjMaxBits, 1);
+ RtlCopyMemory(pvBits, pjInit, cjMaxBits);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ExFreePoolWithTag(pvBits, 'pmeT');
+ _SEH2_YIELD(return 0);
+ }
+ _SEH2_END
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else
{
- _SEH2_YIELD(return 0);
+ pvBits = NULL;
}
- _SEH2_END
/* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
if (!(pdc = DC_LockDc(hdc)))
goto cleanup;
}
- psurfDst = pdc->dclevel.pSurface;
- if (!psurfDst)
- {
- // CHECKME
- bResult = TRUE;
- goto cleanup;
- }
-
/* Calculate source and destination rect */
rcSrc.left = xSrc;
rcSrc.top = ySrc;
}
/* Create a palette for the DIB */
- hpalDIB = BuildDIBPalette(pbmi);
- if (!hpalDIB)
- {
- bResult = FALSE;
- goto cleanup;
- }
-
- /* Lock the DIB palette */
- ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
+ ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
if (!ppalDIB)
{
bResult = FALSE;
goto cleanup;
}
+ /* Prepare DC for blit */
+ DC_vPrepareDCsForBlit(pdc, &rcDst, NULL, NULL);
+
+ psurfDst = pdc->dclevel.pSurface;
+
/* Initialize XLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
pdc->pdcattr->crBackgroundClr,
pdc->pdcattr->crForegroundClr);
- /* Prepare DC for blit */
- DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
-
/* Perform the stretch operation */
bResult = IntEngStretchBlt(&psurfDst->SurfObj,
&psurfTmp->SurfObj,
NULL,
- pdc->rosdc.CombinedClip,
+ &pdc->co.ClipObj,
&exlo.xlo,
+ &pdc->dclevel.ca,
&rcDst,
&rcSrc,
NULL,
EXLATEOBJ_vCleanup(&exlo);
cleanup:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
- if (hpalDIB) GreDeleteObject(hpalDIB);
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
if (hbmTmp) GreDeleteObject(hbmTmp);
if (pdc) DC_UnlockDc(pdc);
- ExFreePoolWithTag(pvBits, 'pmeT');
+ if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
return bResult;
}
if(pjInit && (fInit == CBM_INIT))
{
+ if (cjMaxBits == 0) return NULL;
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
if(!safeBits)
{
pbmi,
iUsage,
fl,
+ cjMaxBits,
hcmXform);
cleanup:
}
HBITMAP
-FASTCALL
+NTAPI
GreCreateDIBitmapInternal(
IN HDC hDc,
IN INT cx,
IN OPTIONAL PBITMAPINFO pbmi,
IN DWORD iUsage,
IN FLONG fl,
+ IN UINT cjMaxBits,
IN HANDLE hcmXform)
{
PDC Dc;
HBITMAP res = 0;
SURFACE *bmp = NULL;
void *mapBits = NULL;
- HPALETTE hpal ;
+ PPALETTE ppalDIB = NULL;
// Fill BITMAP32 structure with DIB data
CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
//SIZEL Size;
HANDLE hSecure;
- DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
+ DPRINT("format (%ld,%ld), planes %u, bpp %u, size %lu, colors %lu (%s)\n",
bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
// hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
- if (usage == DIB_PAL_COLORS)
- {
- if(dc)
- {
- PPALETTE ppalDc;
- ppalDc = PALETTE_ShareLockPalette(dc->dclevel.hpal);
- hpal = DIB_MapPaletteColors(ppalDc, bmi);
- PALETTE_ShareUnlockPalette(ppalDc);
- }
- else
- {
- /* For DIB Brushes */
- DPRINT1("FIXME: Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
- /* HACK */
- hpal = (HPALETTE) 0xFFFFFFFF;
- }
- }
- else
- {
- hpal = BuildDIBPalette(bmi);
- }
-
- if(!hpal)
- {
- DPRINT1("Error: Could not create a palette for the DIB.\n");
- goto cleanup;
- }
// Create Device Dependent Bitmap and add DIB pointer
//Size.cx = bm.bmWidth;
bmp->flags = API_BITMAP;
bmp->biClrImportant = bi->biClrImportant;
- /* HACK */
- if(hpal != (HPALETTE)0xFFFFFFFF)
- {
- bmp->ppal = PALETTE_ShareLockPalette(hpal);
- /* Lazy delete hpal, it will be freed at surface release */
- GreDeleteObject(hpal);
- }
+ /* Create a palette for the DIB */
+ ppalDIB = CreateDIBPalette(bmi, dc, usage);
// Clean up in case of errors
cleanup:
- if (!res || !bmp || !bm.bmBits)
+ if (!res || !bmp || !bm.bmBits || !ppalDIB)
{
- DPRINT("Got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
+ DPRINT("Got an error res=%p, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
if (bm.bmBits)
{
// MmUnsecureVirtualMemory(hSecure); // FIXME: Implement this!
}
if (bmp)
+ {
+ SURFACE_ShareUnlockSurface(bmp);
bmp = NULL;
+ }
if (res)
{
GreDeleteObject(res);
res = 0;
}
+
+ if(ppalDIB)
+ {
+ PALETTE_ShareUnlockPalette(ppalDIB);
+ }
}
if (bmp)
{
+ /* If we're here, everything went fine */
+ SURFACE_vSetPalette(bmp, ppalDIB);
+ PALETTE_ShareUnlockPalette(ppalDIB);
SURFACE_ShareUnlockSurface(bmp);
}
*size = header->biSizeImage;
return 1;
}
- DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
+ DPRINT1("(%u): unknown/wrong size for header\n", header->biSize );
return -1;
}
HPALETTE
FASTCALL
-DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
+DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
{
- PALETTEENTRY* ppalEntries;
+ PPALETTE ppalNew;
ULONG nNumColors,i;
USHORT *lpIndex;
HPALETTE hpal;
- if (!(ppal->flFlags & PAL_INDEXED))
+ if (!(ppalDc->flFlags & PAL_INDEXED))
{
return NULL;
}
nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
}
- ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
- if (ppalEntries == NULL)
+ ppalNew = PALETTE_AllocPalWithHandle(PAL_INDEXED, nNumColors, NULL, 0, 0, 0);
+ if (ppalNew == NULL)
{
- DPRINT1("Could not allocate palette entries\n");
+ DPRINT1("Could not allocate palette\n");
return NULL;
}
for (i = 0; i < nNumColors; i++)
{
- ppalEntries[i] = ppal->IndexedColors[*lpIndex % ppal->NumColors];
-
+ ULONG iColorIndex = *lpIndex % ppalDc->NumColors;
+ ppalNew->IndexedColors[i] = ppalDc->IndexedColors[iColorIndex];
lpIndex++;
}
- hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
-
- ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
+ hpal = ppalNew->BaseObject.hHmgr;
+ PALETTE_UnlockPalette(ppalNew);
return hpal;
}
-HPALETTE
-FASTCALL
-BuildDIBPalette(CONST BITMAPINFO *bmi)
-{
- WORD bits;
- ULONG ColorCount;
- HPALETTE hPal;
- ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
- PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
- INT paletteType;
-
- // Determine Bits Per Pixel
- bits = bmi->bmiHeader.biBitCount;
-
- // Determine paletteType from Bits Per Pixel
- if (bits <= 8)
- {
- paletteType = PAL_INDEXED;
- RedMask = GreenMask = BlueMask = 0;
- }
- else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
- {
- paletteType = PAL_BITFIELDS;
- if (bmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
- {
- PBITMAPV4HEADER pV4Header = (PBITMAPV4HEADER)&bmi->bmiHeader;
- RedMask = pV4Header->bV4RedMask;
- GreenMask = pV4Header->bV4GreenMask;
- BlueMask = pV4Header->bV4BlueMask;
- }
- else
- {
- RedMask = pdwColors[0];
- GreenMask = pdwColors[1];
- BlueMask = pdwColors[2];
- }
- }
- else
- {
- paletteType = PAL_BITFIELDS;
- switch (bits)
- {
- case 16:
- paletteType |= PAL_RGB16_555;
- RedMask = 0x7C00;
- GreenMask = 0x03E0;
- BlueMask = 0x001F;
- break;
-
- case 24:
- case 32:
- paletteType |= PAL_BGR;
- RedMask = 0xFF0000;
- GreenMask = 0x00FF00;
- BlueMask = 0x0000FF;
- break;
- }
- }
-
- if (bmi->bmiHeader.biClrUsed == 0)
- {
- ColorCount = 1 << bmi->bmiHeader.biBitCount;
- }
- else
- {
- ColorCount = bmi->bmiHeader.biClrUsed;
- }
-
- if (PAL_INDEXED == paletteType)
- {
- hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
- }
- else
- {
- hPal = PALETTE_AllocPalette(paletteType, 0,
- NULL,
- RedMask, GreenMask, BlueMask);
- }
-
- return hPal;
-}
-
/* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
* or does nothing if it's already a BITMAPINFO (or V4 or V5) */
BITMAPINFO*
/* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
VOID
FASTCALL
-DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig, DWORD usage)
{
- if(converted != orig)
+ BITMAPCOREINFO* pbmci;
+ if(converted == orig)
+ return;
+
+ if(usage == -1)
+ {
+ /* Caller don't want any conversion */
ExFreePoolWithTag(converted, TAG_DIB);
+ return;
+ }
+
+ /* Perform inverse conversion */
+ pbmci = (BITMAPCOREINFO*)orig;
+
+ ASSERT(pbmci->bmciHeader.bcSize == sizeof(BITMAPCOREHEADER));
+ pbmci->bmciHeader.bcBitCount = converted->bmiHeader.biBitCount;
+ pbmci->bmciHeader.bcWidth = converted->bmiHeader.biWidth;
+ pbmci->bmciHeader.bcHeight = converted->bmiHeader.biHeight;
+ pbmci->bmciHeader.bcPlanes = converted->bmiHeader.biPlanes;
+
+ if(pbmci->bmciHeader.bcBitCount <= 8)
+ {
+ UINT numColors = converted->bmiHeader.biClrUsed;
+ if(!numColors) numColors = 1 << pbmci->bmciHeader.bcBitCount;
+ if(usage == DIB_PAL_COLORS)
+ {
+ RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(WORD));
+ RtlCopyMemory(pbmci->bmciColors, converted->bmiColors, numColors * sizeof(WORD));
+ }
+ else
+ {
+ UINT i;
+ RtlZeroMemory(pbmci->bmciColors, (1 << pbmci->bmciHeader.bcBitCount) * sizeof(RGBTRIPLE));
+ for(i=0; i<numColors; i++)
+ {
+ pbmci->bmciColors[i].rgbtRed = converted->bmiColors[i].rgbRed;
+ pbmci->bmciColors[i].rgbtGreen = converted->bmiColors[i].rgbGreen;
+ pbmci->bmciColors[i].rgbtBlue = converted->bmiColors[i].rgbBlue;
+ }
+ }
+ }
+ /* Now free it, it's not needed anymore */
+ ExFreePoolWithTag(converted, TAG_DIB);
}
/* EOF */