From dd25807ecde2def6b8a763e870a6eff4b926766e Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 14 Sep 2014 20:43:47 +0930 Subject: [PATCH 7/9] pdftocairo: fix win32 page size selection - 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 --- utils/pdftocairo-win32.cc | 83 ++++++++++++++++++++++++++++++++++------------- utils/pdftocairo-win32.h | 2 +- utils/pdftocairo.cc | 20 +++++------- 3 files changed, 70 insertions(+), 35 deletions(-) diff --git a/utils/pdftocairo-win32.cc b/utils/pdftocairo-win32.cc index 7ad5615..ffba984 100644 --- a/utils/pdftocairo-win32.cc +++ b/utils/pdftocairo-win32.cc @@ -7,13 +7,7 @@ #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; struct Win32Option { @@ -39,7 +33,7 @@ static const Win32Option win32PaperSource[] = {NULL, 0} }; -static void parseSource(DEVMODEA *devmode, GooString *source) +static void parseSource(GooString *source) { int src; const Win32Option *option = win32PaperSource; @@ -70,7 +64,7 @@ static const Win32Option win32DuplexMode[] = {NULL, 0} }; -static void parseDuplex(DEVMODEA *devmode, GooString *mode) +static void parseDuplex(GooString *mode) { int win32Duplex; const Win32Option *option = win32DuplexMode; @@ -89,19 +83,33 @@ static void parseDuplex(DEVMODEA *devmode, GooString *mode) devmode->dmFields |= DM_DUPLEX; } -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: =,=,... const char *nextOpt = printOpt->getCString(); @@ -128,12 +136,12 @@ static void fillPrinterOptions(DEVMODEA *devmode, GBool duplex, GooString *print //here opt is "" and value is "" if (opt.cmp("source") == 0) { - parseSource(devmode, &value); + parseSource(&value); } else if (opt.cmp("duplex") == 0) { if (duplex) { fprintf(stderr, "Warning: duplex mode is specified both as standalone and printer options\n"); } else { - parseDuplex(devmode, &value); + parseDuplex( &value); } } else { fprintf(stderr, "Warning: unknown printer option \"%s\"\n", opt.getCString()); @@ -165,7 +173,7 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); exit(99); } - DEVMODEA *devmode = (DEVMODEA*)gmalloc(szProp); + devmode = (DEVMODEA*)gmalloc(szProp); memset(devmode, 0, szProp); devmode->dmSize = sizeof(DEVMODEA); devmode->dmSpecVersion = DM_SPECVERSION; @@ -175,10 +183,9 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); exit(99); } - fillCommonPrinterOptions(devmode, w, h, duplex); - fillPrinterOptions(devmode, duplex, printOpt); + fillCommonPrinterOptions(w, h, duplex); + fillPrinterOptions(duplex, printOpt); hdc = CreateDCA(NULL, cPrinter, NULL, devmode); - gfree(devmode); if (!hdc) { fprintf(stderr, "Error: Printer \"%s\" not found", cPrinter); @@ -204,8 +211,39 @@ cairo_surface_t *win32BeginDocument(GooString *inputFileName, GooString *outputF return cairo_win32_printing_surface_create(hdc); } -void win32BeginPage(double w, double h) +void win32BeginPage(double *w, double *h, GBool useFullPage) { + fillPagePrinterOptions(*w, *h); + 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 +256,7 @@ void win32EndDocument() { EndDoc(hdc); DeleteDC(hdc); + gfree(devmode); } #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.cc b/utils/pdftocairo.cc index aa76226..49e9c1e 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -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) @@ -546,35 +542,35 @@ static void beginDocument(GooString *inputFileName, GooString *outputFileName, d } } -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); + 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)); } } @@ -1098,7 +1094,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); } -- 2.1.0