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;
|
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
|
typedef struct gdi_mf_comment
|
||||||
{
|
{
|
||||||
DWORD ident;
|
DWORD ident;
|
||||||
|
@ -2722,6 +2775,9 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, const BYTE *lpbBuffer, HDC
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = extract_emf_from_comment( lpbBuffer, cbBuffer );
|
||||||
|
if (ret) return ret;
|
||||||
|
|
||||||
if(!hdcRef)
|
if(!hdcRef)
|
||||||
hdcRef = hdcdisp = CreateDCW(szDisplayW, NULL, NULL, NULL);
|
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 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh) DECLSPEC_HIDDEN;
|
||||||
extern METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mr, LPCVOID filename, BOOL unicode ) 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 */
|
/* path.c */
|
||||||
|
|
||||||
extern void free_gdi_path( struct gdi_path *path ) DECLSPEC_HIDDEN;
|
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;
|
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
|
* 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]));
|
chunk = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(emf_in_wmf_comment, emf_data[max_chunk_size]));
|
||||||
if(!chunk) goto end;
|
if(!chunk) goto end;
|
||||||
|
|
||||||
chunk->magic = wmfc_magic;
|
chunk->magic = WMFC_MAGIC;
|
||||||
chunk->unk04 = 1;
|
chunk->unk04 = 1;
|
||||||
chunk->unk06 = 0;
|
chunk->unk06 = 0;
|
||||||
chunk->unk08 = 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)
|
static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
|
||||||
{
|
{
|
||||||
HENHMETAFILE emf;
|
HENHMETAFILE emf, emf2;
|
||||||
HDC display_dc, emf_dc;
|
HDC display_dc, emf_dc;
|
||||||
ENHMETAHEADER *enh_header;
|
ENHMETAHEADER *enh_header, *enh2_header;
|
||||||
UINT size, emf_size, i;
|
UINT size, emf_size, i, emf2_size;
|
||||||
WORD check = 0;
|
WORD check = 0;
|
||||||
DWORD rec_num = 0;
|
DWORD rec_num = 0;
|
||||||
METAHEADER *mh = NULL;
|
METAHEADER *mh = NULL;
|
||||||
METARECORD *rec;
|
METARECORD *rec;
|
||||||
INT horz_res, vert_res, horz_size, vert_size;
|
INT horz_res, vert_res, horz_size, vert_size;
|
||||||
INT curve_caps, line_caps, poly_caps;
|
INT curve_caps, line_caps, poly_caps;
|
||||||
|
METAFILEPICT mfp;
|
||||||
|
|
||||||
display_dc = GetDC(NULL);
|
display_dc = GetDC(NULL);
|
||||||
ok(display_dc != NULL, "display_dc is NULL\n");
|
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);
|
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:
|
end:
|
||||||
HeapFree(GetProcessHeap(), 0, mh);
|
HeapFree(GetProcessHeap(), 0, mh);
|
||||||
HeapFree(GetProcessHeap(), 0, enh_header);
|
HeapFree(GetProcessHeap(), 0, enh_header);
|
||||||
|
|
Loading…
Reference in New Issue