"Fossies" - the Fresh Open Source Software Archive

Member "xpdf-4.02/xpdf-qt/XpdfWidgetPrint.cc" (25 Sep 2019, 13035 Bytes) of package /linux/misc/xpdf-4.02.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "XpdfWidgetPrint.cc" see the Fossies "Dox" file reference documentation.

    1 //========================================================================
    2 //
    3 // XpdfWidgetPrint.cc
    4 //
    5 // Copyright 2012 Glyph & Cog, LLC
    6 //
    7 //========================================================================
    8 
    9 #if XPDFWIDGET_PRINTING
   10 
   11 #include <aconf.h>
   12 
   13 #include <stdlib.h>
   14 #include <QPrinter>
   15 #include "gfile.h"
   16 #include "PDFDoc.h"
   17 #include "ErrorCodes.h"
   18 #include "XpdfWidget.h"
   19 
   20 #if defined(_WIN32)
   21 #elif defined(__APPLE__)
   22 #  include <CoreFoundation/CoreFoundation.h>
   23 #  include <ApplicationServices/ApplicationServices.h>
   24 #elif defined(__linux__)
   25 #  include "PSOutputDev.h"
   26 #  include <cups/cups.h>
   27 #endif
   28 
   29 #include "gmempp.h"
   30 
   31 //------------------------------------------------------------------------
   32 // Windows
   33 //------------------------------------------------------------------------
   34 
   35 #if defined(_WIN32)
   36 
   37 //------------------------------------------------------------------------
   38 // Mac OS X
   39 //------------------------------------------------------------------------
   40 
   41 #elif defined(__APPLE__)
   42 
   43 XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt,
   44                    int hDPI, int vDPI,
   45                    XpdfWidget *widget) {
   46   GString *pdfFileName;
   47   CFStringRef s;
   48   CFURLRef url;
   49   CGPDFDocumentRef pdfDoc;
   50   CGPDFPageRef pdfPage;
   51   GString *printerName;
   52   CFArrayRef printerList, pageFormatList;
   53   char prtName[512];
   54   PMPrinter printer;
   55   PMPrintSession session;
   56   PMPageFormat pageFormat;
   57   PMPrintSettings printSettings;
   58   PMRect paperRect;
   59   CGRect paperRect2;
   60   CGContextRef ctx;
   61   CGAffineTransform pageTransform;
   62   QPrinter::ColorMode colorMode;
   63   QSizeF paperSize;
   64   QPrinter::PaperSource paperSource;
   65   QPageLayout::Orientation pageOrientation;
   66   FILE *f;
   67   GBool deletePDFFile;
   68   int startPage, endPage, pg, i;
   69 
   70   //--- get PDF file name
   71 
   72   deletePDFFile = gFalse;
   73   if (doc->getFileName()) {
   74     pdfFileName = doc->getFileName()->copy();
   75   } else {
   76     if (!openTempFile(&pdfFileName, &f, "wb", ".pdf")) {
   77       goto err0;
   78     }
   79     fclose(f);
   80     deletePDFFile = gTrue;
   81     if (!doc->saveAs(pdfFileName)) {
   82       goto err1;
   83     }
   84   }
   85 
   86   //--- load the PDF file
   87 
   88   s = CFStringCreateWithCString(NULL, pdfFileName->getCString(),
   89                 kCFStringEncodingUTF8);
   90   url = CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, false);
   91   CFRelease(s);
   92   pdfDoc = CGPDFDocumentCreateWithURL(url);
   93   CFRelease(url);
   94   if (!pdfDoc) {
   95     goto err1;
   96   }
   97 
   98   //--- get page range
   99 
  100   startPage = prt->fromPage();
  101   endPage = prt->toPage();
  102   if (startPage == 0) {
  103     startPage = 1;
  104   }
  105   if (endPage == 0) {
  106     endPage = doc->getNumPages();
  107   }
  108   if (startPage > endPage) {
  109     CFRelease(pdfDoc);
  110     if (deletePDFFile) {
  111       unlink(pdfFileName->getCString());
  112     }
  113     delete pdfFileName;
  114     return XpdfWidget::pdfErrBadPageNum;
  115   }
  116 
  117   //--- get other parameters
  118 
  119   colorMode = prt->colorMode();
  120   paperSize = prt->paperSize(QPrinter::Point);
  121   paperSource = prt->paperSource();
  122   pageOrientation = prt->pageLayout().orientation();
  123 
  124   //--- create the Session and PrintSettings
  125 
  126   if (PMCreateSession(&session)) {
  127     goto err2;
  128   }
  129   if (PMCreatePrintSettings(&printSettings)) {
  130     goto err3;
  131   }
  132   if (PMSessionDefaultPrintSettings(session, printSettings)) {
  133     goto err4;
  134   }
  135   s = CFStringCreateWithCString(NULL, pdfFileName->getCString(),
  136                 kCFStringEncodingUTF8);
  137   PMPrintSettingsSetJobName(printSettings, s);
  138   CFRelease(s);
  139 
  140   //--- set up for print-to-file
  141 
  142   if (!prt->outputFileName().isEmpty()) {
  143 
  144     s = CFStringCreateWithCString(NULL,
  145                   prt->outputFileName().toUtf8().constData(),
  146                   kCFStringEncodingUTF8);
  147     url = CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, false);
  148     CFRelease(s);
  149     if (PMSessionSetDestination(session, printSettings, kPMDestinationFile,
  150                 kPMDocumentFormatPDF, url)) {
  151       CFRelease(url);
  152       goto err4;
  153     }
  154     CFRelease(url);
  155 
  156   //--- set the printer
  157 
  158   } else {
  159 
  160     if (PMServerCreatePrinterList(kPMServerLocal, &printerList)) {
  161       goto err4;
  162     }
  163     printer = NULL;
  164     printerName = new GString(prt->printerName().toUtf8().constData());
  165     for (i = 0; i < CFArrayGetCount(printerList); ++i) {
  166       printer = (PMPrinter)CFArrayGetValueAtIndex(printerList, i);
  167 #if QT_VERSION >= 0x050000
  168       s = PMPrinterGetID(printer);
  169 #else
  170       s = PMPrinterGetName(printer);
  171 #endif
  172       if (CFStringGetCString(s, prtName, sizeof(prtName),
  173                  kCFStringEncodingUTF8)) {
  174     if (!strcmp(prtName, printerName->getCString())) {
  175       break;
  176     }
  177       }
  178     }
  179     delete printerName;
  180     if (i >= CFArrayGetCount(printerList)) {
  181       CFRelease(printerList);
  182       PMRelease(printSettings);
  183       PMRelease(session);
  184       CFRelease(pdfDoc);
  185       return XpdfWidget::pdfErrBadPrinter;
  186     }
  187     if (PMSessionSetCurrentPMPrinter(session, printer)) {
  188       CFRelease(printerList);
  189       goto err4;
  190     }
  191     CFRelease(printerList);
  192   }
  193 
  194   //--- set color mode
  195 
  196 #if 0
  197   if (colorMode == QPrinter::GrayScale) {
  198     // this is deprecated, with no replacement
  199     PMSetColorMode(printSettings, kPMGray);
  200   }
  201 #endif
  202 
  203   //--- set paper size
  204 
  205   if (PMSessionGetCurrentPrinter(session, &printer)) {
  206     goto err4;
  207   }
  208   if (PMSessionCreatePageFormatList(session, printer, &pageFormatList)) {
  209     goto err4;
  210   }
  211   pageFormat = NULL;
  212   for (i = 0; i < CFArrayGetCount(pageFormatList); ++i) {
  213     pageFormat = (PMPageFormat)CFArrayGetValueAtIndex(pageFormatList, i);
  214     PMGetUnadjustedPaperRect(pageFormat, &paperRect);
  215     if (fabs((paperRect.right - paperRect.left) - paperSize.width()) < 2 &&
  216     fabs((paperRect.bottom - paperRect.top) - paperSize.height()) < 2) {
  217       PMRetain(pageFormat);
  218       break;
  219     }
  220     pageFormat = NULL;
  221   }
  222   CFRelease(pageFormatList);
  223   if (!pageFormat) {
  224     if (PMCreatePageFormat(&pageFormat)) {
  225       goto err4;
  226     }
  227     if (PMSessionDefaultPageFormat(session, pageFormat)) {
  228       goto err5;
  229     }
  230   }
  231 
  232   //--- set page orientation
  233 
  234   PMGetAdjustedPaperRect(pageFormat, &paperRect);
  235   if (pageOrientation == QPageLayout::Landscape) {
  236     PMSetOrientation(pageFormat, kPMLandscape, kPMUnlocked);
  237     paperRect2 = CGRectMake(paperRect.top,
  238                 paperRect.left,
  239                 paperRect.bottom - paperRect.top,
  240                 paperRect.right - paperRect.left);
  241   } else {
  242     PMSetOrientation(pageFormat, kPMPortrait, kPMUnlocked);
  243     paperRect2 = CGRectMake(paperRect.left,
  244                 paperRect.top,
  245                 paperRect.right - paperRect.left,
  246                 paperRect.bottom - paperRect.top);
  247   }
  248 
  249   //--- print
  250 
  251   if (PMSetPageRange(printSettings, startPage, endPage)) {
  252     goto err5;
  253   }
  254   if (PMSessionBeginCGDocumentNoDialog(session, printSettings, pageFormat)) {
  255     goto err5;
  256   }
  257   for (pg = startPage; pg <= endPage; ++pg) {
  258     widget->updatePrintStatus(pg, startPage, endPage);
  259     if (widget->isPrintCanceled()) {
  260       goto err6;
  261     }
  262     if (PMSessionBeginPageNoDialog(session, pageFormat, NULL)) {
  263       goto err6;
  264     }
  265     if (PMSessionGetCGGraphicsContext(session, &ctx)) {
  266       goto err6;
  267     }
  268     if (!(pdfPage = CGPDFDocumentGetPage(pdfDoc, pg))) {
  269       goto err6;
  270     }
  271     pageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox,
  272                          paperRect2, 0, true);
  273     CGContextSaveGState(ctx);
  274     CGContextConcatCTM(ctx, pageTransform);
  275     CGContextDrawPDFPage(ctx, pdfPage);
  276     CGContextRestoreGState(ctx);
  277     if (PMSessionEndPageNoDialog(session)) {
  278       goto err6;
  279     }
  280   }
  281   widget->updatePrintStatus(endPage + 1, startPage, endPage);
  282   PMSessionEndDocumentNoDialog(session);
  283   PMRelease(pageFormat);
  284   PMRelease(printSettings);
  285   PMRelease(session);
  286 
  287   CFRelease(pdfDoc);
  288   if (deletePDFFile) {
  289     unlink(pdfFileName->getCString());
  290   }
  291   delete pdfFileName;
  292 
  293   return XpdfWidget::pdfOk;
  294 
  295  err6:
  296   PMSessionEndDocumentNoDialog(session);
  297  err5:
  298   PMRelease(pageFormat);
  299  err4:
  300   PMRelease(printSettings);
  301  err3:
  302   PMRelease(session);
  303  err2:
  304   CFRelease(pdfDoc);
  305  err1:
  306   if (deletePDFFile) {
  307     unlink(pdfFileName->getCString());
  308   }
  309   delete pdfFileName;
  310  err0:
  311   return XpdfWidget::pdfErrPrinting;
  312 }
  313 
  314 //------------------------------------------------------------------------
  315 // Linux
  316 //------------------------------------------------------------------------
  317 
  318 #elif defined(__linux__)
  319 
  320 static void fileOut(void *stream, const char *data, int len) {
  321   fwrite(data, 1, len, (FILE *)stream);
  322 }
  323 
  324 XpdfWidget::ErrorCode printPDF(PDFDoc *doc, QPrinter *prt,
  325                    int hDPI, int vDPI,
  326                    XpdfWidget *widget) {
  327   int startPage, endPage;
  328   QPrinter::PaperSize paperSize;
  329   QSizeF paperSizePts;
  330   QPrinter::PaperSource paperSource;
  331   QPrinter::DuplexMode duplex;
  332   GString *psFileName;
  333   FILE *psFile;
  334   PSOutputDev *psOut;
  335   GString *printerName;
  336   cups_dest_t *dests, *dest;
  337   cups_option_t *options;
  338   const char *paperSizeStr, *paperSourceStr;
  339   GString *s;
  340   int nDests, nOptions;
  341   int pg;
  342 
  343   //--- get page range
  344 
  345   startPage = prt->fromPage();
  346   endPage = prt->toPage();
  347   if (startPage == 0) {
  348     startPage = 1;
  349   }
  350   if (endPage == 0) {
  351     endPage = doc->getNumPages();
  352   }
  353   if (startPage > endPage) {
  354     return XpdfWidget::pdfErrBadPageNum;
  355   }
  356 
  357   //--- get other parameters
  358 
  359   paperSize = prt->paperSize();
  360   paperSizePts = prt->paperSize(QPrinter::Point);
  361   paperSource = prt->paperSource();
  362   duplex = prt->duplex();
  363 
  364   //--- print to file
  365 
  366   if (!prt->outputFileName().isEmpty()) {
  367     psFileName = NULL;  // don't delete the PS file
  368     if (!(psFile = fopen(prt->outputFileName().toUtf8().constData(), "wb"))) {
  369       goto err0;
  370     }
  371 
  372   //--- open temporary PS file
  373 
  374   } else {
  375     if (!openTempFile(&psFileName, &psFile, "wb", ".ps")) {
  376       goto err0;
  377     }
  378   }
  379 
  380   //--- generate the PS file
  381 
  382   globalParams->setPSPaperWidth((int)(paperSizePts.width() + 0.5));
  383   globalParams->setPSPaperHeight((int)(paperSizePts.height() + 0.5));
  384 
  385   widget->updatePrintStatus(startPage, startPage, endPage);
  386   psOut = new PSOutputDev(fileOut, psFile, doc, startPage, endPage,
  387               psModePS);
  388   if (!psOut->isOk()) {
  389     delete psOut;
  390     goto err1;
  391   }
  392   for (pg = startPage; pg <= endPage; ++pg) {
  393     if (widget->isPrintCanceled()) {
  394       delete psOut;
  395       fclose(psFile);
  396       goto err1;
  397     }
  398     doc->displayPage(psOut, pg, 72, 72, 0,
  399              !globalParams->getPSUseCropBoxAsPage(),
  400              gTrue, gTrue);
  401     widget->updatePrintStatus(pg + 1, startPage, endPage);
  402   }
  403   delete psOut;
  404   fclose(psFile);
  405 
  406   //--- print the PS file
  407 
  408   if (psFileName) {
  409 
  410     if (!prt->printerName().isEmpty()) {
  411       printerName = new GString(prt->printerName().toLocal8Bit().constData());
  412     } else {
  413       nDests = cupsGetDests(&dests);
  414       if (!(dest = cupsGetDest(NULL, NULL, nDests, dests))) {
  415     unlink(psFileName->getCString());
  416     delete psFileName;
  417     cupsFreeDests(nDests, dests);
  418     return XpdfWidget::pdfErrBadPrinter;
  419       }
  420       printerName = new GString(dest->name);
  421       cupsFreeDests(nDests, dests);
  422     }
  423 
  424     options = NULL;
  425     nOptions = 0;
  426 
  427     switch (paperSize) {
  428     case QPrinter::A4:      paperSizeStr = "A4";     break;
  429     case QPrinter::Comm10E: paperSizeStr = "COM10";  break;
  430     case QPrinter::DLE:     paperSizeStr = "DL";     break;
  431     case QPrinter::Legal:   paperSizeStr = "Legal";  break;
  432     case QPrinter::Letter:  paperSizeStr = "Letter"; break;
  433     default:                paperSizeStr = NULL;     break;
  434     }
  435     switch (paperSource) {
  436     case QPrinter::LargeCapacity: paperSourceStr = "LargeCapacity"; break;
  437     case QPrinter::Lower:         paperSourceStr = "Lower";         break;
  438     default:                      paperSourceStr = NULL;            break;
  439     }
  440     if (paperSizeStr && paperSourceStr) {
  441       s = GString::format("{0:s},{1:s}", paperSizeStr, paperSourceStr);
  442       cupsAddOption("media", s->getCString(), nOptions, &options);
  443       delete s;
  444       ++nOptions;
  445     } else if (paperSizeStr) {
  446       cupsAddOption("media", paperSizeStr, nOptions, &options);
  447       ++nOptions;
  448     } else if (paperSourceStr) {
  449       cupsAddOption("media", paperSourceStr, nOptions, &options);
  450       ++nOptions;
  451     }
  452 
  453     switch (duplex) {
  454     case QPrinter::DuplexNone:
  455       cupsAddOption("sides", "one-sided", nOptions, &options);
  456       ++nOptions;
  457       break;
  458     case QPrinter::DuplexAuto:
  459       break;
  460     case QPrinter::DuplexLongSide:
  461       cupsAddOption("sides", "two-sided-long-edge", nOptions, &options);
  462       ++nOptions;
  463       break;
  464     case QPrinter::DuplexShortSide:
  465       cupsAddOption("sides", "two-sided-short-edge", nOptions, &options);
  466       ++nOptions;
  467       break;
  468     }
  469 
  470     if (!cupsPrintFile(printerName->getCString(),
  471                psFileName->getCString(),
  472                doc->getFileName() ? doc->getFileName()->getCString()
  473                                   : "Xpdf printing",
  474                nOptions, options)) {
  475       cupsFreeOptions(nOptions, options);
  476       delete printerName;
  477       goto err1;
  478     }
  479     cupsFreeOptions(nOptions, options);
  480 
  481     delete printerName;
  482 
  483     unlink(psFileName->getCString());
  484     delete psFileName;
  485   }
  486 
  487   return XpdfWidget::pdfOk;
  488 
  489  err1:
  490   if (psFileName) {
  491     unlink(psFileName->getCString());
  492     delete psFileName;
  493   }
  494  err0:
  495   return XpdfWidget::pdfErrPrinting;
  496 }
  497 
  498 #endif
  499 
  500 #endif // XPDFWIDGET_PRINTING