configure.ac | 2 utils/CMakeLists.txt | 1 utils/Makefile.am | 3 utils/pdftocairo-win32.cc | 549 ++++++++++++++++++++++++++++++++++++++++++++++ utils/pdftocairo-win32.h | 21 + utils/pdftocairo.1 | 39 +++ utils/pdftocairo.cc | 126 ++++++++-- 7 files changed, 713 insertions(+), 28 deletions(-)
New commits: commit 4963332ca4db13d8a9186b06d2aa0d59abbc10ee Author: Adrian Johnson <[email protected]> Date: Sun Oct 5 21:58:37 2014 +1030 pdftocairo: add -printdlg output option for win32 when set the win32 print dialog is displayed before printing diff --git a/configure.ac b/configure.ac index 10a4b39..7a5d747 100644 --- a/configure.ac +++ b/configure.ac @@ -48,7 +48,7 @@ case "$host_os" in ;; mingw*) os_win32=yes - win32_libs="-lgdi32 -lwinspool" + win32_libs="-lgdi32 -lwinspool -lcomdlg32" create_shared_lib="-no-undefined" auto_import_flags="-Wl,--enable-auto-import" diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc index de7da57..565d8a1 100644 --- a/utils/pdftocairo-win32.cc +++ b/utils/pdftocairo-win32.cc @@ -6,7 +6,13 @@ #include "parseargs.h" #include "pdftocairo-win32.h" +#include <dlgs.h> +#include <commctrl.h> +#include <windowsx.h> + static HDC hdc; +static HGLOBAL hDevmode = 0; +static HGLOBAL hDevnames = 0; static DEVMODEA *devmode; static char *printerName; @@ -70,7 +76,7 @@ static void parseDuplex(GooString *mode) fprintf(stderr, "Warning: Unknown duplex mode \"%s\"\n", mode->getCString()); } -static void fillCommonPrinterOptions(double w, double h, GBool duplex) +static void fillCommonPrinterOptions(GBool duplex) { if (duplex) { devmode->dmDuplex = DMDUP_HORIZONTAL; @@ -135,12 +141,214 @@ static void fillPrinterOptions(GBool duplex, GooString *printOpt) } } -cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputFileName, - double w, double h, - GooString *printer, - GooString *printOpt, - GBool setupdlg, - GBool duplex) +static void getLocalPos(HWND wind, HWND dlg, RECT *rect) +{ + GetClientRect(wind, rect); + MapWindowPoints(wind, dlg, (LPPOINT)rect, 2); +} + +static HWND createGroupBox(HWND parent, HINSTANCE hInstance, int id, const char *label, RECT *rect) +{ + HWND hwnd = CreateWindowA(WC_BUTTONA, + label, + WS_CHILD | WS_VISIBLE | BS_GROUPBOX, + rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top, + parent, (HMENU)id, + hInstance, NULL); + HFONT hFont = (HFONT)SendMessage(parent, WM_GETFONT, (WPARAM)0, (LPARAM)0); + if (hFont) + SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0); + return hwnd; +} + +static HWND createCheckBox(HWND parent, HINSTANCE hInstance, int id, const char *label, RECT *rect) +{ + HWND hwnd = CreateWindowA(WC_BUTTONA, + label, + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | WS_TABSTOP, + rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top, + parent, (HMENU)id, + hInstance, NULL); + HFONT hFont = (HFONT)SendMessage(parent, WM_GETFONT, (WPARAM)0, (LPARAM)0); + if (hFont) + SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0); + return hwnd; +} + +static HWND createStaticText(HWND parent, HINSTANCE hinstance, int id, const char *text, RECT *rect) +{ + HWND hwnd = CreateWindowA(WC_STATICA, + text, + WS_CHILD | WS_VISIBLE | SS_LEFT, + rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top, + parent, (HMENU)id, + hinstance, NULL); + HFONT hFont = (HFONT)SendMessage(parent, WM_GETFONT, (WPARAM)0, (LPARAM)0); + if (hFont) + SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0); + return hwnd; +} + +HWND createPageScaleComboBox(HWND parent, HINSTANCE hinstance, int id, RECT *rect) +{ + HWND hwnd = CreateWindowA(WC_COMBOBOX, + "", + WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP | + CBS_DROPDOWNLIST, + rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top, + parent, (HMENU)id, + hinstance, NULL); + HFONT hFont = (HFONT)SendMessage(parent, WM_GETFONT, (WPARAM)0, (LPARAM)0); + if (hFont) + SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0); + ComboBox_AddString(hwnd, "None"); + ComboBox_AddString(hwnd, "Shrink to Printable Area"); + ComboBox_AddString(hwnd, "Fit to Printable Area"); + return hwnd; +} + +enum PageScale { NONE = 0, SHRINK = 1, FIT = 2 }; + +// used to set/get option values in printDialogHookProc +static PageScale pageScale; +static GBool centerPage; +static GBool useOrigPageSize; + +// PrintDlg callback to customize the print dialog with additional controls. +static UINT_PTR CALLBACK printDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) +{ + if (uiMsg == WM_INITDIALOG) { + // Get the extant controls. See dlgs.h and prnsetup.dlg for the PrintDlg control ids. + HWND printerGroupWind = GetDlgItem(hdlg, grp4); + HWND printerComboWind = GetDlgItem(hdlg, cmb4); + HWND nameLabelWind = GetDlgItem(hdlg, stc6); + HWND statusLabelWind = GetDlgItem(hdlg, stc8); + HWND printRangeGroupWind = GetDlgItem(hdlg, grp1); + HWND radio1Wind = GetDlgItem(hdlg, rad1); + HWND radio2Wind = GetDlgItem(hdlg, rad3); + HWND copiesGroupWind = GetDlgItem(hdlg, grp2); + HWND okWind = GetDlgItem(hdlg, IDOK); + HWND cancelWind = GetDlgItem(hdlg, IDCANCEL); + if (!printerGroupWind || !printerComboWind || !nameLabelWind || !statusLabelWind || + !printRangeGroupWind || !radio1Wind || !radio2Wind || !copiesGroupWind || + !okWind || !cancelWind) + return 0; + + // Get the size and position of the above controls relative to the + // print dialog window + RECT printerGroupRect; + RECT printerComboRect; + RECT nameLabelRect; + RECT statusLabelRect; + RECT printRangeGroupRect; + RECT radio1Rect, radio2Rect; + RECT copiesGroupRect; + RECT okRect, cancelRect; + getLocalPos(printerGroupWind, hdlg, &printerGroupRect); + getLocalPos(printerComboWind, hdlg, &printerComboRect); + getLocalPos(nameLabelWind, hdlg, &nameLabelRect); + getLocalPos(statusLabelWind, hdlg, &statusLabelRect); + getLocalPos(printRangeGroupWind, hdlg, &printRangeGroupRect); + getLocalPos(radio1Wind, hdlg, &radio1Rect); + getLocalPos(radio2Wind, hdlg, &radio2Rect); + getLocalPos(copiesGroupWind, hdlg, &copiesGroupRect); + getLocalPos(okWind, hdlg, &okRect); + getLocalPos(cancelWind, hdlg, &cancelRect); + + // Calc space required for new group + int interGroupSpace = printRangeGroupRect.top - printerGroupRect.bottom; + int groupHeight = statusLabelRect.top - printerGroupRect.top + + printRangeGroupRect.bottom - radio1Rect.bottom; + + // Increase dialog size + RECT dlgRect; + GetWindowRect(hdlg, &dlgRect); + SetWindowPos(hdlg, NULL, + dlgRect.left, dlgRect.top, + dlgRect.right - dlgRect.left, + dlgRect.bottom - dlgRect.top + interGroupSpace + groupHeight, + SWP_NOMOVE|SWP_NOREDRAW|SWP_NOZORDER); + + // Add new group and controls + HINSTANCE hinstance = (HINSTANCE)GetWindowLongPtr(hdlg, GWLP_HINSTANCE); + RECT pdfGroupBoxRect; + pdfGroupBoxRect.left = printRangeGroupRect.left; + pdfGroupBoxRect.right = copiesGroupRect.right; + pdfGroupBoxRect.top = printRangeGroupRect.bottom + interGroupSpace; + pdfGroupBoxRect.bottom = pdfGroupBoxRect.top + groupHeight; + createGroupBox(hdlg, hinstance, grp3, "PDF Print Options", &pdfGroupBoxRect); + + RECT textRect; + textRect.left = nameLabelRect.left; + textRect.right = nameLabelRect.left + 1.8*(printerComboRect.left - nameLabelRect.left); + textRect.top = pdfGroupBoxRect.top + nameLabelRect.top - printerGroupRect.top; + textRect.bottom = textRect.top + nameLabelRect.bottom - nameLabelRect.top; + createStaticText(hdlg, hinstance, stc1, "Page Scaling:", &textRect); + + RECT comboBoxRect; + comboBoxRect.left = textRect.right; + comboBoxRect.right = comboBoxRect.left + printerComboRect.right - printerComboRect.left;; + comboBoxRect.top = pdfGroupBoxRect.top + printerComboRect.top - printerGroupRect.top; + comboBoxRect.bottom = textRect.top + 4*(printerComboRect.bottom - printerComboRect.top); + HWND comboBoxWind = createPageScaleComboBox(hdlg, hinstance, cmb1, &comboBoxRect); + + RECT checkBox1Rect; + checkBox1Rect.left = radio1Rect.left; + checkBox1Rect.right = pdfGroupBoxRect.right - 10; + checkBox1Rect.top = pdfGroupBoxRect.top + statusLabelRect.top - printerGroupRect.top; + checkBox1Rect.bottom = checkBox1Rect.top + radio1Rect.bottom - radio1Rect.top; + HWND checkBox1Wind = createCheckBox(hdlg, hinstance, chx3, "Center", &checkBox1Rect); + + RECT checkBox2Rect; + checkBox2Rect.left = radio1Rect.left; + checkBox2Rect.right = pdfGroupBoxRect.right - 10; + checkBox2Rect.top = checkBox1Rect.top + radio2Rect.top - radio1Rect.top; + checkBox2Rect.bottom = checkBox2Rect.top + radio1Rect.bottom - radio1Rect.top; + HWND checkBox2Wind = createCheckBox(hdlg, hinstance, chx4, "Select page size using document page size", &checkBox2Rect); + + // Move OK and Cancel buttons down ensuring they are last in the Z order + // so that the tab order is correct. + SetWindowPos(okWind, + HWND_BOTTOM, + okRect.left, + okRect.top + interGroupSpace + groupHeight, + 0, 0, + SWP_NOSIZE); // keep current size + SetWindowPos(cancelWind, + HWND_BOTTOM, + cancelRect.left, + cancelRect.top + interGroupSpace + groupHeight, + 0, 0, + SWP_NOSIZE); // keep current size + + // Initialize control values + ComboBox_SetCurSel(comboBoxWind, pageScale); + Button_SetCheck(checkBox1Wind, centerPage ? BST_CHECKED : BST_UNCHECKED); + Button_SetCheck(checkBox2Wind, useOrigPageSize ? BST_CHECKED : BST_UNCHECKED); + + } else if (uiMsg == WM_COMMAND) { + // Save settings + UINT id = LOWORD(wParam); + if (id == cmb1) + pageScale = (PageScale)ComboBox_GetCurSel(GetDlgItem(hdlg, cmb1)); + if (id == chx3) + centerPage = IsDlgButtonChecked(hdlg, chx3); + if (id == chx4) + useOrigPageSize = IsDlgButtonChecked(hdlg, chx4); + } + return 0; +} + +void win32SetupPrinter(GooString *printer, GooString *printOpt, + GBool duplex, GBool setupdlg) { if (printer->getCString()[0] == 0) { DWORD size = 0; @@ -168,7 +376,7 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF } // Update devmode with selected print options - fillCommonPrinterOptions(w, h, duplex); + fillCommonPrinterOptions(duplex); fillPrinterOptions(duplex, printOpt); // Call DocumentProperties again so the driver can update its private data @@ -191,7 +399,72 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); } +} + +void win32ShowPrintDialog(GBool *expand, GBool *noShrink, GBool *noCenter, + GBool *usePDFPageSize, GBool *allPages, + int *firstPage, int *lastPage, int maxPages) +{ + PRINTDLG pd; + memset(&pd, 0, sizeof(PRINTDLG)); + pd.lStructSize = sizeof(PRINTDLG); + pd.Flags = PD_NOSELECTION | PD_ENABLEPRINTHOOK | PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; + if (*allPages) { + pd.nFromPage = 1; + pd.nToPage = maxPages; + } else { + pd.Flags |= PD_PAGENUMS; + pd.nFromPage = *firstPage; + pd.nToPage = *lastPage; + } + pd.nCopies = 1; + pd.nMinPage = 1; + pd.nMaxPage = maxPages; + pd.lpfnPrintHook = printDialogHookProc; + if (!*expand && *noShrink) + pageScale = NONE; + else if (!*expand && !*noShrink) + pageScale = SHRINK; + else + pageScale = FIT; + centerPage = !*noCenter; + useOrigPageSize = *usePDFPageSize; + + if (PrintDlgA(&pd)) { + // Ok + hDevnames = pd.hDevNames; + DEVNAMES *devnames = (DEVNAMES*)GlobalLock(hDevnames); + printerName = (char*)devnames + devnames->wDeviceOffset; + hDevmode = pd.hDevMode; + devmode = (DEVMODEA*)GlobalLock(hDevmode); + hdc = pd.hDC; + if (pd.Flags & PD_PAGENUMS) { + *allPages = gFalse; + *firstPage = pd.nFromPage; + *lastPage = pd.nToPage; + } else { + *allPages = gTrue; + } + if (pageScale == NONE) { + *expand = gFalse; + *noShrink = gTrue; + } else if (pageScale == SHRINK) { + *expand = gFalse; + *noShrink = gFalse; + } else { + *expand = gTrue; + *noShrink = gFalse; + } + *noCenter = !centerPage; + *usePDFPageSize = useOrigPageSize; + } else { + // Cancel + exit(0); + } +} +cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputFileName) +{ DOCINFOA docinfo; memset(&docinfo, 0, sizeof(docinfo)); docinfo.cbSize = sizeof(docinfo); @@ -259,8 +532,18 @@ void win32EndDocument() { EndDoc(hdc); DeleteDC(hdc); - gfree(devmode); - gfree(printerName); + if (hDevmode) { + GlobalUnlock(hDevmode); + GlobalFree(hDevmode); + } else { + gfree(devmode); + } + if (hDevnames) { + GlobalUnlock(hDevnames); + GlobalFree(hDevnames); + } else { + gfree(printerName); + } } #endif // CAIRO_HAS_WIN32_SURFACE diff --git a/utils/pdftocairo-win32.h b/utils/pdftocairo-win32.h index 3f797b4..fe2cf4d 100644 --- a/utils/pdftocairo-win32.h +++ b/utils/pdftocairo-win32.h @@ -4,18 +4,16 @@ #include "goo/gtypes_p.h" #include "goo/GooString.h" - #ifdef CAIRO_HAS_WIN32_SURFACE #include <cairo-win32.h> -void win32GetFitToPageTransform(cairo_matrix_t *m); -cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputFileName, - double w, double h, - GooString *printer, - GooString *printOpt, - GBool setupdlg, - GBool duplex); +void win32SetupPrinter(GooString *printer, GooString *printOpt, + GBool duplex, GBool setupdlg); +void win32ShowPrintDialog(GBool *expand, GBool *noShrink, GBool *noCenter, + GBool *usePDFPageSize, GBool *allPages, + int *firstPage, int *lastPage, int maxPages); +cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputFileName); void win32BeginPage(double *w, double *h, GBool changePageSize, GBool useFullPage); void win32EndPage(GooString *imageFileName); void win32EndDocument(); diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1 index 1045436..7575cab 100644 --- a/utils/pdftocairo.1 +++ b/utils/pdftocairo.1 @@ -82,11 +82,6 @@ Generates a TIFF file(s) .BI \-pdf Generates a PDF file .TP -.BI \-print -(Windows only) Prints to a system printer. See also \-printer and \-printeropt. - If an output file is not specified, the output will be sent to the printer. - The output file '-' can not be used with this option. -.TP .BI \-ps Generate a PS file .TP @@ -99,6 +94,15 @@ to specify a single page. The page size options (\-origpagesizes, .BI \-svg Generate a SVG (Scalable Vector Graphics) file .TP +.BI \-print +(Windows only) Prints to a system printer. See also \-printer and \-printeropt. + If an output file is not specified, the output will be sent to the printer. + The output file '-' can not be used with this option. +.TP +.BI \-printdlg +(Windows only) Prints to a system printer. Displays the print dialog to allow +the print options to be modified before printing. +.TP .BI \-f " number" Specifies the first page to convert. .TP diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index 0c25b14..d779123 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -80,6 +80,7 @@ static GBool ps = gFalse; static GBool eps = gFalse; static GBool pdf = gFalse; static GBool printToWin32 = gFalse; +static GBool printdlg = gFalse; static GBool svg = gFalse; static GBool tiff = gFalse; @@ -160,6 +161,8 @@ static const ArgDesc argDesc[] = { #ifdef CAIRO_HAS_WIN32_SURFACE {"-print", argFlag, &printToWin32, 0, "print to a Windows printer"}, + {"-printdlg", argFlag, &printdlg, 0, + "show Windows print dialog and print"}, {"-printer", argGooString, &printer, 0, "printer name or use default if this option is not specified"}, {"-printopt", argGooString, &printOpt, 0, @@ -541,7 +544,7 @@ static void beginDocument(GooString *inputFileName, GooString *outputFileName, d } #ifdef CAIRO_HAS_WIN32_SURFACE if (printToWin32) - surface = win32BeginDocument(inputFileName, outputFileName, w, h, &printer, &printOpt, setupdlg, duplex); + surface = win32BeginDocument(inputFileName, outputFileName); #endif } } @@ -857,13 +860,14 @@ int main(int argc, char *argv[]) { (eps ? 1 : 0) + (pdf ? 1 : 0) + (printToWin32 ? 1 : 0) + + (printdlg ? 1 : 0) + (svg ? 1 : 0); if (num_outputs == 0) { - fprintf(stderr, "Error: one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -print, -svg) must be used.\n"); + fprintf(stderr, "Error: one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -print, -printdlg, -svg) must be used.\n"); exit(99); } if (num_outputs > 1) { - fprintf(stderr, "Error: use only one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -print, -svg).\n"); + fprintf(stderr, "Error: use only one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -printdlg, -print, -svg).\n"); exit(99); } if (png || jpeg || tiff) @@ -947,6 +951,9 @@ int main(int argc, char *argv[]) { else usePDFPageSize = gFalse; + if (printdlg) + printToWin32 = gTrue; + globalParams = new GlobalParams(); if (quiet) { globalParams->setErrQuiet(quiet); @@ -1046,6 +1053,24 @@ int main(int argc, char *argv[]) { lastPage = firstPage; } +#ifdef CAIRO_HAS_WIN32_SURFACE + if (printdlg) { + GBool allPages = gFalse; + if (firstPage == 1 && lastPage == doc->getNumPages()) + allPages = gTrue; + win32ShowPrintDialog(&expand, &noShrink, &noCenter, + &usePDFPageSize, &allPages, + &firstPage, &lastPage, doc->getNumPages()); + if (allPages) { + firstPage = 1; + lastPage = doc->getNumPages(); + } + } else if (printToWin32) { + win32SetupPrinter(&printer, &printOpt, + duplex, setupdlg); + } +#endif + // Make sure firstPage is always used so that beginDocument() is called if ((printOnlyEven && firstPage % 2 == 0) || (printOnlyOdd && firstPage % 2 == 1)) firstPage++; commit d8fe025c36f555a5438677e20df803eee216bb13 Author: Adrian Johnson <[email protected]> Date: Sun Oct 5 18:11:09 2014 +1030 pdftocairo: add a -setupdlg option that will the show printer properties dialog when printing to a win32 printer. diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc index dcabb69..de7da57 100644 --- a/utils/pdftocairo-win32.cc +++ b/utils/pdftocairo-win32.cc @@ -139,6 +139,7 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF double w, double h, GooString *printer, GooString *printOpt, + GBool setupdlg, GBool duplex) { if (printer->getCString()[0] == 0) { @@ -165,12 +166,26 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); } + + // Update devmode with selected print options fillCommonPrinterOptions(w, h, duplex); fillPrinterOptions(duplex, printOpt); - if (DocumentPropertiesA(NULL, NULL, printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER) < 0) { + + // Call DocumentProperties again so the driver can update its private data + // with the modified print options. This will also display the printer + // properties dialog if setupdlg is true. + int ret; + DWORD mode = DM_IN_BUFFER | DM_OUT_BUFFER; + if (setupdlg) + mode |= DM_IN_PROMPT; + ret = DocumentPropertiesA(NULL, NULL, printerName, devmode, devmode, mode); + if (ret < 0) { fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); } + if (setupdlg && ret == IDCANCEL) + exit(0); + hdc = CreateDCA(NULL, printerName, NULL, devmode); if (!hdc) { fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); @@ -194,9 +209,10 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF return cairo_win32_printing_surface_create(hdc); } -void win32BeginPage(double *w, double *h, GBool useFullPage) +void win32BeginPage(double *w, double *h, GBool changePageSize, GBool useFullPage) { - fillPagePrinterOptions(*w, *h); + if (changePageSize) + fillPagePrinterOptions(*w, *h); if (DocumentPropertiesA(NULL, NULL, printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER) < 0) { fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); diff --git a/utils/pdftocairo-win32.h b/utils/pdftocairo-win32.h index 07e200c..3f797b4 100644 --- a/utils/pdftocairo-win32.h +++ b/utils/pdftocairo-win32.h @@ -14,8 +14,9 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF double w, double h, GooString *printer, GooString *printOpt, + GBool setupdlg, GBool duplex); -void win32BeginPage(double *w, double *h, GBool useFullPage); +void win32BeginPage(double *w, double *h, GBool changePageSize, GBool useFullPage); void win32EndPage(GooString *imageFileName); void win32EndDocument(); diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1 index 00d93c4..1045436 100644 --- a/utils/pdftocairo.1 +++ b/utils/pdftocairo.1 @@ -220,6 +220,11 @@ PostScript file (PS only). This tells the print manager to enable duplexing. .B WINDOWS PRINTER OPTIONS for the available options. .TP +.BI \-setupdlg +(Windows only). When used with \-print, the printer properties dialog is displayed +allowing the print settings to be modified before printing. The paper size selected +in the print properties dialog will be used except when -origpagesizes is specified. +.TP .BI \-opw " password" Specify the owner password for the PDF file. Providing this will bypass all security restrictions. diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index b0a689e..0c25b14 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -124,10 +124,9 @@ static GBool quiet = gFalse; static GBool printVersion = gFalse; static GBool printHelp = gFalse; -#ifdef CAIRO_HAS_WIN32_SURFACE static GooString printer; static GooString printOpt; -#endif +static GBool setupdlg = gFalse; static const ArgDesc argDesc[] = { #if ENABLE_LIBPNG @@ -165,6 +164,8 @@ static const ArgDesc argDesc[] = { "printer name or use default if this option is not specified"}, {"-printopt", argGooString, &printOpt, 0, "printer options, with format <opt1>=<val1>[,<optN>=<valN>]*"}, + {"-setupdlg", argFlag, &setupdlg, 0, + "show printer setup dialog before printing"}, #endif {"-f", argInt, &firstPage, 0, @@ -262,6 +263,7 @@ static const ArgDesc argDesc[] = { static cairo_surface_t *surface; static GBool printing; static FILE *output_file; +static GBool usePDFPageSize; #if USE_CMS static unsigned char *icc_data; @@ -435,7 +437,7 @@ static void getOutputSize(double page_w, double page_h, double *width, double *h { if (printing) { - if (origPageSizes) { + if (usePDFPageSize) { *width = page_w; *height = page_h; } else { @@ -539,7 +541,7 @@ static void beginDocument(GooString *inputFileName, GooString *outputFileName, d } #ifdef CAIRO_HAS_WIN32_SURFACE if (printToWin32) - surface = win32BeginDocument(inputFileName, outputFileName, w, h, &printer, &printOpt, duplex); + surface = win32BeginDocument(inputFileName, outputFileName, w, h, &printer, &printOpt, setupdlg, duplex); #endif } } @@ -565,8 +567,12 @@ static void beginPage(double *w, double *h) #endif #ifdef CAIRO_HAS_WIN32_SURFACE - if (printToWin32) - win32BeginPage(w, h, noShrink); // w,h will be changed to actual size used + if (printToWin32) { + GBool changePageSize = gTrue; + if (setupdlg && !origPageSizes) + changePageSize = gFalse; + win32BeginPage(w, h, changePageSize, noShrink); // w,h will be changed to actual size used + } #endif cairo_surface_set_fallback_resolution (surface, x_resolution, y_resolution); @@ -936,8 +942,10 @@ int main(int argc, char *argv[]) { exit(99); } } - if (paperWidth < 0 || paperHeight < 0) - origPageSizes = gTrue; + if (origPageSizes || paperWidth < 0 || paperHeight < 0) + usePDFPageSize = gTrue; + else + usePDFPageSize = gFalse; globalParams = new GlobalParams(); if (quiet) { commit c091aa14513859ab76223f5e4e6055d92082433c Author: Adrian Johnson <[email protected]> Date: Sun Sep 14 20:43:47 2014 +0930 pdftocairo: fix a number of bugs in win32 printing - make origPageSizes work - make landscape pages work - make -noshrink option work - return actual page size in use back to main() so fit page transform works - hdc should be destroyed after cairo surface - improve option parsing and rename duplex values - Add third call to DocumentProperties as discussed in bug 79936 - fix error messages diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc index 7ad5615..dcabb69 100644 --- a/utils/pdftocairo-win32.cc +++ b/utils/pdftocairo-win32.cc @@ -7,13 +7,8 @@ #include "pdftocairo-win32.h" static HDC hdc; - -void win32GetFitToPageTransform(cairo_matrix_t *m) -{ - int logx = GetDeviceCaps(hdc, LOGPIXELSX); - int logy = GetDeviceCaps(hdc, LOGPIXELSY); - cairo_matrix_scale (m, logx / 72.0, logy / 72.0); -} +static DEVMODEA *devmode; +static char *printerName; struct Win32Option { @@ -39,69 +34,69 @@ static const Win32Option win32PaperSource[] = {NULL, 0} }; -static void parseSource(DEVMODEA *devmode, GooString *source) +static void parseSource(GooString *source) { - int src; const Win32Option *option = win32PaperSource; while (option->name) { if (source->cmp(option->name) == 0) { - src = option->value; - break; - } - } - if (!option->name) { - if (isInt(source->getCString())) { - src = atoi(source->getCString()); - } else { - fprintf(stderr, "Warning: Unknown paper source \"%s\"\n", source->getCString()); + devmode->dmDefaultSource = option->value; + devmode->dmFields |= DM_DEFAULTSOURCE; return; } + option++; } - - devmode->dmDefaultSource = src; - devmode->dmFields |= DM_DEFAULTSOURCE; + fprintf(stderr, "Warning: Unknown paper source \"%s\"\n", source->getCString()); } static const Win32Option win32DuplexMode[] = { - {"simplex", DMDUP_SIMPLEX}, - {"horizontal", DMDUP_HORIZONTAL}, - {"vertical", DMDUP_VERTICAL}, + {"off", DMDUP_SIMPLEX}, + {"short", DMDUP_HORIZONTAL}, + {"long", DMDUP_VERTICAL}, {NULL, 0} }; -static void parseDuplex(DEVMODEA *devmode, GooString *mode) +static void parseDuplex(GooString *mode) { - int win32Duplex; const Win32Option *option = win32DuplexMode; while (option->name) { if (mode->cmp(option->name) == 0) { - win32Duplex = option->value; - break; + devmode->dmDuplex = option->value; + devmode->dmFields |= DM_DUPLEX; + return; } + option++; } - if (!option->name) { - fprintf(stderr, "Warning: Unknown duplex mode \"%s\"\n", mode->getCString()); - return; - } - - devmode->dmDuplex = win32Duplex; - devmode->dmFields |= DM_DUPLEX; + fprintf(stderr, "Warning: Unknown duplex mode \"%s\"\n", mode->getCString()); } -static void fillCommonPrinterOptions(DEVMODEA *devmode, double w, double h, GBool duplex) +static void fillCommonPrinterOptions(double w, double h, GBool duplex) { - devmode->dmPaperWidth = w * 254.0 / 72.0; - devmode->dmPaperLength = h * 254.0 / 72.0; - printf("PAPER %d, %d\n", devmode->dmPaperWidth, devmode->dmPaperLength); - devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH; if (duplex) { devmode->dmDuplex = DMDUP_HORIZONTAL; devmode->dmFields |= DM_DUPLEX; } } -static void fillPrinterOptions(DEVMODEA *devmode, GBool duplex, GooString *printOpt) +static void fillPagePrinterOptions(double w, double h) +{ + w *= 254.0 / 72.0; // units are 0.1mm + h *= 254.0 / 72.0; + if (w > h) { + devmode->dmOrientation = DMORIENT_LANDSCAPE; + devmode->dmPaperWidth = h; + devmode->dmPaperLength = w; + } else { + devmode->dmOrientation = DMORIENT_PORTRAIT; + devmode->dmPaperWidth = w; + devmode->dmPaperLength = h; + } + devmode->dmPaperSize = 0; + devmode->dmFields |= DM_ORIENTATION | DM_PAPERWIDTH | DM_PAPERLENGTH; +} + + +static void fillPrinterOptions(GBool duplex, GooString *printOpt) { //printOpt format is: <opt1>=<val1>,<opt2>=<val2>,... const char *nextOpt = printOpt->getCString(); @@ -128,13 +123,12 @@ static void fillPrinterOptions(DEVMODEA *devmode, GBool duplex, GooString *print //here opt is "<optN>" and value is "<valN>" if (opt.cmp("source") == 0) { - parseSource(devmode, &value); + parseSource(&value); } else if (opt.cmp("duplex") == 0) { - if (duplex) { + if (duplex) fprintf(stderr, "Warning: duplex mode is specified both as standalone and printer options\n"); - } else { - parseDuplex(devmode, &value); - } + else + parseDuplex( &value); } else { fprintf(stderr, "Warning: unknown printer option \"%s\"\n", opt.getCString()); } @@ -147,65 +141,96 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF GooString *printOpt, GBool duplex) { - if (printer->getCString()[0] == 0) - { - DWORD szName = 0; - GetDefaultPrinterA(NULL, &szName); - char *devname = (char*)gmalloc(szName); - GetDefaultPrinterA(devname, &szName); - printer->Set(devname); - gfree(devname); + if (printer->getCString()[0] == 0) { + DWORD size = 0; + GetDefaultPrinterA(NULL, &size); + printerName = (char*)gmalloc(size); + GetDefaultPrinterA(printerName, &size); + } else { + printerName = gstrndup(printer->getCString(), printer->getLength()); } - char *cPrinter = printer->getCString(); //Query the size of the DEVMODE struct - LONG szProp = DocumentPropertiesA(NULL, NULL, cPrinter, NULL, NULL, 0); - if (szProp < 0) - { - fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); + LONG szProp = DocumentPropertiesA(NULL, NULL, printerName, NULL, NULL, 0); + if (szProp < 0) { + fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); } - DEVMODEA *devmode = (DEVMODEA*)gmalloc(szProp); + devmode = (DEVMODEA*)gmalloc(szProp); memset(devmode, 0, szProp); devmode->dmSize = sizeof(DEVMODEA); devmode->dmSpecVersion = DM_SPECVERSION; //Load the current default configuration for the printer into devmode - if (DocumentPropertiesA(NULL, NULL, cPrinter, devmode, NULL, DM_OUT_BUFFER) < 0) - { - fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); + if (DocumentPropertiesA(NULL, NULL, printerName, devmode, devmode, DM_OUT_BUFFER) < 0) { + fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); } - fillCommonPrinterOptions(devmode, w, h, duplex); - fillPrinterOptions(devmode, duplex, printOpt); - hdc = CreateDCA(NULL, cPrinter, NULL, devmode); - gfree(devmode); - if (!hdc) - { - fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); + fillCommonPrinterOptions(w, h, duplex); + fillPrinterOptions(duplex, printOpt); + if (DocumentPropertiesA(NULL, NULL, printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER) < 0) { + fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); + exit(99); + } + hdc = CreateDCA(NULL, printerName, NULL, devmode); + if (!hdc) { + fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); exit(99); } DOCINFOA docinfo; memset(&docinfo, 0, sizeof(docinfo)); docinfo.cbSize = sizeof(docinfo); - if (inputFileName->cmp("fd://0") == 0) { + if (inputFileName->cmp("fd://0") == 0) docinfo.lpszDocName = "pdftocairo <stdin>"; - } else { + else docinfo.lpszDocName = inputFileName->getCString(); - } - if (outputFileName) { + if (outputFileName) docinfo.lpszOutput = outputFileName->getCString(); - } if (StartDocA(hdc, &docinfo) <=0) { - fprintf(stderr, "Error: StartDoc failed"); + fprintf(stderr, "Error: StartDoc failed\n"); exit(99); } return cairo_win32_printing_surface_create(hdc); } -void win32BeginPage(double w, double h) +void win32BeginPage(double *w, double *h, GBool useFullPage) { + fillPagePrinterOptions(*w, *h); + if (DocumentPropertiesA(NULL, NULL, printerName, devmode, devmode, DM_IN_BUFFER | DM_OUT_BUFFER) < 0) { + fprintf(stderr, "Error: Printer \"%s\" not found\n", printerName); + exit(99); + } + ResetDCA(hdc, devmode); + + // Get actual paper size or if useFullPage is false the printable area. + // Transform the hdc scale to points to be consistent with other cairo backends + int x_dpi = GetDeviceCaps (hdc, LOGPIXELSX); + int y_dpi = GetDeviceCaps (hdc, LOGPIXELSY); + int x_off = GetDeviceCaps (hdc, PHYSICALOFFSETX); + int y_off = GetDeviceCaps (hdc, PHYSICALOFFSETY); + if (useFullPage) { + *w = GetDeviceCaps (hdc, PHYSICALWIDTH)*72.0/x_dpi; + *h = GetDeviceCaps (hdc, PHYSICALHEIGHT)*72.0/y_dpi; + } else { + *w = GetDeviceCaps (hdc, HORZRES)*72.0/x_dpi; + *h = GetDeviceCaps (hdc, VERTRES)*72.0/y_dpi; + } + XFORM xform; + xform.eM11 = x_dpi/72.0; + xform.eM12 = 0; + xform.eM21 = 0; + xform.eM22 = y_dpi/72.0; + if (useFullPage) { + xform.eDx = -x_off; + xform.eDy = -y_off; + } else { + xform.eDx = 0; + xform.eDy = 0; + } + SetGraphicsMode (hdc, GM_ADVANCED); + SetWorldTransform (hdc, &xform); + StartPage(hdc); } @@ -218,6 +243,8 @@ void win32EndDocument() { EndDoc(hdc); DeleteDC(hdc); + gfree(devmode); + gfree(printerName); } #endif // CAIRO_HAS_WIN32_SURFACE diff --git a/utils/pdftocairo-win32.h b/utils/pdftocairo-win32.h index 8ecd84c..07e200c 100644 --- a/utils/pdftocairo-win32.h +++ b/utils/pdftocairo-win32.h @@ -15,7 +15,7 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF GooString *printer, GooString *printOpt, GBool duplex); -void win32BeginPage(double w, double h); +void win32BeginPage(double *w, double *h, GBool useFullPage); void win32EndPage(GooString *imageFileName); void win32EndDocument(); diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1 index 8725722..00d93c4 100644 --- a/utils/pdftocairo.1 +++ b/utils/pdftocairo.1 @@ -268,7 +268,10 @@ Selects the source paper tray to be used (bin). The possible values are "upper", "envmanual", "auto", "tractor", "smallfmt", "largefmt", "largecapacity", "formsource", or a numeric value to choose a driver specific source. .TP .BI duplex -Sets the duplex mode of the printer. It can be "simplex", "horizontal" or "vertical". General option \-duplex is a synonym of "duplex=horizontal". If both are specified, the \-printopt one has priority. +Sets the duplex mode of the printer. The possible values are "off", "short" or "long", +indicating no duplexing, short-edge binding, or long-edge binding, respectively. +General option \-duplex is a synonym of "duplex=long". If both options are specified, +\-printopt has priority. .SH AUTHOR The pdftocairo software and documentation are copyright 1996-2004 Glyph & Cog, LLC and copyright 2005-2011 The Poppler Developers. diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index aa76226..b0a689e 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -79,7 +79,7 @@ static GBool jpeg = gFalse; static GBool ps = gFalse; static GBool eps = gFalse; static GBool pdf = gFalse; -static GBool print = gFalse; +static GBool printToWin32 = gFalse; static GBool svg = gFalse; static GBool tiff = gFalse; @@ -159,7 +159,7 @@ static const ArgDesc argDesc[] = { "generate a Scalable Vector Graphics (SVG) file"}, #endif #ifdef CAIRO_HAS_WIN32_SURFACE - {"-print", argFlag, &print, 0, + {"-print", argFlag, &printToWin32, 0, "print to a Windows printer"}, {"-printer", argGooString, &printer, 0, "printer name or use default if this option is not specified"}, @@ -483,10 +483,6 @@ static void getFitToPageTransform(double page_w, double page_h, // shrink to fit cairo_matrix_scale (m, scale, scale); } -#ifdef CAIRO_HAS_WIN32_SURFACE - if (print) - win32GetFitToPageTransform(m); -#endif } static cairo_status_t writeStream(void *closure, const unsigned char *data, unsigned int length) @@ -502,7 +498,9 @@ static cairo_status_t writeStream(void *closure, const unsigned char *data, unsi static void beginDocument(GooString *inputFileName, GooString *outputFileName, double w, double h) { if (printing) { - if (!print) { + if (printToWin32) { + output_file = NULL; + } else { if (outputFileName->cmp("fd://0") == 0) output_file = stdout; else @@ -540,41 +538,41 @@ static void beginDocument(GooString *inputFileName, GooString *outputFileName, d #endif } #ifdef CAIRO_HAS_WIN32_SURFACE - if (print) + if (printToWin32) surface = win32BeginDocument(inputFileName, outputFileName, w, h, &printer, &printOpt, duplex); #endif } } -static void beginPage(double w, double h) +static void beginPage(double *w, double *h) { if (printing) { if (ps || eps) { #if CAIRO_HAS_PS_SURFACE - if (w > h) { + if (*w > *h) { cairo_ps_surface_dsc_comment (surface, "%%PageOrientation: Landscape"); - cairo_ps_surface_set_size (surface, h, w); + cairo_ps_surface_set_size (surface, *h, *w); } else { cairo_ps_surface_dsc_comment (surface, "%%PageOrientation: Portrait"); - cairo_ps_surface_set_size (surface, w, h); + cairo_ps_surface_set_size (surface, *w, *h); } #endif } #if CAIRO_HAS_PDF_SURFACE if (pdf) - cairo_pdf_surface_set_size (surface, w, h); + cairo_pdf_surface_set_size (surface, *w, *h); #endif #ifdef CAIRO_HAS_WIN32_SURFACE - if (print) - win32BeginPage(w, h); + if (printToWin32) + win32BeginPage(w, h, noShrink); // w,h will be changed to actual size used #endif cairo_surface_set_fallback_resolution (surface, x_resolution, y_resolution); } else { - surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ceil(w), ceil(h)); + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ceil(*w), ceil(*h)); } } @@ -642,7 +640,7 @@ static void endPage(GooString *imageFileName) cairo_surface_show_page(surface); #ifdef CAIRO_HAS_WIN32_SURFACE - if (print) + if (printToWin32) win32EndPage(imageFileName); #endif @@ -662,15 +660,15 @@ static void endDocument() cairo_status_t status; if (printing) { -#ifdef CAIRO_HAS_WIN32_SURFACE - if (print) - win32EndDocument(); -#endif cairo_surface_finish(surface); status = cairo_surface_status(surface); if (status) error(errInternal, -1, "cairo error: {0:s}\n", cairo_status_to_string(status)); cairo_surface_destroy(surface); +#ifdef CAIRO_HAS_WIN32_SURFACE + if (printToWin32) + win32EndDocument(); +#endif if (output_file) fclose(output_file); } @@ -737,7 +735,7 @@ static GooString *getOutputFileName(GooString *fileName, GooString *outputName) if (outputName) { if (outputName->cmp("-") == 0) { - if (print || (!printing && !singleFile)) { + if (printToWin32 || (!printing && !singleFile)) { fprintf(stderr, "Error: stdout may only be used with the ps, eps, pdf, svg output options or if -singlefile is used.\n"); exit(99); } @@ -746,9 +744,8 @@ static GooString *getOutputFileName(GooString *fileName, GooString *outputName) return new GooString(outputName); } - if (print) { + if (printToWin32) return NULL; // No output file means print to printer - } if (fileName->cmp("fd://0") == 0) { fprintf(stderr, "Error: an output filename or '-' must be supplied when the PDF file is stdin.\n"); @@ -853,7 +850,7 @@ int main(int argc, char *argv[]) { (ps ? 1 : 0) + (eps ? 1 : 0) + (pdf ? 1 : 0) + - (print ? 1 : 0) + + (printToWin32 ? 1 : 0) + (svg ? 1 : 0); if (num_outputs == 0) { fprintf(stderr, "Error: one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -print, -svg) must be used.\n"); @@ -1098,7 +1095,7 @@ int main(int argc, char *argv[]) { if (pg == firstPage) beginDocument(fileName, outputFileName, output_w, output_h); - beginPage(output_w, output_h); + beginPage(&output_w, &output_h); renderPage(doc, cairoOut, pg, pg_w, pg_h, output_w, output_h); endPage(imageFileName); } commit cc3b39d49c656e912a7461212f3bb4e58c6444e7 Author: Adrian Johnson <[email protected]> Date: Fri Sep 12 18:17:49 2014 +0930 make pdftocairo-win32.cc a standalone .cc file instead of #including it in pdftocairo.cc diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 2f04b39..9c16018 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -21,6 +21,7 @@ if (HAVE_CAIRO) # pdftocairo set(pdftocairo_SOURCES ${common_srcs} pdftocairo.cc + pdftocairo-win32.cc ${CMAKE_SOURCE_DIR}/poppler/CairoFontEngine.cc ${CMAKE_SOURCE_DIR}/poppler/CairoOutputDev.cc ${CMAKE_SOURCE_DIR}/poppler/CairoRescaleBox.cc diff --git a/utils/Makefile.am b/utils/Makefile.am index bc0a549..7a5ab4d 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -107,7 +107,8 @@ pdftoppm_SOURCES = \ pdftoppm.cc pdftocairo_SOURCES = \ - pdftocairo.cc + pdftocairo.cc \ + pdftocairo-win32.cc if BUILD_CAIRO_OUTPUT if USE_CMS diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc index 195e6ad..7ad5615 100644 --- a/utils/pdftocairo-win32.cc +++ b/utils/pdftocairo-win32.cc @@ -1,11 +1,15 @@ +#include <cairo.h> +#ifdef CAIRO_HAS_WIN32_SURFACE + #include <cairo-win32.h> -static void win32GetFitToPageTransform(cairo_matrix_t *m) -{ - if (!print) - return; +#include "parseargs.h" +#include "pdftocairo-win32.h" + +static HDC hdc; - HDC hdc = cairo_win32_surface_get_dc(surface); +void win32GetFitToPageTransform(cairo_matrix_t *m) +{ int logx = GetDeviceCaps(hdc, LOGPIXELSX); int logy = GetDeviceCaps(hdc, LOGPIXELSY); cairo_matrix_scale (m, logx / 72.0, logy / 72.0); @@ -68,9 +72,6 @@ static const Win32Option win32DuplexMode[] = static void parseDuplex(DEVMODEA *devmode, GooString *mode) { - if (duplex) - fprintf(stderr, "Warning: duplex mode is specified both as standalone and printer options\n"); - int win32Duplex; const Win32Option *option = win32DuplexMode; while (option->name) { @@ -88,7 +89,7 @@ static void parseDuplex(DEVMODEA *devmode, GooString *mode) devmode->dmFields |= DM_DUPLEX; } -static void fillCommonPrinterOptions(DEVMODEA *devmode, double w, double h) +static void fillCommonPrinterOptions(DEVMODEA *devmode, double w, double h, GBool duplex) { devmode->dmPaperWidth = w * 254.0 / 72.0; devmode->dmPaperLength = h * 254.0 / 72.0; @@ -100,10 +101,10 @@ static void fillCommonPrinterOptions(DEVMODEA *devmode, double w, double h) } } -static void fillPrinterOptions(DEVMODEA *devmode) +static void fillPrinterOptions(DEVMODEA *devmode, GBool duplex, GooString *printOpt) { //printOpt format is: <opt1>=<val1>,<opt2>=<val2>,... - const char *nextOpt = printOpt.getCString(); + const char *nextOpt = printOpt->getCString(); while (nextOpt && *nextOpt) { const char *comma = strchr(nextOpt, ','); @@ -129,28 +130,33 @@ static void fillPrinterOptions(DEVMODEA *devmode) if (opt.cmp("source") == 0) { parseSource(devmode, &value); } else if (opt.cmp("duplex") == 0) { - parseDuplex(devmode, &value); + if (duplex) { + fprintf(stderr, "Warning: duplex mode is specified both as standalone and printer options\n"); + } else { + parseDuplex(devmode, &value); + } } else { fprintf(stderr, "Warning: unknown printer option \"%s\"\n", opt.getCString()); } } } -static void win32BeginDocument(GooString *inputFileName, GooString *outputFileName, double w, double h) +cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputFileName, + double w, double h, + GooString *printer, + GooString *printOpt, + GBool duplex) { - if (!print) - return; - - if (printer.getCString()[0] == 0) + if (printer->getCString()[0] == 0) { DWORD szName = 0; GetDefaultPrinterA(NULL, &szName); char *devname = (char*)gmalloc(szName); GetDefaultPrinterA(devname, &szName); - printer.Set(devname); + printer->Set(devname); gfree(devname); } - char *cPrinter = printer.getCString(); + char *cPrinter = printer->getCString(); //Query the size of the DEVMODE struct LONG szProp = DocumentPropertiesA(NULL, NULL, cPrinter, NULL, NULL, 0); @@ -169,9 +175,9 @@ static void win32BeginDocument(GooString *inputFileName, GooString *outputFileNa fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); exit(99); } - fillCommonPrinterOptions(devmode, w, h); - fillPrinterOptions(devmode); - HDC hdc = CreateDCA(NULL, cPrinter, NULL, devmode); + fillCommonPrinterOptions(devmode, w, h, duplex); + fillPrinterOptions(devmode, duplex, printOpt); + hdc = CreateDCA(NULL, cPrinter, NULL, devmode); gfree(devmode); if (!hdc) { @@ -194,30 +200,24 @@ static void win32BeginDocument(GooString *inputFileName, GooString *outputFileNa fprintf(stderr, "Error: StartDoc failed"); exit(99); } - - surface = cairo_win32_printing_surface_create(hdc); + + return cairo_win32_printing_surface_create(hdc); } -static void win32BeginPage(double w, double h) +void win32BeginPage(double w, double h) { - if (!print) - return; - StartPage(cairo_win32_surface_get_dc(surface)); + StartPage(hdc); } -static void win32EndPage(GooString *imageFileName) +void win32EndPage(GooString *imageFileName) { - if (!print) - return; - EndPage(cairo_win32_surface_get_dc(surface)); + EndPage(hdc); } -static void win32EndDocument() +void win32EndDocument() { - if (!print) - return; - - HDC hdc = cairo_win32_surface_get_dc(surface); EndDoc(hdc); DeleteDC(hdc); } + +#endif // CAIRO_HAS_WIN32_SURFACE diff --git a/utils/pdftocairo-win32.h b/utils/pdftocairo-win32.h new file mode 100644 index 0000000..8ecd84c --- /dev/null +++ b/utils/pdftocairo-win32.h @@ -0,0 +1,22 @@ +#include <cairo.h> +#include "goo/gmem.h" +#include "goo/gtypes.h" +#include "goo/gtypes_p.h" +#include "goo/GooString.h" + + +#ifdef CAIRO_HAS_WIN32_SURFACE + +#include <cairo-win32.h> + +void win32GetFitToPageTransform(cairo_matrix_t *m); +cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputFileName, + double w, double h, + GooString *printer, + GooString *printOpt, + GBool duplex); +void win32BeginPage(double w, double h); +void win32EndPage(GooString *imageFileName); +void win32EndDocument(); + +#endif // CAIRO_HAS_WIN32_SURFACE diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index 65d7c23..aa76226 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -71,6 +71,8 @@ #include <cairo-svg.h> #endif +#include "pdftocairo-win32.h" + static GBool png = gFalse; static GBool jpeg = gFalse; @@ -267,10 +269,6 @@ static int icc_data_size; static cmsHPROFILE profile; #endif -#ifdef CAIRO_HAS_WIN32_SURFACE -#include "pdftocairo-win32.cc" -#endif - void writePageImage(GooString *filename) { ImgWriter *writer = 0; @@ -486,7 +484,8 @@ static void getFitToPageTransform(double page_w, double page_h, cairo_matrix_scale (m, scale, scale); } #ifdef CAIRO_HAS_WIN32_SURFACE - win32GetFitToPageTransform(m); + if (print) + win32GetFitToPageTransform(m); #endif } @@ -541,7 +540,8 @@ static void beginDocument(GooString *inputFileName, GooString *outputFileName, d #endif } #ifdef CAIRO_HAS_WIN32_SURFACE - win32BeginDocument(inputFileName, outputFileName, w, h); + if (print) + surface = win32BeginDocument(inputFileName, outputFileName, w, h, &printer, &printOpt, duplex); #endif } } @@ -565,8 +565,10 @@ static void beginPage(double w, double h) if (pdf) cairo_pdf_surface_set_size (surface, w, h); #endif + #ifdef CAIRO_HAS_WIN32_SURFACE - win32BeginPage(w, h); + if (print) + win32BeginPage(w, h); #endif cairo_surface_set_fallback_resolution (surface, x_resolution, y_resolution); @@ -638,9 +640,12 @@ static void endPage(GooString *imageFileName) if (printing) { cairo_surface_show_page(surface); + #ifdef CAIRO_HAS_WIN32_SURFACE - win32EndPage(imageFileName); + if (print) + win32EndPage(imageFileName); #endif + } else { writePageImage(imageFileName); cairo_surface_finish(surface); @@ -658,7 +663,8 @@ static void endDocument() if (printing) { #ifdef CAIRO_HAS_WIN32_SURFACE - win32EndDocument(); + if (print) + win32EndDocument(); #endif cairo_surface_finish(surface); status = cairo_surface_status(surface); commit 700205af19ef1ae5f2c713d118ebd5dd4a0afba3 Author: Adrian Johnson <[email protected]> Date: Sun Sep 7 20:18:36 2014 +0930 pdftocairo: Allow an output file for win32 printing to be specified Can be used for testing win32 print output without wasting paper. diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc index 515ffa7..195e6ad 100644 --- a/utils/pdftocairo-win32.cc +++ b/utils/pdftocairo-win32.cc @@ -136,7 +136,7 @@ static void fillPrinterOptions(DEVMODEA *devmode) } } -static void win32BeginDocument(GooString *outputFileName, double w, double h) +static void win32BeginDocument(GooString *inputFileName, GooString *outputFileName, double w, double h) { if (!print) return; @@ -182,10 +182,14 @@ static void win32BeginDocument(GooString *outputFileName, double w, double h) DOCINFOA docinfo; memset(&docinfo, 0, sizeof(docinfo)); docinfo.cbSize = sizeof(docinfo); - if (outputFileName->cmp("fd://0") == 0) + if (inputFileName->cmp("fd://0") == 0) { docinfo.lpszDocName = "pdftocairo <stdin>"; - else - docinfo.lpszDocName = outputFileName->getCString(); + } else { + docinfo.lpszDocName = inputFileName->getCString(); + } + if (outputFileName) { + docinfo.lpszOutput = outputFileName->getCString(); + } if (StartDocA(hdc, &docinfo) <=0) { fprintf(stderr, "Error: StartDoc failed"); exit(99); diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1 index 7747409..8725722 100644 --- a/utils/pdftocairo.1 +++ b/utils/pdftocairo.1 @@ -23,6 +23,8 @@ PostScript (PS) Encapsulated PostScript (EPS) .IP \(bu Scalable Vector Graphics (SVG) +.IP \(bu +Windows Printer .PP .B pdftocairo reads the PDF file, @@ -82,6 +84,8 @@ Generates a PDF file .TP .BI \-print (Windows only) Prints to a system printer. See also \-printer and \-printeropt. + If an output file is not specified, the output will be sent to the printer. + The output file '-' can not be used with this option. .TP .BI \-ps Generate a PS file diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index 79d71d9..65d7c23 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -500,7 +500,7 @@ static cairo_status_t writeStream(void *closure, const unsigned char *data, unsi return CAIRO_STATUS_WRITE_ERROR; } -static void beginDocument(GooString *outputFileName, double w, double h) +static void beginDocument(GooString *inputFileName, GooString *outputFileName, double w, double h) { if (printing) { if (!print) { @@ -541,7 +541,7 @@ static void beginDocument(GooString *outputFileName, double w, double h) #endif } #ifdef CAIRO_HAS_WIN32_SURFACE - win32BeginDocument(outputFileName, w, h); + win32BeginDocument(inputFileName, outputFileName, w, h); #endif } } @@ -731,7 +731,7 @@ static GooString *getOutputFileName(GooString *fileName, GooString *outputName) if (outputName) { if (outputName->cmp("-") == 0) { - if (!printing && !singleFile) { + if (print || (!printing && !singleFile)) { fprintf(stderr, "Error: stdout may only be used with the ps, eps, pdf, svg output options or if -singlefile is used.\n"); exit(99); } @@ -740,8 +740,9 @@ static GooString *getOutputFileName(GooString *fileName, GooString *outputName) return new GooString(outputName); } - if (print) - return fileName; //it will be used as the job name + if (print) { + return NULL; // No output file means print to printer + } if (fileName->cmp("fd://0") == 0) { fprintf(stderr, "Error: an output filename or '-' must be supplied when the PDF file is stdin.\n"); @@ -1090,7 +1091,7 @@ int main(int argc, char *argv[]) { getOutputSize(pg_w, pg_h, &output_w, &output_h); if (pg == firstPage) - beginDocument(outputFileName, output_w, output_h); + beginDocument(fileName, outputFileName, output_w, output_h); beginPage(output_w, output_h); renderPage(doc, cairoOut, pg, pg_w, pg_h, output_w, output_h); endPage(imageFileName); commit 40d3ae87befad489fd8c0b38ff2561a0782cae0b Author: Rodrigo Rivas Costa <[email protected]> Date: Sat Sep 6 21:04:10 2014 +0930 Add support for printing to a Windows printer from pdftocairo Bug 79936 diff --git a/configure.ac b/configure.ac index 7a34f82..10a4b39 100644 --- a/configure.ac +++ b/configure.ac @@ -48,7 +48,7 @@ case "$host_os" in ;; mingw*) os_win32=yes - win32_libs="-lgdi32" + win32_libs="-lgdi32 -lwinspool" create_shared_lib="-no-undefined" auto_import_flags="-Wl,--enable-auto-import" diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc new file mode 100644 index 0000000..515ffa7 --- /dev/null +++ b/utils/pdftocairo-win32.cc @@ -0,0 +1,219 @@ +#include <cairo-win32.h> + +static void win32GetFitToPageTransform(cairo_matrix_t *m) +{ + if (!print) + return; + + HDC hdc = cairo_win32_surface_get_dc(surface); + int logx = GetDeviceCaps(hdc, LOGPIXELSX); + int logy = GetDeviceCaps(hdc, LOGPIXELSY); + cairo_matrix_scale (m, logx / 72.0, logy / 72.0); +} + +struct Win32Option +{ + const char *name; + int value; +}; + +static const Win32Option win32PaperSource[] = +{ + {"upper", DMBIN_UPPER}, + {"onlyone", DMBIN_ONLYONE}, + {"lower", DMBIN_LOWER}, + {"middle", DMBIN_MIDDLE}, + {"manual", DMBIN_MANUAL}, + {"envelope", DMBIN_ENVELOPE}, + {"envmanual", DMBIN_ENVMANUAL}, + {"auto", DMBIN_AUTO}, + {"tractor", DMBIN_TRACTOR}, + {"smallfmt", DMBIN_SMALLFMT}, + {"largefmt", DMBIN_LARGEFMT}, + {"largecapacity", DMBIN_LARGECAPACITY}, + {"formsource", DMBIN_FORMSOURCE}, + {NULL, 0} +}; + +static void parseSource(DEVMODEA *devmode, GooString *source) +{ + int src; + const Win32Option *option = win32PaperSource; + while (option->name) { + if (source->cmp(option->name) == 0) { + src = option->value; + break; + } + } + if (!option->name) { + if (isInt(source->getCString())) { + src = atoi(source->getCString()); + } else { + fprintf(stderr, "Warning: Unknown paper source \"%s\"\n", source->getCString()); + return; + } + } + + devmode->dmDefaultSource = src; + devmode->dmFields |= DM_DEFAULTSOURCE; +} + +static const Win32Option win32DuplexMode[] = +{ + {"simplex", DMDUP_SIMPLEX}, + {"horizontal", DMDUP_HORIZONTAL}, + {"vertical", DMDUP_VERTICAL}, + {NULL, 0} +}; + +static void parseDuplex(DEVMODEA *devmode, GooString *mode) +{ + if (duplex) + fprintf(stderr, "Warning: duplex mode is specified both as standalone and printer options\n"); + + int win32Duplex; + const Win32Option *option = win32DuplexMode; + while (option->name) { + if (mode->cmp(option->name) == 0) { + win32Duplex = option->value; + break; + } + } + if (!option->name) { + fprintf(stderr, "Warning: Unknown duplex mode \"%s\"\n", mode->getCString()); + return; + } + + devmode->dmDuplex = win32Duplex; + devmode->dmFields |= DM_DUPLEX; +} + +static void fillCommonPrinterOptions(DEVMODEA *devmode, double w, double h) +{ + devmode->dmPaperWidth = w * 254.0 / 72.0; + devmode->dmPaperLength = h * 254.0 / 72.0; + printf("PAPER %d, %d\n", devmode->dmPaperWidth, devmode->dmPaperLength); + devmode->dmFields |= DM_PAPERWIDTH | DM_PAPERLENGTH; + if (duplex) { + devmode->dmDuplex = DMDUP_HORIZONTAL; + devmode->dmFields |= DM_DUPLEX; + } +} + +static void fillPrinterOptions(DEVMODEA *devmode) +{ + //printOpt format is: <opt1>=<val1>,<opt2>=<val2>,... + const char *nextOpt = printOpt.getCString(); + while (nextOpt && *nextOpt) + { + const char *comma = strchr(nextOpt, ','); + GooString opt; + if (comma) { + opt.Set(nextOpt, comma - nextOpt); + nextOpt = comma + 1; + } else { + opt.Set(nextOpt); + nextOpt = NULL; + } + //here opt is "<optN>=<valN> " + const char *equal = strchr(opt.getCString(), '='); + if (!equal) { + fprintf(stderr, "Warning: unknown printer option \"%s\"\n", opt.getCString()); + continue; + } + int iequal = equal - opt.getCString(); + GooString value(&opt, iequal + 1, opt.getLength() - iequal - 1); + opt.del(iequal, opt.getLength() - iequal); + //here opt is "<optN>" and value is "<valN>" + + if (opt.cmp("source") == 0) { + parseSource(devmode, &value); + } else if (opt.cmp("duplex") == 0) { + parseDuplex(devmode, &value); + } else { + fprintf(stderr, "Warning: unknown printer option \"%s\"\n", opt.getCString()); + } + } +} + +static void win32BeginDocument(GooString *outputFileName, double w, double h) +{ + if (!print) + return; + + if (printer.getCString()[0] == 0) + { + DWORD szName = 0; + GetDefaultPrinterA(NULL, &szName); + char *devname = (char*)gmalloc(szName); + GetDefaultPrinterA(devname, &szName); + printer.Set(devname); + gfree(devname); + } + char *cPrinter = printer.getCString(); + + //Query the size of the DEVMODE struct + LONG szProp = DocumentPropertiesA(NULL, NULL, cPrinter, NULL, NULL, 0); + if (szProp < 0) + { + fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); + exit(99); + } + DEVMODEA *devmode = (DEVMODEA*)gmalloc(szProp); + memset(devmode, 0, szProp); + devmode->dmSize = sizeof(DEVMODEA); + devmode->dmSpecVersion = DM_SPECVERSION; + //Load the current default configuration for the printer into devmode + if (DocumentPropertiesA(NULL, NULL, cPrinter, devmode, NULL, DM_OUT_BUFFER) < 0) + { + fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); + exit(99); + } + fillCommonPrinterOptions(devmode, w, h); + fillPrinterOptions(devmode); + HDC hdc = CreateDCA(NULL, cPrinter, NULL, devmode); + gfree(devmode); + if (!hdc) + { + fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); + exit(99); + } + + DOCINFOA docinfo; + memset(&docinfo, 0, sizeof(docinfo)); + docinfo.cbSize = sizeof(docinfo); + if (outputFileName->cmp("fd://0") == 0) + docinfo.lpszDocName = "pdftocairo <stdin>"; + else + docinfo.lpszDocName = outputFileName->getCString(); + if (StartDocA(hdc, &docinfo) <=0) { + fprintf(stderr, "Error: StartDoc failed"); + exit(99); + } + + surface = cairo_win32_printing_surface_create(hdc); +} + +static void win32BeginPage(double w, double h) +{ + if (!print) + return; + StartPage(cairo_win32_surface_get_dc(surface)); +} + +static void win32EndPage(GooString *imageFileName) +{ + if (!print) + return; + EndPage(cairo_win32_surface_get_dc(surface)); +} + +static void win32EndDocument() +{ + if (!print) + return; + + HDC hdc = cairo_win32_surface_get_dc(surface); + EndDoc(hdc); + DeleteDC(hdc); +} diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1 index c903ffa..7747409 100644 --- a/utils/pdftocairo.1 +++ b/utils/pdftocairo.1 @@ -48,7 +48,7 @@ is not used, the output filename will be derived from the .IR PDF-file filename. .PP -Not all options are valid with all output formats. One (and only one) of the output format options (\-png, \-jpeg, \-tiff, \-pdf, \-ps, \-eps, or \-svg) must be used. +Not all options are valid with all output formats. One (and only one) of the output format options (\-png, \-jpeg, \-tiff, \-pdf, \-print, \-ps, \-eps, or \-svg) must be used. .PP The resolution options (\-r, \-rx, \-ry) set the resolution of the image output formats. The image dimensions will depend on the PDF page @@ -80,6 +80,9 @@ Generates a TIFF file(s) .BI \-pdf Generates a PDF file .TP +.BI \-print +(Windows only) Prints to a system printer. See also \-printer and \-printeropt. +.TP .BI \-ps Generate a PS file .TP @@ -205,6 +208,14 @@ lower-left corner of the paper instead (PS,PDF,SVG only). Adds the %%IncludeFeature: *Duplex DuplexNoTumble DSC comment to the PostScript file (PS only). This tells the print manager to enable duplexing. .TP +.BI \-printer " printer-name" +(Windows only). When used with \-print, specifies the name of the printer to be used, instead of the system default. +.TP +.BI \-printopt " printer-options" +(Windows only). When used with \-print, takes a list of options to be used to configure the printer. See +.B WINDOWS PRINTER OPTIONS +for the available options. +.TP .BI \-opw " password" Specify the owner password for the PDF file. Providing this will bypass all security restrictions. @@ -244,6 +255,16 @@ Error related to ICC profile. .TP 99 Other error. +.SH WINDOWS PRINTER OPTIONS +In Windows, you can use the \-print option to print directly to a system printer. Additionally, you can use the \-printopt +option to configure the printer. It takes a string of the form "<opt>=<val>[,<opt>=<val>]". Currently the available options are: +.TP +.BI source +Selects the source paper tray to be used (bin). The possible values are "upper", "onlyone", "lower", "middle", "manual", "envelope", +"envmanual", "auto", "tractor", "smallfmt", "largefmt", "largecapacity", "formsource", or a numeric value to choose a driver specific source. +.TP +.BI duplex +Sets the duplex mode of the printer. It can be "simplex", "horizontal" or "vertical". General option \-duplex is a synonym of "duplex=horizontal". If both are specified, the \-printopt one has priority. .SH AUTHOR The pdftocairo software and documentation are copyright 1996-2004 Glyph & Cog, LLC and copyright 2005-2011 The Poppler Developers. diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc index b3f57b6..79d71d9 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -77,6 +77,7 @@ static GBool jpeg = gFalse; static GBool ps = gFalse; static GBool eps = gFalse; static GBool pdf = gFalse; +static GBool print = gFalse; static GBool svg = gFalse; static GBool tiff = gFalse; @@ -121,6 +122,11 @@ static GBool quiet = gFalse; static GBool printVersion = gFalse; static GBool printHelp = gFalse; +#ifdef CAIRO_HAS_WIN32_SURFACE +static GooString printer; +static GooString printOpt; +#endif + static const ArgDesc argDesc[] = { #if ENABLE_LIBPNG {"-png", argFlag, &png, 0, @@ -150,6 +156,14 @@ static const ArgDesc argDesc[] = { {"-svg", argFlag, &svg, 0, "generate a Scalable Vector Graphics (SVG) file"}, #endif +#ifdef CAIRO_HAS_WIN32_SURFACE + {"-print", argFlag, &print, 0, + "print to a Windows printer"}, + {"-printer", argGooString, &printer, 0, + "printer name or use default if this option is not specified"}, + {"-printopt", argGooString, &printOpt, 0, + "printer options, with format <opt1>=<val1>[,<optN>=<valN>]*"}, +#endif {"-f", argInt, &firstPage, 0, "first page to print"}, @@ -253,6 +267,9 @@ static int icc_data_size; static cmsHPROFILE profile; #endif +#ifdef CAIRO_HAS_WIN32_SURFACE +#include "pdftocairo-win32.cc" +#endif void writePageImage(GooString *filename) { @@ -468,6 +485,9 @@ static void getFitToPageTransform(double page_w, double page_h, // shrink to fit cairo_matrix_scale (m, scale, scale); } +#ifdef CAIRO_HAS_WIN32_SURFACE + win32GetFitToPageTransform(m); +#endif } static cairo_status_t writeStream(void *closure, const unsigned char *data, unsigned int length) @@ -483,14 +503,16 @@ static cairo_status_t writeStream(void *closure, const unsigned char *data, unsi static void beginDocument(GooString *outputFileName, double w, double h) { if (printing) { - if (outputFileName->cmp("fd://0") == 0) - output_file = stdout; - else - { - output_file = fopen(outputFileName->getCString(), "wb"); - if (!output_file) { - fprintf(stderr, "Error opening output file %s\n", outputFileName->getCString()); - exit(2); + if (!print) { + if (outputFileName->cmp("fd://0") == 0) + output_file = stdout; + else + { + output_file = fopen(outputFileName->getCString(), "wb"); + if (!output_file) { + fprintf(stderr, "Error opening output file %s\n", outputFileName->getCString()); + exit(2); + } } } @@ -518,6 +540,9 @@ static void beginDocument(GooString *outputFileName, double w, double h) cairo_svg_surface_restrict_to_version (surface, CAIRO_SVG_VERSION_1_2); #endif } +#ifdef CAIRO_HAS_WIN32_SURFACE + win32BeginDocument(outputFileName, w, h); +#endif } } @@ -540,6 +565,9 @@ static void beginPage(double w, double h) if (pdf) cairo_pdf_surface_set_size (surface, w, h); #endif +#ifdef CAIRO_HAS_WIN32_SURFACE + win32BeginPage(w, h); +#endif cairo_surface_set_fallback_resolution (surface, x_resolution, y_resolution); @@ -610,6 +638,9 @@ static void endPage(GooString *imageFileName) if (printing) { cairo_surface_show_page(surface); +#ifdef CAIRO_HAS_WIN32_SURFACE + win32EndPage(imageFileName); +#endif } else { writePageImage(imageFileName); cairo_surface_finish(surface); @@ -626,12 +657,16 @@ static void endDocument() cairo_status_t status; if (printing) { +#ifdef CAIRO_HAS_WIN32_SURFACE + win32EndDocument(); +#endif cairo_surface_finish(surface); status = cairo_surface_status(surface); if (status) error(errInternal, -1, "cairo error: {0:s}\n", cairo_status_to_string(status)); cairo_surface_destroy(surface); - fclose(output_file); + if (output_file) + fclose(output_file); } } @@ -705,6 +740,9 @@ static GooString *getOutputFileName(GooString *fileName, GooString *outputName) return new GooString(outputName); } + if (print) + return fileName; //it will be used as the job name + if (fileName->cmp("fd://0") == 0) { fprintf(stderr, "Error: an output filename or '-' must be supplied when the PDF file is stdin.\n"); exit(99); @@ -808,13 +846,14 @@ int main(int argc, char *argv[]) { (ps ? 1 : 0) + (eps ? 1 : 0) + (pdf ? 1 : 0) + + (print ? 1 : 0) + (svg ? 1 : 0); if (num_outputs == 0) { - fprintf(stderr, "Error: one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -svg) must be used.\n"); + fprintf(stderr, "Error: one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -print, -svg) must be used.\n"); exit(99); } if (num_outputs > 1) { - fprintf(stderr, "Error: use only one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -svg).\n"); + fprintf(stderr, "Error: use only one of the output format options (-png, -jpeg, -ps, -eps, -pdf, -print, -svg).\n"); exit(99); } if (png || jpeg || tiff) _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
