user32: Synthesize bitmap clipboard formats on the user32 side.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1993898459
commit
9a652e211c
|
@ -2,9 +2,10 @@
|
|||
* WIN32 clipboard implementation
|
||||
*
|
||||
* Copyright 1994 Martin Ayotte
|
||||
* 1996 Alex Korobka
|
||||
* 1999 Noel Borthwick
|
||||
* 2003 Ulrich Czekalla for CodeWeavers
|
||||
* Copyright 1996 Alex Korobka
|
||||
* Copyright 1999 Noel Borthwick
|
||||
* Copyright 2003 Ulrich Czekalla for CodeWeavers
|
||||
* Copyright 2016 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -20,13 +21,6 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
* NOTES:
|
||||
* This file contains the implementation for the WIN32 Clipboard API
|
||||
* and Wine's internal clipboard cache.
|
||||
* The actual contents of the clipboard are held in the clipboard cache.
|
||||
* The internal implementation talks to a "clipboard driver" to fill or
|
||||
* expose the cache to the native device. (Currently only the X11 and
|
||||
* TTY clipboard driver are available)
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -140,6 +134,33 @@ static void add_synthesized_text(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* add synthesized bitmap formats based on what is already in the clipboard */
|
||||
static void add_synthesized_bitmap(void)
|
||||
{
|
||||
BOOL has_dib = IsClipboardFormatAvailable( CF_DIB );
|
||||
BOOL has_dibv5 = IsClipboardFormatAvailable( CF_DIBV5 );
|
||||
BOOL has_bitmap = IsClipboardFormatAvailable( CF_BITMAP );
|
||||
|
||||
if (!has_bitmap && !has_dib && !has_dibv5) return; /* nothing to do */
|
||||
if (has_bitmap && has_dib && has_dibv5) return; /* nothing to synthesize */
|
||||
|
||||
if (has_bitmap)
|
||||
{
|
||||
if (!has_dib) add_synthesized_format( CF_DIB, CF_BITMAP );
|
||||
if (!has_dibv5) add_synthesized_format( CF_DIBV5, CF_BITMAP );
|
||||
}
|
||||
else if (has_dib)
|
||||
{
|
||||
if (!has_bitmap) add_synthesized_format( CF_BITMAP, CF_DIB );
|
||||
if (!has_dibv5) add_synthesized_format( CF_DIBV5, CF_DIB );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!has_bitmap) add_synthesized_format( CF_BITMAP, CF_DIBV5 );
|
||||
if (!has_dib) add_synthesized_format( CF_DIB, CF_DIBV5 );
|
||||
}
|
||||
}
|
||||
|
||||
/* add synthesized metafile formats based on what is already in the clipboard */
|
||||
static void add_synthesized_metafile(void)
|
||||
{
|
||||
|
@ -200,6 +221,79 @@ static HANDLE render_synthesized_textW( HANDLE data, UINT from )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* render a synthesized bitmap based on the DIB clipboard data */
|
||||
static HANDLE render_synthesized_bitmap( HANDLE data, UINT from )
|
||||
{
|
||||
BITMAPINFO *bmi;
|
||||
HANDLE ret = 0;
|
||||
HDC hdc = GetDC( 0 );
|
||||
|
||||
if ((bmi = GlobalLock( data )))
|
||||
{
|
||||
/* FIXME: validate data size */
|
||||
ret = CreateDIBitmap( hdc, &bmi->bmiHeader, CBM_INIT,
|
||||
(char *)bmi + bitmap_info_size( bmi, DIB_RGB_COLORS ),
|
||||
bmi, DIB_RGB_COLORS );
|
||||
GlobalUnlock( data );
|
||||
}
|
||||
ReleaseDC( 0, hdc );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* render a synthesized DIB based on the clipboard data */
|
||||
static HANDLE render_synthesized_dib( HANDLE data, UINT format, UINT from )
|
||||
{
|
||||
BITMAPINFO *bmi, *src;
|
||||
DWORD src_size, header_size, bits_size;
|
||||
HANDLE ret = 0;
|
||||
HDC hdc = GetDC( 0 );
|
||||
|
||||
if (from == CF_BITMAP)
|
||||
{
|
||||
BITMAP bmp;
|
||||
|
||||
if (!GetObjectW( data, sizeof(bmp), &bmp )) goto done;
|
||||
|
||||
bits_size = abs( bmp.bmHeight ) * (((bmp.bmWidth * bmp.bmBitsPixel + 31) / 8) & ~3);
|
||||
if (bmp.bmBitsPixel <= 8)
|
||||
header_size = offsetof( BITMAPINFO, bmiColors[1 << bmp.bmBitsPixel] );
|
||||
else
|
||||
header_size = (format == CF_DIBV5) ? sizeof(BITMAPV5HEADER) : sizeof(BITMAPINFOHEADER);
|
||||
|
||||
if (!(ret = GlobalAlloc( GMEM_FIXED, header_size + bits_size ))) goto done;
|
||||
bmi = (BITMAPINFO *)ret;
|
||||
memset( bmi, 0, header_size );
|
||||
bmi->bmiHeader.biSize = header_size;
|
||||
bmi->bmiHeader.biWidth = bmp.bmWidth;
|
||||
bmi->bmiHeader.biHeight = bmp.bmHeight;
|
||||
bmi->bmiHeader.biPlanes = 1;
|
||||
bmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
|
||||
bmi->bmiHeader.biCompression = BI_RGB;
|
||||
GetDIBits( hdc, data, 0, bmp.bmHeight, (char *)bmi + header_size, bmi, DIB_RGB_COLORS );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(src = GlobalLock( data ))) goto done;
|
||||
|
||||
src_size = bitmap_info_size( src, DIB_RGB_COLORS );
|
||||
bits_size = GlobalSize( data ) - src_size;
|
||||
header_size = (format == CF_DIBV5) ? sizeof(BITMAPV5HEADER) :
|
||||
offsetof( BITMAPINFO, bmiColors[src->bmiHeader.biCompression == BI_BITFIELDS ? 3 : 0] );
|
||||
|
||||
if (!(ret = GlobalAlloc( GMEM_FIXED, header_size + bits_size ))) goto done;
|
||||
bmi = (BITMAPINFO *)ret;
|
||||
memset( bmi, 0, header_size );
|
||||
memcpy( bmi, src, min( header_size, src_size ));
|
||||
bmi->bmiHeader.biSize = header_size;
|
||||
/* FIXME: convert colors according to DIBv5 color profile */
|
||||
memcpy( (char *)bmi + header_size, (char *)src + src_size, bits_size );
|
||||
}
|
||||
|
||||
done:
|
||||
ReleaseDC( 0, hdc );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* render a synthesized metafile based on the enhmetafile clipboard data */
|
||||
static HANDLE render_synthesized_metafile( HANDLE data )
|
||||
{
|
||||
|
@ -268,6 +362,13 @@ static HANDLE render_synthesized_format( UINT format, UINT from )
|
|||
case CF_UNICODETEXT:
|
||||
data = render_synthesized_textW( data, from );
|
||||
break;
|
||||
case CF_BITMAP:
|
||||
data = render_synthesized_bitmap( data, from );
|
||||
break;
|
||||
case CF_DIB:
|
||||
case CF_DIBV5:
|
||||
data = render_synthesized_dib( data, format, from );
|
||||
break;
|
||||
case CF_METAFILEPICT:
|
||||
data = render_synthesized_metafile( data );
|
||||
break;
|
||||
|
@ -405,6 +506,7 @@ BOOL WINAPI CloseClipboard(void)
|
|||
{
|
||||
memset( synthesized_formats, 0, sizeof(synthesized_formats) );
|
||||
add_synthesized_text();
|
||||
add_synthesized_bitmap();
|
||||
add_synthesized_metafile();
|
||||
}
|
||||
|
||||
|
|
|
@ -306,7 +306,7 @@ static int get_dib_image_size( int width, int height, int depth )
|
|||
*
|
||||
* Return the size of the bitmap info structure including color table.
|
||||
*/
|
||||
static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
|
||||
int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
|
||||
{
|
||||
unsigned int colors, size, masks = 0;
|
||||
|
||||
|
|
|
@ -585,7 +585,6 @@ static void test_synthesized(void)
|
|||
{
|
||||
UINT format;
|
||||
UINT expected[8];
|
||||
UINT todo;
|
||||
} tests[] =
|
||||
{
|
||||
/* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }},
|
||||
|
@ -593,9 +592,9 @@ static void test_synthesized(void)
|
|||
{ CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }},
|
||||
{ CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
|
||||
{ CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
|
||||
/* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }, 1 << 2 },
|
||||
{ CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }, 1 << 2 },
|
||||
{ CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }, (1 << 1) | (1 << 2) },
|
||||
/* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }},
|
||||
{ CF_DIB, { CF_DIB, CF_BITMAP, CF_DIBV5 }},
|
||||
{ CF_DIBV5, { CF_DIBV5, CF_BITMAP, CF_DIB }},
|
||||
};
|
||||
|
||||
HGLOBAL h, htext;
|
||||
|
@ -739,10 +738,8 @@ static void test_synthesized(void)
|
|||
for (j = 0; tests[i].expected[j]; j++)
|
||||
{
|
||||
r = IsClipboardFormatAvailable( tests[i].expected[j] );
|
||||
todo_wine_if (tests[i].todo & (1 << j))
|
||||
ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
|
||||
}
|
||||
todo_wine_if (tests[i].todo)
|
||||
ok( count == j, "%u: count %u instead of %u\n", i, count, j );
|
||||
|
||||
r = OpenClipboard( hwnd );
|
||||
|
@ -751,7 +748,6 @@ static void test_synthesized(void)
|
|||
for (j = 0; tests[i].expected[j]; j++)
|
||||
{
|
||||
cf = EnumClipboardFormats( cf );
|
||||
todo_wine_if (tests[i].todo & (1 << j))
|
||||
ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
|
||||
i, j, cf, tests[i].expected[j] );
|
||||
if (cf != tests[i].expected[j]) break;
|
||||
|
@ -799,10 +795,8 @@ static void test_synthesized(void)
|
|||
for (j = 0; tests[i].expected[j]; j++)
|
||||
{
|
||||
r = IsClipboardFormatAvailable( tests[i].expected[j] );
|
||||
todo_wine_if (tests[i].todo & (1 << j))
|
||||
ok( r, "%u: %04x not available\n", i, tests[i].expected[j] );
|
||||
}
|
||||
todo_wine_if (tests[i].todo)
|
||||
ok( count == j, "%u: count %u instead of %u\n", i, count, j );
|
||||
rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
|
||||
ok( !rendered, "%u: formats %08x have been rendered\n", i, rendered );
|
||||
|
@ -813,7 +807,6 @@ static void test_synthesized(void)
|
|||
for (j = 0; tests[i].expected[j]; j++)
|
||||
{
|
||||
cf = EnumClipboardFormats( cf );
|
||||
todo_wine_if (tests[i].todo & (1 << j))
|
||||
ok(cf == tests[i].expected[j], "%u.%u: got %04x instead of %04x\n",
|
||||
i, j, cf, tests[i].expected[j] );
|
||||
if (cf != tests[i].expected[j]) break;
|
||||
|
@ -834,7 +827,6 @@ static void test_synthesized(void)
|
|||
/* try to render a second time */
|
||||
data = GetClipboardData( cf );
|
||||
rendered = SendMessageA( hwnd, WM_USER, 0, 0 );
|
||||
todo_wine_if( i > 4 && j == 1 )
|
||||
ok( rendered == (1 << tests[i].format),
|
||||
"%u.%u: formats %08x have been rendered\n", i, j, rendered );
|
||||
}
|
||||
|
@ -1707,7 +1699,7 @@ static void test_handles( HWND hwnd )
|
|||
data = GetClipboardData( CF_DIB );
|
||||
ok( is_fixed( data ), "expected fixed mem %p\n", data );
|
||||
data = GetClipboardData( CF_DIBV5 );
|
||||
todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
|
||||
ok( is_fixed( data ), "expected fixed mem %p\n", data );
|
||||
|
||||
ok( GetObjectType( bitmap ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap );
|
||||
ok( GetObjectType( bitmap2 ) == OBJ_BITMAP, "expected bitmap %p\n", bitmap2 );
|
||||
|
@ -1776,7 +1768,7 @@ static DWORD WINAPI test_handles_thread2( void *arg )
|
|||
h = GetClipboardData( CF_DIB );
|
||||
ok( is_fixed( h ), "expected fixed mem %p\n", h );
|
||||
h = GetClipboardData( CF_DIBV5 );
|
||||
todo_wine ok( is_fixed( h ), "expected fixed mem %p\n", h );
|
||||
ok( is_fixed( h ), "expected fixed mem %p\n", h );
|
||||
r = CloseClipboard();
|
||||
ok( r, "gle %d\n", GetLastError() );
|
||||
return 0;
|
||||
|
|
|
@ -343,6 +343,7 @@ typedef struct
|
|||
|
||||
#include "poppack.h"
|
||||
|
||||
extern int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) DECLSPEC_HIDDEN;
|
||||
extern BOOL get_icon_size( HICON handle, SIZE *size ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Mingw's assert() imports MessageBoxA and gets confused by user32 exporting it */
|
||||
|
|
Loading…
Reference in New Issue