X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=paperjam.cc;h=c8e107181d7ad97b1b1bdb195c20e45405a1b6eb;hb=bb6a7cf9ecaec1dbd2837fdddc866be285ce053a;hp=07ae6b4289d40f460bc054373c7bcd3c9d11ac7a;hpb=aedd41800e40767aa9c534569e8e551ab2405cb8;p=paperjam.git diff --git a/paperjam.cc b/paperjam.cc index 07ae6b4..c8e1071 100644 --- a/paperjam.cc +++ b/paperjam.cc @@ -10,70 +10,99 @@ static QPDF in_pdf; static QPDF out_pdf; -string page_out::new_resource(const string type) +string out_context::new_resource(const string type) { return "/" + type + to_string(++res_cnt); } class in_page : public page { QPDFObjectHandle pdf_page; + QPDFObjectHandle xobject; public: BBox media_box; - void render(page_out *out, pdf_matrix xform); + void render(out_context *out, pdf_matrix xform); in_page(QPDFObjectHandle inpg, int idx); }; in_page::in_page(QPDFObjectHandle inpg, int idx) { 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; + } } -void in_page::render(page_out *out, pdf_matrix xform) +void in_page::render(out_context *out, pdf_matrix xform) { // Convert page to xobject - QPDFObjectHandle page_copy = page_to_xobject(&out_pdf, out_pdf.copyForeignObject(pdf_page)); + 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, out_pdf.makeIndirectObject(page_copy)); + 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"; + out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q "; } -static int run_indent; - static void debug_pages(vector &pages) { if (!debug_mode) return; for (auto pg: pages) - debug("%*sPage #%d: w=%.3f h=%.3f", run_indent, "", pg->index, pg->width, pg->height); + debug("Page #%d: media[%.3f %.3f] bbox[%.3f %.3f %.3f %.3f]", + pg->index, + pg->width, pg->height, + pg->bbox.x_min, pg->bbox.y_min, pg->bbox.x_max, pg->bbox.y_max); } vector run_command_list(list &cmds, vector &pages) { - debug("%*s# Input", run_indent, ""); + debug("# Input"); debug_pages(pages); for (auto c: cmds) { - debug("%*s# Executing %s", run_indent, "", c->def->name); - run_indent += 4; + debug("# Executing %s", c->def->name); + debug_indent += 4; pages = c->exec->process(pages); - run_indent -= 4; + debug_indent -= 4; debug_pages(pages); } return pages; } +static void find_bboxes(vector &pages, const char *in_name) +{ + vector bboxes = gs_bboxes(in_name); + if (pages.size() != bboxes.size()) + die("Ghostscript failed to produce the right number of bboxes"); + + for (size_t i=0; ibbox = bboxes[i]; +} + static void process(list &cmds, const char *in_name, const char *out_name) { in_pdf.processFile(in_name); @@ -89,14 +118,15 @@ static void process(list &cmds, const char *in_name, const char *out_name for (auto inpg: in_pages) pages.push_back(new in_page(inpg, ++cnt)); + find_bboxes(pages, in_name); + pages = run_command_list(cmds, pages); for (auto pg: pages) { - page_out out; + out_context out; out.resources = QPDFObjectHandle::newDictionary(); - // FIXME: What if the source page requires a broader ProcSet? - out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF /Text]")); + out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF]")); out.xobjects = QPDFObjectHandle::newDictionary(); out.resources.replaceKey("/XObject", out.xobjects); pg->render(&out, pdf_matrix()); @@ -107,6 +137,8 @@ static void process(list &cmds, const char *in_name, const char *out_name 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()); + // FIXME: + // 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); @@ -132,6 +164,12 @@ static void process(list &cmds, const char *in_name, const char *out_name int main(int argc, char **argv) { + if (argc <= 1 || argc > 1 && !strcmp(argv[1], "--help")) + { + help(); + return 0; + } + if (argc != 4) { fprintf(stderr, "Usage: paperjam \n");