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 \
-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 = \
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)
# ======================
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,
}
// }}}
-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;iA<len;iA++) {
- fprintf(stderr,"[%d,%d),",data[iA].first,data[iA].second);
+ if (doc->logfunc) 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);
}
}
// }}}
#ifndef INTERVALSET_H_
#define INTERVALSET_H_
+#include "pdftopdf.h"
#include <stddef.h>
#include <vector>
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;
#include <string.h>
#include <utility>
-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);
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");
}
// }}}
}
// }}}
-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);
}
// }}}
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
// everything in "outer"-page coordinates
PageRect sub;
- void dump() const;
+ void dump(pdftopdf_doc_t *doc) const;
};
/*
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include "pdftopdf.h"
#include "pdftopdf_processor.h"
#include "pdftopdf_jcl.h"
#include <stdarg.h>
-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 {}
// }}}
// 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;
} 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;
}
// }}}
}
// }}}
-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;
* 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];
(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);
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 */
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);
}
}
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
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;
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;
}
}
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;
} 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);
}
}
} 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;
}
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;
}
}
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
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 " : ""));
}
}
// }}}
-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.
// 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") ||
// }}}
// 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;
// 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
// 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;
}
}
// }}}
-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<PDFTOPDF_Processor> 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<PDFTOPDF_Processor> 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:
}
*/
- 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;
}
--- /dev/null
+//
+// Copyright 2020 by Jai Luthra.
+//
+
+#ifndef PDFTOPDF_H
+#define PDFTOPDF_H
+
+#include <cupsfilters/filter.h>
+
+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
#include <assert.h>
#include <numeric>
-void BookletMode_dump(BookletMode bkm) // {{{
+void BookletMode_dump(BookletMode bkm,pdftopdf_doc_t *doc) // {{{
{
static const char *bstr[3]={"Off","On","Shuffle-Only"};
if ((bkm<BOOKLET_OFF) || (bkm>BOOKLET_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]);
}
}
// }}}
}
// }}}
-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");
}
// }}}
}
// }}}
-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;
}
proc.autoRotateAll(dst_lscape,param.normal_landscape);
}
- std::vector<std::shared_ptr<PDFTOPDF_PageHandle>> pages=proc.get_pages();
+ std::vector<std::shared_ptr<PDFTOPDF_PageHandle>> pages=proc.get_pages(doc);
const int numOrigPages=pages.size();
// TODO FIXME? elsewhere
}
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);
for(int i=0;i<(int)pages.size();i++)
{
std::shared_ptr<PDFTOPDF_PageHandle> 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;
}
// 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.
}
std::shared_ptr<PDFTOPDF_PageHandle> 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]];
}
// 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) {
// 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);
#include "pptypes.h"
#include "nup.h"
+#include "pdftopdf.h"
#include "intervalset.h"
#include <vector>
#include <string>
// helper functions
bool withPage(int outno) const; // 1 based
- void dump() const;
+ void dump(pdftopdf_doc_t *doc) const;
};
#include <stdio.h>
// 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<PDFTOPDF_PageHandle> &sub,float xpos,float ypos,float scale,const PageRect *crop=NULL) =0;
virtual void mirror() =0;
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<std::shared_ptr<PDFTOPDF_PageHandle>> get_pages() =0; // shared_ptr because of type erasure (deleter)
+ virtual std::vector<std::shared_ptr<PDFTOPDF_PageHandle>> get_pages(pdftopdf_doc_t *doc) =0; // shared_ptr because of type erasure (deleter)
- virtual std::shared_ptr<PDFTOPDF_PageHandle> new_page(float width,float height) =0;
+ virtual std::shared_ptr<PDFTOPDF_PageHandle> new_page(float width,float height,pdftopdf_doc_t *doc) =0;
virtual void add_page(std::shared_ptr<PDFTOPDF_PageHandle> page,bool front) =0; // at back/front -- either from get_pages() or new_page()+add_subpage()-calls (or [also allowed]: empty)
virtual void setComments(const std::vector<std::string> &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;
};
std::vector<int> 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
#include <stdio.h>
#include <assert.h>
-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]);
}
}
// }}}
}
// }}}
-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]);
}
}
// }}}
}
// }}}
-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);
#ifndef PPTYPES_H_
#define PPTYPES_H_
+#include "pdftopdf.h"
#include <cmath> // 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);
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) {}
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
#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) // {{{
* 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)
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.
}
// }}}
-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) {
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;
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);
}
// }}}
-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);
}
// }}}
-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<std::shared_ptr<PDFTOPDF_PageHandle>> QPDF_PDFTOPDF_Processor::get_pages() // {{{
+std::vector<std::shared_ptr<PDFTOPDF_PageHandle>> QPDF_PDFTOPDF_Processor::get_pages(pdftopdf_doc_t *doc) // {{{
{
std::vector<std::shared_ptr<PDFTOPDF_PageHandle>> 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;
}
}
// }}}
-std::shared_ptr<PDFTOPDF_PageHandle> QPDF_PDFTOPDF_Processor::new_page(float width,float height) // {{{
+std::shared_ptr<PDFTOPDF_PageHandle> 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<PDFTOPDF_PageHandle>();
}
}
// }}}
-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;
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) {
}
// }}}
-void QPDF_PDFTOPDF_Processor::emitFilename(const char *name) // {{{
+void QPDF_PDFTOPDF_Processor::emitFilename(const char *name,pdftopdf_doc_t *doc) // {{{
{
if (!pdf) {
return;
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");
}
// }}}
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:
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<std::shared_ptr<PDFTOPDF_PageHandle>> get_pages();
- virtual std::shared_ptr<PDFTOPDF_PageHandle> new_page(float width,float height);
+ virtual std::vector<std::shared_ptr<PDFTOPDF_PageHandle>> get_pages(pdftopdf_doc_t *doc);
+ virtual std::shared_ptr<PDFTOPDF_PageHandle> new_page(float width,float height,pdftopdf_doc_t *doc);
virtual void add_page(std::shared_ptr<PDFTOPDF_PageHandle> page,bool front);
virtual void setComments(const std::vector<std::string> &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<QPDF> pdf;
--- /dev/null
+/*
+ * Pdf to pdf filter based on pdftopdf() filter function.
+ */
+
+
+/*
+ * Include necessary headers...
+ */
+#include <cupsfilters/filter.h>
+#include <signal.h>
+
+
+/*
+ * 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;
+}