[poppler] 6 commits - configure.ac utils/CMakeLists.txt utils/Makefile.am utils/pdftocairo.1 utils/pdftocairo.cc utils/pdftocairo-win32.cc utils/pdftocairo-win32.h
Adrian Johnson
ajohnson at kemper.freedesktop.org
Tue Oct 21 04:39:24 PDT 2014
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 <ajohnson at redneon.com>
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 <ajohnson at redneon.com>
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 <ajohnson at redneon.com>
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 <ajohnson at redneon.com>
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 <ajohnson at redneon.com>
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 <rodrigorivascosta at gmail.com>
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)
More information about the poppler
mailing list