Commit 2e363267 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

ole32: Synthesize dibs or bitmaps as appropriate.

parent e27708f2
......@@ -297,13 +297,21 @@ static void DataCache_Destroy(
static DataCacheEntry *DataCache_GetEntryForFormatEtc(DataCache *This, const FORMATETC *formatetc)
{
DataCacheEntry *cache_entry;
FORMATETC fmt = *formatetc;
if (fmt.cfFormat == CF_BITMAP)
{
fmt.cfFormat = CF_DIB;
fmt.tymed = TYMED_HGLOBAL;
}
LIST_FOR_EACH_ENTRY(cache_entry, &This->cache_list, DataCacheEntry, entry)
{
/* FIXME: also compare DVTARGETDEVICEs */
if ((!cache_entry->fmtetc.cfFormat || !formatetc->cfFormat || (formatetc->cfFormat == cache_entry->fmtetc.cfFormat)) &&
(formatetc->dwAspect == cache_entry->fmtetc.dwAspect) &&
(formatetc->lindex == cache_entry->fmtetc.lindex) &&
(!cache_entry->fmtetc.tymed || !formatetc->tymed || (formatetc->tymed == cache_entry->fmtetc.tymed)))
if ((!cache_entry->fmtetc.cfFormat || !fmt.cfFormat || (fmt.cfFormat == cache_entry->fmtetc.cfFormat)) &&
(fmt.dwAspect == cache_entry->fmtetc.dwAspect) &&
(fmt.lindex == cache_entry->fmtetc.lindex) &&
(!cache_entry->fmtetc.tymed || !fmt.tymed || (fmt.tymed == cache_entry->fmtetc.tymed)))
return cache_entry;
}
return NULL;
......@@ -901,11 +909,56 @@ static HRESULT copy_stg_medium(CLIPFORMAT cf, STGMEDIUM *dest_stgm,
return S_OK;
}
static HGLOBAL synthesize_dib( HBITMAP bm )
{
HDC hdc = GetDC( 0 );
BITMAPINFOHEADER header;
BITMAPINFO *bmi;
HGLOBAL ret = 0;
DWORD header_size;
memset( &header, 0, sizeof(header) );
header.biSize = sizeof(header);
if (!GetDIBits( hdc, bm, 0, 0, NULL, (BITMAPINFO *)&header, DIB_RGB_COLORS )) goto done;
header_size = bitmap_info_size( (BITMAPINFO *)&header, DIB_RGB_COLORS );
if (!(ret = GlobalAlloc( GMEM_MOVEABLE, header_size + header.biSizeImage ))) goto done;
bmi = GlobalLock( ret );
memset( bmi, 0, header_size );
memcpy( bmi, &header, header.biSize );
GetDIBits( hdc, bm, 0, abs(header.biHeight), (char *)bmi + header_size, bmi, DIB_RGB_COLORS );
GlobalUnlock( ret );
done:
ReleaseDC( 0, hdc );
return ret;
}
static HBITMAP synthesize_bitmap( HGLOBAL dib )
{
HBITMAP ret = 0;
BITMAPINFO *bmi;
HDC hdc = GetDC( 0 );
if ((bmi = GlobalLock( dib )))
{
/* 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( dib );
}
ReleaseDC( 0, hdc );
return ret;
}
static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
const FORMATETC *formatetc,
const STGMEDIUM *stgmedium,
STGMEDIUM *stgmedium,
BOOL fRelease)
{
STGMEDIUM dib_copy;
if ((!cache_entry->fmtetc.cfFormat && !formatetc->cfFormat) ||
(cache_entry->fmtetc.tymed == TYMED_NULL && formatetc->tymed == TYMED_NULL) ||
stgmedium->tymed == TYMED_NULL)
......@@ -917,6 +970,17 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
cache_entry->dirty = TRUE;
ReleaseStgMedium(&cache_entry->stgmedium);
cache_entry->data_cf = cache_entry->fmtetc.cfFormat ? cache_entry->fmtetc.cfFormat : formatetc->cfFormat;
if (formatetc->cfFormat == CF_BITMAP)
{
dib_copy.tymed = TYMED_HGLOBAL;
dib_copy.u.hGlobal = synthesize_dib( stgmedium->u.hBitmap );
dib_copy.pUnkForRelease = NULL;
if (fRelease) ReleaseStgMedium(stgmedium);
stgmedium = &dib_copy;
fRelease = TRUE;
}
if (fRelease)
{
cache_entry->stgmedium = *stgmedium;
......@@ -927,7 +991,7 @@ static HRESULT DataCacheEntry_SetData(DataCacheEntry *cache_entry,
&cache_entry->stgmedium, stgmedium);
}
static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, STGMEDIUM *stgmedium)
static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, FORMATETC *fmt, STGMEDIUM *stgmedium)
{
if (cache_entry->stgmedium.tymed == TYMED_NULL && cache_entry->stream)
{
......@@ -937,6 +1001,14 @@ static HRESULT DataCacheEntry_GetData(DataCacheEntry *cache_entry, STGMEDIUM *st
}
if (cache_entry->stgmedium.tymed == TYMED_NULL)
return OLE_E_BLANK;
if (fmt->cfFormat == CF_BITMAP)
{
stgmedium->tymed = TYMED_GDI;
stgmedium->u.hBitmap = synthesize_bitmap( cache_entry->stgmedium.u.hGlobal );
stgmedium->pUnkForRelease = NULL;
return S_OK;
}
return copy_stg_medium(cache_entry->data_cf, stgmedium, &cache_entry->stgmedium);
}
......@@ -1109,7 +1181,7 @@ static HRESULT WINAPI DataCache_GetData(
if (!cache_entry)
return OLE_E_BLANK;
return DataCacheEntry_GetData(cache_entry, pmedium);
return DataCacheEntry_GetData(cache_entry, pformatetcIn, pmedium);
}
static HRESULT WINAPI DataCache_GetDataHere(
......
......@@ -1993,6 +1993,18 @@ static IStorage *create_storage( int num )
return stg;
}
static HGLOBAL create_dib( void )
{
HGLOBAL h;
void *ptr;
h = GlobalAlloc( GMEM_MOVEABLE, sizeof(dib) - sizeof(BITMAPFILEHEADER) );
ptr = GlobalLock( h );
memcpy( ptr, dib + sizeof(BITMAPFILEHEADER), sizeof(dib) - sizeof(BITMAPFILEHEADER) );
GlobalUnlock( h );
return h;
}
static void test_data_cache_dib_contents_stream(int num)
{
HRESULT hr;
......@@ -2083,12 +2095,33 @@ static void test_data_cache_dib_contents_stream(int num)
IUnknown_Release( unk );
}
static void check_bitmap_size( HBITMAP h, int cx, int cy )
{
BITMAP bm;
GetObjectW( h, sizeof(bm), &bm );
ok( bm.bmWidth == cx, "got %d expect %d\n", bm.bmWidth, cx );
ok( bm.bmHeight == cy, "got %d expect %d\n", bm.bmHeight, cy );
}
static void check_dib_size( HGLOBAL h, int cx, int cy )
{
BITMAPINFO *info;
info = GlobalLock( h );
ok( info->bmiHeader.biWidth == cx, "got %d expect %d\n", info->bmiHeader.biWidth, cx );
ok( info->bmiHeader.biHeight == cy, "got %d expect %d\n", info->bmiHeader.biHeight, cy );
GlobalUnlock( h );
}
static void test_data_cache_bitmap(void)
{
HRESULT hr;
IOleCache2 *cache;
IDataObject *data;
FORMATETC fmt;
DWORD conn;
STGMEDIUM med;
STATDATA expect[] =
{
{{ CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, 0, NULL, 0 },
......@@ -2165,6 +2198,57 @@ static void test_data_cache_bitmap(void)
check_enum_cache( cache, expect, 2 );
/* Try setting a 1x1 bitmap */
hr = IOleCache2_QueryInterface( cache, &IID_IDataObject, (void **) &data );
ok( hr == S_OK, "got %08x\n", hr );
med.tymed = TYMED_GDI;
U(med).hBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
med.pUnkForRelease = NULL;
hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
ok( hr == S_OK, "got %08x\n", hr );
hr = IDataObject_GetData( data, &fmt, &med );
ok( hr == S_OK, "got %08x\n", hr );
ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
check_bitmap_size( U(med).hBitmap, 1, 1 );
ReleaseStgMedium( &med );
fmt.cfFormat = CF_DIB;
fmt.tymed = TYMED_HGLOBAL;
hr = IDataObject_GetData( data, &fmt, &med );
ok( hr == S_OK, "got %08x\n", hr );
ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
check_dib_size( U(med).hGlobal, 1, 1 );
ReleaseStgMedium( &med );
/* Now set a 2x1 dib */
fmt.cfFormat = CF_DIB;
fmt.tymed = TYMED_HGLOBAL;
med.tymed = TYMED_HGLOBAL;
U(med).hGlobal = create_dib();
hr = IOleCache2_SetData( cache, &fmt, &med, TRUE );
ok( hr == S_OK, "got %08x\n", hr );
fmt.cfFormat = CF_BITMAP;
fmt.tymed = TYMED_GDI;
hr = IDataObject_GetData( data, &fmt, &med );
ok( hr == S_OK, "got %08x\n", hr );
ok( med.tymed == TYMED_GDI, "got %d\n", med.tymed );
check_bitmap_size( U(med).hBitmap, 2, 1 );
ReleaseStgMedium( &med );
fmt.cfFormat = CF_DIB;
fmt.tymed = TYMED_HGLOBAL;
hr = IDataObject_GetData( data, &fmt, &med );
ok( hr == S_OK, "got %08x\n", hr );
ok( med.tymed == TYMED_HGLOBAL, "got %d\n", med.tymed );
check_dib_size( U(med).hGlobal, 2, 1 );
ReleaseStgMedium( &med );
IDataObject_Release( data );
IOleCache2_Release( cache );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment