Printing using EMF spool files is still missing some features and has some bugs: - ResetDC should generally work on gdi side but is ignored on playback - because of that it wasn't really tested - no support for ExtEscape / Escape yet - DC bounds are incorrect
In order to enable printing using EMF spool files it's needed to change printer print processor to wineps.
From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index d09ac4420c3..6ff6e8997bc 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -237,6 +237,7 @@ typedef struct { WCHAR *port; WCHAR *print_proc; WCHAR *datatype; + DWORD attributes;
CRITICAL_SECTION jobs_cs; struct list jobs; @@ -546,6 +547,17 @@ static WCHAR * reg_query_value(HKEY key, const WCHAR *name) return ret; }
+static DWORD reg_query_dword(HKEY hkey, const WCHAR *name) +{ + DWORD type, val, size = sizeof(size); + + if (RegQueryValueExW(hkey, name, 0, &type, (BYTE*)&val, &size)) + return 0; + if (type != REG_DWORD) + return 0; + return val; +} + static printer_info_t* get_printer_info(const WCHAR *name) { HKEY hkey, hprinter = NULL; @@ -582,6 +594,7 @@ static printer_info_t* get_printer_info(const WCHAR *name) info->port = reg_query_value(hprinter, L"Port"); info->print_proc = reg_query_value(hprinter, L"Print Processor"); info->datatype = reg_query_value(hprinter, L"Datatype"); + info->attributes = reg_query_dword(hprinter, L"Attributes"); RegCloseKey(hprinter);
if (!info->name || !info->port || !info->print_proc || !info->datatype) @@ -3281,6 +3294,7 @@ static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_in { printer_t *printer = (printer_t *)hprinter; DOC_INFO_1W *info = (DOC_INFO_1W *)doc_info; + WCHAR *datatype;
TRACE("(%p %ld %p {pDocName = %s, pOutputFile = %s, pDatatype = %s})\n", hprinter, level, doc_info, debugstr_w(info->pDocName), @@ -3318,6 +3332,23 @@ static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_in return 0; }
+ if (info->pDatatype) + datatype = info->pDatatype; + else if (printer->datatype) + datatype = printer->datatype; + else + datatype = printer->info->datatype; + + if (!datatype || printer->info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY) + { + if (!datatype || wcsicmp(datatype, L"RAW")) + { + TRACE("non RAW datatype specified on RAW-only printer (%s)\n", debugstr_w(datatype)); + SetLastError(ERROR_INVALID_DATATYPE); + return 0; + } + } + printer->doc = add_job(printer, info, TRUE); return printer->doc ? printer->doc->id : 0; }
From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 243 +++++++++++++++++++++------------------ 1 file changed, 132 insertions(+), 111 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 6ff6e8997bc..b268c796afe 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -3290,11 +3290,124 @@ static BOOL WINAPI fpAddJob(HANDLE hprinter, DWORD level, BYTE *data, DWORD size return TRUE; }
+typedef struct { + HMODULE hmod; + WCHAR *name; + BOOL (WINAPI *enum_datatypes)(WCHAR *, WCHAR *, DWORD, + BYTE *, DWORD, DWORD *, DWORD *); + HANDLE (WINAPI *open)(WCHAR *, PRINTPROCESSOROPENDATA *); + BOOL (WINAPI *print)(HANDLE, WCHAR *); + BOOL (WINAPI *close)(HANDLE); +} printproc_t; + +static printproc_t * print_proc_load(const WCHAR *name) +{ + WCHAR *reg_path, path[2 * MAX_PATH]; + printproc_t *ret; + DWORD size, len; + LSTATUS status; + HKEY hkey; + + size = sizeof(fmt_printprocessorsW) + + (wcslen(env_arch.envname) + wcslen(name)) * sizeof(WCHAR); + reg_path = malloc(size); + if (!reg_path) + return NULL; + swprintf(reg_path, size / sizeof(WCHAR), fmt_printprocessorsW, env_arch.envname); + wcscat(reg_path, name); + + status = RegOpenKeyW(HKEY_LOCAL_MACHINE, reg_path, &hkey); + free(reg_path); + if (status != ERROR_SUCCESS) + return NULL; + + if (!fpGetPrintProcessorDirectory(NULL, NULL, 1, (BYTE *)path, sizeof(path), &size)) + { + RegCloseKey(hkey); + return NULL; + } + len = size / sizeof(WCHAR); + path[len - 1] = '\'; + + size = sizeof(path) - len * sizeof(WCHAR); + status = RegQueryValueExW(hkey, L"Driver", NULL, NULL, (BYTE *)(path + len), &size); + RegCloseKey(hkey); + if (status != ERROR_SUCCESS) + return NULL; + + ret = malloc(sizeof(*ret)); + if (!ret) + return NULL; + + TRACE("loading print processor: %s\n", debugstr_w(path)); + + ret->hmod = LoadLibraryW(path); + if (!ret->hmod) + { + free(ret); + return NULL; + } + + ret->enum_datatypes = (void *)GetProcAddress(ret->hmod, "EnumPrintProcessorDatatypesW"); + ret->open = (void *)GetProcAddress(ret->hmod, "OpenPrintProcessor"); + ret->print = (void *)GetProcAddress(ret->hmod, "PrintDocumentOnPrintProcessor"); + ret->close = (void *)GetProcAddress(ret->hmod, "ClosePrintProcessor"); + if (!ret->enum_datatypes || !ret->open || !ret->print || !ret->close) + { + FreeLibrary(ret->hmod); + free(ret); + return NULL; + } + + ret->name = wcsdup(name); + return ret; +} + +static BOOL print_proc_check_datatype(printproc_t *pp, const WCHAR *datatype) +{ + DATATYPES_INFO_1W *types; + DWORD size, no, i; + + if (!datatype) + return FALSE; + + pp->enum_datatypes(NULL, pp->name, 1, NULL, 0, &size, &no); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return FALSE; + + types = malloc(size); + if (!types) + return FALSE; + + if (!pp->enum_datatypes(NULL, pp->name, 1, (BYTE *)types, size, &size, &no)) + { + free(types); + return FALSE; + } + + for (i = 0; i < no; i++) + { + if (!wcscmp(types[i].pName, datatype)) + break; + } + free(types); + return i < no; +} + +static void print_proc_unload(printproc_t *pp) +{ + FreeLibrary(pp->hmod); + free(pp->name); + free(pp); +} + static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_info) { printer_t *printer = (printer_t *)hprinter; DOC_INFO_1W *info = (DOC_INFO_1W *)doc_info; + BOOL datatype_valid; WCHAR *datatype; + printproc_t *pp;
TRACE("(%p %ld %p {pDocName = %s, pOutputFile = %s, pDatatype = %s})\n", hprinter, level, doc_info, debugstr_w(info->pDocName), @@ -3349,6 +3462,25 @@ static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_in } }
+ pp = print_proc_load(printer->info->print_proc); + if (!pp) + { + WARN("failed to load %s print processor\n", debugstr_w(printer->info->print_proc)); + pp = print_proc_load(L"winprint"); + } + if (!pp) + return 0; + + datatype_valid = print_proc_check_datatype(pp, datatype); + print_proc_unload(pp); + if (!datatype_valid) + { + TRACE("%s datatype not supported by %s\n", debugstr_w(datatype), + debugstr_w(printer->info->print_proc)); + SetLastError(ERROR_INVALID_DATATYPE); + return 0; + } + printer->doc = add_job(printer, info, TRUE); return printer->doc ? printer->doc->id : 0; } @@ -3588,117 +3720,6 @@ static BOOL WINAPI fpGetJob(HANDLE hprinter, DWORD job_id, DWORD level, return ret; }
-typedef struct { - HMODULE hmod; - WCHAR *name; - BOOL (WINAPI *enum_datatypes)(WCHAR *, WCHAR *, DWORD, - BYTE *, DWORD, DWORD *, DWORD *); - HANDLE (WINAPI *open)(WCHAR *, PRINTPROCESSOROPENDATA *); - BOOL (WINAPI *print)(HANDLE, WCHAR *); - BOOL (WINAPI *close)(HANDLE); -} printproc_t; - -static printproc_t * print_proc_load(const WCHAR *name) -{ - WCHAR *reg_path, path[2 * MAX_PATH]; - printproc_t *ret; - DWORD size, len; - LSTATUS status; - HKEY hkey; - - size = sizeof(fmt_printprocessorsW) + - (wcslen(env_arch.envname) + wcslen(name)) * sizeof(WCHAR); - reg_path = malloc(size); - if (!reg_path) - return NULL; - swprintf(reg_path, size / sizeof(WCHAR), fmt_printprocessorsW, env_arch.envname); - wcscat(reg_path, name); - - status = RegOpenKeyW(HKEY_LOCAL_MACHINE, reg_path, &hkey); - free(reg_path); - if (status != ERROR_SUCCESS) - return NULL; - - if (!fpGetPrintProcessorDirectory(NULL, NULL, 1, (BYTE *)path, sizeof(path), &size)) - { - RegCloseKey(hkey); - return NULL; - } - len = size / sizeof(WCHAR); - path[len - 1] = '\'; - - size = sizeof(path) - len * sizeof(WCHAR); - status = RegQueryValueExW(hkey, L"Driver", NULL, NULL, (BYTE *)(path + len), &size); - RegCloseKey(hkey); - if (status != ERROR_SUCCESS) - return NULL; - - ret = malloc(sizeof(*ret)); - if (!ret) - return NULL; - - TRACE("loading print processor: %s\n", debugstr_w(path)); - - ret->hmod = LoadLibraryW(path); - if (!ret->hmod) - { - free(ret); - return NULL; - } - - ret->enum_datatypes = (void *)GetProcAddress(ret->hmod, "EnumPrintProcessorDatatypesW"); - ret->open = (void *)GetProcAddress(ret->hmod, "OpenPrintProcessor"); - ret->print = (void *)GetProcAddress(ret->hmod, "PrintDocumentOnPrintProcessor"); - ret->close = (void *)GetProcAddress(ret->hmod, "ClosePrintProcessor"); - if (!ret->enum_datatypes || !ret->open || !ret->print || !ret->close) - { - FreeLibrary(ret->hmod); - free(ret); - return NULL; - } - - ret->name = wcsdup(name); - return ret; -} - -static BOOL print_proc_check_datatype(printproc_t *pp, const WCHAR *datatype) -{ - DATATYPES_INFO_1W *types; - DWORD size, no, i; - - if (!datatype) - return FALSE; - - pp->enum_datatypes(NULL, pp->name, 1, NULL, 0, &size, &no); - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - return FALSE; - - types = malloc(size); - if (!types) - return FALSE; - - if (!pp->enum_datatypes(NULL, pp->name, 1, (BYTE *)types, size, &size, &no)) - { - free(types); - return FALSE; - } - - for (i = 0; i < no; i++) - { - if (!wcscmp(types[i].pName, datatype)) - break; - } - free(types); - return i < no; -} - -static void print_proc_unload(printproc_t *pp) -{ - FreeLibrary(pp->hmod); - free(pp->name); - free(pp); -} - static BOOL WINAPI fpScheduleJob(HANDLE hprinter, DWORD job_id) { printer_t *printer = (printer_t *)hprinter;
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 914fc23f69e..9b96b2c1465 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -3040,6 +3040,7 @@ static BOOL print_metafile(struct pp_data *data, HANDLE hdata) return FALSE;
AbortPath(data->pdev->dev.hdc); + MoveToEx(data->pdev->dev.hdc, 0, 0, NULL); SetBkColor(data->pdev->dev.hdc, RGB(255, 255, 255)); SetBkMode(data->pdev->dev.hdc, OPAQUE); SetMapMode(data->pdev->dev.hdc, MM_TEXT);
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/dc.c | 45 ++++++++++++++++++++++++++++++++++++--------- include/ntgdi.h | 3 +-- 2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 8fa30884baf..6a5bb86d4f1 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -51,6 +51,11 @@ struct graphics_driver driver_entry_point entry_point; };
+struct print +{ + HANDLE printer; + WCHAR *output; +};
DC_ATTR *get_dc_attr( HDC hdc ) { @@ -200,6 +205,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, driver_entry_point entry_point = NULL; const WCHAR *display = NULL, *p; WCHAR buf[300], *port = NULL; + struct print *print = NULL; BOOL is_display = FALSE; HANDLE hspool = NULL; DC_ATTR *dc_attr; @@ -249,6 +255,11 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, ClosePrinter( hspool ); return 0; } + else if (!(print = HeapAlloc( GetProcessHeap(), 0, sizeof(*print) ))) + { + ClosePrinter( hspool ); + HeapFree( GetProcessHeap(), 0, port ); + }
if (display) { @@ -275,13 +286,15 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, memcpy( port, output, output_str.Length ); port[output_str.Length / sizeof(WCHAR)] = 0; } - dc_attr->hspool = HandleToULong( hspool ); - dc_attr->output = (ULONG_PTR)port; + print->printer = hspool; + print->output = port; + dc_attr->print = (UINT_PTR)print; } else if (hspool) { ClosePrinter( hspool ); HeapFree( GetProcessHeap(), 0, port ); + HeapFree( GetProcessHeap(), 0, print ); }
return ret; @@ -392,6 +405,21 @@ DEVMODEW *WINAPI GdiConvertToDevmodeW( const DEVMODEA *dmA ) return dmW; }
+static inline struct print *get_dc_print( DC_ATTR *dc_attr ) +{ + return (struct print *)(UINT_PTR)dc_attr->print; +} + +static void delete_print_dc( DC_ATTR *dc_attr ) +{ + struct print *print = get_dc_print( dc_attr ); + + ClosePrinter( print->printer ); + HeapFree( GetProcessHeap(), 0, print->output ); + HeapFree( GetProcessHeap(), 0, print ); + dc_attr->print = 0; +} + /*********************************************************************** * DeleteDC (GDI32.@) */ @@ -401,10 +429,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
if (is_meta_dc( hdc )) return METADC_DeleteDC( hdc ); if (!(dc_attr = get_dc_attr( hdc ))) return FALSE; - HeapFree( GetProcessHeap(), 0, (WCHAR *)(ULONG_PTR)dc_attr->output ); - dc_attr->output = 0; - if (dc_attr->hspool) ClosePrinter( ULongToHandle(dc_attr->hspool) ); - dc_attr->hspool = 0; + if (dc_attr->print) delete_print_dc( dc_attr ); if (dc_attr->emf) EMFDC_DeleteDC( dc_attr ); return NtGdiDeleteObjectApp( hdc ); } @@ -2192,6 +2217,7 @@ BOOL WINAPI CancelDC(HDC hdc) INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc ) { WCHAR *output = NULL; + struct print *print; DC_ATTR *dc_attr; ABORTPROC proc; DOCINFOW info; @@ -2218,10 +2244,11 @@ INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc ) proc = (ABORTPROC)(UINT_PTR)dc_attr->abort_proc; if (proc && !proc( hdc, 0 )) return 0;
- if (dc_attr->hspool) + print = get_dc_print( dc_attr ); + if (print) { - if (!info.lpszOutput) info.lpszOutput = (const WCHAR *)(ULONG_PTR)dc_attr->output; - output = StartDocDlgW( ULongToHandle( dc_attr->hspool ), &info ); + if (!info.lpszOutput) info.lpszOutput = print->output; + output = StartDocDlgW( print->printer, &info ); if (output) info.lpszOutput = output; }
diff --git a/include/ntgdi.h b/include/ntgdi.h index 1aa5cad468f..7d00ced2d19 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -198,8 +198,7 @@ typedef struct DC_ATTR RECTL emf_bounds; UINT64 emf; /* client EMF record pointer */ UINT64 abort_proc; /* AbortProc for printing */ - UINT64 hspool; - UINT64 output; + UINT64 print; /* client printer info pointer */ } DC_ATTR;
struct font_enum_entry
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/emfdc.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index 42330a22861..47f48bef9d3 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -2384,6 +2384,9 @@ void EMFDC_DeleteDC( DC_ATTR *dc_attr ) struct emf *emf = get_dc_emf( dc_attr ); UINT index;
+ if (emf->dc_brush) DeleteObject( emf->dc_brush ); + if (emf->dc_pen) DeleteObject( emf->dc_pen ); + CloseHandle( emf->file ); HeapFree( GetProcessHeap(), 0, emf->palette ); HeapFree( GetProcessHeap(), 0, emf->emh ); for (index = 0; index < emf->handles_size; index++) @@ -2597,7 +2600,9 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) RestoreDC( hdc, 1 );
if (emf->dc_brush) DeleteObject( emf->dc_brush ); + emf->dc_brush = 0; if (emf->dc_pen) DeleteObject( emf->dc_pen ); + emf->dc_pen = 0;
emr->emr.iType = EMR_EOF; @@ -2630,6 +2635,7 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) if (!WriteFile( emf->file, emf->emh, emf->emh->nBytes, NULL, NULL )) { CloseHandle( emf->file ); + emf->file = 0; return 0; } HeapFree( GetProcessHeap(), 0, emf->emh ); @@ -2642,6 +2648,7 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) }
hmf = EMF_Create_HENHMETAFILE( emf->emh, emf->emh->nBytes, emf->file != 0 ); + emf->file = 0; emf->emh = NULL; /* So it won't be deleted */ DeleteDC( hdc ); return hmf;
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/emfdc.c | 57 +++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 24 deletions(-)
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index 47f48bef9d3..2e4b0a85de6 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -2575,35 +2575,16 @@ HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, return ret; }
-/****************************************************************** - * CloseEnhMetaFile (GDI32.@) - */ -HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) +static BOOL emf_eof( DC_ATTR *dc_attr ) { + struct emf *emf = get_dc_emf( dc_attr ); UINT size, palette_size; - HENHMETAFILE hmf; - struct emf *emf; - DC_ATTR *dc_attr; EMREOF *emr; - HANDLE mapping = 0; - - TRACE("(%p)\n", hdc ); - - if (!(dc_attr = get_dc_attr( hdc )) || !get_dc_emf( dc_attr )) return 0; - emf = get_dc_emf( dc_attr ); + BOOL ret;
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 ); - emf->dc_brush = 0; - if (emf->dc_pen) DeleteObject( emf->dc_pen ); - emf->dc_pen = 0; - + if (!(emr = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
emr->emr.iType = EMR_EOF; emr->emr.nSize = size; @@ -2612,8 +2593,9 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) memcpy( (BYTE *)emr + emr->offPalEntries, emf->palette, palette_size ); /* Set nSizeLast */ ((DWORD *)((BYTE *)emr + size))[-1] = size; - emfdc_record( emf, &emr->emr ); + ret = emfdc_record( emf, &emr->emr ); HeapFree( GetProcessHeap(), 0, emr ); + if (!ret) return FALSE;
emf->emh->rclBounds = dc_attr->emf_bounds;
@@ -2629,6 +2611,33 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) emf->emh->rclFrame.bottom = emf->emh->rclBounds.bottom * emf->emh->szlMillimeters.cy * 100 / emf->emh->szlDevice.cy; } + return TRUE; +} + +/****************************************************************** + * CloseEnhMetaFile (GDI32.@) + */ +HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) +{ + HENHMETAFILE hmf; + struct emf *emf; + DC_ATTR *dc_attr; + HANDLE mapping = 0; + + TRACE("(%p)\n", hdc ); + + if (!(dc_attr = get_dc_attr( hdc )) || !get_dc_emf( dc_attr )) return 0; + emf = get_dc_emf( dc_attr ); + + if (dc_attr->save_level) + RestoreDC( hdc, 1 ); + + if (emf->dc_brush) DeleteObject( emf->dc_brush ); + emf->dc_brush = 0; + if (emf->dc_pen) DeleteObject( emf->dc_pen ); + emf->dc_pen = 0; + + if (!emf_eof( dc_attr )) return 0;
if (emf->file) /* disk based metafile */ {
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/emfdc.c | 140 +++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 57 deletions(-)
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index 2e4b0a85de6..e483b6a3498 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -2460,61 +2460,20 @@ HDC WINAPI CreateEnhMetaFileA( HDC hdc, const char *filename, const RECT *rect, return ret; }
-/********************************************************************** - * CreateEnhMetaFileW (GDI32.@) - */ -HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, - const WCHAR *description ) +static void emf_reset( DC_ATTR *dc_attr, const RECT *rect ) { - HDC ret; - struct emf *emf; - DC_ATTR *dc_attr; - HANDLE file; - DWORD size = 0, length = 0; - - TRACE( "(%p %s %s %s)\n", hdc, debugstr_w(filename), wine_dbgstr_rect(rect), - debugstr_w(description) ); - - if (!(ret = NtGdiCreateMetafileDC( hdc ))) return 0; - - if (!(dc_attr = get_dc_attr( ret )) || !(emf = HeapAlloc( GetProcessHeap(), 0, sizeof(*emf) ))) - { - DeleteDC( ret ); - return 0; - } - - emf->dc_attr = dc_attr; - dc_attr->emf = (UINT_PTR)emf; - - if (description) /* App name\0Title\0\0 */ - { - length = lstrlenW( description ); - length += lstrlenW( description + length + 1 ); - length += 3; - length *= 2; - } - size = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4; - - if (!(emf->emh = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size))) - { - DeleteDC( ret ); - return 0; - } + struct emf *emf = get_dc_emf( dc_attr ); + HDC hdc = dc_attr_handle( dc_attr );
- emf->handles = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - HANDLE_LIST_INC * sizeof(emf->handles[0]) ); - emf->handles_size = HANDLE_LIST_INC; + memset( emf->handles, 0, emf->handles_size * sizeof(emf->handles[0]) ); emf->cur_handles = 1; emf->file = 0; + if (emf->dc_brush) DeleteObject( emf->dc_brush ); emf->dc_brush = 0; + if (emf->dc_pen) DeleteObject( emf->dc_pen ); 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;
dc_attr->emf_bounds.left = dc_attr->emf_bounds.top = 0; dc_attr->emf_bounds.right = dc_attr->emf_bounds.bottom = -1; @@ -2538,28 +2497,95 @@ HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, emf->emh->nBytes = emf->emh->nSize; emf->emh->nRecords = 1; emf->emh->nHandles = 1; - emf->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */ - emf->emh->nDescription = length / 2; - - emf->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0; - - emf->emh->nPalEntries = 0; /* I guess this should start at 0 */ + emf->emh->nPalEntries = 0;
/* Size in pixels */ - emf->emh->szlDevice.cx = GetDeviceCaps( ret, HORZRES ); - emf->emh->szlDevice.cy = GetDeviceCaps( ret, VERTRES ); + emf->emh->szlDevice.cx = GetDeviceCaps( hdc, HORZRES ); + emf->emh->szlDevice.cy = GetDeviceCaps( hdc, VERTRES );
/* Size in millimeters */ - emf->emh->szlMillimeters.cx = GetDeviceCaps( ret, HORZSIZE ); - emf->emh->szlMillimeters.cy = GetDeviceCaps( ret, VERTSIZE ); + emf->emh->szlMillimeters.cx = GetDeviceCaps( hdc, HORZSIZE ); + emf->emh->szlMillimeters.cy = GetDeviceCaps( hdc, VERTSIZE ); + + emf->emh->cbPixelFormat = 0; + emf->emh->offPixelFormat = 0; + emf->emh->bOpenGL = 0;
/* Size in micrometers */ emf->emh->szlMicrometers.cx = emf->emh->szlMillimeters.cx * 1000; emf->emh->szlMicrometers.cy = emf->emh->szlMillimeters.cy * 1000; +} + +static struct emf *emf_create( HDC hdc, const RECT *rect, const WCHAR *description ) +{ + DWORD size = 0, length = 0; + DC_ATTR *dc_attr; + struct emf *emf; + + if (!(dc_attr = get_dc_attr( hdc )) || !(emf = HeapAlloc( GetProcessHeap(), 0, sizeof(*emf) ))) + return NULL; + + if (description) /* App name\0Title\0\0 */ + { + length = lstrlenW( description ); + length += lstrlenW( description + length + 1 ); + length += 3; + length *= 2; + } + size = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4; + + if (!(emf->emh = HeapAlloc( GetProcessHeap(), 0, size )) || + !(emf->handles = HeapAlloc( GetProcessHeap(), 0, + HANDLE_LIST_INC * sizeof(emf->handles[0]) ))) + { + HeapFree( GetProcessHeap(), 0, emf->emh ); + HeapFree( GetProcessHeap(), 0, emf ); + return NULL; + } + + emf->dc_attr = dc_attr; + dc_attr->emf = (UINT_PTR)emf; + + emf->handles_size = HANDLE_LIST_INC; + emf->dc_brush = 0; + emf->dc_pen = 0; + emf->palette_size = 0; + emf->palette = NULL; + + emf->emh->iType = EMR_HEADER; + emf->emh->nSize = size; + emf->emh->nDescription = length / 2; + emf->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0;
memcpy( (char *)emf->emh + sizeof(ENHMETAHEADER), description, length );
+ emf_reset( dc_attr, rect ); + return emf; +} + +/********************************************************************** + * CreateEnhMetaFileW (GDI32.@) + */ +HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, + const WCHAR *description ) +{ + struct emf *emf; + HANDLE file; + HDC ret; + + TRACE( "(%p %s %s %s)\n", hdc, debugstr_w(filename), wine_dbgstr_rect(rect), + debugstr_w(description) ); + + if (!(ret = NtGdiCreateMetafileDC( hdc ))) return 0; + + emf = emf_create( ret, rect, description ); + if (!emf) + { + DeleteDC( ret ); + return 0; + } + if (filename) /* disk based metafile */ { if ((file = CreateFileW( filename, GENERIC_WRITE | GENERIC_READ, 0,
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/dc.c | 43 ++++++++++ dlls/gdi32/emfdc.c | 181 +++++++++++++++++++++++++++++++++++++++ dlls/gdi32/gdi_private.h | 7 ++ 3 files changed, 231 insertions(+)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 6a5bb86d4f1..459d0dfb8c1 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -2216,6 +2216,7 @@ BOOL WINAPI CancelDC(HDC hdc) */ INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc ) { + DOC_INFO_1W spool_info; WCHAR *output = NULL; struct print *print; DC_ATTR *dc_attr; @@ -2240,6 +2241,7 @@ INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc ) debugstr_w(info.lpszDatatype), info.fwType);
if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR; + if (dc_attr->print && dc_attr->emf) return SP_ERROR;
proc = (ABORTPROC)(UINT_PTR)dc_attr->abort_proc; if (proc && !proc( hdc, 0 )) return 0; @@ -2250,6 +2252,23 @@ INT WINAPI StartDocW( HDC hdc, const DOCINFOW *doc ) if (!info.lpszOutput) info.lpszOutput = print->output; output = StartDocDlgW( print->printer, &info ); if (output) info.lpszOutput = output; + + if (!info.lpszDatatype || !wcsicmp(info.lpszDatatype, L"EMF")) + { + spool_info.pDocName = (WCHAR *)info.lpszDocName; + spool_info.pOutputFile = (WCHAR *)info.lpszOutput; + spool_info.pDatatype = (WCHAR *)L"NT EMF 1.003"; + if ((ret = StartDocPrinterW( print->printer, 1, (BYTE *)&spool_info ))) + { + if (!spool_start_doc( dc_attr, print->printer, &info )) + { + AbortDoc( hdc ); + ret = 0; + } + HeapFree( GetProcessHeap(), 0, output ); + return ret; + } + } }
ret = NtGdiStartDoc( hdc, &info, NULL, 0 ); @@ -2306,6 +2325,12 @@ INT WINAPI StartDocA( HDC hdc, const DOCINFOA *doc ) */ INT WINAPI StartPage( HDC hdc ) { + struct print *print; + DC_ATTR *dc_attr; + + if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR; + if ((print = get_dc_print( dc_attr )) && dc_attr->emf) + return spool_start_page( dc_attr, print->printer ); return NtGdiStartPage( hdc ); }
@@ -2314,6 +2339,12 @@ INT WINAPI StartPage( HDC hdc ) */ INT WINAPI EndPage( HDC hdc ) { + struct print *print; + DC_ATTR *dc_attr; + + if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR; + if ((print = get_dc_print( dc_attr )) && dc_attr->emf) + return spool_end_page( dc_attr, print->printer ); return NtGdiEndPage( hdc ); }
@@ -2322,6 +2353,12 @@ INT WINAPI EndPage( HDC hdc ) */ INT WINAPI EndDoc( HDC hdc ) { + struct print *print; + DC_ATTR *dc_attr; + + if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR; + if ((print = get_dc_print( dc_attr )) && dc_attr->emf) + return spool_end_doc( dc_attr, print->printer ); return NtGdiEndDoc( hdc ); }
@@ -2330,6 +2367,12 @@ INT WINAPI EndDoc( HDC hdc ) */ INT WINAPI AbortDoc( HDC hdc ) { + struct print *print; + DC_ATTR *dc_attr; + + if (!(dc_attr = get_dc_attr( hdc ))) return SP_ERROR; + if ((print = get_dc_print( dc_attr )) && dc_attr->emf) + return spool_abort_doc( dc_attr, print->printer ); return NtGdiAbortDoc( hdc ); }
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index e483b6a3498..9690bee2a17 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -44,8 +44,39 @@ struct emf DWORD palette_size; DWORD palette_used; PALETTEENTRY *palette; + enum + { + DOCUMENT_NOT_STARTED, + NEEDS_START_PAGE, + NEEDS_END_PAGE + } document_state; };
+typedef enum +{ + EMRI_METAFILE = 1, + EMRI_ENGINE_FONT, + EMRI_DEVMODE, + EMRI_TYPE1_FONT, + EMRI_PRESTARTPAGE, + EMRI_DESIGNVECTOR, + EMRI_SUBSET_FONT, + EMRI_DELTA_FONT, + EMRI_FORM_METAFILE, + EMRI_BW_METAFILE, + EMRI_BW_FORM_METAFILE, + EMRI_METAFILE_DATA, + EMRI_METAFILE_EXT, + EMRI_BW_METAFILE_EXT, + EMRI_ENGINE_FONT_EXT, + EMRI_TYPE1_FONT_EXT, + EMRI_DESIGNVECTOR_EXT, + EMRI_SUBSET_FONT_EXT, + EMRI_DELTA_FONT_EXT, + EMRI_PS_JOB_DATA, + EMRI_EMBED_FONT_EXT, +} emfspool_record_type; + #define HANDLE_LIST_INC 20 static const RECTL empty_bounds = { 0, 0, -1, -1 };
@@ -2474,6 +2505,7 @@ static void emf_reset( DC_ATTR *dc_attr, const RECT *rect ) emf->dc_pen = 0; emf->path = FALSE; emf->palette_used = 0; + emf->document_state = DOCUMENT_NOT_STARTED;
dc_attr->emf_bounds.left = dc_attr->emf_bounds.top = 0; dc_attr->emf_bounds.right = dc_attr->emf_bounds.bottom = -1; @@ -2688,3 +2720,152 @@ HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) DeleteDC( hdc ); return hmf; } + +BOOL spool_start_doc( DC_ATTR *dc_attr, HANDLE hspool, const DOCINFOW *doc_info ) +{ + struct + { + unsigned int dwVersion; + unsigned int cjSize; + unsigned int dpszDocName; + unsigned int dpszOutput; + } *header; + size_t size = sizeof(*header); + struct emf *emf; + DWORD written; + WCHAR *p; + + TRACE( "(%p %p)\n", dc_attr, hspool ); + + if (doc_info->lpszDocName) + size += (wcslen( doc_info->lpszDocName ) + 1) * sizeof(WCHAR); + if (doc_info->lpszOutput) + size += (wcslen( doc_info->lpszOutput ) + 1) * sizeof(WCHAR); + header = HeapAlloc( GetProcessHeap(), 0, size ); + if (!header) return FALSE; + + header->dwVersion = 0x10000; + header->cjSize = size; + p = (WCHAR *)(header + 1); + if (doc_info->lpszDocName) + { + header->dpszDocName = (BYTE *)p - (BYTE *)header; + wcscpy( p, doc_info->lpszDocName ); + p += wcslen( doc_info->lpszDocName ) + 1; + } + else + { + header->dpszDocName = 0; + } + if (doc_info->lpszOutput) + { + header->dpszOutput = (BYTE *)p - (BYTE *)header; + wcscpy( p, doc_info->lpszOutput ); + } + else + { + header->dpszOutput = 0; + } + if (!WritePrinter( hspool, header, size, &written )) written = 0; + HeapFree( GetProcessHeap(), 0, header ); + if (written != size) return FALSE; + + emf = emf_create( dc_attr_handle(dc_attr), NULL, NULL ); + if (!emf) return FALSE; + emf->document_state = NEEDS_START_PAGE; + return TRUE; +} + +int spool_start_page( DC_ATTR *dc_attr, HANDLE hspool ) +{ + struct emf *emf = get_dc_emf( dc_attr ); + HDC hdc = dc_attr_handle( dc_attr ); + POINT pos = { 0 }; + XFORM xform; + + TRACE( "(%p)\n", dc_attr ); + + /* Save current DC state to EMF */ + /* FIXME: SetTextJustification if needed */ + EMFDC_SelectObject( dc_attr, GetCurrentObject(hdc, OBJ_PEN) ); + EMFDC_SelectObject( dc_attr, GetCurrentObject(hdc, OBJ_BRUSH) ); + EMFDC_SelectObject( dc_attr, GetCurrentObject(hdc, OBJ_FONT) ); + if (GetBkColor( hdc ) != 0xffffff) + EMFDC_SetBkColor( dc_attr, GetBkColor(hdc) ); + if (GetBkMode( hdc ) != OPAQUE) + EMFDC_SetBkMode( dc_attr, GetBkMode(hdc) ); + GetCurrentPositionEx( hdc, &pos ); + if (pos.x || pos.y) + EMFDC_MoveTo( dc_attr, pos.x, pos.y ); + if (GetMapMode( hdc ) != MM_TEXT) + EMFDC_SetMapMode( dc_attr, GetMapMode(hdc) ); + if (GetPolyFillMode( hdc ) != ALTERNATE) + EMFDC_SetPolyFillMode( dc_attr, GetPolyFillMode(hdc) ); + if (GetROP2( hdc ) != R2_COPYPEN) + EMFDC_SetROP2( dc_attr, GetROP2(hdc) ); + if (GetStretchBltMode( hdc ) != BLACKONWHITE) + EMFDC_SetStretchBltMode( dc_attr, GetStretchBltMode(hdc) ); + if (GetTextAlign( hdc ) != (TA_LEFT | TA_TOP)) + EMFDC_SetTextAlign( dc_attr, GetTextAlign(hdc) ); + if (GetTextColor( hdc )) + EMFDC_SetTextColor( dc_attr, GetTextColor(hdc) ); + GetWorldTransform(hdc, &xform); + if (xform.eM11 != 1 || xform.eM22 != 1 || xform.eM12 || xform.eM21 || xform.eDx || xform.eDy) + EMFDC_SetWorldTransform( dc_attr, &xform ); + + emf->document_state = NEEDS_END_PAGE; + return StartPagePrinter( hspool ); +} + +int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool ) +{ + struct record_hdr + { + unsigned int ulID; + unsigned int cjSize; + } record_hdr; + struct + { + struct record_hdr hdr; + LARGE_INTEGER pos; + } metafile_ext; + struct emf *emf = get_dc_emf( dc_attr ); + DWORD written; + + TRACE( "(%p %p)\n", dc_attr, hspool ); + + if (!emf_eof( dc_attr )) return 0; + + record_hdr.ulID = EMRI_METAFILE_DATA; + record_hdr.cjSize = emf->emh->nBytes; + if (!WritePrinter( hspool, &record_hdr, sizeof(record_hdr), &written )) return 0; + if (!WritePrinter( hspool, emf->emh, emf->emh->nBytes, &written )) return 0; + + metafile_ext.hdr.ulID = EMRI_METAFILE_EXT; + metafile_ext.hdr.cjSize = sizeof(metafile_ext) - sizeof(struct record_hdr); + metafile_ext.pos.QuadPart = emf->emh->nBytes + sizeof(record_hdr); + if (!WritePrinter( hspool, &metafile_ext, sizeof(metafile_ext), &written )) return 0; + + emf_reset( dc_attr, NULL ); + emf->document_state = NEEDS_START_PAGE; + return EndPagePrinter( hspool ); +} + +int spool_abort_doc( DC_ATTR *dc_attr, HANDLE hspool ) +{ + TRACE( "(%p %p)\n", dc_attr, hspool ); + + EMFDC_DeleteDC( dc_attr ); + return AbortPrinter( hspool ); +} + +int spool_end_doc( DC_ATTR *dc_attr, HANDLE hspool ) +{ + struct emf *emf = get_dc_emf( dc_attr ); + + TRACE( "(%p %p)\n", dc_attr, hspool ); + + if (emf->document_state == NEEDS_END_PAGE) spool_end_page( dc_attr, hspool ); + EMFDC_DeleteDC( dc_attr ); + return EndDocPrinter( hspool ); +} diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 4a9c70dcbc3..157e438c687 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -280,6 +280,13 @@ extern BOOL EMFDC_WidenPath( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN; extern HENHMETAFILE EMF_Create_HENHMETAFILE( ENHMETAHEADER *emh, DWORD filesize, BOOL on_disk ) DECLSPEC_HIDDEN;
+extern BOOL spool_start_doc( DC_ATTR *dc_attr, HANDLE hspool, + const DOCINFOW *doc_info ) DECLSPEC_HIDDEN; +extern int spool_start_page( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; +extern int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; +extern int spool_end_doc( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; +extern int spool_abort_doc( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; + static inline int get_dib_stride( int width, int bpp ) { return ((width * bpp + 31) >> 3) & ~3;
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/emfdc.c | 114 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 20 deletions(-)
diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index 9690bee2a17..990ee6e8109 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -892,13 +892,16 @@ BOOL EMFDC_MoveTo( DC_ATTR *dc_attr, INT x, INT y )
BOOL EMFDC_LineTo( DC_ATTR *dc_attr, INT x, INT y ) { + struct emf *emf = get_dc_emf( dc_attr ); EMRLINETO emr;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + emr.emr.iType = EMR_LINETO; emr.emr.nSize = sizeof(emr); emr.ptl.x = x; emr.ptl.y = y; - return emfdc_record( get_dc_emf( dc_attr ), &emr.emr ); + return emfdc_record( emf, &emr.emr ); }
BOOL EMFDC_ArcChordPie( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom, @@ -909,6 +912,7 @@ BOOL EMFDC_ArcChordPie( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bott INT temp;
if (left == right || top == bottom) return FALSE; + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) );
if (left > right) { temp = left; left = right; right = temp; } if (top > bottom) { temp = top; top = bottom; bottom = temp; } @@ -934,8 +938,11 @@ BOOL EMFDC_ArcChordPie( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bott
BOOL EMFDC_AngleArc( DC_ATTR *dc_attr, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep ) { + struct emf *emf = get_dc_emf( dc_attr ); EMRANGLEARC emr;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + emr.emr.iType = EMR_ANGLEARC; emr.emr.nSize = sizeof( emr ); emr.ptlCenter.x = x; @@ -943,7 +950,7 @@ BOOL EMFDC_AngleArc( DC_ATTR *dc_attr, INT x, INT y, DWORD radius, FLOAT start, emr.nRadius = radius; emr.eStartAngle = start; emr.eSweepAngle = sweep; - return emfdc_record( get_dc_emf( dc_attr ), &emr.emr ); + return emfdc_record( emf, &emr.emr ); }
BOOL EMFDC_Ellipse( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom ) @@ -952,6 +959,7 @@ BOOL EMFDC_Ellipse( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom ) EMRELLIPSE emr;
if (left == right || top == bottom) return FALSE; + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) );
emr.emr.iType = EMR_ELLIPSE; emr.emr.nSize = sizeof(emr); @@ -972,7 +980,8 @@ BOOL EMFDC_Rectangle( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom struct emf *emf = get_dc_emf( dc_attr ); EMRRECTANGLE emr;
- if(left == right || top == bottom) return FALSE; + if (left == right || top == bottom) return FALSE; + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) );
emr.emr.iType = EMR_RECTANGLE; emr.emr.nSize = sizeof(emr); @@ -995,6 +1004,7 @@ BOOL EMFDC_RoundRect( DC_ATTR *dc_attr, INT left, INT top, INT right, EMRROUNDRECT emr;
if (left == right || top == bottom) return FALSE; + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) );
emr.emr.iType = EMR_ROUNDRECT; emr.emr.nSize = sizeof(emr); @@ -1014,14 +1024,17 @@ BOOL EMFDC_RoundRect( DC_ATTR *dc_attr, INT left, INT top, INT right,
BOOL EMFDC_SetPixel( DC_ATTR *dc_attr, INT x, INT y, COLORREF color ) { + struct emf *emf = get_dc_emf( dc_attr ); EMRSETPIXELV emr;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + emr.emr.iType = EMR_SETPIXELV; emr.emr.nSize = sizeof(emr); emr.ptlPixel.x = x; emr.ptlPixel.y = y; emr.crColor = color; - return emfdc_record( get_dc_emf( dc_attr ), &emr.emr ); + return emfdc_record( emf, &emr.emr ); }
static BOOL emfdc_polylinegon( DC_ATTR *dc_attr, const POINT *points, INT count, DWORD type ) @@ -1031,6 +1044,8 @@ static BOOL emfdc_polylinegon( DC_ATTR *dc_attr, const POINT *points, INT count, DWORD size; BOOL ret, use_small_emr = can_use_short_points( points, count );
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + size = use_small_emr ? offsetof( EMRPOLYLINE16, apts[count] ) : offsetof( EMRPOLYLINE, aptl[count] );
emr = HeapAlloc( GetProcessHeap(), 0, size ); @@ -1131,11 +1146,17 @@ static BOOL emfdc_poly_polylinegon( struct emf *emf, const POINT *pt, const INT
BOOL EMFDC_PolyPolyline( DC_ATTR *dc_attr, const POINT *pt, const DWORD *counts, DWORD polys) { + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); return emfdc_poly_polylinegon( get_dc_emf( dc_attr ), pt, (const INT *)counts, polys, EMR_POLYPOLYLINE ); }
BOOL EMFDC_PolyPolygon( DC_ATTR *dc_attr, const POINT *pt, const INT *counts, UINT polys ) { + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); return emfdc_poly_polylinegon( get_dc_emf( dc_attr ), pt, counts, polys, EMR_POLYPOLYGON ); }
@@ -1148,6 +1169,8 @@ BOOL EMFDC_PolyDraw( DC_ATTR *dc_attr, const POINT *pts, const BYTE *types, DWOR BOOL use_small_emr = can_use_short_points( pts, count ); DWORD size;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + size = use_small_emr ? offsetof( EMRPOLYDRAW16, apts[count] ) : offsetof( EMRPOLYDRAW, aptl[count] ); size += (count + 3) & ~3; @@ -1175,15 +1198,18 @@ BOOL EMFDC_PolyDraw( DC_ATTR *dc_attr, const POINT *pts, const BYTE *types, DWOR
BOOL EMFDC_ExtFloodFill( DC_ATTR *dc_attr, INT x, INT y, COLORREF color, UINT fill_type ) { + struct emf *emf = get_dc_emf( dc_attr ); EMREXTFLOODFILL emr;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + emr.emr.iType = EMR_EXTFLOODFILL; emr.emr.nSize = sizeof(emr); emr.ptlStart.x = x; emr.ptlStart.y = y; emr.crColor = color; emr.iMode = fill_type; - return emfdc_record( get_dc_emf( dc_attr ), &emr.emr ); + return emfdc_record( emf, &emr.emr ); }
BOOL EMFDC_FillRgn( DC_ATTR *dc_attr, HRGN hrgn, HBRUSH hbrush ) @@ -1193,6 +1219,8 @@ BOOL EMFDC_FillRgn( DC_ATTR *dc_attr, HRGN hrgn, HBRUSH hbrush ) DWORD size, rgnsize, index; BOOL ret;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + if (!(index = emfdc_create_brush( emf, hbrush ))) return FALSE;
rgnsize = NtGdiGetRegionData( hrgn, 0, NULL ); @@ -1223,6 +1251,8 @@ BOOL EMFDC_FrameRgn( DC_ATTR *dc_attr, HRGN hrgn, HBRUSH hbrush, INT width, INT DWORD size, rgnsize, index; BOOL ret;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + index = emfdc_create_brush( emf, hbrush ); if(!index) return FALSE;
@@ -1277,12 +1307,18 @@ static BOOL emfdc_paint_invert_region( struct emf *emf, HRGN hrgn, DWORD iType )
BOOL EMFDC_PaintRgn( DC_ATTR *dc_attr, HRGN hrgn ) { - return emfdc_paint_invert_region( get_dc_emf( dc_attr ), hrgn, EMR_PAINTRGN ); + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdc_paint_invert_region( emf, hrgn, EMR_PAINTRGN ); }
BOOL EMFDC_InvertRgn( DC_ATTR *dc_attr, HRGN hrgn ) { - return emfdc_paint_invert_region( get_dc_emf( dc_attr ), hrgn, EMR_INVERTRGN ); + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdc_paint_invert_region( emf, hrgn, EMR_INVERTRGN ); }
BOOL EMFDC_ExtTextOut( DC_ATTR *dc_attr, INT x, INT y, UINT flags, const RECT *rect, @@ -1298,6 +1334,8 @@ BOOL EMFDC_ExtTextOut( DC_ATTR *dc_attr, INT x, INT y, UINT flags, const RECT *r DWORD size; BOOL ret;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + size = sizeof(*emr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT);
TRACE( "%s %s count %d size = %ld\n", debugstr_wn(str, count), @@ -1431,11 +1469,14 @@ no_bounds: BOOL EMFDC_GradientFill( DC_ATTR *dc_attr, TRIVERTEX *vert_array, ULONG nvert, void *grad_array, ULONG ngrad, ULONG mode ) { + struct emf *emf = get_dc_emf( dc_attr ); EMRGRADIENTFILL *emr; ULONG i, pt, size, num_pts = ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2); const ULONG *pts = (const ULONG *)grad_array; BOOL ret;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + size = FIELD_OFFSET(EMRGRADIENTFILL, Ver[nvert]) + num_pts * sizeof(pts[0]);
emr = HeapAlloc( GetProcessHeap(), 0, size ); @@ -1473,25 +1514,34 @@ BOOL EMFDC_GradientFill( DC_ATTR *dc_attr, TRIVERTEX *vert_array, ULONG nvert, memcpy( emr->Ver, vert_array, nvert * sizeof(vert_array[0]) ); memcpy( emr->Ver + nvert, pts, num_pts * sizeof(pts[0]) );
- emfdc_update_bounds( get_dc_emf( dc_attr ), &emr->rclBounds ); - ret = emfdc_record( get_dc_emf( dc_attr ), &emr->emr ); + emfdc_update_bounds( emf, &emr->rclBounds ); + ret = emfdc_record( emf, &emr->emr ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
BOOL EMFDC_FillPath( DC_ATTR *dc_attr ) { - return emfdrv_stroke_and_fill_path( get_dc_emf( dc_attr ), EMR_FILLPATH ); + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stroke_and_fill_path( emf, EMR_FILLPATH ); }
BOOL EMFDC_StrokeAndFillPath( DC_ATTR *dc_attr ) { - return emfdrv_stroke_and_fill_path( get_dc_emf( dc_attr ), EMR_STROKEANDFILLPATH ); + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stroke_and_fill_path( emf, EMR_STROKEANDFILLPATH ); }
BOOL EMFDC_StrokePath( DC_ATTR *dc_attr ) { - return emfdrv_stroke_and_fill_path( get_dc_emf( dc_attr ), EMR_STROKEPATH ); + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stroke_and_fill_path( emf, EMR_STROKEPATH ); }
/* Generate an EMRBITBLT, EMRSTRETCHBLT or EMRALPHABLEND record depending on the type parameter */ @@ -1567,7 +1617,10 @@ BOOL EMFDC_AlphaBlend( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, IN HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, BLENDFUNCTION blend_function ) { - return emfdrv_stretchblt( get_dc_emf( dc_attr ), x_dst, y_dst, width_dst, height_dst, hdc_src, + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stretchblt( emf, x_dst, y_dst, width_dst, height_dst, hdc_src, x_src, y_src, width_src, height_src, *(DWORD *)&blend_function, EMR_ALPHABLEND ); } @@ -1578,6 +1631,8 @@ BOOL EMFDC_PatBlt( DC_ATTR *dc_attr, INT left, INT top, INT width, INT height, D EMRBITBLT emr; BOOL ret;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + emr.emr.iType = EMR_BITBLT; emr.emr.nSize = sizeof(emr); emr.rclBounds.left = left; @@ -1617,8 +1672,11 @@ static inline BOOL rop_uses_src( DWORD rop ) BOOL EMFDC_BitBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width, INT height, HDC hdc_src, INT x_src, INT y_src, DWORD rop ) { + struct emf *emf = get_dc_emf( dc_attr ); + if (!rop_uses_src( rop )) return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width, height, rop ); - return emfdrv_stretchblt( get_dc_emf( dc_attr ), x_dst, y_dst, width, height, + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stretchblt( emf, x_dst, y_dst, width, height, hdc_src, x_src, y_src, width, height, rop, EMR_BITBLT ); }
@@ -1626,8 +1684,11 @@ BOOL EMFDC_StretchBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, IN HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, DWORD rop ) { + struct emf *emf = get_dc_emf( dc_attr ); + if (!rop_uses_src( rop )) return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width_dst, height_dst, rop ); - return emfdrv_stretchblt( get_dc_emf( dc_attr ), x_dst, y_dst, width_dst, height_dst, + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stretchblt( emf, x_dst, y_dst, width_dst, height_dst, hdc_src, x_src, y_src, width_src, height_src, rop, EMR_STRETCHBLT ); } @@ -1636,7 +1697,10 @@ BOOL EMFDC_TransparentBlt( DC_ATTR *dc_attr, int x_dst, int y_dst, int width_dst HDC hdc_src, int x_src, int y_src, int width_src, int height_src, UINT color ) { - return emfdrv_stretchblt( get_dc_emf( dc_attr ), x_dst, y_dst, width_dst, height_dst, + struct emf *emf = get_dc_emf( dc_attr ); + + if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + return emfdrv_stretchblt( emf, x_dst, y_dst, width_dst, height_dst, hdc_src, x_src, y_src, width_src, height_src, color, EMR_TRANSPARENTBLT ); } @@ -1657,6 +1721,8 @@ BOOL EMFDC_MaskBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT h HDC blit_dc, mask_dc = NULL; BOOL ret = FALSE;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + if (!rop_uses_src( rop )) return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width_dst, height_dst, rop );
@@ -1753,6 +1819,8 @@ BOOL EMFDC_PlgBlt( DC_ATTR *dc_attr, const POINT *points, HDC hdc_src, INT x_src int x_min, y_min, x_max, y_max, i; BOOL ret = FALSE;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE;
blit_dc = hdc_src; @@ -1844,12 +1912,15 @@ BOOL EMFDC_StretchDIBits( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT x_src, INT y_src, INT width_src, INT height_src, const void *bits, const BITMAPINFO *info, UINT usage, DWORD rop ) { + struct emf *emf = get_dc_emf( dc_attr ); EMRSTRETCHDIBITS *emr; BOOL ret; UINT bmi_size, img_size, payload_size, emr_size; BITMAPINFOHEADER bih; BITMAPINFO *bi;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + /* calculate the size of the colour table and the image */ if (!emf_parse_user_bitmapinfo( &bih, &info->bmiHeader, usage, TRUE, &bmi_size, &img_size )) return 0; @@ -1899,8 +1970,8 @@ BOOL EMFDC_StretchDIBits( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, emr->rclBounds.bottom = y_dst + height_dst - 1;
/* save the record we just created */ - ret = emfdc_record( get_dc_emf( dc_attr ), &emr->emr ); - if (ret) emfdc_update_bounds( get_dc_emf( dc_attr ), &emr->rclBounds ); + ret = emfdc_record( emf, &emr->emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; } @@ -1909,6 +1980,7 @@ BOOL EMFDC_SetDIBitsToDevice( DC_ATTR *dc_attr, INT x_dst, INT y_dst, DWORD widt INT x_src, INT y_src, UINT startscan, UINT lines, const void *bits, const BITMAPINFO *info, UINT usage ) { + struct emf *emf = get_dc_emf( dc_attr ); EMRSETDIBITSTODEVICE *emr; BOOL ret; UINT bmi_size, img_size, payload_size, emr_size; @@ -1916,6 +1988,8 @@ BOOL EMFDC_SetDIBitsToDevice( DC_ATTR *dc_attr, INT x_dst, INT y_dst, DWORD widt BITMAPINFOHEADER bih; BITMAPINFO *bi;
+ if (emf->document_state == NEEDS_START_PAGE) StartPage( dc_attr_handle(dc_attr) ); + /* calculate the size of the colour table and the image */ if (!emf_parse_user_bitmapinfo( &bih, &info->bmiHeader, usage, TRUE, &bmi_size, &img_size )) return 0; @@ -1977,8 +2051,8 @@ BOOL EMFDC_SetDIBitsToDevice( DC_ATTR *dc_attr, INT x_dst, INT y_dst, DWORD widt emr->iStartScan = startscan; emr->cScans = lines;
- if ((ret = emfdc_record( get_dc_emf( dc_attr ), (EMR*)emr ))) - emfdc_update_bounds( get_dc_emf( dc_attr ), &emr->rclBounds ); + if ((ret = emfdc_record( emf, (EMR*)emr ))) + emfdc_update_bounds( emf, &emr->rclBounds );
HeapFree( GetProcessHeap(), 0, emr ); return ret;
From: Piotr Caban piotr@codeweavers.com
--- dlls/gdi32/dc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 459d0dfb8c1..011bded3523 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -2408,8 +2408,12 @@ INT WINAPI SetICMMode( HDC hdc, INT mode ) */ BOOL WINAPI GdiIsMetaPrintDC( HDC hdc ) { - FIXME( "%p\n", hdc ); - return FALSE; + DC_ATTR *dc_attr; + + TRACE( "%p\n", hdc ); + + if (!(dc_attr = get_dc_attr( hdc ))) return FALSE; + return dc_attr->print && dc_attr->emf; }
/***********************************************************************
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=132244
Your paranoid android.
=== debian11 (32 bit report) ===
ntoskrnl.exe: driver_pnp.c:727: Test failed: Got 1 remove events.
Huw Davies (@huw) commented about dlls/localspl/provider.c:
- if (info->pDatatype)
datatype = info->pDatatype;
- else if (printer->datatype)
datatype = printer->datatype;
- else
datatype = printer->info->datatype;
- if (!datatype || printer->info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)
- {
if (!datatype || wcsicmp(datatype, L"RAW"))
{
TRACE("non RAW datatype specified on RAW-only printer (%s)\n", debugstr_w(datatype));
SetLastError(ERROR_INVALID_DATATYPE);
return 0;
}
- }
Is there more code to go in here or could it be simplified to:
```suggestion:-8+0 if (!datatype || ((printer->info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY) && wcsicmp(datatype, L"RAW"))) { TRACE("non RAW datatype specified on RAW-only printer (%s)\n", debugstr_w(datatype)); SetLastError(ERROR_INVALID_DATATYPE); return 0; } ```