From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 48f584e1a7e..37053e8061f 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -2977,6 +2977,7 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, case EMR_CREATEBRUSHINDIRECT: case EMR_SELECTPALETTE: case EMR_CREATEPALETTE: + case EMR_REALIZEPALETTE: case EMR_SETARCDIRECTION: case EMR_CLOSEFIGURE: case EMR_FLATTENPATH:
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 37053e8061f..f72a1a08b5b 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -2977,6 +2977,7 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, case EMR_CREATEBRUSHINDIRECT: case EMR_SELECTPALETTE: case EMR_CREATEPALETTE: + case EMR_RESIZEPALETTE: case EMR_REALIZEPALETTE: case EMR_SETARCDIRECTION: case EMR_CLOSEFIGURE:
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index f72a1a08b5b..0169873ceaf 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -2977,6 +2977,7 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, case EMR_CREATEBRUSHINDIRECT: case EMR_SELECTPALETTE: case EMR_CREATEPALETTE: + case EMR_SETPALETTEENTRIES: case EMR_RESIZEPALETTE: case EMR_REALIZEPALETTE: case EMR_SETARCDIRECTION:
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/dc.c | 4 ++++ dlls/gdi32/emfdc.c | 14 ++++++++++++++ dlls/gdi32/gdi_private.h | 1 + 3 files changed, 19 insertions(+)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 44dd9b9373d..8fa30884baf 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -2153,7 +2153,11 @@ HPALETTE WINAPI SelectPalette( HDC hdc, HPALETTE palette, BOOL force_background */ UINT WINAPI RealizePalette( HDC hdc ) { + DC_ATTR *dc_attr; + if (is_meta_dc( hdc )) return METADC_RealizePalette( hdc ); + if (!(dc_attr = get_dc_attr( hdc ))) return FALSE; + if (dc_attr->emf && !EMFDC_RealizePalette( dc_attr )) return 0; return pfnRealizePalette( hdc ); }
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index bf35450cfb3..f3ee0e3611c 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -696,6 +696,20 @@ BOOL EMFDC_SelectPalette( DC_ATTR *dc_attr, HPALETTE palette ) return emfdc_record( emf, &emr.emr ); }
+BOOL EMFDC_RealizePalette( DC_ATTR *dc_attr ) +{ + HPALETTE palette = GetCurrentObject( dc_attr_handle( dc_attr ), OBJ_PAL ); + struct emf *emf = get_dc_emf( dc_attr ); + EMRREALIZEPALETTE emr; + + if (palette == GetStockObject( DEFAULT_PALETTE )) + return TRUE; + + emr.emr.iType = EMR_REALIZEPALETTE; + emr.emr.nSize = sizeof(emr); + return emfdc_record( emf, &emr.emr ); +} + BOOL EMFDC_SelectObject( DC_ATTR *dc_attr, HGDIOBJ obj ) { switch (gdi_handle_type( obj )) diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index da4c951eb00..4a9c70dcbc3 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -225,6 +225,7 @@ extern BOOL EMFDC_PolyPolygon( DC_ATTR *dc_attr, const POINT *points, const INT extern BOOL EMFDC_Polygon( DC_ATTR *dc_attr, const POINT *points, INT count ) DECLSPEC_HIDDEN; extern BOOL EMFDC_Polyline( DC_ATTR *dc_attr, const POINT *points, INT count) DECLSPEC_HIDDEN; extern BOOL EMFDC_PolylineTo( DC_ATTR *dc_attr, const POINT *points, INT count ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_RealizePalette( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN; extern BOOL EMFDC_Rectangle( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom) DECLSPEC_HIDDEN; extern BOOL EMFDC_RestoreDC( DC_ATTR *dc_attr, INT level ) DECLSPEC_HIDDEN;
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/emfdc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index f3ee0e3611c..cc8e78a3cb5 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -651,27 +651,27 @@ static BOOL emfdc_select_pen( DC_ATTR *dc_attr, HPEN pen )
static DWORD emfdc_create_palette( struct emf *emf, HPALETTE hPal ) { + BYTE data[offsetof( EMRCREATEPALETTE, lgpl.palPalEntry[256] )]; + EMRCREATEPALETTE *hdr = (EMRCREATEPALETTE *)data; WORD i; - struct { - EMRCREATEPALETTE hdr; - PALETTEENTRY entry[255]; - } pal;
- memset( &pal, 0, sizeof(pal) ); + memset( data, 0, sizeof(data) );
- if (!GetObjectW( hPal, sizeof(pal.hdr.lgpl) + sizeof(pal.entry), &pal.hdr.lgpl )) + hdr->lgpl.palVersion = 0x300; + hdr->lgpl.palNumEntries = GetPaletteEntries( hPal, 0, 256, hdr->lgpl.palPalEntry ); + if (!hdr->lgpl.palNumEntries) return 0;
- for (i = 0; i < pal.hdr.lgpl.palNumEntries; i++) - pal.hdr.lgpl.palPalEntry[i].peFlags = 0; + for (i = 0; i < hdr->lgpl.palNumEntries; i++) + hdr->lgpl.palPalEntry[i].peFlags = 0;
- pal.hdr.emr.iType = EMR_CREATEPALETTE; - pal.hdr.emr.nSize = sizeof(pal.hdr) + pal.hdr.lgpl.palNumEntries * sizeof(PALETTEENTRY); - pal.hdr.ihPal = emfdc_add_handle( emf, hPal ); + hdr->emr.iType = EMR_CREATEPALETTE; + hdr->emr.nSize = offsetof( EMRCREATEPALETTE, lgpl.palPalEntry[hdr->lgpl.palNumEntries] ); + hdr->ihPal = emfdc_add_handle( emf, hPal );
- if (!emfdc_record( emf, &pal.hdr.emr )) - pal.hdr.ihPal = 0; - return pal.hdr.ihPal; + if (!emfdc_record( emf, &hdr->emr )) + hdr->ihPal = 0; + return hdr->ihPal; }
BOOL EMFDC_SelectPalette( DC_ATTR *dc_attr, HPALETTE palette )
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/emfdc.c | 67 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-)
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index cc8e78a3cb5..42330a22861 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -41,6 +41,9 @@ struct emf HBRUSH dc_brush; HPEN dc_pen; BOOL path; + DWORD palette_size; + DWORD palette_used; + PALETTEENTRY *palette; };
#define HANDLE_LIST_INC 20 @@ -394,6 +397,40 @@ static void emfdc_delete_object( HDC hdc, HGDIOBJ obj ) emf->cur_handles--; }
+static BOOL emfdc_add_palette_entry( struct emf *emf, PALETTEENTRY *entry ) +{ + int i; + + for (i = 0; i < emf->palette_used; i++) + { + if (emf->palette[i].peRed == entry->peRed && + emf->palette[i].peGreen == entry->peGreen && + emf->palette[i].peBlue == entry->peBlue) return TRUE; + } + + if (emf->palette_size == emf->palette_used) + { + if (!emf->palette_size) + { + emf->palette = HeapAlloc( GetProcessHeap(), 0, + 8 * sizeof(*emf->palette) ); + if (!emf->palette) return FALSE; + emf->palette_size = 8; + } + else + { + void *new_palette = HeapReAlloc( GetProcessHeap(), 0, emf->palette, + 2 * emf->palette_size * sizeof(*emf->palette) ); + if (!new_palette) return FALSE; + emf->palette = new_palette; + emf->palette_size *= 2; + } + } + + emf->palette[emf->palette_used++] = *entry; + return TRUE; +} + static DWORD emfdc_create_brush( struct emf *emf, HBRUSH brush ) { DWORD index = 0; @@ -663,7 +700,10 @@ static DWORD emfdc_create_palette( struct emf *emf, HPALETTE hPal ) return 0;
for (i = 0; i < hdr->lgpl.palNumEntries; i++) + { hdr->lgpl.palPalEntry[i].peFlags = 0; + emfdc_add_palette_entry( emf, hdr->lgpl.palPalEntry + i ); + }
hdr->emr.iType = EMR_CREATEPALETTE; hdr->emr.nSize = offsetof( EMRCREATEPALETTE, lgpl.palPalEntry[hdr->lgpl.palNumEntries] ); @@ -2344,6 +2384,7 @@ void EMFDC_DeleteDC( DC_ATTR *dc_attr ) struct emf *emf = get_dc_emf( dc_attr ); UINT index;
+ HeapFree( GetProcessHeap(), 0, emf->palette ); HeapFree( GetProcessHeap(), 0, emf->emh ); for (index = 0; index < emf->handles_size; index++) if (emf->handles[index]) @@ -2465,6 +2506,9 @@ HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, emf->dc_brush = 0; emf->dc_pen = 0; emf->path = FALSE; + emf->palette_size = 0; + emf->palette_used = 0; + emf->palette = NULL;
emf->emh->iType = EMR_HEADER; emf->emh->nSize = size; @@ -2533,10 +2577,11 @@ HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, */ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) { + UINT size, palette_size; HENHMETAFILE hmf; struct emf *emf; DC_ATTR *dc_attr; - EMREOF emr; + EMREOF *emr; HANDLE mapping = 0;
TRACE("(%p)\n", hdc ); @@ -2544,18 +2589,26 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) if (!(dc_attr = get_dc_attr( hdc )) || !get_dc_emf( dc_attr )) return 0; emf = get_dc_emf( dc_attr );
+ palette_size = emf->palette_used * sizeof(*emf->palette); + size = sizeof(*emr) + palette_size; + if (!(emr = HeapAlloc( GetProcessHeap(), 0, size ))) return 0; + if (dc_attr->save_level) RestoreDC( hdc, 1 );
if (emf->dc_brush) DeleteObject( emf->dc_brush ); if (emf->dc_pen) DeleteObject( emf->dc_pen );
- emr.emr.iType = EMR_EOF; - emr.emr.nSize = sizeof(emr); - emr.nPalEntries = 0; - emr.offPalEntries = FIELD_OFFSET(EMREOF, nSizeLast); - emr.nSizeLast = emr.emr.nSize; - emfdc_record( emf, &emr.emr ); + + emr->emr.iType = EMR_EOF; + emr->emr.nSize = size; + emr->nPalEntries = emf->palette_used; + emr->offPalEntries = FIELD_OFFSET(EMREOF, nSizeLast); + memcpy( (BYTE *)emr + emr->offPalEntries, emf->palette, palette_size ); + /* Set nSizeLast */ + ((DWORD *)((BYTE *)emr + size))[-1] = size; + emfdc_record( emf, &emr->emr ); + HeapFree( GetProcessHeap(), 0, emr );
emf->emh->rclBounds = dc_attr->emf_bounds;
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/tests/metafile.c | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+)
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c index 2b7e53b2529..0e5da463f7f 100644 --- a/dlls/gdi32/tests/metafile.c +++ b/dlls/gdi32/tests/metafile.c @@ -4802,6 +4802,83 @@ static void test_mf_palette(void) ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError()); }
+static void test_emf_palette(void) +{ + char logpalettebuf[sizeof(LOGPALETTE) + sizeof(logpalettedata)]; + LOGPALETTE *logpalette = (PLOGPALETTE)logpalettebuf; + HPALETTE hpal, old_pal, def_pal; + HENHMETAFILE emf; + HDC hdc; + BOOL ret; + + static const unsigned char palette_bits[] = + { + 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe6, 0xff, 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, + 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x80, 0x07, 0x00, 0x00, 0xcd, 0x03, 0x00, 0x00, + 0xfc, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00, + 0x9f, 0xed, 0x03, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x08, 0x00, 0x10, 0x20, 0x30, 0x00, + 0x20, 0x30, 0x40, 0x00, 0x30, 0x40, 0x50, 0x00, + 0x40, 0x50, 0x60, 0x00, 0x50, 0x60, 0x70, 0x00, + 0x60, 0x70, 0x80, 0x00, 0x70, 0x80, 0x90, 0x00, + 0x80, 0x90, 0xa0, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x80, 0x0e, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, + 0x20, 0x30, 0x40, 0x00, 0x30, 0x40, 0x50, 0x00, + 0x40, 0x50, 0x60, 0x00, 0x50, 0x60, 0x70, 0x00, + 0x60, 0x70, 0x80, 0x00, 0x70, 0x80, 0x90, 0x00, + 0x80, 0x90, 0xa0, 0x00, 0x34, 0x00, 0x00, 0x00 + }; + + hdc = CreateEnhMetaFileA(NULL, NULL, NULL, NULL); + ok(hdc != 0, "CreateMetaFileA error %ld\n", GetLastError()); + + /* Initialize the logical palette with a few colours */ + logpalette->palVersion = 0x300; + logpalette->palNumEntries = ARRAY_SIZE(logpalettedata); + memcpy(logpalette->palPalEntry, logpalettedata, sizeof(logpalettedata)); + hpal = CreatePalette(logpalette); + old_pal = SelectPalette(hdc, hpal, FALSE); + def_pal = GetStockObject(DEFAULT_PALETTE); + ok(old_pal == def_pal, "old_pal=%p, expected %p\n", old_pal, def_pal); + + ret = RealizePalette(hdc); + ok(!ret, "RealizePalette returned %d\n", ret); + + old_pal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE); + ok(old_pal == hpal, "old_pal=%p, expected %p\n", old_pal, hpal); + + ret = RealizePalette(hdc); + ok(!ret, "RealizePalette returned %d\n", ret); + + emf = CloseEnhMetaFile(hdc); + ok(emf != 0, "CloseEnhMetaFile error %ld\n", GetLastError()); + + if (compare_emf_bits(emf, palette_bits, sizeof(palette_bits), "emf_palette", FALSE)) + { + dump_emf_bits(emf, "emf_palette"); + dump_emf_records(emf, "emf_palette"); + } + + ret = DeleteEnhMetaFile(emf); + ok(ret, "DeleteMetaFile error %ld\n", GetLastError()); +} + static void test_mf_blit(void) { BITMAPINFO bmi = {{ sizeof(bmi) }}; @@ -10670,6 +10747,7 @@ START_TEST(metafile) test_emf_mask_blit(); test_emf_StretchDIBits(); test_emf_SetDIBitsToDevice(); + test_emf_palette();
/* For win-format metafiles (mfdrv) */ test_mf_SaveDC();
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=132118
Your paranoid android.
=== debian11 (32 bit report) ===
ddraw: ddraw1.c:3878: Test failed: Got unexpected screen width 640. ddraw1.c:3880: Test failed: Got unexpected screen height 480. ddraw1.c:3901: Test failed: Got unexpected screen width 640. ddraw1.c:3903: Test failed: Got unexpected screen height 480. ddraw1.c:3908: Test failed: Got unexpected screen width 640. ddraw1.c:3910: Test failed: Got unexpected screen height 480.
This merge request was approved by Huw Davies.