X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=cmds.cc;h=7d0f9b659d934323bd02ef1b336c1811990867b6;hb=f9f510737accd2022b293eb32dba8a097b88791d;hp=73daa4cbc4211419c3a939f11a8e833c9c5b8d08;hpb=2a7ea65f10962f86dedfac00367aa1124c19496d;p=paperjam.git diff --git a/cmds.cc b/cmds.cc index 73daa4c..7d0f9b6 100644 --- a/cmds.cc +++ b/cmds.cc @@ -32,6 +32,11 @@ class xform_page : public page { pdf_matrix xform; public: void render(out_context *out, pdf_matrix xform) override; + void debug_dump() override + { + debug("Transform [%s]", xform.to_string().c_str()); + orig_page->debug_dump(); + } xform_page(page *p, pdf_matrix xf); }; @@ -199,8 +204,8 @@ public: { bb->x_min += l; bb->x_max -= r; - bb->y_min += b; - bb->y_max -= t; + bb->y_min += t; + bb->y_max -= b; if (bb->x_min >= bb->x_max || bb->y_min >= bb->y_max) err("Margins cannot be larger than the whole page"); } @@ -208,8 +213,8 @@ public: { bb->x_min -= l; bb->x_max += r; - bb->y_min -= b; - bb->y_max += t; + bb->y_min -= t; + bb->y_max += b; } }; @@ -575,7 +580,7 @@ vector select_cmd::process(vector &pages) int f = validate_page_index(pages, ps.from); int t = validate_page_index(pages, ps.to); int step = (f <= t) ? 1 : -1; - for (int i=f; f<=t; f += step) + for (int i=f; i<=t; i += step) selected.push_back(pages[i]); } auto processed = run_command_list(pb->commands, selected); @@ -718,6 +723,11 @@ public: out->contents += page_cm->pdf_stream(out, page_bbox, xform); out->contents += image_cm->pdf_stream(out, image_box, xform); } + void debug_dump() override + { + debug("Draw debugging boxes"); + orig_page->debug_dump(); + } }; class debug_cmd : public cmd_exec_simple { @@ -778,6 +788,14 @@ public: for (auto p: orig_pages) p->render(out, xform); } + void debug_dump() override + { + debug("Merge pages"); + debug_indent += 4; + for (auto p: orig_pages) + p->debug_dump(); + debug_indent -= 4; + } }; vector merge_cmd::process(vector &pages) @@ -920,14 +938,10 @@ public: margins_cmd(cmd *c) : marg(c, "size", "") { } page *process_page(page *p) override { - pdf_matrix xf; - xf.shift(-p->image_box.x_min, -p->image_box.y_min); - xf.shift(marg.l, marg.b); - page *q = new xform_page(p, xf); - q->width = p->image_box.width() + marg.l + marg.r; - q->height = p->image_box.height() + marg.t + marg.b; - if (q->width < 0.001 || q->height < 0.001) - err("Margins must result in positive page dimensions"); + page *q = new xform_page(p, pdf_matrix()); + q->image_box = BBox(marg.l, marg.t, p->width - marg.r, p->height - marg.b); + if (q->image_box.width() < 0.001 || q->image_box.height() < 0.001) + err("Margins must result in positive image dimensions"); return q; } }; @@ -1267,6 +1281,14 @@ public: cropmark_spec *cmarks; void render(out_context *out, pdf_matrix xform) override; nup_page(nup_state &st) : page(st.paper_w, st.paper_h) { } + void debug_dump() override + { + debug("N-up printing"); + debug_indent += 4; + for (auto p: orig_pages) + p->debug_dump(); + debug_indent -= 4; + } }; void nup_page::render(out_context *out, pdf_matrix parent_xform) @@ -1364,6 +1386,11 @@ public: orig_page->render(out, xform); out->contents += cm->pdf_stream(out, image_box, xform); } + void debug_dump() override + { + debug("Add cropmarks"); + orig_page->debug_dump(); + } cropmarks_page(page *p, cropmark_spec *cms) : page(p), orig_page(p), cm(cms) { } }; @@ -1394,6 +1421,11 @@ public: orig_page->render(out, xform); out->contents += "Q "; } + void debug_dump() override + { + debug("Clip [%.3f %.3f %.3f %.3f]", clip_to.x_min, clip_to.y_min, clip_to.x_max, clip_to.y_max); + orig_page->debug_dump(); + } clip_page(page *p, BBox &to) : page(p), orig_page(p), clip_to(to) { } }; @@ -1416,6 +1448,103 @@ static const arg_def clip_args[] = { { NULL, 0, NULL } }; +/*** common ***/ + +class common_cmd : public cmd_exec { + vector process(vector &pages) override + { + if (!pages.size()) + return pages; + + const page *first = pages[0]; + BBox pbox(first->width, first->height); + BBox ibox = first->image_box; + for (auto p: pages) + { + BBox pg(p->width, p->height); + pbox.join(pg); + ibox.join(p->image_box); + } + + vector out; + for (auto p: pages) + { + page *q = new xform_page(p, pdf_matrix()); + q->width = pbox.width(); + q->height = pbox.height(); + q->image_box = ibox; + out.push_back(q); + } + + return out; + } +public: + common_cmd(cmd *c UNUSED) { } +}; + +/*** slice ***/ + +class slice_cmd : public cmd_exec { + paper_spec paper; + pos_spec pos; + margin_spec margin; + double bleed; +public: + slice_cmd(cmd *c) : paper(c), pos(c), margin(c, "margin", "margin") + { + if (is_zero(paper.w) || is_zero(paper.h)) + err("Paper format must be given"); + bleed = c->arg("bleed")->as_double(0); + } + vector process(vector &pages) override; +}; + +vector slice_cmd::process(vector &pages) +{ + vector out; + + for (auto p: pages) + { + double pw = paper.w - margin.l - margin.r; + double ph = paper.h - margin.t - margin.b; + if (pw < 0 || ph < 0) + err("Margins larger than paper"); + + int cols = (int) ceil((p->image_box.width() - 2*mm) / pw); + int rows = (int) ceil((p->image_box.height() - 2*mm) / ph); + BBox big_box(cols*pw, rows*ph); + pdf_matrix placement = pos.place(p->image_box, big_box); + + debug("Slicing [%.3f,%.3f] to %dx%d [%.3f,%.3f]", p->image_box.width(), p->image_box.height(), rows, cols, pw, ph); + for (int r=0; rwidth = paper.w; + q->height = paper.h; + BBox slice_box = BBox(margin.l, margin.t, paper.w - margin.r, paper.h - margin.b); + q->image_box = p->image_box.transformed(xf); + q->image_box.intersect(slice_box); + BBox bleeding_slice = slice_box.enlarged(bleed); + out.push_back(new clip_page(q, bleeding_slice)); + } + } + + return out; +} + +static const arg_def slice_args[] = { + PAPER_ARGS, + POS_ARGS, + MARGIN_ARGS1_NAMED("margin"), + MARGIN_ARGS2("margin"), + { "bleed", AT_DIMEN, "Allow bleeding of image outside its box" }, + { NULL, 0, NULL } +}; + /*** Command table ***/ template cmd_exec *ctor(cmd *c) { return new T(c); } @@ -1429,6 +1558,8 @@ const cmd_def cmd_table[] = { "Prepare booklets for book binding" }, { "clip", clip_args, 0, &ctor, "Suppress page contents drawn outside the image box" }, + { "common", no_args, 0, &ctor, + "Use a common page size and image box for all pages" }, { "cropmarks",cropmarks_args, 0, &ctor, "Draw cropping marks around the image box" }, { "debug", no_args, 0, &ctor, @@ -1461,6 +1592,8 @@ const cmd_def cmd_table[] = { "Scale the page to a given size" }, { "select", no_args, 1, &ctor, "Select a subset of pages" }, + { "slice", slice_args, 0, &ctor, + "Slice to smaller pages" }, { NULL, NULL, 0, NULL, NULL, } };