]> mj.ucw.cz Git - paperjam.git/blobdiff - cmds.cc
Store duplicate pages only once
[paperjam.git] / cmds.cc
diff --git a/cmds.cc b/cmds.cc
index 10dd4e0a17d4cc3f40eecd86128f0e6d73da8585..fa4f615fadeedf28b62aa917422dca6927b4c8f8 100644 (file)
--- a/cmds.cc
+++ b/cmds.cc
@@ -7,10 +7,10 @@
 /*** null ***/
 
 class null_cmd : public cmd_exec {
-    vector<page *> process(vector<page *> pages) { return pages; }
+  vector<page *> process(vector<page *> &pages) { return pages; }
 };
 
-static const arg_def null_args[] = {
+static const arg_def no_args[] = {
   { NULL,      0 }
 };
 
@@ -24,7 +24,7 @@ static cmd_exec *null_ctor(cmd *c UNUSED)
 class move_cmd : public cmd_exec {
 public:
   double x, y;
-  vector<page *> process(vector<page *> pages);
+  vector<page *> process(vector<page *> &pages);
 };
 
 class xform_page : public page {
@@ -40,7 +40,7 @@ void xform_page::render(page_out *out, pdf_matrix parent_xform)
   orig_page->render(out, xform * parent_xform);
 }
 
-vector<page *> move_cmd::process(vector<page *> pages)
+vector<page *> move_cmd::process(vector<page *> &pages)
 {
   vector<page *> out;
   for (auto p: pages)
@@ -61,8 +61,8 @@ static const arg_def move_args[] = {
 static cmd_exec *move_ctor(cmd *c)
 {
   move_cmd *m = new move_cmd;
-  m->x = c->args.at(0)->double_default(0);
-  m->y = c->args.at(1)->double_default(0);
+  m->x = c->args.at(0)->as_double(0);
+  m->y = c->args.at(1)->as_double(0);
   return m;
 }
 
@@ -71,10 +71,10 @@ static cmd_exec *move_ctor(cmd *c)
 class scale_cmd : public cmd_exec {
 public:
   double x_factor, y_factor;
-  vector<page *> process(vector<page *> pages);
+  vector<page *> process(vector<page *> &pages);
 };
 
-vector<page *> scale_cmd::process(vector<page *> pages)
+vector<page *> scale_cmd::process(vector<page *> &pages)
 {
   vector<page *> out;
   for (auto p: pages)
@@ -95,16 +95,119 @@ static const arg_def scale_args[] = {
 static cmd_exec *scale_ctor(cmd *c)
 {
   scale_cmd *s = new scale_cmd;
-  s->x_factor = c->args.at(0)->double_default(1);
-  s->y_factor = c->args.at(1)->double_default(s->x_factor);
+  s->x_factor = c->args.at(0)->as_double(1);
+  s->y_factor = c->args.at(1)->as_double(s->x_factor);
   return s;
 }
 
+/*** rotate ***/
+
+class rotate_cmd : public cmd_exec {
+public:
+  int deg;
+  vector<page *> process(vector<page *> &pages);
+};
+
+vector<page *> rotate_cmd::process(vector<page *> &pages)
+{
+  vector<page *> out;
+  for (auto p: pages)
+    {
+      xform_page *q = new xform_page(p, p->width, p->height);
+      switch (deg)
+       {
+       case 0:
+         break;
+       case 90:
+         q->xform.rotate_deg(-90);
+         q->xform.shift(0, p->width);
+         swap(q->width, q->height);
+         break;
+       case 180:
+         q->xform.rotate_deg(180);
+         q->xform.shift(p->width, p->height);
+         break;
+       case 270:
+         q->xform.rotate_deg(90);
+         q->xform.shift(p->height, 0);
+         swap(q->width, q->height);
+         break;
+       default:
+         abort();
+       }
+      out.push_back(q);
+    }
+  return out;
+}
+
+static const arg_def rotate_args[] = {
+  { "angle",   AT_INT | AT_MANDATORY | AT_POSITIONAL },
+  { NULL,      0 }
+};
+
+static cmd_exec *rotate_ctor(cmd *c)
+{
+  rotate_cmd *r = new rotate_cmd;
+  r->deg = c->args.at(0)->as_int(0) % 360;
+  if (r->deg < 0)
+    r->deg += 360;
+  if (r->deg % 90)
+    die("Rotate requires a multiple of 90 degrees");
+  return r;
+}
+
+/*** select ***/
+
+class select_cmd : public cmd_exec {
+public:
+  pipeline *pipe;
+  vector<page *> process(vector<page *> &pages);
+};
+
+static int validate_page_index(vector<page *> &pages, int idx)
+{
+  if (idx >= 1 && idx <= (int) pages.size())
+    return idx - 1;
+  if (idx <= -1 && idx >= (int) -pages.size())
+    return idx + pages.size();
+  die("Page index %d out of range", idx);
+}
+
+vector<page *> select_cmd::process(vector<page *> &pages)
+{
+  vector<page *> out;
+  for (auto pb: pipe->branches)
+    for (auto ps: pb->selectors)
+      {
+       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)
+         {
+           vector<page *> selected;
+           selected.push_back(pages[i]);
+           selected = run_command_list(pb->commands, selected);
+           for (auto p: selected)
+             out.push_back(p);
+         }
+      }
+  return out;
+}
+
+static cmd_exec *select_ctor(cmd *c)
+{
+  select_cmd *r = new select_cmd;
+  r->pipe = c->pipe;
+  return r;
+}
+
 /*** Command table ***/
 
 const cmd_def cmd_table[] = {
+  { "null",    no_args,        0,      null_ctor       },
   { "move",    move_args,      0,      move_ctor       },
   { "scale",   scale_args,     0,      scale_ctor      },
-  { "null",    null_args,      0,      null_ctor       },
+  { "rotate",  rotate_args,    0,      rotate_ctor     },
+  { "select",  no_args,        1,      select_ctor     },
   { NULL,      NULL,           0,      NULL    }
 };