X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=paperjam.cc;h=0d3bf12c57fe95452fcd8cb1ec5b626966ce2f6d;hb=refs%2Fheads%2Fmaster;hp=22dd9f5e8d47068bd8c169d3f6f9252d297166f2;hpb=bc0c38a2fd19e04770b25536e1eb6549b48ce1f3;p=paperjam.git diff --git a/paperjam.cc b/paperjam.cc index 22dd9f5..0d3bf12 100644 --- a/paperjam.cc +++ b/paperjam.cc @@ -1,167 +1,152 @@ +/* + * PaperJam -- Main program + * + * (c) 2018--2022 Martin Mares + */ + #include #include #include #include +#include #include "jam.h" -#include - -static QPDF in_pdf; -static QPDF out_pdf; +/*** Options ***/ -string out_context::new_resource(const string type) -{ - return "/" + type + to_string(++res_cnt); -} +const char *in_name; +const char *out_name; +bool recalc_bbox; +bool no_auto_transforms; +int debug_level; +int debug_indent; -class in_page : public page { - QPDFObjectHandle pdf_page; - QPDFObjectHandle xobject; -public: - BBox media_box; - void render(out_context *out, pdf_matrix xform); - in_page(QPDFObjectHandle inpg, int idx); -}; +/*** Messages ***/ -in_page::in_page(QPDFObjectHandle inpg, int idx) +void debug(const char *msg, ...) { - pdf_page = inpg; - xobject = QPDFObjectHandle::newNull(); - index = idx; - - media_box = BBox(inpg.getKey("/MediaBox")); - width = media_box.width(); - height = media_box.height(); - - QPDFObjectHandle art_box = inpg.getKey("/ArtBox"); - if (art_box.isNull()) - art_box = inpg.getKey("/CropBox"); - if (art_box.isNull()) - bbox = BBox(width, height); - else - { - bbox = BBox(art_box); - bbox.x_min -= media_box.x_min; - bbox.x_max -= media_box.x_min; - bbox.y_min -= media_box.y_min; - bbox.y_max -= media_box.y_min; - } + if (!debug_level) + return; + va_list args; + va_start(args, msg); + fprintf(stderr, "%*s", debug_indent, ""); + vfprintf(stderr, msg, args); + fputc('\n', stderr); + va_end(args); } -void in_page::render(out_context *out, pdf_matrix xform) +void warn(const char *msg, ...) { - // Convert page to xobject - if (xobject.isNull()) - xobject = out_pdf.makeIndirectObject( page_to_xobject(&out_pdf, out_pdf.copyForeignObject(pdf_page)) ); - string xobj_res = out->new_resource("XO"); - out->xobjects.replaceKey(xobj_res, xobject); - - pdf_matrix m; - m.shift(-media_box.x_min, -media_box.y_min); - m.concat(xform); - - out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q"; + va_list args; + va_start(args, msg); + fprintf(stderr, "Warning: "); + vfprintf(stderr, msg, args); + fputc('\n', stderr); + va_end(args); } -static void debug_pages(vector &pages) +void die(const char *msg, ...) { - if (!debug_mode) - return; - - for (auto pg: pages) - debug("Page #%d: w=%.3f h=%.3f", pg->index, pg->width, pg->height); + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + fputc('\n', stderr); + va_end(args); + exit(1); } -vector run_command_list(list &cmds, vector &pages) +void err(const char *msg, ...) { - debug("# Input"); - debug_pages(pages); - - for (auto c: cmds) - { - debug("# Executing %s", c->def->name); - debug_indent += 4; - pages = c->exec->process(pages); - debug_indent -= 4; - debug_pages(pages); - } - - return pages; + va_list args; + va_start(args, msg); + char buf[1024]; + vsnprintf(buf, sizeof(buf), msg, args); + va_end(args); + throw paperjam_error(buf); } -static void process(list &cmds, const char *in_name, const char *out_name) -{ - in_pdf.processFile(in_name); - in_pdf.pushInheritedAttributesToPage(); - out_pdf.emptyPDF(); - - vector const &in_pages = in_pdf.getAllPages(); - vector pages; +/*** Arguments ***/ - QPDFObjectHandle page_copy = out_pdf.copyForeignObject(in_pages[0]); +enum opt { + OPT_HELP = 256, + OPT_VERSION, + OPT_NO_AUTO, +}; - int cnt = 0; - for (auto inpg: in_pages) - pages.push_back(new in_page(inpg, ++cnt)); +static const struct option long_opts[] = { + { "debug", 0, 0, 'd' }, + { "help", 0, 0, OPT_HELP }, + { "version", 0, 0, OPT_VERSION }, + { "bbox", 0, 0, 'b' }, + { 0, 0, 0, 0 } +}; - pages = run_command_list(cmds, pages); +static const char short_opts[] = "bd"; - for (auto pg: pages) - { - out_context out; - out.resources = QPDFObjectHandle::newDictionary(); - out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF]")); - out.xobjects = QPDFObjectHandle::newDictionary(); - out.resources.replaceKey("/XObject", out.xobjects); - pg->render(&out, pdf_matrix()); - - QPDFObjectHandle contents = QPDFObjectHandle::newStream(&out_pdf, out.contents); - - // Create the page object - QPDFObjectHandle out_page = out_pdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); - out_page.replaceKey("/Type", QPDFObjectHandle::newName("/Page")); - out_page.replaceKey("/MediaBox", BBox(pg->width, pg->height).to_array()); - out_page.replaceKey("/CropBox", pg->bbox.to_array()); - out_page.replaceKey("/Contents", contents); - out_page.replaceKey("/Resources", out.resources); - out_pdf.addPage(out_page, false); - } +static void usage() +{ + printf("Usage: paperjam [] \n\ +\n\ +Options:\n\ +-b, --bbox Recalculate bounding boxes\n\ +-d, --debug Show debugging messages\n\ + --no-auto Disable automatic rotation of pages\n\ +\n\ + = (, [=], ...) []\n\ + = { , , ... }\n\ + = ... [: ]\n\ +\n\ +Example:\n\ +paperjam 'book nup(2, paper=a4)' input.pdf output.pdf\n\ +\n\ +Commands:\n\ +"); + parser_help(); +} - // Produce info dictionary - QPDFObjectHandle trailer = out_pdf.getTrailer(); - QPDFObjectHandle info = trailer.getKey("/Info"); - if (info.isNull()) - { - info = QPDFObjectHandle::newDictionary(); - trailer.replaceKey("/Info", info); - } - else - assert(info.isDictionary()); - // FIXME: More meta-data - info.replaceKey("/Producer", unicode_string("PaperJam")); - - // Write the output file - QPDFWriter writer(out_pdf, out_name); - writer.write(); +static void show_version() +{ + printf("PaperJam " VERSION " -- a PDF processor\n"); + printf("(c) " YEAR " Martin Mares, distributed under GNU GPL 2+\n"); + printf("Built on " BUILD_DATE " from Git commit " BUILD_COMMIT "\n"); } int main(int argc, char **argv) { - if (argc != 4) - { - fprintf(stderr, "Usage: paperjam \n"); - return 1; - } - - debug_mode = 100; + int c; + while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0) + switch (c) + { + case 'b': + recalc_bbox = 1; + break; + case 'd': + debug_level++; + break; + case OPT_VERSION: + show_version(); + return 0; + case OPT_HELP: + usage(); + return 0; + case OPT_NO_AUTO: + no_auto_transforms = true; + break; + default: + exit(1); + } + + if (optind + 3 != argc) + die("Exactly three positional parameters should be given"); list cmds; - parse(argv[1], cmds); + parse(argv[optind], cmds); + in_name = argv[optind+1]; + out_name = argv[optind+2]; try { - process(cmds, argv[2], argv[3]); + process(cmds); } catch (exception& e) {