9 class null_cmd : public cmd_exec {
10 vector<page *> process(vector<page *> &pages) override { 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) override;
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);
52 class cmd_exec_simple : public cmd_exec {
53 virtual page *process_page(page *p) = 0;
54 vector<page *> process(vector<page *> &pages) override;
57 vector<page *> cmd_exec_simple::process(vector<page *> &pages)
61 out.push_back(process_page(p));
67 class move_cmd : public cmd_exec_simple {
70 page *process_page(page *p) override
74 return new xform_page(p, m);
78 static const arg_def move_args[] = {
79 { "x", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
80 { "y", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
84 static cmd_exec *move_ctor(cmd *c)
86 move_cmd *m = new move_cmd;
87 m->x = c->args.at(0)->as_double(0);
88 m->y = c->args.at(1)->as_double(0);
94 class scale_cmd : public cmd_exec_simple {
96 double x_factor, y_factor;
97 page *process_page(page *p) override
100 m.scale(x_factor, y_factor);
101 return new xform_page(p, m);
105 static const arg_def scale_args[] = {
106 { "x", AT_DOUBLE | AT_MANDATORY | AT_POSITIONAL },
107 { "y", AT_DOUBLE | AT_POSITIONAL },
111 static cmd_exec *scale_ctor(cmd *c)
113 scale_cmd *s = new scale_cmd;
114 s->x_factor = c->args.at(0)->as_double(1);
115 s->y_factor = c->args.at(1)->as_double(s->x_factor);
121 class rotate_cmd : public cmd_exec_simple {
124 page *process_page(page *p) override
133 m.shift(0, p->width);
137 m.shift(p->width, p->height);
141 m.shift(p->height, 0);
146 return new xform_page(p, m);
150 static const arg_def rotate_args[] = {
151 { "angle", AT_INT | AT_MANDATORY | AT_POSITIONAL },
155 static cmd_exec *rotate_ctor(cmd *c)
157 rotate_cmd *r = new rotate_cmd;
158 r->deg = c->args.at(0)->as_int(0) % 360;
162 die("Rotate requires a multiple of 90 degrees");
168 class flip_cmd : public cmd_exec_simple {
172 page *process_page(page *p) override
178 m.shift(0, p->height);
183 m.shift(p->width, 0);
185 return new xform_page(p, m);
189 static const arg_def flip_args[] = {
195 static cmd_exec *flip_ctor(cmd *c)
197 flip_cmd *f = new flip_cmd;
198 f->horizontal = c->args.at(0)->as_int(0);
199 f->vertical = c->args.at(1)->as_int(0);
200 if (!f->horizontal && !f->vertical)
201 die("Flip has no direction specified");
207 class select_cmd : public cmd_exec {
210 vector<page *> process(vector<page *> &pages);
213 static int validate_page_index(vector<page *> &pages, int idx)
215 if (idx >= 1 && idx <= (int) pages.size())
217 if (idx <= -1 && idx >= (int) -pages.size())
218 return idx + pages.size();
219 die("Page index %d out of range", idx);
222 vector<page *> select_cmd::process(vector<page *> &pages)
225 for (auto pb: pipe->branches)
227 vector<page *> selected;
228 for (auto ps: pb->selectors)
230 int f = validate_page_index(pages, ps.from);
231 int t = validate_page_index(pages, ps.to);
232 int step = (f <= t) ? 1 : -1;
233 for (int i=f; f<=t; f += step)
234 selected.push_back(pages[i]);
236 auto processed = run_command_list(pb->commands, selected);
237 for (auto p: processed)
243 static cmd_exec *select_ctor(cmd *c)
245 select_cmd *r = new select_cmd;
252 class apply_cmd : public cmd_exec {
255 vector<page *> process(vector<page *> &pages);
258 static pipeline_branch *find_branch(pipeline *pipe, vector <page *> &pages, int idx)
260 for (auto pb: pipe->branches)
261 for (auto ps: pb->selectors)
263 int f = validate_page_index(pages, ps.from);
264 int t = validate_page_index(pages, ps.to);
265 if (f <= idx && idx <= t || t <= idx && idx <= f)
271 vector<page *> apply_cmd::process(vector<page *> &pages)
278 pipeline_branch *pb = find_branch(pipe, pages, cnt);
283 auto processed = run_command_list(pb->commands, tmp);
284 for (auto q: processed)
295 static cmd_exec *apply_ctor(cmd *c)
297 apply_cmd *r = new apply_cmd;
304 class modulo_cmd : public cmd_exec {
308 vector<page *> process(vector<page *> &pages);
311 vector<page *> modulo_cmd::process(vector<page *> &pages)
314 int tuples = ((int) pages.size() + n - 1) / n;
316 for (int tuple=0; tuple < tuples; tuple++)
318 debug("# Tuple %d", tuple);
320 for (auto pb: pipe->branches)
323 for (auto ps: pb->selectors)
327 int step = (f <= t) ? 1 : -1;
328 for (int i=f; i<=t; i += step)
333 else if (i < 0 && i >= -n)
334 j = (tuples-1-tuple)*n + (-i) - 1;
336 die("Modulo: invalid index %d", i);
337 if (j < (int) pages.size())
338 tmp.push_back(pages[j]);
341 page *ref_page = pages[tuple*n];
342 tmp.push_back(new empty_page(ref_page->width, ref_page->height));
346 auto processed = run_command_list(pb->commands, tmp);
347 for (auto q: processed)
356 static const arg_def modulo_args[] = {
357 { "n", AT_INT | AT_MANDATORY | AT_POSITIONAL },
361 static cmd_exec *modulo_ctor(cmd *c)
363 modulo_cmd *m = new modulo_cmd;
364 m->n = c->args.at(0)->as_int(0);
366 die("Modulo must have n > 0");
373 class draw_bbox_cmd : public cmd_exec {
375 vector<page *> process(vector<page *> &pages);
378 class draw_bbox_page : public page {
381 void render(out_context *out, pdf_matrix xform);
382 draw_bbox_page(page *p) : page(p) { orig_page = p; }
385 void draw_bbox_page::render(out_context *out, pdf_matrix xform)
387 orig_page->render(out, xform);
390 xform.to_string() + " cm " +
392 bbox.to_rect() + " re S " +
396 vector<page *> draw_bbox_cmd::process(vector<page *> &pages)
400 out.push_back(new draw_bbox_page(p));
404 static cmd_exec *draw_bbox_ctor(cmd *c UNUSED)
406 draw_bbox_cmd *m = new draw_bbox_cmd;
410 /*** Command table ***/
412 const cmd_def cmd_table[] = {
413 { "null", no_args, 0, null_ctor },
414 { "move", move_args, 0, move_ctor },
415 { "scale", scale_args, 0, scale_ctor },
416 { "rotate", rotate_args, 0, rotate_ctor },
417 { "flip", flip_args, 0, flip_ctor },
418 { "select", no_args, 1, select_ctor },
419 { "apply", no_args, 1, apply_ctor },
420 { "modulo", modulo_args, 1, modulo_ctor },
421 { "draw_bbox",no_args, 0, draw_bbox_ctor },
422 { NULL, NULL, 0, NULL }