[PATCH v2 1/4] winex11.drv: Fix handling of DIBs on the clipboard.
Charles Davis
cdavis5x at gmail.com
Tue May 3 14:03:23 CDT 2016
Signed-off-by: Charles Davis <cdavis5x at gmail.com>
---
Try 2:
* Stop assuming biSize is the size of the whole DIB, not just the header size.
* Handle OS/2 bitmaps. (Yes, Windows really does support this!)
---
dlls/winex11.drv/bitblt.c | 97 +++++++++--
dlls/winex11.drv/clipboard.c | 379 +++++++++++++++++++++++++++++++++++++++----
2 files changed, 431 insertions(+), 45 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c
index 8d61a4b..d7405e6 100644
--- a/dlls/winex11.drv/bitblt.c
+++ b/dlls/winex11.drv/bitblt.c
@@ -928,10 +928,10 @@ static void free_ximage_bits( struct gdi_image_bits *bits )
static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse )
{
if (info->bmiHeader.biCompression == BI_BITFIELDS)
- return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
+ return max( sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD), info->bmiHeader.biSize );
if (coloruse == DIB_PAL_COLORS)
- return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD);
- return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] );
+ return info->bmiHeader.biSize + info->bmiHeader.biClrUsed * sizeof(WORD);
+ return info->bmiHeader.biSize + info->bmiHeader.biClrUsed * sizeof(RGBQUAD);
}
static inline int get_dib_stride( int width, int bpp )
@@ -975,15 +975,38 @@ static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info, BOOL has_a
break;
}
case 16:
- colors[0] = vis->red_mask;
- colors[1] = vis->green_mask;
- colors[2] = vis->blue_mask;
+ if (info->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
+ {
+ /* In V4/V5 DIBs, the BI_BITFIELDS masks are part of the header. */
+ BITMAPV4HEADER *v4info = (BITMAPV4HEADER *)&info->bmiHeader;
+ v4info->bV4RedMask = vis->red_mask;
+ v4info->bV4GreenMask = vis->green_mask;
+ v4info->bV4BlueMask = vis->blue_mask;
+ v4info->bV4AlphaMask = has_alpha ? ~(vis->red_mask|vis->green_mask|vis->blue_mask) & 0xffff : 0;
+ }
+ else
+ {
+ colors[0] = vis->red_mask;
+ colors[1] = vis->green_mask;
+ colors[2] = vis->blue_mask;
+ }
info->bmiHeader.biCompression = BI_BITFIELDS;
break;
case 32:
- colors[0] = vis->red_mask;
- colors[1] = vis->green_mask;
- colors[2] = vis->blue_mask;
+ if (info->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
+ {
+ BITMAPV4HEADER *v4info = (BITMAPV4HEADER *)&info->bmiHeader;
+ v4info->bV4RedMask = vis->red_mask;
+ v4info->bV4GreenMask = vis->green_mask;
+ v4info->bV4BlueMask = vis->blue_mask;
+ v4info->bV4AlphaMask = has_alpha ? ~(vis->red_mask|vis->green_mask|vis->blue_mask) : 0;
+ }
+ else
+ {
+ colors[0] = vis->red_mask;
+ colors[1] = vis->green_mask;
+ colors[2] = vis->blue_mask;
+ }
if (colors[0] != 0xff0000 || colors[1] != 0x00ff00 || colors[2] != 0x0000ff || !has_alpha)
info->bmiHeader.biCompression = BI_BITFIELDS;
break;
@@ -993,7 +1016,11 @@ static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info, BOOL has_a
/* check if the specified color info is suitable for PutImage */
static BOOL matching_color_info( const XVisualInfo *vis, const BITMAPINFO *info )
{
- DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
+ DWORD *colors;
+ if (info->bmiHeader.biCompression == BI_BITFIELDS)
+ colors = (DWORD *)((char *)info + sizeof(BITMAPINFOHEADER));
+ else
+ colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
switch (info->bmiHeader.biBitCount)
{
@@ -1458,8 +1485,8 @@ Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPIN
const struct gdi_image_bits *bits, UINT coloruse )
{
static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } };
- char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
- char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+ char dst_buffer[sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD)];
+ char src_buffer[sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD)];
BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
struct gdi_image_bits dst_bits;
@@ -1478,12 +1505,13 @@ Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPIN
(err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT)
{
if (dst_info->bmiHeader.biBitCount == 1) /* set a default color table for 1-bpp */
- memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) );
+ memcpy( dst_buffer + dst_info->bmiHeader.biSize, default_colortable, sizeof(default_colortable) );
dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 );
if (dib)
{
if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
- memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) );
+ memcpy( src_buffer + src_info->bmiHeader.biSize, default_colortable,
+ sizeof(default_colortable) );
SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse );
dst_bits.free = NULL;
dst_bits.is_copy = TRUE;
@@ -1518,7 +1546,6 @@ DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo
if (!format) return ERROR_INVALID_PARAMETER;
- info->bmiHeader.biSize = sizeof(info->bmiHeader);
info->bmiHeader.biWidth = width;
info->bmiHeader.biHeight = -height;
info->bmiHeader.biPlanes = 1;
@@ -1527,6 +1554,46 @@ DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrImportant = 0;
set_color_info( vis, info, FALSE );
+ if (info->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
+ {
+ HDC hdc = GetDC( 0 );
+ LOGCOLORSPACEW lcs;
+ BITMAPV4HEADER *v4info = (BITMAPV4HEADER *)&info->bmiHeader;
+
+ if (GetLogColorSpaceW( GetColorSpace( hdc ), &lcs, sizeof(lcs) ))
+ {
+ v4info->bV4CSType = lcs.lcsCSType;
+ v4info->bV4Endpoints = lcs.lcsEndpoints;
+ v4info->bV4GammaRed = lcs.lcsGammaRed;
+ v4info->bV4GammaGreen = lcs.lcsGammaGreen;
+ v4info->bV4GammaBlue = lcs.lcsGammaBlue;
+ if (info->bmiHeader.biSize >= sizeof(BITMAPV5HEADER))
+ {
+ BITMAPV5HEADER *v5info = (BITMAPV5HEADER *)&info->bmiHeader;
+ v5info->bV5Intent = lcs.lcsIntent;
+ v5info->bV5ProfileData = 0;
+ v5info->bV5ProfileSize = 0;
+ v5info->bV5Reserved = 0;
+ }
+ }
+ else
+ {
+ v4info->bV4CSType = LCS_DEVICE_RGB;
+ memset( &v4info->bV4Endpoints, 0, sizeof(v4info->bV4Endpoints) );
+ v4info->bV4GammaRed = 0;
+ v4info->bV4GammaGreen = 0;
+ v4info->bV4GammaBlue = 0;
+ if (info->bmiHeader.biSize >= sizeof(BITMAPV5HEADER))
+ {
+ BITMAPV5HEADER *v5info = (BITMAPV5HEADER *)&info->bmiHeader;
+ v5info->bV5Intent = LCS_GM_GRAPHICS;
+ v5info->bV5ProfileData = 0;
+ v5info->bV5ProfileSize = 0;
+ v5info->bV5Reserved = 0;
+ }
+ }
+ ReleaseDC( 0, hdc );
+ }
if (!bits) return ERROR_SUCCESS; /* just querying the color information */
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 5dc5e3c..c514a7f 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -134,7 +134,9 @@ static HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Display *d, Window w, Atom pr
static HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *d, Window w, Atom prop);
+static HANDLE X11DRV_CLIPBOARD_ImportV5XAPIXMAP(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *d, Window w, Atom prop);
+static HANDLE X11DRV_CLIPBOARD_ImportImageV5Bmp(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *d, Window w, Atom prop);
static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *d, Window w, Atom prop);
@@ -166,7 +168,7 @@ static BOOL X11DRV_CLIPBOARD_RenderFormat(Display *display, LPWINE_CLIPDATA lpDa
static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out);
static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID);
static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(Display *display, LPWINE_CLIPDATA lpData);
-static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display);
+static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display, BOOL isV5);
static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display);
static BOOL X11DRV_CLIPBOARD_RenderSynthesizedEnhMetaFile(Display *display);
static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
@@ -191,6 +193,7 @@ static const struct
{ CF_TIFF, XATOM_WCF_TIFF, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_OEMTEXT, XATOM_WCF_OEMTEXT, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DIB, XA_PIXMAP, X11DRV_CLIPBOARD_ImportXAPIXMAP, X11DRV_CLIPBOARD_ExportXAPIXMAP },
+ { CF_DIBV5, XA_PIXMAP, X11DRV_CLIPBOARD_ImportV5XAPIXMAP, X11DRV_CLIPBOARD_ExportXAPIXMAP },
{ CF_PALETTE, XATOM_WCF_PALETTE, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_PENDATA, XATOM_WCF_PENDATA, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_RIFF, XATOM_WCF_RIFF, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
@@ -201,13 +204,13 @@ static const struct
{ CF_ENHMETAFILE, XATOM_WCF_ENHMETAFILE, X11DRV_CLIPBOARD_ImportEnhMetaFile, X11DRV_CLIPBOARD_ExportEnhMetaFile },
{ CF_HDROP, XATOM_text_uri_list, X11DRV_CLIPBOARD_ImportTextUriList, X11DRV_CLIPBOARD_ExportHDROP },
{ CF_LOCALE, XATOM_WCF_LOCALE, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
- { CF_DIBV5, XATOM_WCF_DIBV5, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_OWNERDISPLAY, XATOM_WCF_OWNERDISPLAY, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DSPTEXT, XATOM_WCF_DSPTEXT, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DSPBITMAP, XATOM_WCF_DSPBITMAP, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DSPMETAFILEPICT, XATOM_WCF_DSPMETAFILEPICT, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DSPENHMETAFILE, XATOM_WCF_DSPENHMETAFILE, X11DRV_CLIPBOARD_ImportClipboardData, X11DRV_CLIPBOARD_ExportClipboardData },
{ CF_DIB, XATOM_image_bmp, X11DRV_CLIPBOARD_ImportImageBmp, X11DRV_CLIPBOARD_ExportImageBmp },
+ { CF_DIBV5, XATOM_image_bmp, X11DRV_CLIPBOARD_ImportImageV5Bmp, X11DRV_CLIPBOARD_ExportImageBmp },
};
static struct list format_list = LIST_INIT( format_list );
@@ -581,12 +584,14 @@ static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData)
lpData->wFormatID <= CF_GDIOBJLAST) ||
lpData->wFormatID == CF_BITMAP ||
lpData->wFormatID == CF_DIB ||
+ lpData->wFormatID == CF_DIBV5 ||
lpData->wFormatID == CF_PALETTE)
{
if (lpData->hData)
DeleteObject(lpData->hData);
- if ((lpData->wFormatID == CF_DIB) && lpData->drvData)
+ if ((lpData->wFormatID == CF_DIB || lpData->wFormatID == CF_DIBV5) &&
+ lpData->drvData)
XFreePixmap(gdi_display, lpData->drvData);
}
else if (lpData->wFormatID == CF_METAFILEPICT)
@@ -773,7 +778,8 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(Display *display, LPWINE_CL
switch (wFormatID)
{
case CF_DIB:
- bret = X11DRV_CLIPBOARD_RenderSynthesizedDIB( display );
+ case CF_DIBV5:
+ bret = X11DRV_CLIPBOARD_RenderSynthesizedDIB( display, wFormatID == CF_DIBV5 );
break;
case CF_BITMAP:
@@ -917,12 +923,38 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
}
+static inline int bitmap_image_stride( int width, int bpp )
+{
+ return ((width * bpp + 31) >> 3) & ~3;
+}
+
+
+/***********************************************************************
+ * bitmap_image_size
+ *
+ * Return the size of the bitmap's image data.
+ */
+static int bitmap_image_size( const BITMAPINFOHEADER * info )
+{
+ if (info->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
+ return bitmap_image_stride( core->bcWidth, core->bcBitCount ) * core->bcHeight;
+ }
+ else /* assume BITMAPINFOHEADER */
+ {
+ return info->biSizeImage ? info->biSizeImage :
+ bitmap_image_stride( info->biWidth, info->biBitCount ) * abs( info->biHeight );
+ }
+}
+
+
/***********************************************************************
* create_dib_from_bitmap
*
* Allocates a packed DIB and copies the bitmap data into it.
*/
-static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
+static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp, BOOL isV5)
{
BITMAP bmp;
HDC hdc;
@@ -941,7 +973,7 @@ static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
/* Calculate the size of the packed DIB */
cDataSize = abs( bmp.bmHeight ) * (((bmp.bmWidth * bmp.bmBitsPixel + 31) / 8) & ~3);
- cPackedSize = sizeof(BITMAPINFOHEADER)
+ cPackedSize = isV5 ? sizeof(BITMAPV5HEADER) : sizeof(BITMAPINFOHEADER)
+ ( (bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0 )
+ cDataSize;
/* Get the offset to the bits */
@@ -961,8 +993,10 @@ static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
pPackedDIB = GlobalLock(hPackedDIB);
pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
+ hdc = GetDC( 0 );
+
/* Init the BITMAPINFOHEADER */
- pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
+ pbmiHeader->biSize = isV5 ? sizeof(BITMAPV5HEADER) : sizeof(BITMAPINFOHEADER);
pbmiHeader->biWidth = bmp.bmWidth;
pbmiHeader->biHeight = bmp.bmHeight;
pbmiHeader->biPlanes = 1;
@@ -972,10 +1006,37 @@ static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
pbmiHeader->biClrUsed = 0;
pbmiHeader->biClrImportant = 0;
+ if (isV5)
+ {
+ LOGCOLORSPACEW lcs;
+ BITMAPV5HEADER *pbV5Header = (BITMAPV5HEADER *)pbmiHeader;
+
+ pbV5Header->bV5AlphaMask = 0;
+ if (GetLogColorSpaceW( GetColorSpace( hdc ), &lcs, sizeof(lcs) ))
+ {
+ pbV5Header->bV5CSType = lcs.lcsCSType;
+ pbV5Header->bV5Endpoints = lcs.lcsEndpoints;
+ pbV5Header->bV5GammaRed = lcs.lcsGammaRed;
+ pbV5Header->bV5GammaGreen = lcs.lcsGammaGreen;
+ pbV5Header->bV5GammaBlue = lcs.lcsGammaBlue;
+ pbV5Header->bV5Intent = lcs.lcsIntent;
+ }
+ else
+ {
+ pbV5Header->bV5CSType = LCS_DEVICE_RGB;
+ memset( &pbV5Header->bV5Endpoints, 0, sizeof(pbV5Header->bV5Endpoints) );
+ pbV5Header->bV5GammaRed = 0;
+ pbV5Header->bV5GammaGreen = 0;
+ pbV5Header->bV5GammaBlue = 0;
+ pbV5Header->bV5Intent = LCS_GM_GRAPHICS;
+ }
+ pbV5Header->bV5ProfileData = 0;
+ pbV5Header->bV5ProfileSize = 0;
+ pbV5Header->bV5Reserved = 0;
+ }
/* Retrieve the DIB bits from the bitmap and fill in the
* DIB color table if present */
- hdc = GetDC( 0 );
nLinesCopied = GetDIBits(hdc, /* Handle to device context */
hBmp, /* Handle to bitmap */
0, /* First scan line to set in dest bitmap */
@@ -1086,17 +1147,209 @@ static WCHAR* uri_to_dos(char *encodedURI)
*
* Renders synthesized DIB
*/
-static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display)
+static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display, BOOL isV5)
{
BOOL bret = FALSE;
LPWINE_CLIPDATA lpSource = NULL;
+ UINT cf = isV5 ? CF_DIBV5 : CF_DIB;
TRACE("\n");
- if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) && lpSource->hData)
+ if ((lpSource = X11DRV_CLIPBOARD_LookupData(cf)) && lpSource->hData)
{
bret = TRUE;
}
+ /* If we have a V3/V4 DIB and it's not synthesized or it has been rendered */
+ else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) && isV5 &&
+ (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
+ {
+ /* Render source if required */
+ if (lpSource->hData || X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
+ {
+ BITMAPINFOHEADER *bmih = GlobalLock(lpSource->hData);
+ if (bmih)
+ {
+ size_t imgsize = bitmap_image_size( bmih );
+ unsigned int colors, bpp;
+ if (bmih->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ bpp = ((BITMAPCOREHEADER *)bmih)->bcBitCount;
+ colors = 1 << bpp;
+ }
+ else
+ {
+ bpp = bmih->biBitCount;
+ colors = bmih->biClrUsed;
+ }
+ HGLOBAL data = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(BITMAPV5HEADER) +
+ (bpp <= 8 ? sizeof(RGBQUAD) * colors : 0) +
+ imgsize);
+
+ if (data)
+ {
+ /* Convert to a V5 DIB */
+ BITMAPV5HEADER *bV5 = GlobalLock(data);
+ if (bV5)
+ {
+ BYTE *srcbits = (BYTE *)bmih + bmih->biSize;
+ BYTE *destbits = (BYTE *)(bV5 + 1);
+
+ if (bmih->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ /* Due to an impedance mismatch between BITMAPCOREHEADER and
+ * BITMAPV5HEADER, the fields need to be copied manually. And yes,
+ * Windows really does support this.
+ */
+ BITMAPCOREHEADER *bch = (BITMAPCOREHEADER *)bmih;
+
+ bV5->bV5Width = bch->bcWidth;
+ bV5->bV5Height = bch->bcHeight;
+ bV5->bV5Planes = bch->bcPlanes;
+ bV5->bV5BitCount = bch->bcBitCount;
+ bV5->bV5Compression = BI_RGB;
+ bV5->bV5SizeImage = imgsize;
+ bV5->bV5XPelsPerMeter = 0;
+ bV5->bV5YPelsPerMeter = 0;
+ bV5->bV5ClrUsed = bch->bcBitCount <= 8 ? colors : 0;
+ bV5->bV5ClrImportant = 0;
+ }
+ else
+ memcpy(bV5, bmih, min(bmih->biSize, sizeof(BITMAPV5HEADER)));
+ if (bmih->biSize < sizeof(BITMAPV5HEADER))
+ {
+ HDC hdc = GetDC(0);
+ LOGCOLORSPACEW lcs;
+
+ if (GetLogColorSpaceW(GetColorSpace(hdc), &lcs, sizeof(lcs)))
+ {
+ if (sizeof(BITMAPV4HEADER) > bmih->biSize)
+ {
+ bV5->bV5CSType = lcs.lcsCSType;
+ bV5->bV5Endpoints = lcs.lcsEndpoints;
+ bV5->bV5GammaRed = lcs.lcsGammaRed;
+ bV5->bV5GammaGreen = lcs.lcsGammaGreen;
+ bV5->bV5GammaBlue = lcs.lcsGammaBlue;
+ }
+ bV5->bV5Intent = lcs.lcsIntent;
+ }
+ else
+ {
+ if (bmih->biSize < sizeof(BITMAPV4HEADER))
+ {
+ memset(&bV5->bV5RedMask, 0,
+ sizeof(BITMAPV5HEADER) - sizeof(BITMAPINFOHEADER));
+ bV5->bV5CSType = LCS_DEVICE_RGB;
+ }
+ bV5->bV5Intent = LCS_GM_GRAPHICS;
+ }
+ ReleaseDC(0, hdc);
+ }
+ bV5->bV5Size = sizeof(BITMAPV5HEADER);
+ if (bmih->biSize < sizeof(BITMAPV4HEADER) &&
+ bV5->bV5Compression == BI_BITFIELDS)
+ {
+ /* These aren't part of the V3 BITMAPINFOHEADER. */
+ DWORD *masks = (DWORD *)(bmih+1);
+
+ bV5->bV5RedMask = masks[0];
+ bV5->bV5GreenMask = masks[1];
+ bV5->bV5BlueMask = masks[2];
+ if (bmih->biSize == sizeof(BITMAPINFOHEADER))
+ srcbits += 3 * sizeof(DWORD);
+ }
+ if (bV5->bV5BitCount <= 8)
+ {
+ if (bmih->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ /* Another impedance mismatch. The DIB format really changed a lot
+ * between OS/2 and Windows 3.0.
+ */
+ RGBTRIPLE *srcpal = (RGBTRIPLE *)srcbits;
+ RGBQUAD *destpal = (RGBQUAD *)destbits;
+ int i;
+
+ for (i = 0; i < bV5->bV5ClrUsed; ++i)
+ {
+ destpal[i].rgbRed = srcpal[i].rgbtRed;
+ destpal[i].rgbGreen = srcpal[i].rgbtGreen;
+ destpal[i].rgbBlue = srcpal[i].rgbtBlue;
+ destpal[i].rgbReserved = 0;
+ }
+ srcbits += sizeof(RGBTRIPLE) * bV5->bV5ClrUsed;
+ }
+ else
+ {
+ memcpy(destbits, srcbits, sizeof(RGBQUAD) * bV5->bV5ClrUsed);
+ srcbits += sizeof(RGBQUAD) * bV5->bV5ClrUsed;
+ }
+ destbits += sizeof(RGBQUAD) * bV5->bV5ClrUsed;
+ }
+ memcpy(destbits, srcbits, imgsize);
+ GlobalUnlock(data);
+ X11DRV_CLIPBOARD_InsertClipboardData(cf, data, 0, NULL, TRUE);
+ bret = TRUE;
+ }
+ else
+ GlobalFree(data);
+ }
+ GlobalUnlock(lpSource->hData);
+ }
+ }
+ }
+ /* If we have a V5 DIB and it's not synthesized or it has been rendered */
+ else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIBV5)) && !isV5 &&
+ (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
+ {
+ /* Render source if required */
+ if (lpSource->hData || X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
+ {
+ BITMAPV5HEADER *bV5 = (BITMAPV5HEADER *)GlobalLock(lpSource->hData);
+ if (bV5)
+ {
+ size_t imgsize = bitmap_image_size( (BITMAPINFOHEADER *)bV5 );
+ HGLOBAL data = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, sizeof(BITMAPINFOHEADER) +
+ (bV5->bV5Compression == BI_BITFIELDS ? 3 * sizeof(DWORD) : 0) +
+ (bV5->bV5BitCount <= 8 ? sizeof(RGBQUAD) * bV5->bV5ClrUsed : 0) +
+ imgsize);
+
+ if (data)
+ {
+ /* Convert to a V3 DIB */
+ BITMAPINFOHEADER *bmih = (BITMAPINFOHEADER *)GlobalLock(data);
+ if (bmih)
+ {
+ BYTE *srcbits = (BYTE *)bV5 + bV5->bV5Size;
+ BYTE *destbits = (BYTE *)bmih + sizeof(BITMAPINFOHEADER);
+
+ memcpy(bmih, bV5, sizeof(BITMAPINFOHEADER));
+ bmih->biSize = sizeof(BITMAPINFOHEADER);
+ if (bmih->biCompression == BI_BITFIELDS)
+ {
+ /* These aren't part of the V3 BITMAPINFOHEADER. */
+ DWORD *masks = (DWORD *)destbits;
+ masks[0] = bV5->bV5RedMask;
+ masks[1] = bV5->bV5GreenMask;
+ masks[2] = bV5->bV5BlueMask;
+ destbits += 3 * sizeof(DWORD);
+ }
+ if (bmih->biBitCount <= 8)
+ {
+ memcpy(destbits, srcbits, sizeof(RGBQUAD) * bmih->biClrUsed);
+ srcbits += sizeof(RGBQUAD) * bmih->biClrUsed;
+ destbits += sizeof(RGBQUAD) * bmih->biClrUsed;
+ }
+ memcpy(destbits, srcbits, imgsize);
+ GlobalUnlock(data);
+ X11DRV_CLIPBOARD_InsertClipboardData(cf, data, 0, NULL, TRUE);
+ bret = TRUE;
+ }
+ else
+ GlobalFree(data);
+ }
+ GlobalUnlock(lpSource->hData);
+ }
+ }
+ }
/* If we have a bitmap and it's not synthesized or it has been rendered */
else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
(!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
@@ -1104,10 +1357,10 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display)
/* Render source if required */
if (lpSource->hData || X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
{
- HGLOBAL hData = create_dib_from_bitmap( lpSource->hData );
+ HGLOBAL hData = create_dib_from_bitmap( lpSource->hData, isV5 );
if (hData)
{
- X11DRV_CLIPBOARD_InsertClipboardData(CF_DIB, hData, 0, NULL, TRUE);
+ X11DRV_CLIPBOARD_InsertClipboardData(cf, hData, 0, NULL, TRUE);
bret = TRUE;
}
}
@@ -1149,7 +1402,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display)
lpbmih = GlobalLock(lpSource->hData);
if (lpbmih)
{
- offset = sizeof(BITMAPINFOHEADER)
+ offset = lpbmih->biSize
+ ((lpbmih->biBitCount <= 8) ? (sizeof(RGBQUAD) *
(1 << lpbmih->biBitCount)) : 0);
@@ -1167,6 +1420,39 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display)
}
}
}
+ else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIBV5)) &&
+ (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
+ {
+ /* Render source if required */
+ if (lpSource->hData || X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
+ {
+ HDC hdc;
+ HBITMAP hData = NULL;
+ unsigned int offset;
+ LPBITMAPV5HEADER lpbmih;
+
+ hdc = GetDC(NULL);
+ lpbmih = GlobalLock(lpSource->hData);
+ if (lpbmih)
+ {
+ offset = lpbmih->bV5Size
+ + ((lpbmih->bV5BitCount <= 8) ? (sizeof(RGBQUAD) *
+ lpbmih->bV5ClrUsed) : 0);
+
+ hData = CreateDIBitmap(hdc, (BITMAPINFOHEADER *) lpbmih, CBM_INIT, (LPBYTE)lpbmih +
+ offset, (LPBITMAPINFO) lpbmih, DIB_RGB_COLORS);
+
+ GlobalUnlock(lpSource->hData);
+ }
+ ReleaseDC(NULL, hdc);
+
+ if (hData)
+ {
+ X11DRV_CLIPBOARD_InsertClipboardData(CF_BITMAP, hData, 0, NULL, TRUE);
+ bret = TRUE;
+ }
+ }
+ }
return bret;
}
@@ -1382,11 +1668,11 @@ static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *display, Window w, At
/**************************************************************************
- * X11DRV_CLIPBOARD_ImportXAPIXMAP
+ * import_pixmap_to_dib
*
- * Import XA_PIXMAP, converting the image to CF_DIB.
+ * Import XA_PIXMAP, converting the image to either CF_DIB or CF_DIBV5.
*/
-static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom prop)
+static HANDLE import_pixmap_to_dib(Display *display, Window w, Atom prop, BOOL isV5)
{
LPBYTE lpdata;
unsigned long cbytes;
@@ -1396,7 +1682,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom p
if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
{
XVisualInfo vis = default_visual;
- char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+ char buffer[sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD)];
BITMAPINFO *info = (BITMAPINFO *)buffer;
struct gdi_image_bits bits;
Window root;
@@ -1434,6 +1720,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom p
default:
return 0;
}
+ info->bmiHeader.biSize = isV5 ? sizeof(BITMAPV5HEADER) : sizeof(BITMAPINFOHEADER);
if (!get_pixmap_image( *pPixmap, width, height, &vis, info, &bits ))
{
@@ -1460,11 +1747,33 @@ static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom p
/**************************************************************************
- * X11DRV_CLIPBOARD_ImportImageBmp
+ * X11DRV_CLIPBOARD_ImportXAPIXMAP
*
- * Import image/bmp, converting the image to CF_DIB.
+ * Import XA_PIXMAP, converting the image to CF_DIB.
*/
-static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *display, Window w, Atom prop)
+static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom prop)
+{
+ return import_pixmap_to_dib( display, w, prop, FALSE );
+}
+
+
+/**************************************************************************
+ * X11DRV_CLIPBOARD_ImportV5XAPIXMAP
+ *
+ * Import XA_PIXMAP, converting the image to CF_DIBV5.
+ */
+static HANDLE X11DRV_CLIPBOARD_ImportV5XAPIXMAP(Display *display, Window w, Atom prop)
+{
+ return import_pixmap_to_dib( display, w, prop, TRUE );
+}
+
+
+/**************************************************************************
+ * import_bmp_to_dib
+ *
+ * Import image/bmp, converting the image to either CF_DIB or CF_DIBV5.
+ */
+static HANDLE import_bmp_to_dib(Display *display, Window w, Atom prop, BOOL isV5)
{
LPBYTE lpdata;
unsigned long cbytes;
@@ -1491,7 +1800,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *display, Window w, Atom p
DIB_RGB_COLORS
);
- hClipData = create_dib_from_bitmap( hbmp );
+ hClipData = create_dib_from_bitmap( hbmp, isV5 );
DeleteObject(hbmp);
ReleaseDC(0, hdc);
@@ -1505,6 +1814,16 @@ static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *display, Window w, Atom p
}
+static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *display, Window w, Atom prop)
+{
+ return import_bmp_to_dib(display, w, prop, FALSE);
+}
+
+static HANDLE X11DRV_CLIPBOARD_ImportImageV5Bmp(Display *display, Window w, Atom prop)
+{
+ return import_bmp_to_dib(display, w, prop, TRUE);
+}
+
/**************************************************************************
* X11DRV_CLIPBOARD_ImportMetaFilePict
*
@@ -3201,15 +3520,14 @@ static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_ENHMETAFILE)) &&
~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
}
- else if (wFormatID == CF_DIB)
+ else if (wFormatID == CF_BITMAP || wFormatID == CF_DIB || wFormatID == CF_DIBV5)
{
- bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
- ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
- }
- else if (wFormatID == CF_BITMAP)
- {
- bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
- ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
+ bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
+ ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
+ ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
+ ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
+ ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIBV5)) &&
+ ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
}
if (bsyn)
@@ -3239,8 +3557,9 @@ void CDECL X11DRV_EndClipboardUpdate(void)
X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
/* DIB <-> Bitmap mapping */
- X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
+ X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
+ X11DRV_CLIPBOARD_SynthesizeData(CF_DIBV5);
TRACE("%d formats added to cached data\n", ClipDataCount - count);
}
--
2.8.1
More information about the wine-patches
mailing list