gdi32: If the WMF was created by GetWinMetaFileBits() then return the original EMF.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7be1c53d82
commit
19d1416cef
|
@ -2686,6 +2686,59 @@ UINT WINAPI GetEnhMetaFilePaletteEntries( HENHMETAFILE hEmf,
|
|||
return infoForCallBack.cEntries;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* extract_emf_from_comment
|
||||
*
|
||||
* If the WMF was created by GetWinMetaFileBits, then extract the
|
||||
* original EMF that is stored in MFCOMMENT chunks.
|
||||
*/
|
||||
static HENHMETAFILE extract_emf_from_comment( const BYTE *buf, UINT mf_size )
|
||||
{
|
||||
METAHEADER *mh = (METAHEADER *)buf;
|
||||
METARECORD *mr;
|
||||
emf_in_wmf_comment *chunk;
|
||||
WORD checksum = 0;
|
||||
DWORD size = 0, remaining, chunks;
|
||||
BYTE *emf_bits = NULL, *ptr;
|
||||
UINT offset;
|
||||
HENHMETAFILE emf = NULL;
|
||||
|
||||
if (mf_size < sizeof(*mh)) return NULL;
|
||||
|
||||
for (offset = mh->mtHeaderSize * 2; offset < mf_size; offset += (mr->rdSize * 2))
|
||||
{
|
||||
mr = (METARECORD *)((char *)mh + offset);
|
||||
chunk = (emf_in_wmf_comment *)(mr->rdParm + 2);
|
||||
|
||||
if (mr->rdFunction != META_ESCAPE || mr->rdParm[0] != MFCOMMENT) goto done;
|
||||
if (chunk->magic != WMFC_MAGIC) goto done;
|
||||
|
||||
if (!emf_bits)
|
||||
{
|
||||
size = remaining = chunk->emf_size;
|
||||
chunks = chunk->num_chunks;
|
||||
emf_bits = ptr = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
if (!emf_bits) goto done;
|
||||
}
|
||||
if (chunk->chunk_size > remaining) goto done;
|
||||
remaining -= chunk->chunk_size;
|
||||
if (chunk->remaining_size != remaining) goto done;
|
||||
memcpy( ptr, chunk->emf_data, chunk->chunk_size );
|
||||
ptr += chunk->chunk_size;
|
||||
if (--chunks == 0) break;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < mf_size / 2; offset++)
|
||||
checksum += *((WORD *)buf + offset);
|
||||
if (checksum) goto done;
|
||||
|
||||
emf = SetEnhMetaFileBits( size, emf_bits );
|
||||
|
||||
done:
|
||||
HeapFree( GetProcessHeap(), 0, emf_bits );
|
||||
return emf;
|
||||
}
|
||||
|
||||
typedef struct gdi_mf_comment
|
||||
{
|
||||
DWORD ident;
|
||||
|
@ -2722,6 +2775,9 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, const BYTE *lpbBuffer, HDC
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ret = extract_emf_from_comment( lpbBuffer, cbBuffer );
|
||||
if (ret) return ret;
|
||||
|
||||
if(!hdcRef)
|
||||
hdcRef = hdcdisp = CreateDCW(szDisplayW, NULL, NULL, NULL);
|
||||
|
||||
|
|
|
@ -311,6 +311,27 @@ extern void GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc) DECLSPEC_HIDDEN;
|
|||
extern HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh) DECLSPEC_HIDDEN;
|
||||
extern METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mr, LPCVOID filename, BOOL unicode ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Format of comment record added by GetWinMetaFileBits */
|
||||
#include <pshpack2.h>
|
||||
typedef struct
|
||||
{
|
||||
DWORD magic; /* WMFC */
|
||||
WORD unk04; /* 1 */
|
||||
WORD unk06; /* 0 */
|
||||
WORD unk08; /* 0 */
|
||||
WORD unk0a; /* 1 */
|
||||
WORD checksum;
|
||||
DWORD unk0e; /* 0 */
|
||||
DWORD num_chunks;
|
||||
DWORD chunk_size;
|
||||
DWORD remaining_size;
|
||||
DWORD emf_size;
|
||||
BYTE emf_data[1];
|
||||
} emf_in_wmf_comment;
|
||||
#include <poppack.h>
|
||||
|
||||
#define WMFC_MAGIC 0x43464d57
|
||||
|
||||
/* path.c */
|
||||
|
||||
extern void free_gdi_path( struct gdi_path *path ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1114,26 +1114,6 @@ UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf )
|
|||
return mfSize;
|
||||
}
|
||||
|
||||
#include <pshpack2.h>
|
||||
typedef struct
|
||||
{
|
||||
DWORD magic; /* WMFC */
|
||||
WORD unk04; /* 1 */
|
||||
WORD unk06; /* 0 */
|
||||
WORD unk08; /* 0 */
|
||||
WORD unk0a; /* 1 */
|
||||
WORD checksum;
|
||||
DWORD unk0e; /* 0 */
|
||||
DWORD num_chunks;
|
||||
DWORD chunk_size;
|
||||
DWORD remaining_size;
|
||||
DWORD emf_size;
|
||||
BYTE emf_data[1];
|
||||
} emf_in_wmf_comment;
|
||||
#include <poppack.h>
|
||||
|
||||
static const DWORD wmfc_magic = 0x43464d57;
|
||||
|
||||
/******************************************************************
|
||||
* add_mf_comment
|
||||
*
|
||||
|
@ -1158,7 +1138,7 @@ static BOOL add_mf_comment(HDC hdc, HENHMETAFILE emf)
|
|||
chunk = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(emf_in_wmf_comment, emf_data[max_chunk_size]));
|
||||
if(!chunk) goto end;
|
||||
|
||||
chunk->magic = wmfc_magic;
|
||||
chunk->magic = WMFC_MAGIC;
|
||||
chunk->unk04 = 1;
|
||||
chunk->unk06 = 0;
|
||||
chunk->unk08 = 0;
|
||||
|
|
|
@ -3249,16 +3249,17 @@ static BOOL near_match(int x, int y)
|
|||
|
||||
static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
|
||||
{
|
||||
HENHMETAFILE emf;
|
||||
HENHMETAFILE emf, emf2;
|
||||
HDC display_dc, emf_dc;
|
||||
ENHMETAHEADER *enh_header;
|
||||
UINT size, emf_size, i;
|
||||
ENHMETAHEADER *enh_header, *enh2_header;
|
||||
UINT size, emf_size, i, emf2_size;
|
||||
WORD check = 0;
|
||||
DWORD rec_num = 0;
|
||||
METAHEADER *mh = NULL;
|
||||
METARECORD *rec;
|
||||
INT horz_res, vert_res, horz_size, vert_size;
|
||||
INT curve_caps, line_caps, poly_caps;
|
||||
METAFILEPICT mfp;
|
||||
|
||||
display_dc = GetDC(NULL);
|
||||
ok(display_dc != NULL, "display_dc is NULL\n");
|
||||
|
@ -3401,6 +3402,21 @@ static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
|
|||
rec = (METARECORD*)((WORD*)rec + rec->rdSize);
|
||||
}
|
||||
|
||||
/* Show that we get the original back when we do the reverse conversion.
|
||||
mfp is ignored in this case. */
|
||||
mfp.mm = MM_ISOTROPIC;
|
||||
mfp.xExt = 0xcafe;
|
||||
mfp.yExt = 0xbeef;
|
||||
emf2 = SetWinMetaFileBits( size, (BYTE*)mh, NULL, &mfp );
|
||||
ok( !!emf2, "got NULL\n" );
|
||||
emf2_size = GetEnhMetaFileBits( emf2, 0, NULL );
|
||||
enh2_header = HeapAlloc( GetProcessHeap(), 0, emf2_size );
|
||||
emf2_size = GetEnhMetaFileBits( emf2, emf2_size, (BYTE*)enh2_header );
|
||||
ok( emf_size == emf2_size, "%d %d\n", emf_size, emf2_size );
|
||||
ok( !memcmp( enh_header, enh2_header, emf_size ), "mismatch\n" );
|
||||
HeapFree( GetProcessHeap(), 0, enh2_header );
|
||||
DeleteEnhMetaFile( emf2 );
|
||||
|
||||
end:
|
||||
HeapFree(GetProcessHeap(), 0, mh);
|
||||
HeapFree(GetProcessHeap(), 0, enh_header);
|
||||
|
|
Loading…
Reference in New Issue