9 class null_cmd : public cmd_exec {
10 vector<page *> process(vector<page *> &pages) { return pages; }
13 static const arg_def no_args[] = {
17 static cmd_exec *null_ctor(cmd *c UNUSED)
22 /*** Generic transformed page ***/
24 class xform_page : public page {
28 void render(out_context *out, pdf_matrix xform);
29 xform_page(page *p, pdf_matrix xf);
32 xform_page::xform_page(page *p, pdf_matrix xf)
38 BBox media(p->width, p->height);
40 width = media.width();
41 height = media.height();
47 void xform_page::render(out_context *out, pdf_matrix parent_xform)
49 orig_page->render(out, xform * parent_xform);
54 class move_cmd : public cmd_exec {
57 vector<page *> process(vector<page *> &pages);
60 vector<page *> move_cmd::process(vector<page *> &pages)
67 out.push_back(new xform_page(p, m));
72 static const arg_def move_args[] = {
73 { "x", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
74 { "y", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
78 static cmd_exec *move_ctor(cmd *c)
80 move_cmd *m = new move_cmd;
81 m->x = c->args.at(0)->as_double(0);
82 m->y = c->args.at(1)->as_double(0);
88 class scale_cmd : public cmd_exec {
90 double x_factor, y_factor;
91 vector<page *> process(vector<page *> &pages);
94 vector<page *> scale_cmd::process(vector<page *> &pages)
100 m.scale(x_factor, y_factor);
101 out.push_back(new xform_page(p, m));
106 static const arg_def scale_args[] = {
107 { "x", AT_DOUBLE | AT_MANDATORY | AT_POSITIONAL },
108 { "y", AT_DOUBLE | AT_POSITIONAL },
112 static cmd_exec *scale_ctor(cmd *c)
114 scale_cmd *s = new scale_cmd;
115 s->x_factor = c->args.at(0)->as_double(1);
116 s->y_factor = c->args.at(1)->as_double(s->x_factor);
122 class rotate_cmd : public cmd_exec {
125 vector<page *> process(vector<page *> &pages);
128 vector<page *> rotate_cmd::process(vector<page *> &pages)
140 m.shift(0, p->width);
144 m.shift(p->width, p->height);
148 m.shift(p->height, 0);
153 out.push_back(new xform_page(p, m));
158 static const arg_def rotate_args[] = {
159 { "angle", AT_INT | AT_MANDATORY | AT_POSITIONAL },
163 static cmd_exec *rotate_ctor(cmd *c)
165 rotate_cmd *r = new rotate_cmd;
166 r->deg = c->args.at(0)->as_int(0) % 360;
170 die("Rotate requires a multiple of 90 degrees");
176 class select_cmd : public cmd_exec {
179 vector<page *> process(vector<page *> &pages);
182 static int validate_page_index(vector<page *> &pages, int idx)
184 if (idx >= 1 && idx <= (int) pages.size())
186 if (idx <= -1 && idx >= (int) -pages.size())
187 return idx + pages.size();
188 die("Page index %d out of range", idx);
191 vector<page *> select_cmd::process(vector<page *> &pages)
194 for (auto pb: pipe->branches)
196 vector<page *> selected;
197 for (auto ps: pb->selectors)
199 int f = validate_page_index(pages, ps.from);
200 int t = validate_page_index(pages, ps.to);
201 int step = (f <= t) ? 1 : -1;
202 for (int i=f; f<=t; f += step)
203 selected.push_back(pages[i]);
205 auto processed = run_command_list(pb->commands, selected);
206 for (auto p: processed)
212 static cmd_exec *select_ctor(cmd *c)
214 select_cmd *r = new select_cmd;
221 class apply_cmd : public cmd_exec {
224 vector<page *> process(vector<page *> &pages);
227 static pipeline_branch *find_branch(pipeline *pipe, vector <page *> &pages, int idx)
229 for (auto pb: pipe->branches)
230 for (auto ps: pb->selectors)
232 int f = validate_page_index(pages, ps.from);
233 int t = validate_page_index(pages, ps.to);
234 if (f <= idx && idx <= t || t <= idx && idx <= f)
240 vector<page *> apply_cmd::process(vector<page *> &pages)
247 pipeline_branch *pb = find_branch(pipe, pages, cnt);
252 auto processed = run_command_list(pb->commands, tmp);
253 for (auto q: processed)
264 static cmd_exec *apply_ctor(cmd *c)
266 apply_cmd *r = new apply_cmd;
273 class modulo_cmd : public cmd_exec {
277 vector<page *> process(vector<page *> &pages);
280 vector<page *> modulo_cmd::process(vector<page *> &pages)
283 int tuples = ((int) pages.size() + n - 1) / n;
285 for (int tuple=0; tuple < tuples; tuple++)
287 debug("# Tuple %d", tuple);
289 for (auto pb: pipe->branches)
292 for (auto ps: pb->selectors)
296 int step = (f <= t) ? 1 : -1;
297 for (int i=f; i<=t; i += step)
302 else if (i < 0 && i >= -n)
303 j = (tuples-1-tuple)*n + (-i) - 1;
305 die("Modulo: invalid index %d", i);
306 if (j < (int) pages.size())
307 tmp.push_back(pages[j]);
310 page *ref_page = pages[tuple*n];
311 tmp.push_back(new empty_page(ref_page->width, ref_page->height));
315 auto processed = run_command_list(pb->commands, tmp);
316 for (auto q: processed)
325 static const arg_def modulo_args[] = {
326 { "n", AT_INT | AT_MANDATORY | AT_POSITIONAL },
330 static cmd_exec *modulo_ctor(cmd *c)
332 modulo_cmd *m = new modulo_cmd;
333 m->n = c->args.at(0)->as_int(0);
335 die("Modulo must have n > 0");
342 class draw_bbox_cmd : public cmd_exec {
344 vector<page *> process(vector<page *> &pages);
347 class draw_bbox_page : public page {
350 void render(out_context *out, pdf_matrix xform);
351 draw_bbox_page(page *p) : page(p) { orig_page = p; }
354 void draw_bbox_page::render(out_context *out, pdf_matrix xform)
356 orig_page->render(out, xform);
359 xform.to_string() + " cm " +
361 bbox.to_rect() + " re S " +
365 vector<page *> draw_bbox_cmd::process(vector<page *> &pages)
369 out.push_back(new draw_bbox_page(p));
373 static cmd_exec *draw_bbox_ctor(cmd *c UNUSED)
375 draw_bbox_cmd *m = new draw_bbox_cmd;
379 /*** Command table ***/
381 const cmd_def cmd_table[] = {
382 { "null", no_args, 0, null_ctor },
383 { "move", move_args, 0, move_ctor },
384 { "scale", scale_args, 0, scale_ctor },
385 { "rotate", rotate_args, 0, rotate_ctor },
386 { "select", no_args, 1, select_ctor },
387 { "apply", no_args, 1, apply_ctor },
388 { "modulo", modulo_args, 1, modulo_ctor },
389 { "draw_bbox",no_args, 0, draw_bbox_ctor },
390 { NULL, NULL, 0, NULL }