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<page *> process(vector<page *> &pages) override;
+};
+
+vector<page *> slice_cmd::process(vector<page *> &pages)
+{
+ vector<page *> 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; r<rows; r++)
+ for (int c=0; c<cols; c++)
+ {
+ pdf_matrix xf = placement;
+ xf.shift(-c*pw, -(rows-1-r)*ph);
+ xf.shift(margin.l, margin.t);
+ page *q = new xform_page(p, xf);
+ q->width = 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<typename T> cmd_exec *ctor(cmd *c) { return new T(c); }
"Scale the page to a given size" },
{ "select", no_args, 1, &ctor<select_cmd>,
"Select a subset of pages" },
+ { "slice", slice_args, 0, &ctor<slice_cmd>,
+ "Slice to smaller pages" },
{ NULL, NULL, 0, NULL,
NULL, }
};
command forms two temporary documents, concatenates them to the result of select, and finally applies
common.
+slice
+~~~~~
+Slices the image to several smaller pages. Each page receives a part of the original
+image, gluing the parts together produces the original image.
+
+*[paper=]*'string', *w=*'dimen', *h=*'dimen'::
+ Paper size of the produced pages (see Paper formats above).
+
+*pos=*'string'::
+ Position of the original image on a "canvas" obtained by gluing
+ together non-margin parts of the produced pages (see Positioning above).
+ Default: *cc*.
+
+*margin=*'dimen', *hmargin=*'dimen', *vmargin=*'dimen', *lmargin=*'dimen', *rmargin=*'dimen', *tmargin=*'dimen', *bmargin=*'dimen'::
+ Set margins of the produced pages (see Margins above). Defaults to 0.
+
+*bleed=*'dimen'::
+ Let the parts of the image bleed this far outside their boxes.
+
LICENSE
-------
PaperJam was written by Martin Mares.
y_max = max(y_max, with.y_max);
}
+static double clamp(double x, double min, double max)
+{
+ if (x < min)
+ return min;
+ if (x > max)
+ return max;
+ return x;
+}
+
+void BBox::intersect(BBox &with)
+{
+ x_min = clamp(x_min, with.x_min, with.x_max);
+ x_max = clamp(x_max, with.x_min, with.x_max);
+ y_min = clamp(y_min, with.y_min, with.y_max);
+ y_max = clamp(y_max, with.y_min, with.y_max);
+}
+
void BBox::enlarge(double by)
{
x_min -= by;