moving xhtml_utils to objavi because only objavi uses it, and combining document...
[objavi2.git] / wk_objavi.qs
blob77afe899b5016b98cf51cb8cb9bbbcc3e91aabff
1 // Console: wk_objavi
2 // Description: shift margins left and right and add page numbers for wkhtmltopdf PDFs
4 /* ^^^^ previous lines are pdfedit magic. Let them be!
6 Part of Objavi2, which makes pdf versions of FLOSSManuals books.
8 This file is QSAscript for pdfedit. It makes pdfs more book-like,
9 adding gutters and page numbers.
11 Copyright (C) 2009 Douglas Bagnall
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or (at
16 your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License along
24 with this program; if not, write to the Free Software Foundation, Inc.,
25 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
30 run("libobjavi.qs");
32 run( "pdfoperator.qs" ); // pdfedit stdlib, from /usr/share/pdfedit
34 function get_page_inverse_transform(page){
35     /*This is somewhat inefficient if the only transformation is at
36      the beginning of stream 0, which seems invariably to be the case.
37      */
39     var stream = page.getContentStream(page.getContentStreamCount() - 1);
40     var op = stream.getLastOperator();
41     //from /usr/share/pdfedit/pdfoperator.qs
42     var transform = get_cmToDetransformation(page, op);
43     var transform = getDetransformationMatrix(page, op);
44     return transform;
47 function number_check(parser, name, default_value){
48     return function(s){
49         var x = parser(s);
50         if (isNaN(x) && name)
51             throw(name + ' should be a number! (not "' + s + '")');
52         if (default_value != undefined)
53             return x || default_value;
54         return x;
55     };
59 const OPERATIONS = {
60     adjust_for_direction: 1,
61     resize: 2,
62     transform: 4,
63     shift: 8,
64     page_numbers: 16,
65     index: 32,
66     even_pages: 64,
68     all: 0xffff
71 const DEFAULT_OPERATION = 0;
73 function convert_operation(x){
74     if (! x){
75         x = 'all';
76     }
77     var words = x.lower().split(',');
78     var ops = 0;
79     for (var i = 0; i < words.length; i++){
80         var op = OPERATIONS[words[i]];
81         if (op)
82             ops |= op;
83     }
84     return ops;
88 function onConsoleStart() {
89     print("in wk_objavi");
91     var convertors = {
92         offset: number_check(parseFloat, 'offset'),
93         dir: function(x){return x.upper();},
94         number_style: function(x){return x.lower();},
95         centre_first: function(x){return x.lower() == 'true';},
96         centre_last: function(x){return x.lower() == 'true';},
97         number_start: number_check(parseInt, 'number_start', 1),
98         number_bottom: number_check(parseFloat, 'number_bottom'),
99         number_margin: number_check(parseFloat, 'number_margin'),
100         width: number_check(parseFloat, 'width'),
101         height: number_check(parseFloat, 'height'),
102         operation: convert_operation
103     };
105     var options = {
106         offset: DEFAULT_OFFSET,
107         dir:    DEFAULT_DIR,
108         number_style: DEFAULT_NUMBER_STYLE,
109         number_start: 1,
110         number_bottom: 20,
111         number_margin: 60,
112         filename: '',
113         output_filename: undefined,
114         width: COMIC_WIDTH,
115         height: COMIC_HEIGHT,
116         engine: DEFAULT_ENGINE,
117         centre_first: 'false',
118         centre_last: 'false',
119         operation: DEFAULT_OPERATION
120     };
122     options = parse_options(parameters(), options, convertors);
124     /* Rather than overwrite the file, copy it first to a similar name
125     and work on that ("saveas" doesn't work) */
126     var re = /^(.+)\.pdf$/i;
127     var m = re.search(options.filename);
128     if (m == -1){
129         throw(options.filename + " doesn't look like a pdf filename");
130     }
131     var newfilename = options.output_filename;
132     if (newfilename == undefined)
133         newfilename = re.cap(1) + '-PDFEDIT.pdf';
134     if (newfilename != options.filename)
135         Process.execute("cp " + options.filename + ' ' + newfilename);
137     var pdf = this.loadPdf(newfilename, 1);
140     function doing_op(op){
141         var ret = options.operation & OPERATIONS[op];
142         if (ret)
143             print("doing " + op);
144         return ret;
145     }
147     if (doing_op('even_pages')){
148         even_pages(pdf);
149     }
151     if (doing_op('adjust_for_direction')){
152         adjust_for_direction(pdf, options.offset, options.dir);
153     }
155     if (doing_op('resize')){
156         process_pdf(pdf, shift_page_mediabox, {offset: 0,
157                                                width: options.width,
158                                                height: options.height,
159                                                flip: undefined
160                                               });
161     }
162     if (doing_op('transform')){
163         process_pdf(pdf, transform_page, {offset: options.offset,
164                                           dir: options.dir,
165                                           flip: "offset"
166                                          },
167                                          (options.centre_first) ? 1 : undefined,
168                                          (options.centre_last) ? 1 : undefined
169                    );
170     }
171     if (doing_op('shift')){
172         process_pdf(pdf, shift_page_mediabox, {offset: options.offset,
173                                                flip: "offset",
174                                                width: options.width,
175                                                height: options.height
176                                               },
177                                               (options.centre_first) ? 1 : undefined,
178                                               (options.centre_last) ? 1 : undefined
179                    );
180     }
181     if (doing_op('page_numbers') &&
182         options.number_style != 'none'){
183         number_pdf_pages(pdf, options.dir, options.number_style,
184                          options.number_start, options.number_margin, options.number_bottom
185                         );
186     }
187     if (doing_op('index')){
188         save_text_index(pdf, newfilename+'.index');
189     }
191     pdf.save();
193     pdf.unloadPdf();