]> mj.ucw.cz Git - paperjam.git/commitdiff
Implemented slice
authorMartin Mares <mj@ucw.cz>
Fri, 1 Jun 2018 22:14:02 +0000 (00:14 +0200)
committerMartin Mares <mj@ucw.cz>
Fri, 1 Jun 2018 22:26:34 +0000 (00:26 +0200)
cmds.cc
paperjam.1.txt
pdf-tools.cc
pdf-tools.h

diff --git a/cmds.cc b/cmds.cc
index a0be5731a04188d1c7792007003c9bbfd628a0da..3fc12142d10333db5bc53f23be2c19983b6a3f45 100644 (file)
--- a/cmds.cc
+++ b/cmds.cc
@@ -1450,6 +1450,69 @@ 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<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); }
@@ -1497,6 +1560,8 @@ const cmd_def cmd_table[] = {
                "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, }
 };
index 412f8df26a85c869a6c1ec0543dc6a4756ee0285..471e30ef7fff93e1733127be178bb6438c2e5aff 100644 (file)
@@ -459,6 +459,25 @@ which immediately becomes the result of select, to which the final common is app
 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.
index 809238c3b662e6138f55eecd2f968584c61e89c5..6a0b9b6e01db0d82a594f3e51cae8a51a45ca212 100644 (file)
@@ -99,6 +99,23 @@ void BBox::join(BBox &with)
        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;
index de79f534565d51476914470bb74755712754975f..46430f4bd426d9f9835b5db7b6ba1ec6127dfa14 100644 (file)
@@ -133,6 +133,7 @@ struct BBox {
        void enlarge(double by);
        BBox enlarged(double by);
        void join(BBox &with);
+       void intersect(BBox &with);
 private:
        bool parse(QPDFObjectHandle h);
 };