return r;
}
+/*** apply ***/
+
+class apply_cmd : public cmd_exec {
+public:
+ pipeline *pipe;
+ vector<page *> process(vector<page *> &pages);
+};
+
+static pipeline_branch *find_branch(pipeline *pipe, vector <page *> &pages, int idx)
+{
+ 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);
+ if (f <= idx && idx <= t || t <= idx && idx <= f)
+ return pb;
+ }
+ return NULL;
+}
+
+vector<page *> apply_cmd::process(vector<page *> &pages)
+{
+ vector<page *> out;
+
+ int cnt = 0;
+ for (auto p: pages)
+ {
+ pipeline_branch *pb = find_branch(pipe, pages, cnt);
+ if (pb)
+ {
+ vector<page *> tmp;
+ tmp.push_back(p);
+ auto processed = run_command_list(pb->commands, tmp);
+ for (auto q: processed)
+ out.push_back(q);
+ }
+ else
+ out.push_back(p);
+ cnt++;
+ }
+
+ return out;
+}
+
+static cmd_exec *apply_ctor(cmd *c)
+{
+ apply_cmd *r = new apply_cmd;
+ r->pipe = c->pipe;
+ return r;
+}
+
+/*** modulo ***/
+
+class modulo_cmd : public cmd_exec {
+public:
+ pipeline *pipe;
+ int n;
+ vector<page *> process(vector<page *> &pages);
+};
+
+vector<page *> modulo_cmd::process(vector<page *> &pages)
+{
+ vector<page *> out;
+ int tuples = ((int) pages.size() + n - 1) / n;
+
+ for (int tuple=0; tuple < tuples; tuple++)
+ {
+ debug("# Tuple %d", tuple);
+ debug_indent += 4;
+ for (auto pb: pipe->branches)
+ {
+ vector<page *> tmp;
+ for (auto ps: pb->selectors)
+ {
+ int f = ps.from;
+ int t = ps.to;
+ int step = (f <= t) ? 1 : -1;
+ for (int i=f; i<=t; i += step)
+ {
+ int j;
+ if (i > 0 && i <= n)
+ j = tuple*n + i - 1;
+ else if (i < 0 && i >= -n)
+ j = (tuples-1-tuple)*n + (-i) - 1;
+ else
+ die("Modulo: invalid index %d", i);
+ if (j < (int) pages.size())
+ tmp.push_back(pages[j]);
+ else
+ {
+ page *ref_page = pages[tuple*n];
+ tmp.push_back(new empty_page(ref_page->width, ref_page->height));
+ }
+ }
+ }
+ auto processed = run_command_list(pb->commands, tmp);
+ for (auto q: processed)
+ out.push_back(q);
+ }
+ debug_indent -= 4;
+ }
+
+ return out;
+}
+
+static const arg_def modulo_args[] = {
+ { "n", AT_INT | AT_MANDATORY | AT_POSITIONAL },
+ { NULL, 0 }
+};
+
+static cmd_exec *modulo_ctor(cmd *c)
+{
+ modulo_cmd *m = new modulo_cmd;
+ m->n = c->args.at(0)->as_int(0);
+ if (m->n <= 0)
+ die("Modulo must have n > 0");
+ m->pipe = c->pipe;
+ return m;
+}
+
/*** Command table ***/
const cmd_def cmd_table[] = {
{ "scale", scale_args, 0, scale_ctor },
{ "rotate", rotate_args, 0, rotate_ctor },
{ "select", no_args, 1, select_ctor },
+ { "apply", no_args, 1, apply_ctor },
+ { "modulo", modulo_args, 1, modulo_ctor },
{ NULL, NULL, 0, NULL }
};