-- v2: wineps: Handle EMR_LINETO record in spool files. wineps: Handle EMR_MOVETOEX record in spool files. wineps: Handle EMR_RECTANGLE record in spool files. wineps: Handle pen selection in spool files. wineps: Handle brush selection in spool files. wineps: Handle EMR_EOF record in spool files. wineps: Handle EMR_HEADER record in spool files. wineps: Write document header and footer in PrintDocumentOnPrintProcessor.
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/init.c | 4 ++-- dlls/wineps.drv/printproc.c | 24 ++++++++++++++++++++++++ dlls/wineps.drv/psdrv.h | 3 +++ 3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index 1fc861dc924..779abf1c98b 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -338,8 +338,8 @@ static void PSDRV_UpdateDevCaps( PSDRV_PDEVICE *physDev ) physDev->horzRes, physDev->vertRes); }
-static PSDRV_PDEVICE *create_psdrv_physdev( HDC hdc, const WCHAR *device, - const PSDRV_DEVMODE *devmode ) +PSDRV_PDEVICE *create_psdrv_physdev( HDC hdc, const WCHAR *device, + const PSDRV_DEVMODE *devmode ) { PRINTERINFO *pi = PSDRV_FindPrinterInfo( device ); PSDRV_PDEVICE *pdev; diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index b7b4749afcd..67a9dfd9ce8 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -24,6 +24,8 @@ #include <winspool.h> #include <ddk/winsplp.h>
+#include "psdrv.h" + #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(psdrv); @@ -37,6 +39,7 @@ struct pp_data HANDLE hport; WCHAR *doc_name; WCHAR *out_file; + PSDRV_PDEVICE *pdev; };
typedef enum @@ -215,6 +218,7 @@ HANDLE WINAPI OpenPrintProcessor(WCHAR *port, PRINTPROCESSOROPENDATA *open_data) { struct pp_data *data; HANDLE hport; + HDC hdc;
TRACE("%s, %p\n", debugstr_w(port), open_data);
@@ -239,6 +243,23 @@ HANDLE WINAPI OpenPrintProcessor(WCHAR *port, PRINTPROCESSOROPENDATA *open_data) data->hport = hport; data->doc_name = wcsdup(open_data->pDocumentName); data->out_file = wcsdup(open_data->pOutputFile); + + hdc = CreateCompatibleDC(NULL); + if (!hdc) + { + LocalFree(data); + return NULL; + } + SetGraphicsMode(hdc, GM_ADVANCED); + data->pdev = create_psdrv_physdev(hdc, open_data->pPrinterName, + (const PSDRV_DEVMODE *)open_data->pDevMode); + if (!data->pdev) + { + DeleteDC(hdc); + LocalFree(data); + return NULL; + } + data->pdev->dev.hdc = hdc; return (HANDLE)data; }
@@ -368,6 +389,9 @@ BOOL WINAPI ClosePrintProcessor(HANDLE pp) ClosePrinter(data->hport); free(data->doc_name); free(data->out_file); + DeleteDC(data->pdev->dev.hdc); + HeapFree(GetProcessHeap(), 0, data->pdev->Devmode); + HeapFree(GetProcessHeap(), 0, data->pdev);
memset(data, 0, sizeof(*data)); LocalFree(data); diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 153601d4c86..9817128fc70 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -393,6 +393,9 @@ static inline PSDRV_PDEVICE *get_psdrv_dev( PHYSDEV dev ) return (PSDRV_PDEVICE *)dev; }
+extern PSDRV_PDEVICE *create_psdrv_physdev( HDC hdc, const WCHAR *device, + const PSDRV_DEVMODE *devmode ) DECLSPEC_HIDDEN; + /* * Every glyph name in the Adobe Glyph List and the 35 core PostScript fonts */
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/init.c | 85 ++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 44 deletions(-)
diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index 579e59e621b..1fc861dc924 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -338,25 +338,50 @@ static void PSDRV_UpdateDevCaps( PSDRV_PDEVICE *physDev ) physDev->horzRes, physDev->vertRes); }
-static PSDRV_PDEVICE *create_psdrv_physdev( PRINTERINFO *pi ) +static PSDRV_PDEVICE *create_psdrv_physdev( HDC hdc, const WCHAR *device, + const PSDRV_DEVMODE *devmode ) { - PSDRV_PDEVICE *physDev; + PRINTERINFO *pi = PSDRV_FindPrinterInfo( device ); + PSDRV_PDEVICE *pdev;
- physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) ); - if (!physDev) return NULL; + if (!pi) return NULL; + if (!pi->Fonts) + { + RASTERIZER_STATUS status; + if (!GetRasterizerCaps( &status, sizeof(status) ) || + !(status.wFlags & TT_AVAILABLE) || + !(status.wFlags & TT_ENABLED)) + { + MESSAGE( "Disabling printer %s since it has no builtin fonts and " + "there are no TrueType fonts available.\n", debugstr_w(device) ); + return FALSE; + } + }
- physDev->Devmode = HeapAlloc( GetProcessHeap(), 0, sizeof(PSDRV_DEVMODE) ); - if (!physDev->Devmode) + pdev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pdev) ); + if (!pdev) return NULL; + + pdev->Devmode = HeapAlloc( GetProcessHeap(), 0, sizeof(PSDRV_DEVMODE) ); + if (!pdev->Devmode) { - HeapFree( GetProcessHeap(), 0, physDev ); + HeapFree( GetProcessHeap(), 0, pdev ); return NULL; }
- *physDev->Devmode = *pi->Devmode; - physDev->pi = pi; - physDev->logPixelsX = pi->ppd->DefaultResolution; - physDev->logPixelsY = pi->ppd->DefaultResolution; - return physDev; + *pdev->Devmode = *pi->Devmode; + pdev->pi = pi; + pdev->logPixelsX = pi->ppd->DefaultResolution; + pdev->logPixelsY = pi->ppd->DefaultResolution; + + if (devmode) + { + dump_devmode( &devmode->dmPublic ); + PSDRV_MergeDevmodes( pdev->Devmode, devmode, pi ); + } + + PSDRV_UpdateDevCaps( pdev ); + SelectObject( hdc, PSDRV_DefaultFont ); + return pdev; }
/********************************************************************** @@ -366,35 +391,12 @@ static BOOL CDECL PSDRV_CreateDC( PHYSDEV *pdev, LPCWSTR device, LPCWSTR output, const DEVMODEW *initData ) { PSDRV_PDEVICE *physDev; - PRINTERINFO *pi;
TRACE("(%s %s %p)\n", debugstr_w(device), debugstr_w(output), initData);
if (!device) return FALSE; - pi = PSDRV_FindPrinterInfo( device ); - if(!pi) return FALSE; - - if(!pi->Fonts) { - RASTERIZER_STATUS status; - if(!GetRasterizerCaps(&status, sizeof(status)) || - !(status.wFlags & TT_AVAILABLE) || - !(status.wFlags & TT_ENABLED)) { - MESSAGE("Disabling printer %s since it has no builtin fonts and there are no TrueType fonts available.\n", - debugstr_w(device)); - return FALSE; - } - } - - if (!(physDev = create_psdrv_physdev( pi ))) return FALSE; - - if(initData) - { - dump_devmode(initData); - PSDRV_MergeDevmodes(physDev->Devmode, (const PSDRV_DEVMODE *)initData, pi); - } - - PSDRV_UpdateDevCaps(physDev); - SelectObject( (*pdev)->hdc, PSDRV_DefaultFont ); + if (!(physDev = create_psdrv_physdev( (*pdev)->hdc, device, + (const PSDRV_DEVMODE *)initData ))) return FALSE; push_dc_driver( pdev, &physDev->dev, &psdrv_funcs ); return TRUE; } @@ -405,15 +407,10 @@ static BOOL CDECL PSDRV_CreateDC( PHYSDEV *pdev, LPCWSTR device, LPCWSTR output, */ static BOOL CDECL PSDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev ) { - HDC hdc = (*pdev)->hdc; PSDRV_PDEVICE *physDev, *orig_dev = get_psdrv_dev( orig ); - PRINTERINFO *pi = PSDRV_FindPrinterInfo( orig_dev->pi->friendly_name );
- if (!pi) return FALSE; - if (!(physDev = create_psdrv_physdev( pi ))) return FALSE; - PSDRV_MergeDevmodes( physDev->Devmode, orig_dev->Devmode, pi ); - PSDRV_UpdateDevCaps(physDev); - SelectObject( hdc, PSDRV_DefaultFont ); + if (!(physDev = create_psdrv_physdev( (*pdev)->hdc, orig_dev->pi->friendly_name, + orig_dev->Devmode ))) return FALSE; push_dc_driver( pdev, &physDev->dev, &psdrv_funcs ); return TRUE; }
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 67a9dfd9ce8..4c0271d4bd1 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -285,7 +285,8 @@ BOOL WINAPI PrintDocumentOnPrintProcessor(HANDLE pp, WCHAR *doc_name) info.pDocName = data->doc_name; info.pOutputFile = data->out_file; info.pDatatype = (WCHAR *)L"RAW"; - if (!StartDocPrinterW(data->hport, 1, (BYTE *)&info)) + data->pdev->job.id = StartDocPrinterW(data->hport, 1, (BYTE *)&info); + if (!data->pdev->job.id) { ClosePrinter(spool_data); return FALSE; @@ -310,6 +311,14 @@ BOOL WINAPI PrintDocumentOnPrintProcessor(HANDLE pp, WCHAR *doc_name) if (!(ret = SeekPrinter(spool_data, pos, NULL, FILE_BEGIN, FALSE))) goto cleanup;
+ data->pdev->job.hprinter = data->hport; + data->pdev->job.banding = FALSE; + data->pdev->job.OutOfPage = TRUE; + data->pdev->job.PageNo = 0; + data->pdev->job.quiet = FALSE; + data->pdev->job.passthrough_state = passthrough_none; + data->pdev->job.doc_name = strdupW(data->doc_name); + while (1) { if (!(ret = ReadPrinter(spool_data, &record, sizeof(record), &r))) @@ -366,6 +375,7 @@ BOOL WINAPI PrintDocumentOnPrintProcessor(HANDLE pp, WCHAR *doc_name) }
cleanup: + HeapFree(GetProcessHeap(), 0, data->pdev->job.doc_name); ClosePrinter(spool_data); return EndDocPrinter(data->hport) && ret; }
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 4c0271d4bd1..8ea2aa09015 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -312,6 +312,11 @@ BOOL WINAPI PrintDocumentOnPrintProcessor(HANDLE pp, WCHAR *doc_name) goto cleanup;
data->pdev->job.hprinter = data->hport; + if (!PSDRV_WriteHeader(&data->pdev->dev, data->doc_name)) + { + WARN("Failed to write header\n"); + goto cleanup; + } data->pdev->job.banding = FALSE; data->pdev->job.OutOfPage = TRUE; data->pdev->job.PageNo = 0; @@ -375,6 +380,9 @@ BOOL WINAPI PrintDocumentOnPrintProcessor(HANDLE pp, WCHAR *doc_name) }
cleanup: + if (data->pdev->job.PageNo) + PSDRV_WriteFooter(&data->pdev->dev); + HeapFree(GetProcessHeap(), 0, data->pdev->job.doc_name); ClosePrinter(spool_data); return EndDocPrinter(data->hport) && ret;
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 62d0dc7c300..722bfc39cc0 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -139,6 +139,8 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, { case EMR_HEADER: return PSDRV_StartPage(&data->pdev->dev); + case EMR_EOF: + return PSDRV_EndPage(&data->pdev->dev); default: FIXME("unsupported record: %ld\n", rec->iType); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 8ea2aa09015..62d0dc7c300 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -133,7 +133,16 @@ static struct pp_data* get_handle_data(HANDLE pp) static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, const ENHMETARECORD *rec, int n, LPARAM arg) { - FIXME("unsupported record: %ld\n", rec->iType); + struct pp_data *data = (struct pp_data *)arg; + + switch (rec->iType) + { + case EMR_HEADER: + return PSDRV_StartPage(&data->pdev->dev); + default: + FIXME("unsupported record: %ld\n", rec->iType); + } + return 1; }
@@ -174,7 +183,7 @@ static BOOL print_metafile(struct pp_data *data, HANDLE hdata) if (!hmf) return FALSE;
- ret = EnumEnhMetaFile(NULL, hmf, hmf_proc, NULL, NULL); + ret = EnumEnhMetaFile(NULL, hmf, hmf_proc, (void *)data, NULL); DeleteEnhMetaFile(hmf); return ret; }
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 722bfc39cc0..5a4504dbd4d 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -40,6 +40,7 @@ struct pp_data WCHAR *doc_name; WCHAR *out_file; PSDRV_PDEVICE *pdev; + struct brush_pattern *patterns; };
typedef enum @@ -138,9 +139,40 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, switch (rec->iType) { case EMR_HEADER: - return PSDRV_StartPage(&data->pdev->dev); + { + const ENHMETAHEADER *header = (const ENHMETAHEADER *)rec; + + data->patterns = calloc(sizeof(*data->patterns), header->nHandles); + return data->patterns && PSDRV_StartPage(&data->pdev->dev); + } case EMR_EOF: return PSDRV_EndPage(&data->pdev->dev); + case EMR_SELECTOBJECT: + { + const EMRSELECTOBJECT *so = (const EMRSELECTOBJECT *)rec; + struct brush_pattern *pattern; + HGDIOBJ obj; + + if (so->ihObject & 0x80000000) + { + obj = GetStockObject(so->ihObject & 0x7fffffff); + pattern = NULL; + } + else + { + obj = (htable->objectHandle)[so->ihObject]; + pattern = data->patterns + so->ihObject; + } + SelectObject(data->pdev->dev.hdc, obj); + + switch (GetObjectType(obj)) + { + case OBJ_BRUSH: return PSDRV_SelectBrush(&data->pdev->dev, obj, pattern) != NULL; + default: + FIXME("unhandled object type %ld\n", GetObjectType(obj)); + return 1; + } + } default: FIXME("unsupported record: %ld\n", rec->iType); } @@ -187,6 +219,8 @@ static BOOL print_metafile(struct pp_data *data, HANDLE hdata)
ret = EnumEnhMetaFile(NULL, hmf, hmf_proc, (void *)data, NULL); DeleteEnhMetaFile(hmf); + free(data->patterns); + data->patterns = NULL; return ret; }
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 5a4504dbd4d..22985e0827c 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -167,6 +167,7 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable,
switch (GetObjectType(obj)) { + case OBJ_PEN: return PSDRV_SelectPen(&data->pdev->dev, obj, NULL) != NULL; case OBJ_BRUSH: return PSDRV_SelectBrush(&data->pdev->dev, obj, pattern) != NULL; default: FIXME("unhandled object type %ld\n", GetObjectType(obj));
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 22985e0827c..f0acc6dd5f1 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -174,6 +174,13 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, return 1; } } + case EMR_RECTANGLE: + { + const EMRRECTANGLE *rect = (const EMRRECTANGLE *)rec; + + return PSDRV_Rectangle(&data->pdev->dev, rect->rclBox.left, + rect->rclBox.top, rect->rclBox.right, rect->rclBox.bottom); + } default: FIXME("unsupported record: %ld\n", rec->iType); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index f0acc6dd5f1..c7c7d61437d 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -181,6 +181,9 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, return PSDRV_Rectangle(&data->pdev->dev, rect->rclBox.left, rect->rclBox.top, rect->rclBox.right, rect->rclBox.bottom); } + + case EMR_MOVETOEX: + return PlayEnhMetaFileRecord(data->pdev->dev.hdc, htable, rec, n); default: FIXME("unsupported record: %ld\n", rec->iType); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/wineps.drv/printproc.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index c7c7d61437d..30ca6ef0ce9 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -181,6 +181,13 @@ static int WINAPI hmf_proc(HDC hdc, HANDLETABLE *htable, return PSDRV_Rectangle(&data->pdev->dev, rect->rclBox.left, rect->rclBox.top, rect->rclBox.right, rect->rclBox.bottom); } + case EMR_LINETO: + { + const EMRLINETO *line = (const EMRLINETO *)rec; + + return PSDRV_LineTo(&data->pdev->dev, line->ptl.x, line->ptl.y) && + MoveToEx(data->pdev->dev.hdc, line->ptl.x, line->ptl.y, NULL); + }
case EMR_MOVETOEX: return PlayEnhMetaFileRecord(data->pdev->dev.hdc, htable, rec, n);
This merge request was approved by Huw Davies.
I've pushed a new version with a trivial brace placement 'fix'.