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/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/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 | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 4c0271d4bd1..317ef63822e 100644 --- a/dlls/wineps.drv/printproc.c +++ b/dlls/wineps.drv/printproc.c @@ -312,6 +312,10 @@ 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 +379,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 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 317ef63822e..5a213fca7a1 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 | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 5a213fca7a1..77c80a11cf0 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 | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/dlls/wineps.drv/printproc.c b/dlls/wineps.drv/printproc.c index 77c80a11cf0..78b582477de 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 78b582477de..89c9e3d45a8 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 89c9e3d45a8..9c595005ee6 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 9c595005ee6..3798d325936 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 3798d325936..59d4ce2400e 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);
Attaching [patch](/uploads/6cb5adf9cd6505d1a72f920b89400bf0/0001-print-test.txt) to winspool.drv info tests so it can be used to print EMF spool files. Also attaching [example spool file](/uploads/710f33ea7ac59059b181a55eee9a9489/00004.SPL) that can be used to test Rectangle and LineTo drawing. In order to use wineps print processor it's also needed to change print processor in printer configuration to wineps (and probably redirect printer output to file).