From f3c78da695c5ba12cf9e7471d3d52e922d514578 Mon Sep 17 00:00:00 2001 From: Jai Luthra Date: Tue, 25 Aug 2020 14:59:17 +0530 Subject: [PATCH] libcupsfilters, pdftopdf: Convert pdftopdf to a filter function. --- Makefile.am | 50 +- cupsfilters/filter.h | 7 + .../pdftopdf/intervalset.cc | 16 +- .../pdftopdf/intervalset.h | 3 +- {filter => cupsfilters}/pdftopdf/nup.cc | 37 +- {filter => cupsfilters}/pdftopdf/nup.h | 4 +- {filter => cupsfilters}/pdftopdf/pdftopdf.cc | 515 +++++------------- cupsfilters/pdftopdf/pdftopdf.h | 17 + .../pdftopdf/pdftopdf_jcl.cc | 0 .../pdftopdf/pdftopdf_jcl.h | 0 .../pdftopdf/pdftopdf_processor.cc | 140 +++-- .../pdftopdf/pdftopdf_processor.h | 21 +- {filter => cupsfilters}/pdftopdf/pptypes.cc | 40 +- {filter => cupsfilters}/pdftopdf/pptypes.h | 11 +- {filter => cupsfilters}/pdftopdf/qpdf_cm.cc | 0 {filter => cupsfilters}/pdftopdf/qpdf_cm.h | 0 .../pdftopdf/qpdf_pdftopdf.cc | 0 .../pdftopdf/qpdf_pdftopdf.h | 0 .../pdftopdf/qpdf_pdftopdf_processor.cc | 59 +- .../pdftopdf/qpdf_pdftopdf_processor.h | 17 +- .../pdftopdf/qpdf_tools.cc | 0 {filter => cupsfilters}/pdftopdf/qpdf_tools.h | 0 .../pdftopdf/qpdf_xobject.cc | 0 .../pdftopdf/qpdf_xobject.h | 0 filter/pdftopdf.c | 75 +++ 25 files changed, 460 insertions(+), 552 deletions(-) rename {filter => cupsfilters}/pdftopdf/intervalset.cc (76%) rename {filter => cupsfilters}/pdftopdf/intervalset.h (91%) rename {filter => cupsfilters}/pdftopdf/nup.cc (81%) rename {filter => cupsfilters}/pdftopdf/nup.h (96%) rename {filter => cupsfilters}/pdftopdf/pdftopdf.cc (67%) create mode 100644 cupsfilters/pdftopdf/pdftopdf.h rename {filter => cupsfilters}/pdftopdf/pdftopdf_jcl.cc (100%) rename {filter => cupsfilters}/pdftopdf/pdftopdf_jcl.h (100%) rename {filter => cupsfilters}/pdftopdf/pdftopdf_processor.cc (71%) rename {filter => cupsfilters}/pdftopdf/pdftopdf_processor.h (85%) rename {filter => cupsfilters}/pdftopdf/pptypes.cc (67%) rename {filter => cupsfilters}/pdftopdf/pptypes.h (78%) rename {filter => cupsfilters}/pdftopdf/qpdf_cm.cc (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_cm.h (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_pdftopdf.cc (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_pdftopdf.h (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_pdftopdf_processor.cc (91%) rename {filter => cupsfilters}/pdftopdf/qpdf_pdftopdf_processor.h (79%) rename {filter => cupsfilters}/pdftopdf/qpdf_tools.cc (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_tools.h (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_xobject.cc (100%) rename {filter => cupsfilters}/pdftopdf/qpdf_xobject.h (100%) create mode 100644 filter/pdftopdf.c diff --git a/Makefile.am b/Makefile.am index 251f16d01..fcd3ca0ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -301,6 +301,28 @@ libcupsfilters_la_SOURCES = \ cupsfilters/pack.c \ cupsfilters/pclmtoraster.cxx \ cupsfilters/pdf.cxx \ + cupsfilters/pdftopdf/pdftopdf.cc \ + cupsfilters/pdftopdf/pdftopdf.h \ + cupsfilters/pdftopdf/pdftopdf_jcl.cc \ + cupsfilters/pdftopdf/pdftopdf_jcl.h \ + cupsfilters/pdftopdf/pdftopdf_processor.cc \ + cupsfilters/pdftopdf/pdftopdf_processor.h \ + cupsfilters/pdftopdf/qpdf_pdftopdf_processor.cc \ + cupsfilters/pdftopdf/qpdf_pdftopdf_processor.h \ + cupsfilters/pdftopdf/pptypes.cc \ + cupsfilters/pdftopdf/pptypes.h \ + cupsfilters/pdftopdf/nup.cc \ + cupsfilters/pdftopdf/nup.h \ + cupsfilters/pdftopdf/intervalset.cc \ + cupsfilters/pdftopdf/intervalset.h \ + cupsfilters/pdftopdf/qpdf_tools.cc \ + cupsfilters/pdftopdf/qpdf_tools.h \ + cupsfilters/pdftopdf/qpdf_xobject.cc \ + cupsfilters/pdftopdf/qpdf_xobject.h \ + cupsfilters/pdftopdf/qpdf_pdftopdf.cc \ + cupsfilters/pdftopdf/qpdf_pdftopdf.h \ + cupsfilters/pdftopdf/qpdf_cm.cc \ + cupsfilters/pdftopdf/qpdf_cm.h \ cupsfilters/pdftoippprinter.c \ cupsfilters/pdftops.c \ cupsfilters/ppdgenerator.c \ @@ -338,6 +360,7 @@ libcupsfilters_la_LDFLAGS = \ -version-info 1 if BUILD_DBUS libcupsfilters_la_CFLAGS += $(DBUS_CFLAGS) -DHAVE_DBUS +libcupsfilters_CXXFLAGS = -std=c++0x $(libcupsfilters_CFLAGS) # -std=c++11 libcupsfilters_la_LIBADD += $(DBUS_LIBS) endif libcupsfilters_la_DEPENDENCIES = \ @@ -615,35 +638,14 @@ pkgfilterdir = $(CUPS_SERVERBIN)/filter pkgfilter_PROGRAMS += pdftopdf pdftopdf_SOURCES = \ - filter/pdftopdf/pdftopdf.cc \ - filter/pdftopdf/pdftopdf_jcl.cc \ - filter/pdftopdf/pdftopdf_jcl.h \ - filter/pdftopdf/pdftopdf_processor.cc \ - filter/pdftopdf/pdftopdf_processor.h \ - filter/pdftopdf/qpdf_pdftopdf_processor.cc \ - filter/pdftopdf/qpdf_pdftopdf_processor.h \ - filter/pdftopdf/pptypes.cc \ - filter/pdftopdf/pptypes.h \ - filter/pdftopdf/nup.cc \ - filter/pdftopdf/nup.h \ - filter/pdftopdf/intervalset.cc \ - filter/pdftopdf/intervalset.h \ - filter/pdftopdf/qpdf_tools.cc \ - filter/pdftopdf/qpdf_tools.h \ - filter/pdftopdf/qpdf_xobject.cc \ - filter/pdftopdf/qpdf_xobject.h \ - filter/pdftopdf/qpdf_pdftopdf.cc \ - filter/pdftopdf/qpdf_pdftopdf.h \ - filter/pdftopdf/qpdf_cm.cc \ - filter/pdftopdf/qpdf_cm.h + filter/pdftopdf.c pdftopdf_CFLAGS = \ -I$(srcdir)/ppd/ \ - $(LIBQPDF_CFLAGS) \ + -I$(srcdir)/cupsfilters/ \ $(CUPS_CFLAGS) -pdftopdf_CXXFLAGS = -std=c++0x $(pdftopdf_CFLAGS) # -std=c++11 pdftopdf_LDADD = \ libppd.la \ - $(LIBQPDF_LIBS) \ + libcupsfilters.la \ $(CUPS_LIBS) # ====================== diff --git a/cupsfilters/filter.h b/cupsfilters/filter.h index 0f63c1f2a..36bda22db 100644 --- a/cupsfilters/filter.h +++ b/cupsfilters/filter.h @@ -101,6 +101,13 @@ extern int pclmtoraster(int inputfd, filter_data_t *data, void *parameters); +extern int pdftopdf(int inputfd, + int outputfd, + int inputseekable, + int *jobcanceled, + filter_data_t *data, + void *parameters); + extern int pdftops(int inputfd, int outputfd, int inputseekable, diff --git a/filter/pdftopdf/intervalset.cc b/cupsfilters/pdftopdf/intervalset.cc similarity index 76% rename from filter/pdftopdf/intervalset.cc rename to cupsfilters/pdftopdf/intervalset.cc index 2967d597a..a624a2f44 100644 --- a/filter/pdftopdf/intervalset.cc +++ b/cupsfilters/pdftopdf/intervalset.cc @@ -101,21 +101,27 @@ void IntervalSet::unite(value_t &aret,const value_t &b) const // {{{ } // }}} -void IntervalSet::dump() const // {{{ +void IntervalSet::dump(pdftopdf_doc_t *doc) const // {{{ { int len=data.size(); if (len==0) { - fprintf(stderr,"(empty)\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: (empty)\n"); return; } len--; + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: "); for (int iA=0;iAlogfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "[%d,%d),",data[iA].first,data[iA].second); } if (data[len].second==npos) { - fprintf(stderr,"[%d,inf)\n",data[len].first); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "[%d,inf)\n",data[len].first); } else { - fprintf(stderr,"[%d,%d)\n",data[len].first,data[len].second); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "[%d,%d)\n",data[len].first,data[len].second); } } // }}} diff --git a/filter/pdftopdf/intervalset.h b/cupsfilters/pdftopdf/intervalset.h similarity index 91% rename from filter/pdftopdf/intervalset.h rename to cupsfilters/pdftopdf/intervalset.h index 67b486fff..885b807de 100644 --- a/filter/pdftopdf/intervalset.h +++ b/cupsfilters/pdftopdf/intervalset.h @@ -1,6 +1,7 @@ #ifndef INTERVALSET_H_ #define INTERVALSET_H_ +#include "pdftopdf.h" #include #include @@ -22,7 +23,7 @@ class IntervalSet { bool contains(key_t val) const; key_t next(key_t val) const; - void dump() const; + void dump(pdftopdf_doc_t *doc) const; private: // currently not used bool intersect(const value_t &a,const value_t &b) const; diff --git a/filter/pdftopdf/nup.cc b/cupsfilters/pdftopdf/nup.cc similarity index 81% rename from filter/pdftopdf/nup.cc rename to cupsfilters/pdftopdf/nup.cc index 8be9b86c1..6375576c3 100644 --- a/filter/pdftopdf/nup.cc +++ b/cupsfilters/pdftopdf/nup.cc @@ -4,9 +4,10 @@ #include #include -void NupParameters::dump() const // {{{ +void NupParameters::dump(pdftopdf_doc_t *doc) const // {{{ { - fprintf(stderr,"NupX: %d, NupY: %d\n" + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: NupX: %d, NupY: %d\n" "width: %f, height: %f\n", nupX,nupY, width,height); @@ -23,28 +24,35 @@ void NupParameters::dump() const // {{{ spos=1; } if (first==Axis::X) { - fprintf(stderr,"First Axis: X\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: First Axis: X\n"); opos=0; } else if (first==Axis::Y) { - fprintf(stderr,"First Axis: Y\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: First Axis: Y\n"); opos=2; std::swap(fpos,spos); } if ( (opos==-1)||(fpos==-1)||(spos==-1) ) { - fprintf(stderr,"Bad Spec: %d; start: %d, %d\n\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Bad Spec: %d; start: %d, %d\n\n", first,xstart,ystart); } else { static const char *order[4]={"lr","rl","bt","tb"}; - fprintf(stderr,"Order: %s%s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Order: %s%s\n", order[opos+fpos],order[(opos+2)%4+spos]); } - fputs("Alignment: ",stderr); - Position_dump(xalign,Axis::X); - fputs("/",stderr); - Position_dump(yalign,Axis::Y); - fputs("\n",stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Alignment: "); + Position_dump(xalign,Axis::X,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "/"); + Position_dump(yalign,Axis::Y,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "\n"); } // }}} @@ -133,11 +141,12 @@ void NupState::reset() // {{{ } // }}} -void NupPageEdit::dump() const // {{{ +void NupPageEdit::dump(pdftopdf_doc_t *doc) const // {{{ { - fprintf(stderr,"xpos: %f, ypos: %f, scale: %f\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: xpos: %f, ypos: %f, scale: %f\n", xpos,ypos,scale); - sub.dump(); + sub.dump(doc); } // }}} diff --git a/filter/pdftopdf/nup.h b/cupsfilters/pdftopdf/nup.h similarity index 96% rename from filter/pdftopdf/nup.h rename to cupsfilters/pdftopdf/nup.h index 0523cc782..3fa443cca 100644 --- a/filter/pdftopdf/nup.h +++ b/cupsfilters/pdftopdf/nup.h @@ -31,7 +31,7 @@ struct NupParameters { static void preset(int nup,NupParameters &ret); static float calculate(int nup, float in_ratio, float out_ratio,NupParameters &ret); // returns "quality", 1 is best - void dump() const; + void dump(pdftopdf_doc_t *doc) const; }; // you get this @@ -47,7 +47,7 @@ struct NupPageEdit { // everything in "outer"-page coordinates PageRect sub; - void dump() const; + void dump(pdftopdf_doc_t *doc) const; }; /* diff --git a/filter/pdftopdf/pdftopdf.cc b/cupsfilters/pdftopdf/pdftopdf.cc similarity index 67% rename from filter/pdftopdf/pdftopdf.cc rename to cupsfilters/pdftopdf/pdftopdf.cc index ad59b6d61..1fae430d8 100644 --- a/filter/pdftopdf/pdftopdf.cc +++ b/cupsfilters/pdftopdf/pdftopdf.cc @@ -21,23 +21,13 @@ #include #include #include +#include "pdftopdf.h" #include "pdftopdf_processor.h" #include "pdftopdf_jcl.h" #include -static void error(const char *fmt,...) // {{{ -{ - va_list ap; - va_start(ap,fmt); - fputs("ERROR: ",stderr); - vfprintf(stderr,fmt,ap); - fputs("\n",stderr); - - va_end(ap); -} -// }}} // namespace {} @@ -149,7 +139,7 @@ static bool ppdGetDuplex(ppd_file_t *ppd) // {{{ // }}} // TODO: enum -static bool ppdDefaultOrder(ppd_file_t *ppd) // {{{ -- is reverse? +static bool ppdDefaultOrder(ppd_file_t *ppd, pdftopdf_doc_t *doc) // {{{ -- is reverse? { ppd_choice_t *choice; ppd_attr_t *attr; @@ -169,7 +159,9 @@ static bool ppdDefaultOrder(ppd_file_t *ppd) // {{{ -- is reverse? } else if (strcasecmp(val,"Reverse")==0||(strcasecmp(val,"reverse-order")==0)) { return true; } - error("Unsupported output-order value %s, using 'normal'!",val); + + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported output-order value %s, using 'normal'!",val); return false; } // }}} @@ -301,7 +293,7 @@ static bool parseBorder(const char *val,BorderType &ret) // {{{ } // }}} -void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,ProcessingParameters ¶m) // {{{ +void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,ProcessingParameters ¶m,char *final_content_type,pdftopdf_doc_t *doc) // {{{ { const char *val; @@ -376,7 +368,8 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces * 3: 0 degrees, 4: 90 degrees, 5: -90 degrees, 6: 180 degrees */ if ((ipprot<3)||(ipprot>6)) { - error("Bad value (%d) for orientation-requested, using 0 degrees",ipprot); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Bad value (%d) for orientation-requested, using 0 degrees",ipprot); } else { static const Rotation ipp2rot[4]={ROT_0, ROT_90, ROT_270, ROT_180}; param.orientation=ipp2rot[ipprot-3]; @@ -402,7 +395,7 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces (val = cupsGetOption("page-size", num_options, options)) != NULL || (val = cupsGetOption("PageSize", num_options, options)) != NULL) { pwg_media_t *size_found = NULL; - fprintf(stderr, "DEBUG: Page size from command line: %s\n", val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, "pdftopdf: Page size from command line: %s\n", val); if ((size_found = pwgMediaForPWG(val)) == NULL) if ((size_found = pwgMediaForPPD(val)) == NULL) size_found = pwgMediaForLegacy(val); @@ -413,10 +406,10 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces param.page.right=param.page.left=18.0; param.page.right=param.page.width-param.page.right; param.page.top=param.page.height-param.page.top; - fprintf(stderr, "DEBUG: Width: %f, Length: %f\n", param.page.width, param.page.height); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, "pdftopdf: Width: %f, Length: %f\n", param.page.width, param.page.height); } else - fprintf(stderr, "DEBUG: Unsupported page size %s.\n", val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, "pdftopdf: Unsupported page size %s.\n", val); } } #endif /* HAVE_CUPS_1_7 */ @@ -467,7 +460,8 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces param.duplex=true; param.setDuplex=true; } else if (strcasecmp(val,"one-sided")!=0) { - error("Unsupported sides value %s, using sides=one-sided!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported sides value %s, using sides=one-sided!",val); } } @@ -475,7 +469,8 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces int nup=1; if (optGetInt("number-up",num_options,options,&nup)) { if (!NupParameters::possible(nup)) { - error("Unsupported number-up value %d, using number-up=1!",nup); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported number-up value %d, using number-up=1!",nup); nup=1; } // TODO ; TODO? nup enabled? ... fitplot @@ -485,7 +480,8 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces if ((val=cupsGetOption("number-up-layout",num_options,options)) != NULL) { if (!parseNupLayout(val,param.nup)) { - error("Unsupported number-up-layout %s, using number-up-layout=lrtb!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported number-up-layout %s, using number-up-layout=lrtb!",val); param.nup.first=Axis::X; param.nup.xstart=Position::LEFT; param.nup.ystart=Position::TOP; @@ -494,7 +490,8 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces if ((val=cupsGetOption("page-border",num_options,options)) != NULL) { if (!parseBorder(val,param.border)) { - error("Unsupported page-border value %s, using page-border=none!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported page-border value %s, using page-border=none!",val); param.border=BorderType::NONE; } } @@ -505,7 +502,7 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces param.reverse = (strcasecmp(val, "Reverse") == 0 || strcasecmp(val, "reverse-order") == 0); } else if (ppd) { - param.reverse=ppdDefaultOrder(ppd); + param.reverse=ppdDefaultOrder(ppd, doc); } std::string rawlabel; @@ -536,7 +533,8 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces } else if (strcasecmp(val,"odd")==0) { param.evenPages=false; } else if (strcasecmp(val,"all")!=0) { - error("Unsupported page-set value %s, using page-set=all!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported page-set value %s, using page-set=all!",val); } } @@ -563,20 +561,23 @@ void getParameters(ppd_file_t *ppd,int num_options,cups_option_t *options,Proces } else if (is_true(val)) { param.booklet=BookletMode::BOOKLET_ON; } else if (!is_false(val)) { - error("Unsupported booklet value %s, using booklet=off!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported booklet value %s, using booklet=off!",val); } } param.bookSignature=-1; if (optGetInt("booklet-signature",num_options,options,¶m.bookSignature)) { if (param.bookSignature==0) { - error("Unsupported booklet-signature value, using booklet-signature=-1 (all)!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported booklet-signature value, using booklet-signature=-1 (all)!",val); param.bookSignature=-1; } } if ((val=cupsGetOption("position",num_options,options)) != NULL) { if (!parsePosition(val,param.xpos,param.ypos)) { - error("Unrecognized position value %s, using position=center!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unrecognized position value %s, using position=center!",val); param.xpos=Position::CENTER; param.ypos=Position::CENTER; } @@ -652,18 +653,19 @@ bool checkFeature(const char *feature, int num_options, cups_option_t *options) if ((val=cupsGetOption("page-logging",num_options,options)) != NULL) { if (strcasecmp(val,"auto") == 0) { param.page_logging = -1; - fprintf(stderr, - "DEBUG: pdftopdf: Automatic page logging selected by command line.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Automatic page logging selected by command line.\n"); } else if (is_true(val)) { param.page_logging = 1; - fprintf(stderr, - "DEBUG: pdftopdf: Forced page logging selected by command line.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Forced page logging selected by command line.\n"); } else if (is_false(val)) { param.page_logging = 0; - fprintf(stderr, - "DEBUG: pdftopdf: Suppressed page logging selected by command line.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Suppressed page logging selected by command line.\n"); } else { - error("Unsupported page-logging value %s, using page-logging=auto!",val); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unsupported page-logging value %s, using page-logging=auto!",val); param.page_logging = -1; } } @@ -674,17 +676,16 @@ bool checkFeature(const char *feature, int num_options, cups_option_t *options) if (!ppd) { // If there is no PPD do not log when not requested by command line param.page_logging = 0; - fprintf(stderr, - "DEBUG: pdftopdf: No PPD file specified, could not determine whether to log pages or not, so turned off page logging.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: No PPD file specified, could not determine whether to log pages or not, so turned off page logging.\n"); } else { - char *final_content_type = getenv("FINAL_CONTENT_TYPE"); char *lastfilter = NULL; if (final_content_type == NULL) { // No FINAL_CONTENT_TYPE env variable set, we cannot determine // whether we have to log pages, so do not log. param.page_logging = 0; - fprintf(stderr, - "DEBUG: pdftopdf: No FINAL_CONTENT_TYPE environment variable, could not determine whether to log pages or not, so turned off page logging.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: No FINAL_CONTENT_TYPE environment variable, could not determine whether to log pages or not, so turned off page logging.\n"); // Proceed depending on number of cupsFilter(2) lines in PPD } else if (ppd->num_filters == 0) { // No filter line, manufacturer-supplied PostScript PPD @@ -775,12 +776,13 @@ bool checkFeature(const char *feature, int num_options, cups_option_t *options) param.page_logging = 0; } } else { - error("pdftopdf: Last filter could not get determined, page logging turned off."); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Last filter could not get determined, page logging turned off."); param.page_logging = 0; } } - fprintf(stderr, - "DEBUG: pdftopdf: Last filter determined by the PPD: %s; FINAL_CONTENT_TYPE: %s => pdftopdf will %slog pages in page_log.\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Last filter determined by the PPD: %s; FINAL_CONTENT_TYPE: %s => pdftopdf will %slog pages in page_log.\n", (lastfilter ? lastfilter : "None"), final_content_type, (param.page_logging == 0 ? "not " : "")); } @@ -803,7 +805,7 @@ static bool printerWillCollate(ppd_file_t *ppd) // {{{ } // }}} -void calculate(ppd_file_t *ppd,ProcessingParameters ¶m) // {{{ +void calculate(ppd_file_t *ppd,ProcessingParameters ¶m,char *final_content_type) // {{{ { if (param.reverse) // Enable evenDuplex or the first page may be empty. @@ -822,7 +824,6 @@ void calculate(ppd_file_t *ppd,ProcessingParameters ¶m) // {{{ // of a driverless IPP printer (PDF, Apple Raster, PWG Raster, PCLm). // These printers do always hardware collate if they do hardware copies. // https://github.com/apple/cups/issues/5433 - char *final_content_type = getenv("FINAL_CONTENT_TYPE"); if (final_content_type && (strcasestr(final_content_type, "/pdf") || strcasestr(final_content_type, "/vnd.cups-pdf") || @@ -869,7 +870,7 @@ void calculate(ppd_file_t *ppd,ProcessingParameters ¶m) // {{{ // }}} // reads from stdin into temporary file. returns FILE * or NULL on error -FILE *copy_stdin_to_temp() // {{{ +FILE *copy_stdin_to_temp(pdftopdf_doc_t *doc) // {{{ { char buf[BUFSIZ]; int n; @@ -877,7 +878,8 @@ FILE *copy_stdin_to_temp() // {{{ // FIXME: what does >buf mean here? int fd=cupsTempFd(buf,sizeof(buf)); if (fd<0) { - error("Can't create temporary file"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Can't create temporary file"); return NULL; } // remove name @@ -886,20 +888,23 @@ FILE *copy_stdin_to_temp() // {{{ // copy stdin to the tmp file while ((n=read(0,buf,BUFSIZ)) > 0) { if (write(fd,buf,n) != n) { - error("Can't copy stdin to temporary file"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Can't copy stdin to temporary file"); close(fd); return NULL; } } if (lseek(fd,0,SEEK_SET) < 0) { - error("Can't rewind temporary file"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Can't rewind temporary file"); close(fd); return NULL; } FILE *f; if ((f=fdopen(fd,"rb")) == 0) { - error("Can't fdopen temporary file"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Can't fdopen temporary file"); close(fd); return NULL; } @@ -922,369 +927,106 @@ bool is_empty(FILE *f) // {{{ } // }}} -static int -sub_process_spawn (const char *filename, - cups_array_t *sub_process_args, - FILE *fp) // {{{ -{ - char *argument; - char buf[BUFSIZ]; - char **sub_process_argv; - const char* apos; - int fds[2]; - int i; - int n; - int numargs; - int pid; - int status = 65536; - int wstatus; - - /* Put sub-process command line argument into an array for the "exec()" - call */ - numargs = cupsArrayCount(sub_process_args); - sub_process_argv = (char **)calloc(numargs + 1, sizeof(char *)); - for (argument = (char *)cupsArrayFirst(sub_process_args), i = 0; argument; - argument = (char *)cupsArrayNext(sub_process_args), i++) { - sub_process_argv[i] = argument; - } - sub_process_argv[i] = NULL; - - /* Debug output: Full sub-process command line */ - fprintf(stderr, "DEBUG: PDF form flattening command line:"); - for (i = 0; sub_process_argv[i]; i ++) { - if ((strchr(sub_process_argv[i],' ')) || (strchr(sub_process_argv[i],'\t'))) - apos = "'"; - else - apos = ""; - fprintf(stderr, " %s%s%s", apos, sub_process_argv[i], apos); - } - fprintf(stderr, "\n"); - - /* Create a pipe for feeding the job into sub-process */ - if (pipe(fds)) - { - fds[0] = -1; - fds[1] = -1; - fprintf(stderr, "ERROR: Unable to establish pipe for sub-process call\n"); - goto out; - } - - /* Set the "close on exec" flag on each end of the pipe... */ - if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC)) - { - close(fds[0]); - close(fds[1]); - fds[0] = -1; - fds[1] = -1; - fprintf(stderr, "ERROR: Unable to set \"close on exec\" flag on read end of the pipe for sub-process call\n"); - goto out; - } - if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC)) - { - close(fds[0]); - close(fds[1]); - fprintf(stderr, "ERROR: Unable to set \"close on exec\" flag on write end of the pipe for sub-process call\n"); - goto out; - } - - if ((pid = fork()) == 0) - { - /* Couple pipe with STDIN of sub-process */ - if (fds[0] != 0) { - close(0); - if (fds[0] > 0) { - if (dup(fds[0]) < 0) { - fprintf(stderr, "ERROR: Unable to couple pipe with STDIN of sub-process\n"); - goto out; - } - } else { - fprintf(stderr, "ERROR: Unable to couple pipe with STDIN of sub-process\n"); - goto out; - } - } - close(fds[1]); - - /* Execute sub-process command line ... */ - execvp(filename, sub_process_argv); - perror(filename); - close(fds[0]); - goto out; - } - close(fds[0]); - /* Feed job data into the sub-process */ - while ((n = fread(buf, 1, BUFSIZ, fp)) > 0) { - int count; -retry_write: - count = write(fds[1], buf, n); - if (count != n) { - if (count == -1) { - if (errno == EINTR) { - goto retry_write; - } - fprintf(stderr, "ERROR: write failed: %s\n", strerror(errno)); - } - fprintf(stderr, "ERROR: Can't feed job data into the sub-process\n"); - goto out; - } - } - close (fds[1]); - -retry_wait: - if (waitpid (pid, &wstatus, 0) == -1) { - if (errno == EINTR) - goto retry_wait; - perror ("sub-process"); - goto out; - } +int /* O - Error status */ +pdftopdf(int inputfd, /* I - File descriptor input stream */ + int outputfd, /* I - File descriptor output stream */ + int inputseekable, /* I - Is input stream seekable? (unused) */ + int *jobcanceled, /* I - Pointer to integer marking + whether job is canceled */ + filter_data_t *data, /* I - Job and printer data */ + void *parameters) /* I - Filter-specific parameters (unused) */ +{ + pdftopdf_doc_t doc; /* Document information */ + filter_logfunc_t log = data->logfunc; + void *ld = data->logdata; + char *final_content_type = NULL; - /* How did the sub-process terminate */ - if (WIFEXITED(wstatus)) - /* Via exit() anywhere or return() in the main() function */ - status = WEXITSTATUS(wstatus); - else if (WIFSIGNALED(wstatus)) - /* Via signal */ - status = 256 * WTERMSIG(wstatus); - -out: - free(sub_process_argv); - return status; -} -// }}} + (void)inputseekable; -int main(int argc,char **argv) -{ - if ((argc<6)||(argc>7)) { - fprintf(stderr,"Usage: %s job-id user title copies options [file]\n",argv[0]); -#ifdef DEBUG - ProcessingParameters param; - std::unique_ptr proc1(PDFTOPDF_Factory::processor()); - param.page.width=595.276; // A4 - param.page.height=841.89; - - param.page.top=param.page.bottom=36.0; - param.page.right=param.page.left=18.0; - param.page.right=param.page.width-param.page.right; - param.page.top=param.page.height-param.page.top; - - //param.nup.calculate(4,0.707,0.707,param.nup); - param.nup.nupX=2; - param.nup.nupY=2; - //param.nup.yalign=TOP; - param.border=BorderType::NONE; - //param.fillprint = true; - //param.mirror=true; - //param.reverse=true; - //param.numCopies=3; - if (!proc1->loadFilename("in.pdf",1)) return 2; - param.dump(); - if (!processPDFTOPDF(*proc1,param)) return 3; - emitComment(*proc1,param); - proc1->emitFilename("out.pdf"); -#endif - return 1; - } + if (parameters) + final_content_type = (char *)parameters; try { ProcessingParameters param; - param.jobId=atoi(argv[1]); - param.user=argv[2]; - param.title=argv[3]; - param.numCopies=atoi(argv[4]); - param.copies_to_be_logged=atoi(argv[4]); + param.jobId=data->job_id; + param.user=data->job_user; + param.title=data->job_title; + param.numCopies=data->copies; + param.copies_to_be_logged=data->copies; // TODO?! sanity checks - int num_options=0; - cups_option_t *options=NULL; - num_options=cupsParseOptions(argv[5],num_options,&options); + doc.JobCanceled = jobcanceled; + doc.logdata = ld; + doc.logfunc = log; - ppd_file_t *ppd=NULL; - ppd=ppdOpenFile(getenv("PPD")); // getenv (and thus ppd) may be null. This will not cause problems. - ppdMarkDefaults(ppd); + if (data->ppdfile == NULL && data->ppd == NULL) + { + char *p = getenv("PPD"); + + if (p) + data->ppdfile = strdup(p); + } + + if (data->ppdfile) + data->ppd = ppdOpenFile(data->ppdfile); + + ppdMarkDefaults(data->ppd); - ppdMarkOptions(ppd,num_options,options); + ppdMarkOptions(data->ppd,data->num_options,data->options); - getParameters(ppd,num_options,options,param); - calculate(ppd,param); + getParameters(data->ppd,data->num_options,data->options,param,final_content_type,&doc); + calculate(data->ppd,param,final_content_type); #ifdef DEBUG - param.dump(); + param.dump(&doc); #endif - /* Check with which method we will flatten interactive PDF forms - and annotations so that they get printed also after page - manipulations (scaling, N-up, ...). Flattening means to - integrate the filled in data and the printable annotations into - the pages themselves instead of holding them in an extra - layer. Default method is using QPDF, alternatives are the - external utilities pdftocairo or Ghostscript, but these make - the processing slower, especially due to extra piping of the - data between processes. */ int empty = 0; - int qpdf_flatten = 1; - int pdftocairo_flatten = 0; - int gs_flatten = 0; - int external_auto_flatten = 0; - const char *val; - if ((val = cupsGetOption("pdftopdf-form-flattening", num_options, options)) != NULL) { - if (strcasecmp(val, "qpdf") == 0 || strcasecmp(val, "internal") == 0 || - strcasecmp(val, "auto") == 0) { - qpdf_flatten = 1; - } else if (strcasecmp(val, "external") == 0) { - qpdf_flatten = 0; - external_auto_flatten = 1; - } else if (strcasecmp(val, "pdftocairo") == 0) { - qpdf_flatten = 0; - pdftocairo_flatten = 1; - } else if (strcasecmp(val, "ghostscript") == 0 || strcasecmp(val, "gs") == 0) { - qpdf_flatten = 0; - gs_flatten = 1; - } else - fprintf(stderr, - "WARNING: Invalid value for \"pdftopdf-form-flattening\": \"%s\"\n", val); - } - - cupsFreeOptions(num_options,options); std::unique_ptr proc(PDFTOPDF_Factory::processor()); FILE *tmpfile = NULL; - if (argc==7) { + + if (inputfd == 0) + { + tmpfile = copy_stdin_to_temp(&doc); + if (tmpfile && is_empty(tmpfile)) { + fclose(tmpfile); + // ppdClose(ppd); + empty = 1; + } else if ((!tmpfile)|| + (!proc->loadFile(tmpfile, &doc, WillStayAlive, 1))) + { + // ppdClose(ppd); + return 1; + } + } + else + { FILE *f = NULL; - if ((f = fopen(argv[6], "rb")) == NULL) { - ppdClose(ppd); + if ((f = fdopen(inputfd, "rb")) == NULL) { + // ppdClose(ppd); return 1; } else if (is_empty(f)) { fclose(f); - ppdClose(ppd); + // ppdClose(ppd); empty = 1; - } else if (!proc->loadFilename(argv[6],qpdf_flatten)) { + } else if (!proc->loadFile(f, &doc, WillStayAlive, 1)) { fclose(f); - ppdClose(ppd); + // ppdClose(ppd); return 1; - } else - fclose(f); - } else { - tmpfile = copy_stdin_to_temp(); - if (tmpfile && is_empty(tmpfile)) { - fclose(tmpfile); - ppdClose(ppd); - empty = 1; - } else if ((!tmpfile)|| - (!proc->loadFile(tmpfile,WillStayAlive,qpdf_flatten))) { - ppdClose(ppd); - return 1; } } if(empty) { - fprintf(stderr, "DEBUG: Input is empty, outputting empty file.\n"); + if (log) log(ld, FILTER_LOGLEVEL_DEBUG, "pdftopdf: Input is empty, outputting empty file.\n"); return 0; } - /* If the input file contains a PDF form and we opted for not - using QPDF for flattening the form, we pipe the PDF through - pdftocairo or Ghostscript here */ - if (!qpdf_flatten && proc->hasAcroForm()) { - /* Prepare the input file for being read by the form flattening - process */ - FILE *infile = NULL; - if (argc == 7) { - /* We read from a named file */ - infile = fopen(argv[6], "r"); - } else { - /* We read from a temporary file */ - if (tmpfile) rewind(tmpfile); - infile = tmpfile; - } - if (infile == NULL) { - error("Could not open the input file for flattening the PDF form!"); - return 1; - } - /* Create a temporary file for the output of the flattened PDF */ - char buf[BUFSIZ]; - int fd = cupsTempFd(buf,sizeof(buf)); - if (fd<0) { - error("Can't create temporary file for flattened PDF form!"); - return 1; - } - FILE *outfile = NULL; - if ((outfile=fdopen(fd,"rb")) == 0) { - error("Can't fdopen temporary file for the flattened PDF form!"); - close(fd); - return 1; - } - int flattening_done = 0; - const char *command; - cups_array_t *args; - /* Choose the utility to be used and create its command line */ - if (pdftocairo_flatten || external_auto_flatten) { - /* Try pdftocairo first, the preferred utility for form-flattening */ - command = CUPS_POPPLER_PDFTOCAIRO; - args = cupsArrayNew(NULL, NULL); - cupsArrayAdd(args, strdup(command)); - cupsArrayAdd(args, strdup("-pdf")); - cupsArrayAdd(args, strdup("-")); - cupsArrayAdd(args, strdup(buf)); - /* Run the pdftocairo form flattening process */ - rewind(infile); - int status = sub_process_spawn (command, args, infile); - cupsArrayDelete(args); - if (status == 0) - flattening_done = 1; - else - error("Unable to execute pdftocairo for form flattening!"); - } - if (flattening_done == 0 && - (gs_flatten || external_auto_flatten)) { - /* Try Ghostscript */ - command = CUPS_GHOSTSCRIPT; - args = cupsArrayNew(NULL, NULL); - cupsArrayAdd(args, strdup(command)); - cupsArrayAdd(args, strdup("-dQUIET")); - cupsArrayAdd(args, strdup("-dSAFER")); - cupsArrayAdd(args, strdup("-dNOPAUSE")); - cupsArrayAdd(args, strdup("-dBATCH")); - cupsArrayAdd(args, strdup("-dNOINTERPOLATE")); - cupsArrayAdd(args, strdup("-dNOMEDIAATTRS")); - cupsArrayAdd(args, strdup("-sDEVICE=pdfwrite")); - cupsArrayAdd(args, strdup("-dShowAcroForm")); - cupsArrayAdd(args, strdup("-sstdout=%stderr")); - memmove(buf + 13, buf, sizeof(buf) - 13); - memcpy(buf, "-sOutputFile=", 13); - cupsArrayAdd(args, strdup(buf)); - cupsArrayAdd(args, strdup("-")); - /* Run the Ghostscript form flattening process */ - rewind(infile); - int status = sub_process_spawn (command, args, infile); - cupsArrayDelete(args); - if (status == 0) - flattening_done = 1; - else - error("Unable to execute Ghostscript for form flattening!"); - } - if (flattening_done == 0) { - error("No suitable utility for flattening filled PDF forms available, no flattening performed. Filled in content will possibly not be printed."); - rewind(infile); - } - /* Clean up */ - if (infile != tmpfile) - fclose(infile); - /* Load the flattened PDF file into our PDF processor */ - if (flattening_done) { - rewind(outfile); - unlink(buf); - if (!proc->loadFile(outfile,TakeOwnership,0)) { - error("Unable to create a PDF processor on the flattened form!"); - return 1; - } - } - } else if (qpdf_flatten) - fprintf(stderr, "DEBUG: PDF interactive form and annotation flattening done via QPDF\n"); - /* TODO // color management --- PPD: @@ -1298,27 +1040,32 @@ int main(int argc,char **argv) } */ - if (!processPDFTOPDF(*proc,param)) { - ppdClose(ppd); + if (!processPDFTOPDF(*proc,param,&doc)) { + // ppdClose(ppd); return 2; } - emitPreamble(ppd,param); // ppdEmit, JCL stuff + emitPreamble(data->ppd,param); // ppdEmit, JCL stuff emitComment(*proc,param); // pass information to subsequent filters via PDF comments - //proc->emitFile(stdout); - proc->emitFilename(NULL); + FILE *outputfp; + outputfp = fdopen(outputfd, "w"); + if(outputfp == NULL) return 1; + proc->emitFile(outputfp, &doc, TakeOwnership); + // proc->emitFilename(NULL); - emitPostamble(ppd,param); - ppdClose(ppd); + emitPostamble(data->ppd,param); + // ppdClose(ppd); if (tmpfile) fclose(tmpfile); } catch (std::exception &e) { // TODO? exception type - error("Exception: %s",e.what()); + if (log) log(ld, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Exception: %s",e.what()); return 5; } catch (...) { - error("Unknown exception caught. Exiting."); + if (log) log(ld, FILTER_LOGLEVEL_ERROR, + "pdftopdf: Unknown exception caught. Exiting."); return 6; } diff --git a/cupsfilters/pdftopdf/pdftopdf.h b/cupsfilters/pdftopdf/pdftopdf.h new file mode 100644 index 000000000..b61d04cc2 --- /dev/null +++ b/cupsfilters/pdftopdf/pdftopdf.h @@ -0,0 +1,17 @@ +// +// Copyright 2020 by Jai Luthra. +// + +#ifndef PDFTOPDF_H +#define PDFTOPDF_H + +#include + +typedef struct /***** Document information *****/ +{ + filter_logfunc_t logfunc; /* Log function */ + void *logdata; /* Log data */ + int *JobCanceled; /* Set to 1 by caller */ +} pdftopdf_doc_t; + +#endif diff --git a/filter/pdftopdf/pdftopdf_jcl.cc b/cupsfilters/pdftopdf/pdftopdf_jcl.cc similarity index 100% rename from filter/pdftopdf/pdftopdf_jcl.cc rename to cupsfilters/pdftopdf/pdftopdf_jcl.cc diff --git a/filter/pdftopdf/pdftopdf_jcl.h b/cupsfilters/pdftopdf/pdftopdf_jcl.h similarity index 100% rename from filter/pdftopdf/pdftopdf_jcl.h rename to cupsfilters/pdftopdf/pdftopdf_jcl.h diff --git a/filter/pdftopdf/pdftopdf_processor.cc b/cupsfilters/pdftopdf/pdftopdf_processor.cc similarity index 71% rename from filter/pdftopdf/pdftopdf_processor.cc rename to cupsfilters/pdftopdf/pdftopdf_processor.cc index 6d2d32ff5..53c6168b7 100644 --- a/filter/pdftopdf/pdftopdf_processor.cc +++ b/cupsfilters/pdftopdf/pdftopdf_processor.cc @@ -4,13 +4,15 @@ #include #include -void BookletMode_dump(BookletMode bkm) // {{{ +void BookletMode_dump(BookletMode bkm,pdftopdf_doc_t *doc) // {{{ { static const char *bstr[3]={"Off","On","Shuffle-Only"}; if ((bkmBOOKLET_JUSTSHUFFLE)) { - fprintf(stderr,"(bad booklet mode: %d)",bkm); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "(bad booklet mode: %d)",bkm); } else { - fputs(bstr[bkm],stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "%s",bstr[bkm]); } } // }}} @@ -28,76 +30,102 @@ bool ProcessingParameters::withPage(int outno) const // {{{ } // }}} -void ProcessingParameters::dump() const // {{{ +void ProcessingParameters::dump(pdftopdf_doc_t *doc) const // {{{ { - fprintf(stderr,"jobId: %d, numCopies: %d\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: jobId: %d, numCopies: %d\n", jobId,numCopies); - fprintf(stderr,"user: %s, title: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: user: %s, title: %s\n", (user)?user:"(null)",(title)?title:"(null)"); - fprintf(stderr,"fitplot: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: fitplot: %s\n", (fitplot)?"true":"false"); - page.dump(); + page.dump(doc); - fprintf(stderr,"Rotation(CCW): "); - Rotation_dump(orientation); - fprintf(stderr,"\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Rotation(CCW): "); + Rotation_dump(orientation,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: \n"); - fprintf(stderr,"paper_is_landscape: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: paper_is_landscape: %s\n", (paper_is_landscape)?"true":"false"); - fprintf(stderr,"duplex: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: duplex: %s\n", (duplex)?"true":"false"); - fprintf(stderr,"Border: "); - BorderType_dump(border); - fprintf(stderr,"\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Border: "); + BorderType_dump(border,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: \n"); - nup.dump(); + nup.dump(doc); - fprintf(stderr,"reverse: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: reverse: %s\n", (reverse)?"true":"false"); - fprintf(stderr,"evenPages: %s, oddPages: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: evenPages: %s, oddPages: %s\n", (evenPages)?"true":"false", (oddPages)?"true":"false"); - fprintf(stderr,"page range: "); - pageRange.dump(); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: page range: "); + pageRange.dump(doc); - fprintf(stderr,"mirror: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: mirror: %s\n", (mirror)?"true":"false"); - fprintf(stderr,"Position: "); - Position_dump(xpos,Axis::X); - fprintf(stderr,"/"); - Position_dump(ypos,Axis::Y); - fprintf(stderr,"\n"); - - fprintf(stderr,"collate: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Position: "); + Position_dump(xpos,Axis::X,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "/"); + Position_dump(ypos,Axis::Y,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "\n"); + + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: collate: %s\n", (collate)?"true":"false"); - fprintf(stderr,"evenDuplex: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: evenDuplex: %s\n", (evenDuplex)?"true":"false"); - fprintf(stderr,"pageLabel: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: pageLabel: %s\n", pageLabel.empty () ? "(none)" : pageLabel.c_str()); - fprintf(stderr,"bookletMode: "); - BookletMode_dump(booklet); - fprintf(stderr,"\nbooklet signature: %d\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: bookletMode: "); + BookletMode_dump(booklet,doc); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "\nbooklet signature: %d\n", bookSignature); - fprintf(stderr,"autoRotate: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: autoRotate: %s\n", (autoRotate)?"true":"false"); - fprintf(stderr,"emitJCL: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: emitJCL: %s\n", (emitJCL)?"true":"false"); - fprintf(stderr,"deviceCopies: %d\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: deviceCopies: %d\n", deviceCopies); - fprintf(stderr,"deviceCollate: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: deviceCollate: %s\n", (deviceCollate)?"true":"false"); - fprintf(stderr,"setDuplex: %s\n", + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: setDuplex: %s\n", (setDuplex)?"true":"false"); } // }}} @@ -142,10 +170,11 @@ std::vector bookletShuffle(int numPages,int signature) // {{{ } // }}} -bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{{ +bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m,pdftopdf_doc_t *doc) // {{{ { - if (!proc.check_print_permissions()) { - fprintf(stderr,"Not allowed to print\n"); + if (!proc.check_print_permissions(doc)) { + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Not allowed to print\n"); return false; } @@ -156,7 +185,7 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ proc.autoRotateAll(dst_lscape,param.normal_landscape); } - std::vector> pages=proc.get_pages(); + std::vector> pages=proc.get_pages(doc); const int numOrigPages=pages.size(); // TODO FIXME? elsewhere @@ -216,7 +245,8 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ } if(param.fillprint||param.cropfit){ - fprintf(stderr,"[DEBUG]: Cropping input pdf and Enabling fitplot.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: Cropping input pdf and Enabling fitplot.\n"); if(param.noOrientation&&pages.size()) { bool land = pages[0]->is_landscape(param.orientation); @@ -226,7 +256,7 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ for(int i=0;i<(int)pages.size();i++) { std::shared_ptr page = pages[i]; - page->crop(param.page,param.orientation,param.xpos,param.ypos,!param.cropfit); + page->crop(param.page,param.orientation,param.xpos,param.ypos,!param.cropfit,doc); } param.fitplot = 1; } @@ -249,11 +279,12 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ // Log page in /var/log/cups/page_log if (param.page_logging == 1) - fprintf(stderr, "PAGE: %d %d\n", iA + 1, param.copies_to_be_logged); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: PAGE: %d %d\n", iA + 1, param.copies_to_be_logged); if (shuffle[iA]>=numOrigPages) { // add empty page as filler - proc.add_page(proc.new_page(param.page.width,param.page.height),param.reverse); + proc.add_page(proc.new_page(param.page.width,param.page.height,doc),param.reverse); outputno++; continue; // no border, etc. } @@ -318,7 +349,7 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ std::shared_ptr page; if (shuffle[iA]>=numOrigPages) { // add empty page as filler - page=proc.new_page(param.page.width,param.page.height); + page=proc.new_page(param.page.width,param.page.height,doc); } else { page=pages[shuffle[iA]]; } @@ -354,10 +385,11 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ // Log page in /var/log/cups/page_log outputno++; if (param.page_logging == 1) - fprintf(stderr, "PAGE: %d %d\n", outputno, + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: PAGE: %d %d\n", outputno, param.copies_to_be_logged); } - curpage=proc.new_page(param.page.width,param.page.height); + curpage=proc.new_page(param.page.width,param.page.height,doc); outputpage++; } if (shuffle[iA]>=numOrigPages) { @@ -411,16 +443,18 @@ bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m) // {{ // Log page in /var/log/cups/page_log outputno ++; if (param.page_logging == 1) - fprintf(stderr, "PAGE: %d %d\n", outputno, param.copies_to_be_logged); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: PAGE: %d %d\n", outputno, param.copies_to_be_logged); } } if ((param.evenDuplex || !param.oddPages) && (outputno & 1)) { // need to output empty page to not confuse duplex - proc.add_page(proc.new_page(param.page.width,param.page.height),param.reverse); + proc.add_page(proc.new_page(param.page.width,param.page.height,doc),param.reverse); // Log page in /var/log/cups/page_log if (param.page_logging == 1) - fprintf(stderr, "PAGE: %d %d\n", outputno + 1, param.copies_to_be_logged); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: PAGE: %d %d\n", outputno + 1, param.copies_to_be_logged); } proc.multiply(param.numCopies,param.collate); diff --git a/filter/pdftopdf/pdftopdf_processor.h b/cupsfilters/pdftopdf/pdftopdf_processor.h similarity index 85% rename from filter/pdftopdf/pdftopdf_processor.h rename to cupsfilters/pdftopdf/pdftopdf_processor.h index ec7b2997b..052d61ea7 100644 --- a/filter/pdftopdf/pdftopdf_processor.h +++ b/cupsfilters/pdftopdf/pdftopdf_processor.h @@ -3,6 +3,7 @@ #include "pptypes.h" #include "nup.h" +#include "pdftopdf.h" #include "intervalset.h" #include #include @@ -103,7 +104,7 @@ ProcessingParameters() // helper functions bool withPage(int outno) const; // 1 based - void dump() const; + void dump(pdftopdf_doc_t *doc) const; }; #include @@ -118,7 +119,7 @@ class PDFTOPDF_PageHandle { // fscale: inverse_scale (from nup, fitplot) virtual void add_border_rect(const PageRect &rect,BorderType border,float fscale) =0; // TODO?! add standalone crop(...) method (not only for subpages) - virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale) =0; + virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale,pdftopdf_doc_t *doc) =0; virtual bool is_landscape(Rotation orientation) =0 ; virtual void add_subpage(const std::shared_ptr &sub,float xpos,float ypos,float scale,const PageRect *crop=NULL) =0; virtual void mirror() =0; @@ -132,15 +133,15 @@ class PDFTOPDF_Processor { // abstract interface virtual ~PDFTOPDF_Processor() {} // TODO: ... qpdf wants password at load time - virtual bool loadFile(FILE *f,ArgOwnership take=WillStayAlive,int flatten_forms=1) =0; - virtual bool loadFilename(const char *name,int flatten_forms=1) =0; + virtual bool loadFile(FILE *f,pdftopdf_doc_t *doc,ArgOwnership take=WillStayAlive,int flatten_forms=1) =0; + virtual bool loadFilename(const char *name,pdftopdf_doc_t *doc,int flatten_forms=1) =0; // TODO? virtual bool may_modify/may_print/? - virtual bool check_print_permissions() =0; + virtual bool check_print_permissions(pdftopdf_doc_t *doc) =0; - virtual std::vector> get_pages() =0; // shared_ptr because of type erasure (deleter) + virtual std::vector> get_pages(pdftopdf_doc_t *doc) =0; // shared_ptr because of type erasure (deleter) - virtual std::shared_ptr new_page(float width,float height) =0; + virtual std::shared_ptr new_page(float width,float height,pdftopdf_doc_t *doc) =0; virtual void add_page(std::shared_ptr page,bool front) =0; // at back/front -- either from get_pages() or new_page()+add_subpage()-calls (or [also allowed]: empty) @@ -153,8 +154,8 @@ class PDFTOPDF_Processor { // abstract interface virtual void setComments(const std::vector &comments) =0; - virtual void emitFile(FILE *dst,ArgOwnership take=WillStayAlive) =0; - virtual void emitFilename(const char *name) =0; // NULL -> stdout + virtual void emitFile(FILE *dst,pdftopdf_doc_t *doc,ArgOwnership take=WillStayAlive) =0; + virtual void emitFilename(const char *name,pdftopdf_doc_t *doc) =0; // NULL -> stdout virtual bool hasAcroForm() =0; }; @@ -169,6 +170,6 @@ class PDFTOPDF_Factory { std::vector bookletShuffle(int numPages,int signature=-1); // This is all we want: -bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m); +bool processPDFTOPDF(PDFTOPDF_Processor &proc,ProcessingParameters ¶m,pdftopdf_doc_t *doc); #endif diff --git a/filter/pdftopdf/pptypes.cc b/cupsfilters/pdftopdf/pptypes.cc similarity index 67% rename from filter/pdftopdf/pptypes.cc rename to cupsfilters/pdftopdf/pptypes.cc index 542176685..3298e5b55 100644 --- a/filter/pdftopdf/pptypes.cc +++ b/cupsfilters/pdftopdf/pptypes.cc @@ -3,41 +3,48 @@ #include #include -void Position_dump(Position pos) // {{{ +void Position_dump(Position pos,pdftopdf_doc_t *doc) // {{{ { static const char *pstr[3]={"Left/Bottom","Center","Right/Top"}; if ((pos < LEFT) || (pos > RIGHT)) { - fprintf(stderr,"(bad position: %d)",pos); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: (bad position: %d)\n",pos); } else { - fputs(pstr[pos+1],stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: %s\n",pstr[pos+1]); } } // }}} -void Position_dump(Position pos,Axis axis) // {{{ +void Position_dump(Position pos,Axis axis,pdftopdf_doc_t *doc) // {{{ { assert((axis == Axis::X) || (axis == Axis::Y)); if ((pos < LEFT) || (pos > RIGHT)) { - fprintf(stderr,"(bad position: %d)",pos); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "(bad position: %d)",pos); return; } if (axis==Axis::X) { static const char *pxstr[3]={"Left","Center","Right"}; - fputs(pxstr[pos+1],stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "%s", pxstr[pos+1]); } else { static const char *pystr[3]={"Bottom","Center","Top"}; - fputs(pystr[pos+1],stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "%s",pystr[pos+1]); } } // }}} -void Rotation_dump(Rotation rot) // {{{ +void Rotation_dump(Rotation rot,pdftopdf_doc_t *doc) // {{{ { static const char *rstr[4]={"0 deg","90 deg","180 deg","270 deg"}; // CCW if ((rot < ROT_0) || (rot > ROT_270)) { - fprintf(stderr,"(bad rotation: %d)",rot); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "(bad rotation: %d)",rot); } else { - fputs(rstr[rot],stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "%s",rstr[rot]); } } // }}} @@ -60,13 +67,15 @@ Rotation operator-(Rotation rhs) // {{{ } // }}} -void BorderType_dump(BorderType border) // {{{ +void BorderType_dump(BorderType border,pdftopdf_doc_t *doc) // {{{ { if ((border < NONE) || (border == 1) || (border > TWO_THICK)) { - fprintf(stderr,"(bad border: %d)",border); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "(bad border: %d)",border); } else { static const char *bstr[6]={"None",NULL,"one thin","one thick","two thin","two thick"}; - fputs(bstr[border],stderr); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_CONTROL, + "%s",bstr[border]); } } // }}} @@ -167,9 +176,10 @@ void PageRect::set(const PageRect &rhs) // {{{ } // }}} -void PageRect::dump() const // {{{ +void PageRect::dump(pdftopdf_doc_t *doc) const // {{{ { - fprintf(stderr,"top: %f, left: %f, right: %f, bottom: %f\n" + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: top: %f, left: %f, right: %f, bottom: %f\n" "width: %f, height: %f\n", top,left,right,bottom, width,height); diff --git a/filter/pdftopdf/pptypes.h b/cupsfilters/pdftopdf/pptypes.h similarity index 78% rename from filter/pdftopdf/pptypes.h rename to cupsfilters/pdftopdf/pptypes.h index 4f4df6d4d..bff54f8a4 100644 --- a/filter/pdftopdf/pptypes.h +++ b/cupsfilters/pdftopdf/pptypes.h @@ -1,17 +1,18 @@ #ifndef PPTYPES_H_ #define PPTYPES_H_ +#include "pdftopdf.h" #include // NAN // namespace PPTypes {} TODO? enum Axis { X, Y }; enum Position { CENTER=0, LEFT=-1, RIGHT=1, TOP=1, BOTTOM=-1 }; // PS order -void Position_dump(Position pos); -void Position_dump(Position pos,Axis axis); +void Position_dump(Position pos,pdftopdf_doc_t *doc); +void Position_dump(Position pos,Axis axis,pdftopdf_doc_t *doc); enum Rotation { ROT_0, ROT_90, ROT_180, ROT_270 }; // CCW -void Rotation_dump(Rotation rot); +void Rotation_dump(Rotation rot,pdftopdf_doc_t *doc); Rotation operator+(Rotation lhs,Rotation rhs); Rotation operator-(Rotation lhs,Rotation rhs); Rotation operator-(Rotation rhs); @@ -19,7 +20,7 @@ Rotation operator-(Rotation rhs); enum BorderType { NONE=0, ONE_THIN=2, ONE_THICK=3, TWO_THIN=4, TWO_THICK=5, ONE=0x02, TWO=0x04, THICK=0x01}; -void BorderType_dump(BorderType border); +void BorderType_dump(BorderType border,pdftopdf_doc_t *doc); struct PageRect { PageRect() : top(NAN),left(NAN),right(NAN),bottom(NAN),width(NAN),height(NAN) {} @@ -31,7 +32,7 @@ PageRect() : top(NAN),left(NAN),right(NAN),bottom(NAN),width(NAN),height(NAN) {} void translate(float tx,float ty); void set(const PageRect &rhs); // only for rhs.* != NAN - void dump() const; + void dump(pdftopdf_doc_t *doc) const; }; // bool parseBorder(const char *val,BorderType &ret); // none,single,...,double-thick diff --git a/filter/pdftopdf/qpdf_cm.cc b/cupsfilters/pdftopdf/qpdf_cm.cc similarity index 100% rename from filter/pdftopdf/qpdf_cm.cc rename to cupsfilters/pdftopdf/qpdf_cm.cc diff --git a/filter/pdftopdf/qpdf_cm.h b/cupsfilters/pdftopdf/qpdf_cm.h similarity index 100% rename from filter/pdftopdf/qpdf_cm.h rename to cupsfilters/pdftopdf/qpdf_cm.h diff --git a/filter/pdftopdf/qpdf_pdftopdf.cc b/cupsfilters/pdftopdf/qpdf_pdftopdf.cc similarity index 100% rename from filter/pdftopdf/qpdf_pdftopdf.cc rename to cupsfilters/pdftopdf/qpdf_pdftopdf.cc diff --git a/filter/pdftopdf/qpdf_pdftopdf.h b/cupsfilters/pdftopdf/qpdf_pdftopdf.h similarity index 100% rename from filter/pdftopdf/qpdf_pdftopdf.h rename to cupsfilters/pdftopdf/qpdf_pdftopdf.h diff --git a/filter/pdftopdf/qpdf_pdftopdf_processor.cc b/cupsfilters/pdftopdf/qpdf_pdftopdf_processor.cc similarity index 91% rename from filter/pdftopdf/qpdf_pdftopdf_processor.cc rename to cupsfilters/pdftopdf/qpdf_pdftopdf_processor.cc index d06ca5f77..34e852bce 100644 --- a/filter/pdftopdf/qpdf_pdftopdf_processor.cc +++ b/cupsfilters/pdftopdf/qpdf_pdftopdf_processor.cc @@ -10,6 +10,7 @@ #include "qpdf_tools.h" #include "qpdf_xobject.h" #include "qpdf_pdftopdf.h" +#include "pdftopdf.h" // Use: content.append(debug_box(pe.sub,xpos,ypos)); static std::string debug_box(const PageRect &box,float xshift,float yshift) // {{{ @@ -176,7 +177,7 @@ void QPDF_PDFTOPDF_PageHandle::add_border_rect(const PageRect &_rect,BorderType * Trim Box is used for trimming the page in required size. * scale tells if we need to scale input file. */ -Rotation QPDF_PDFTOPDF_PageHandle::crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale) +Rotation QPDF_PDFTOPDF_PageHandle::crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale,pdftopdf_doc_t *doc) { page.assertInitialized(); if(orientation==ROT_0||orientation==ROT_180) @@ -212,7 +213,8 @@ Rotation QPDF_PDFTOPDF_PageHandle::crop(const PageRect &cropRect,Rotation orient final_w = std::min(width,pageWidth); final_h = std::min(height,pageHeight); } - fprintf(stderr,"After Cropping: %lf %lf %lf %lf\n",width,height,final_w,final_h); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: After Cropping: %lf %lf %lf %lf\n",width,height,final_w,final_h); double posw = (width-final_w)/2, posh = (height-final_h)/2; // posw, posh : Position along width and height respectively. @@ -450,21 +452,9 @@ void QPDF_PDFTOPDF_Processor::closeFile() // {{{ } // }}} -void QPDF_PDFTOPDF_Processor::error(const char *fmt,...) // {{{ -{ - va_list ap; - - va_start(ap,fmt); - fputs("ERROR: ",stderr); - vfprintf(stderr,fmt,ap); - fputs("\n",stderr); - va_end(ap); -} -// }}} - // TODO? try/catch for PDF parsing errors? -bool QPDF_PDFTOPDF_Processor::loadFile(FILE *f,ArgOwnership take,int flatten_forms) // {{{ +bool QPDF_PDFTOPDF_Processor::loadFile(FILE *f,pdftopdf_doc_t *doc,ArgOwnership take,int flatten_forms) // {{{ { closeFile(); if (!f) { @@ -483,7 +473,8 @@ bool QPDF_PDFTOPDF_Processor::loadFile(FILE *f,ArgOwnership take,int flatten_for try { pdf->processFile("temp file",f,false); } catch (const std::exception &e) { - error("loadFile failed: %s",e.what()); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: loadFile failed: %s",e.what()); return false; } break; @@ -491,12 +482,14 @@ bool QPDF_PDFTOPDF_Processor::loadFile(FILE *f,ArgOwnership take,int flatten_for try { pdf->processFile("temp file",f,true); } catch (const std::exception &e) { - error("loadFile failed: %s",e.what()); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: loadFile failed: %s",e.what()); return false; } break; case MustDuplicate: - error("loadFile with MustDuplicate is not supported"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: loadFile with MustDuplicate is not supported"); return false; } start(flatten_forms); @@ -504,14 +497,15 @@ bool QPDF_PDFTOPDF_Processor::loadFile(FILE *f,ArgOwnership take,int flatten_for } // }}} -bool QPDF_PDFTOPDF_Processor::loadFilename(const char *name,int flatten_forms) // {{{ +bool QPDF_PDFTOPDF_Processor::loadFilename(const char *name,pdftopdf_doc_t *doc,int flatten_forms) // {{{ { closeFile(); try { pdf.reset(new QPDF); pdf->processFile(name); } catch (const std::exception &e) { - error("loadFilename failed: %s",e.what()); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: loadFilename failed: %s",e.what()); return false; } start(flatten_forms); @@ -548,21 +542,23 @@ void QPDF_PDFTOPDF_Processor::start(int flatten_forms) // {{{ } // }}} -bool QPDF_PDFTOPDF_Processor::check_print_permissions() // {{{ +bool QPDF_PDFTOPDF_Processor::check_print_permissions(pdftopdf_doc_t *doc) // {{{ { if (!pdf) { - error("No PDF loaded"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: No PDF loaded"); return false; } return pdf->allowPrintHighRes() || pdf->allowPrintLowRes(); // from legacy pdftopdf } // }}} -std::vector> QPDF_PDFTOPDF_Processor::get_pages() // {{{ +std::vector> QPDF_PDFTOPDF_Processor::get_pages(pdftopdf_doc_t *doc) // {{{ { std::vector> ret; if (!pdf) { - error("No PDF loaded"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: No PDF loaded"); assert(0); return ret; } @@ -575,10 +571,11 @@ std::vector> QPDF_PDFTOPDF_Processor::get_p } // }}} -std::shared_ptr QPDF_PDFTOPDF_Processor::new_page(float width,float height) // {{{ +std::shared_ptr QPDF_PDFTOPDF_Processor::new_page(float width,float height,pdftopdf_doc_t *doc) // {{{ { if (!pdf) { - error("No PDF loaded"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: No PDF loaded"); assert(0); return std::shared_ptr(); } @@ -691,7 +688,7 @@ void QPDF_PDFTOPDF_Processor::setComments(const std::vector &commen } // }}} -void QPDF_PDFTOPDF_Processor::emitFile(FILE *f,ArgOwnership take) // {{{ +void QPDF_PDFTOPDF_Processor::emitFile(FILE *f,pdftopdf_doc_t *doc,ArgOwnership take) // {{{ { if (!pdf) { return; @@ -705,7 +702,8 @@ void QPDF_PDFTOPDF_Processor::emitFile(FILE *f,ArgOwnership take) // {{{ out.setOutputFile("temp file",f,true); break; case MustDuplicate: - error("emitFile with MustDuplicate is not supported"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_ERROR, + "pdftopdf: emitFile with MustDuplicate is not supported"); return; } if (hasCM) { @@ -721,7 +719,7 @@ void QPDF_PDFTOPDF_Processor::emitFile(FILE *f,ArgOwnership take) // {{{ } // }}} -void QPDF_PDFTOPDF_Processor::emitFilename(const char *name) // {{{ +void QPDF_PDFTOPDF_Processor::emitFilename(const char *name,pdftopdf_doc_t *doc) // {{{ { if (!pdf) { return; @@ -742,7 +740,8 @@ void QPDF_PDFTOPDF_Processor::emitFilename(const char *name) // {{{ if (len) out.write(); else - fprintf(stderr, "DEBUG: No pages left, outputting empty file.\n"); + if (doc->logfunc) doc->logfunc(doc->logdata, FILTER_LOGLEVEL_DEBUG, + "pdftopdf: No pages left, outputting empty file.\n"); } // }}} diff --git a/filter/pdftopdf/qpdf_pdftopdf_processor.h b/cupsfilters/pdftopdf/qpdf_pdftopdf_processor.h similarity index 79% rename from filter/pdftopdf/qpdf_pdftopdf_processor.h rename to cupsfilters/pdftopdf/qpdf_pdftopdf_processor.h index f721d9390..9e13348ab 100644 --- a/filter/pdftopdf/qpdf_pdftopdf_processor.h +++ b/cupsfilters/pdftopdf/qpdf_pdftopdf_processor.h @@ -12,7 +12,7 @@ class QPDF_PDFTOPDF_PageHandle : public PDFTOPDF_PageHandle { virtual void mirror(); virtual void rotate(Rotation rot); virtual void add_label(const PageRect &rect, const std::string label); - virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale); + virtual Rotation crop(const PageRect &cropRect,Rotation orientation,Position xpos,Position ypos,bool scale,pdftopdf_doc_t *doc); virtual bool is_landscape(Rotation orientation); void debug(const PageRect &rect,float xpos,float ypos); private: @@ -35,16 +35,16 @@ class QPDF_PDFTOPDF_PageHandle : public PDFTOPDF_PageHandle { class QPDF_PDFTOPDF_Processor : public PDFTOPDF_Processor { public: - virtual bool loadFile(FILE *f,ArgOwnership take=WillStayAlive,int flatten_forms=1); - virtual bool loadFilename(const char *name,int flatten_forms=1); + virtual bool loadFile(FILE *f,pdftopdf_doc_t *doc,ArgOwnership take=WillStayAlive,int flatten_forms=1); + virtual bool loadFilename(const char *name,pdftopdf_doc_t *doc,int flatten_forms=1); // TODO: virtual bool may_modify/may_print/? - virtual bool check_print_permissions(); + virtual bool check_print_permissions(pdftopdf_doc_t *doc); // virtual bool setProcess(const ProcessingParameters ¶m) =0; - virtual std::vector> get_pages(); - virtual std::shared_ptr new_page(float width,float height); + virtual std::vector> get_pages(pdftopdf_doc_t *doc); + virtual std::shared_ptr new_page(float width,float height,pdftopdf_doc_t *doc); virtual void add_page(std::shared_ptr page,bool front); @@ -55,13 +55,12 @@ class QPDF_PDFTOPDF_Processor : public PDFTOPDF_Processor { virtual void setComments(const std::vector &comments); - virtual void emitFile(FILE *dst,ArgOwnership take=WillStayAlive); - virtual void emitFilename(const char *name); + virtual void emitFile(FILE *dst,pdftopdf_doc_t *doc,ArgOwnership take=WillStayAlive); + virtual void emitFilename(const char *name,pdftopdf_doc_t *doc); virtual bool hasAcroForm(); private: void closeFile(); - void error(const char *fmt,...); void start(int flatten_forms); private: std::unique_ptr pdf; diff --git a/filter/pdftopdf/qpdf_tools.cc b/cupsfilters/pdftopdf/qpdf_tools.cc similarity index 100% rename from filter/pdftopdf/qpdf_tools.cc rename to cupsfilters/pdftopdf/qpdf_tools.cc diff --git a/filter/pdftopdf/qpdf_tools.h b/cupsfilters/pdftopdf/qpdf_tools.h similarity index 100% rename from filter/pdftopdf/qpdf_tools.h rename to cupsfilters/pdftopdf/qpdf_tools.h diff --git a/filter/pdftopdf/qpdf_xobject.cc b/cupsfilters/pdftopdf/qpdf_xobject.cc similarity index 100% rename from filter/pdftopdf/qpdf_xobject.cc rename to cupsfilters/pdftopdf/qpdf_xobject.cc diff --git a/filter/pdftopdf/qpdf_xobject.h b/cupsfilters/pdftopdf/qpdf_xobject.h similarity index 100% rename from filter/pdftopdf/qpdf_xobject.h rename to cupsfilters/pdftopdf/qpdf_xobject.h diff --git a/filter/pdftopdf.c b/filter/pdftopdf.c new file mode 100644 index 000000000..27867fe52 --- /dev/null +++ b/filter/pdftopdf.c @@ -0,0 +1,75 @@ +/* + * Pdf to pdf filter based on pdftopdf() filter function. + */ + + +/* + * Include necessary headers... + */ +#include +#include + + +/* + * Local globals... + */ + +static int JobCanceled = 0;/* Set to 1 on SIGTERM */ + + +/* + * Local functions... + */ + +static void cancel_job(int sig); + + +/* + * 'main()' - Main entry. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + int ret; +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + /* + * Register a signal handler to cleanly cancel a job. + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, cancel_job); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = cancel_job; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, cancel_job); +#endif /* HAVE_SIGSET */ + + ret = filterCUPSWrapper(argc, argv, pdftopdf, NULL, &JobCanceled); + + if (ret) + fprintf(stderr, "ERROR: pdftopdf filter function failed.\n"); + + return (ret); +} + + +/* + * 'cancel_job()' - Flag the job as canceled. + */ + +static void +cancel_job(int sig) /* I - Signal number (unused) */ +{ + (void)sig; + + JobCanceled = 1; +} -- 2.47.2