1. Changed license year
[apps/home/mobileprint.git] / mobileprint / previewgen / lib / page_preview.c
1 /*
2 *  Mobileprint
3 *
4 * Copyright 2012  Samsung Electronics Co., Ltd
5
6 * Licensed under the Flora License, Version 1.1 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://floralicense.org/license/
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include <Ecore.h>
29 #include <Evas.h>
30 /*#include <Evas_Engine_Buffer.h>*/
31
32 #include "evas_render.h"
33 #include "image_scaler.h"
34 #include "paper_size.h"
35 #include "pgen_debug.h"
36 #include "preview_util.h"
37
38 #include "page_preview.h"
39
40 const int gl_is_image_downscale = 1;
41 const int gl_is_half_pdf_raster = 1;
42
43 /**
44  * @brief       Get PDF page content image
45  * @param[in]   canvas          canvas of new image object
46  * @param[in]   img_buf
47  * @param[in]   img_size
48  * @return      image object with page content image
49  */
50 Evas_Object *get_pdf_img(Evas *canvas,
51                                                  void *img_buf, int img_size)
52 {
53         PGEN_TRACE_BEGIN;
54         PGEN_RETV_IF(canvas == NULL || img_buf == NULL || img_size <= 0, NULL, "Invalid argument");
55
56         Evas_Object *img = NULL;
57         img = evas_object_image_filled_add(canvas);
58         evas_object_image_memfile_set(img, img_buf, img_size,"ppm", NULL);
59         PGEN_IF_FREE_MEM(img_buf); /* copy saved in image */
60
61         PGEN_TRACE_END;
62         return img;
63 }
64
65 /**
66  * @brief       Grayscales provided RGBA pixel
67  * @param[in]   rgba_val        pixel to grayscale
68  * @result      grayscaled pixel
69  */
70 inline int grayscale_rgba(int rgba_val)
71 {
72         /* just sumple formula for sRGB conversion, maybe gamma-correction
73            or color profile using is required */
74         unsigned char *bytes = (unsigned char *)&rgba_val;
75         double res = 0.21 * bytes[0] + 0.72 * bytes[1] + 0.07 * bytes[2];
76         int i;
77
78         for (i = 0; i < 3; ++i) {
79                 bytes[i] = (unsigned char)res;
80         }
81
82         return rgba_val;
83 }
84
85 /**
86  * @brief       Grayscales image
87  * @param[in]   img     image to grayscale
88  */
89 void grayscale_img(Evas_Object *img)
90 {
91         int h;
92         int w;
93         int i;
94         int *data;
95
96         PGEN_TRACE_BEGIN;
97         PGEN_RET_IF(img == NULL, "Invalid argument");
98
99         evas_object_image_size_get(img, &w, &h);
100         PGEN_RET_IF(w == 0 || h == 0 , "can't get (w, h)");
101         PGEN_DEBUG("grayscale_img(): size: (%d, %d)", w, h);
102
103         data = evas_object_image_data_get(img, EINA_TRUE);
104         PGEN_RET_IF(data == NULL, "can't get data");
105
106         for (i = 0; i < w * h; ++i) {
107                 data[i] = grayscale_rgba(data[i]);
108         }
109         evas_object_image_data_set(img, data);
110
111         PGEN_TRACE_END;
112 }
113
114 int set_canvas_background(Evas *canvas, const struct size_px *full_size)
115 {
116         Evas_Object *bg;
117
118         PGEN_RETV_IF(canvas == NULL || full_size == NULL, -1, "Invalid argument");
119
120         /* background */
121         bg = evas_object_rectangle_add(canvas);
122         //evas_object_color_set(bg, 242, 238, 233, 255);
123         evas_object_color_set(bg, 255,255, 255, 255);
124         evas_object_move(bg, 0, 0);
125         evas_object_resize(bg, full_size->x, full_size->y);
126         evas_object_show(bg);
127
128         return 0;
129 }
130
131 /**
132  *
133  *
134  */
135 int set_preview_page(Evas *canvas,
136                                          const struct size_px *b_s, const struct size_px *p_s,
137                                          const struct size_px *border_size,
138                                          const struct size_px *off)
139 {
140         PGEN_TRACE_BEGIN;
141         PGEN_RETV_IF(canvas == NULL || b_s == NULL || p_s == NULL || off == NULL, -1 , "Invalid argument");
142
143         Evas_Object *bg;
144         int shadow_offset_x;
145         int shadow_offset_y;
146
147         shadow_offset_x = (b_s->x - p_s->x);
148         shadow_offset_y = (b_s->y - p_s->y);
149
150         /* background */
151         bg = evas_object_rectangle_add(canvas);
152         //evas_object_color_set(bg, 242, 238, 233, 255);
153         evas_object_color_set(bg, 255, 255, 255, 255);
154         evas_object_move(bg, off->x, off->y);
155         evas_object_resize(bg, b_s->x, b_s->y);
156         evas_object_show(bg);
157
158         bg = evas_object_rectangle_add(canvas);
159         evas_object_color_set(bg, 100, 100, 100, 255); /* shadow color */
160         evas_object_move(bg, shadow_offset_x + off->x - border_size->x * 2,
161                                          shadow_offset_y + off->y - border_size->y * 2);
162         evas_object_resize(bg, p_s->x + border_size->x,
163                                            p_s->y + border_size->y);
164         evas_object_show(bg);
165
166         bg = evas_object_rectangle_add(canvas);
167         evas_object_color_set(bg, 0, 0, 0, 255); /* border color */
168         evas_object_move(bg, off->x, off->y);
169         evas_object_resize(bg, p_s->x + border_size->x * 2,
170                                            p_s->y + border_size->y * 2);
171         evas_object_show(bg);
172
173         bg = evas_object_rectangle_add(canvas);
174         evas_object_color_set(bg, 255, 255, 255, 255); /* page color */
175         evas_object_move(bg, border_size->x + off->x, border_size->y + off->y);
176         evas_object_resize(bg, p_s->x, p_s->y);
177         evas_object_show(bg);
178
179         PGEN_TRACE_END;
180         return 0;
181 }
182
183 int load_pdf_page_img(const char *fname, int page,
184                                           const struct preview_page_px *settings_px,
185                                           void **out_img, int *size)
186 {
187         struct pdf_preview_settings pdf_settings;
188         PGEN_RETV_IF(fname == NULL || page <= 0  || settings_px == NULL || out_img == NULL || size == NULL
189                                 , -1 , "Invalid argument");
190
191         /* put page image */
192         pdf_settings.w = settings_px->area_size.x;
193         pdf_settings.h = settings_px->area_size.y;
194         if (gl_is_half_pdf_raster) {
195                 /* half-rasterization hack is used to increase speed */
196                 pdf_settings.w = pdf_settings.w / 2;
197                 pdf_settings.h = pdf_settings.h / 2;
198         }
199         pdf_settings.page = page;
200
201         return get_pdf_preview(fname, &pdf_settings, out_img, size);
202 }
203
204 /**
205  *
206  *
207  *
208  */
209 int set_pdf_preview_page_image(Evas *canvas,
210                                                            void *img_buf, int img_size,
211                                                            const struct size_px *off,
212                                                            const struct preview_page_px *settings_px)
213 {
214         PGEN_RETV_IF(canvas == NULL || img_buf == NULL || img_size <=0 || off == NULL || settings_px == NULL
215                                 , -1 , "Invalid argument");
216
217         Evas_Object *img;
218         struct size_px border_size = {1, 1};
219
220         if (set_preview_page(canvas, &(settings_px->full_size),
221                                                  &(settings_px->paper_size), &border_size, off) < 0) {
222                 PGEN_DEBUG("ERROR in set_preview_page()");
223                 return -1;
224         }
225
226         img = get_pdf_img(canvas, img_buf, img_size);
227         PGEN_RETV_IF(img == NULL, -1 , "img is NULL");
228
229         if (settings_px->is_rotate90
230                         && rotate90_image(img) < 0) {
231                 PGEN_DEBUG("ERROR in rotate90_image()");
232                 return -1;
233         }
234         evas_object_resize(img, settings_px->area_size.x,
235                                            settings_px->area_size.y);
236         if (settings_px->is_grayscale) {
237                 PGEN_DEBUG("Grayscaling image");
238                 grayscale_img(img);
239         }
240
241         evas_object_move(img, settings_px->area_offset.x + off->x,
242                                          settings_px->area_offset.y + off->y);
243         evas_object_show(img);
244
245         return 0;
246 }
247
248 /**
249  *
250  *
251  *
252  */
253 int set_pdf_preview_page_image_w_np(Evas *canvas,
254                                                                         void *img_buf, int img_size,
255                                                                         int page_num, int pages_count,
256                                                                         const struct preview_settings_px *settings_px)
257 {
258         struct size_px border_size = {1, 1};
259         struct size_px center_off = {0, 0};
260         struct size_px left_off = {0, 0};
261         struct size_px right_off = {0, 0};
262
263         PGEN_TRACE_BEGIN;
264         PGEN_RETV_IF(canvas == NULL || img_buf == NULL || img_size <=0 || page_num <=0
265                                 || pages_count <=0 || settings_px == NULL, -1, "Invalid argument");
266
267         center_off.x = settings_px->center_off;
268         left_off.x = settings_px->left_off;
269         right_off.x = settings_px->right_off;
270
271         if (set_pdf_preview_page_image(canvas, img_buf, img_size,
272                                                                    &center_off, &(settings_px->page_px)) < 0) {
273                 PGEN_DEBUG("ERROR in set_pdf_preview_page_image()");
274                 PGEN_TRACE_END;
275                 return -1;
276         }
277
278         /* put side (previous and next) pages images */
279         /* TODO: check for pages availability */
280         if (pages_count > 1) {
281                 if (page_num > 1 &&
282                                 set_preview_page(canvas,
283                                                                  &(settings_px->page_px.full_size),
284                                                                  &(settings_px->page_px.paper_size),
285                                                                  &border_size, &left_off) < 0) {
286                         PGEN_DEBUG("ERROR in set_preview_page()");
287                         PGEN_TRACE_END;
288                         return -1;
289                 }
290
291                 if (page_num < pages_count &&
292                                 set_preview_page(canvas,
293                                                                  &(settings_px->page_px.full_size),
294                                                                  &(settings_px->page_px.paper_size),
295                                                                  &border_size, &right_off) < 0) {
296                         PGEN_DEBUG("ERROR in set_preview_page()");
297                         PGEN_TRACE_END;
298                         return -1;
299                 }
300         }
301
302         PGEN_TRACE_END;
303
304         return 0;
305 }
306
307 /**
308  * @brief       Writes preview page images to file
309  * @param[in]   pdf_fname       input PDF file name
310  * @param[in]   page_num        page number
311  * @param[in]   settings_pts    preview generation settings
312  * @param[in]   out_pic_fname   output image file name (PPM)
313  * @return      -1              error
314  *              0               OK
315  */
316 int save_pdf_preview_page_image(const char *pdf_fname, int page_num,
317                                                                 const struct preview_page_req *settings_pts,
318                                                                 const char *out_pic_fname)
319 {
320         Evas *canvas;
321         struct preview_page_px settings_px;
322         struct size_px off = {0, 0};
323         void *img_buf;
324         int img_size;
325
326         PGEN_TRACE_BEGIN;
327
328         if (get_preview_page_settings(settings_pts, &settings_px) < 0) {
329                 PGEN_DEBUG("ERROR: get_pdf_preview_page_image():"
330                                    " get_preview_page_settings()");
331                 PGEN_TRACE_END;
332                 return -1;
333         }
334
335         canvas = create_canvas(&(settings_px.full_size));
336         PGEN_RETV_IF(canvas == NULL, -1, "canvas is NULL");
337
338         if (load_pdf_page_img(pdf_fname, page_num, &settings_px,
339                                                   &img_buf, &img_size) < 0) {
340                 PGEN_TRACE_END;
341                 return -1;
342         }
343
344         if (set_pdf_preview_page_image(canvas, img_buf, img_size,
345                                                                    &off, &settings_px) < 0) {
346                 PGEN_DEBUG("ERROR in set_pdf_preview_page_image()");
347                 destroy_canvas(canvas);
348                 PGEN_TRACE_END;
349                 return -1;
350         }
351
352         draw_scene(canvas);
353         save_scene(canvas, out_pic_fname);
354         destroy_canvas(canvas);
355
356         PGEN_TRACE_END;
357
358         return 0;
359 }
360
361
362 int save_empty_preview_page_image(const struct preview_page_req *settings_pts,
363                                 const char *out_pic_fname)
364 {
365         Evas *canvas;
366         struct preview_page_px settings_px;
367         struct size_px off = {0, 0};
368         struct size_px border_size = {1, 1};
369
370         PGEN_TRACE_BEGIN;
371
372         if (get_preview_page_settings(settings_pts, &settings_px) < 0) {
373                 PGEN_DEBUG("ERROR: get_pdf_preview_page_image():"
374                                    " get_preview_page_settings()");
375                 PGEN_TRACE_END;
376                 return -1;
377         }
378
379         canvas = create_canvas(&(settings_px.full_size));
380         PGEN_RETV_IF(canvas == NULL, -1, "canvas is NULL");
381
382         if (set_preview_page(canvas, &(settings_px.full_size),
383                          &(settings_px.paper_size), &border_size, &off) < 0) {
384                 PGEN_DEBUG("ERROR in set_preview_page()");
385                 destroy_canvas(canvas);
386                 PGEN_TRACE_END;
387                 return -1;
388         }
389
390         draw_scene(canvas);
391         save_scene(canvas, out_pic_fname);
392         destroy_canvas(canvas);
393
394         PGEN_TRACE_END;
395
396         return 0;
397 }
398
399
400 int save_pdf_preview_page_image_w_np(
401         void *img_buf, int img_size,
402         int page_num, int pages_count,
403         const struct preview_settings_px *settings_px,
404         const char *out_pic_fname)
405 {
406         PGEN_TRACE_BEGIN;
407         Evas *canvas;
408         canvas = create_canvas(&(settings_px->full_size));
409         PGEN_RETV_IF(canvas == NULL, -1, "canvas is NULL");
410
411         /* till we save page images in PPM this is required */
412         if (set_canvas_background(canvas, &(settings_px->full_size)) < 0) {
413                 PGEN_DEBUG("ERROR in set_canvas_background()");
414                 destroy_canvas(canvas);
415                 PGEN_TRACE_END;
416                 return -1;
417         }
418
419         if (set_pdf_preview_page_image_w_np(canvas, img_buf, img_size,
420                                                                                 page_num, pages_count, settings_px) < 0) {
421                 PGEN_DEBUG("ERROR in set_pdf_preview_page_image_w_np()");
422                 destroy_canvas(canvas);
423                 PGEN_TRACE_END;
424                 return -1;
425         }
426
427         draw_scene(canvas);
428         save_scene(canvas, out_pic_fname);
429         destroy_canvas(canvas);
430
431
432         PGEN_TRACE_END;
433
434         return 0;
435 }
436
437
438 int save_pdf_preview_page_image_w_np_fname(const char *pdf_fname,
439                 int page_num, int pages_count,
440                 const struct preview_settings_px *settings_px,
441                 const char *out_pic_fname)
442 {
443         int res;
444         void *img_buf;
445         int img_size;
446         if (load_pdf_page_img(pdf_fname, page_num, &(settings_px->page_px),
447                                 &img_buf, &img_size) < 0) {
448                 PGEN_TRACE_END;
449                 return -1;
450         }
451
452         /* called function is responsible for img_buf allocation */
453         res = save_pdf_preview_page_image_w_np(img_buf, img_size,
454                         page_num, pages_count, settings_px, out_pic_fname);
455         return res;
456 }
457
458
459 /* fix pdftopdf page rotation problem by manual scaling option */
460 int fix_pdf_page_scale(const char *fname,
461                                            const struct size_pts *req_size,
462                                            struct pdfgen_settings *settings)
463 {
464         PGEN_TRACE_BEGIN;
465         PGEN_RETV_IF(NULL == fname || NULL == req_size || NULL == settings, -1, "Invalid argument");
466
467         struct size_pts input_pdf_pts = {0.0, };
468
469         int result = get_pdf_page_size(fname, &input_pdf_pts);
470         PGEN_RETV_IF(result < 0, -1, "can't get pdf page size");
471
472         /* check rotation */
473         if ((PAGE_ORIENTATION_LANDSCAPE == settings->orientation
474                         && input_pdf_pts.x < input_pdf_pts.y)
475                         || (PAGE_ORIENTATION_PORTRAIT == settings->orientation
476                                 && input_pdf_pts.x > input_pdf_pts.y)) {
477                 double tmp = input_pdf_pts.x;
478                 input_pdf_pts.x = input_pdf_pts.y;
479                 input_pdf_pts.y = tmp;
480
481                 /*when page is rotated we need to fix its size
482                   if source page is small and desired is big, then enlarge
483                   if source is big and desired is small, diminish*/
484                 int zoomHorizontal =
485                         (int)(100 * req_size->x / input_pdf_pts.x);
486                 int zoomVertical =
487                         (int)(100 * req_size->y / input_pdf_pts.y);
488
489                 /* minimal zoom is needed from vertical/horizontal
490                    - for the whole picture fitness */
491                 settings->scale.zoom = (zoomHorizontal < zoomVertical)
492                                                            ? zoomHorizontal : zoomVertical;
493                 settings->scale.type = SCALE_RELATIVE;
494         }
495         settings->scale.w = 0;
496         settings->scale.h = 0;
497
498         PGEN_DEBUG("page zoom fix calculated");
499         PGEN_DEBUG("input_pdf_size (x,y) = (%lf, %lf)",
500                            input_pdf_pts.x, input_pdf_pts.y);
501         PGEN_DEBUG("req_size (x,y) = (%lf, %lf)",
502                            req_size->x, req_size->y);
503
504         PGEN_TRACE_END;
505         return 0;
506 }
507
508
509 /**
510  * @brief       Generates preview images for all PDF pages in temporary files
511  *              (/tmp/mobileprint_xxxx.ppm)
512  * @param[in]   fname                   PDF file name
513  * @param[in]   paper_size              paper size in pts
514  * @param[in]   available_size_px       available size for images in px
515  * @param[in]   is_grayscale            is image must be grascaled
516  * @return      -1                      error
517  *              > 0                     generated pages count
518  */
519 int generate_pdf_preview_pages(const char *fname,
520                 const struct size_pts *paper_size,
521                 const struct size_px *available_size_px,
522                 int is_grayscale)
523 {
524         int pages_count;
525         int cur_page;
526         struct size_pts page_size = {0.0, 0.0};
527
528         struct size_px shadow_size_px = {10, 10};
529         struct preview_page_req settings_req;
530         /*struct preview_settings_px settings_px;*/
531         char out_fname[sizeof("/tmp/mobileprint_xxxx.ppm ")];
532
533         PGEN_TRACE_BEGIN;
534
535         /*PGEN_DEBUG("available_size: (%d, %d)",
536                         available_size_px->x, available_size_px->y);*/
537
538
539         if (get_pdf_page_size(fname, &page_size) < 0) {
540                 PGEN_DEBUG("ERROR in get_pdf_page_size()\n");
541                 return -1;
542         }
543         pages_count = get_pdf_pages_count(fname);
544         if (pages_count <= 0) {
545                 PGEN_DEBUG("ERROR: pages_count = %d (<=0)\n", pages_count);
546                 return -1;
547         }
548
549         settings_req.paper_size = *paper_size;
550         settings_req.available_size_px = *available_size_px;
551         settings_req.shadow_offset = shadow_size_px;
552         settings_req.is_rotate90 = 0;
553         settings_req.is_grayscale = is_grayscale;
554
555         /*if (get_preview_settings(&settings_req, &settings_px) < 0) {
556                 PGEN_DEBUG("ERROR in get_preview_settings()");
557                 PGEN_TRACE_END;
558                 return -1;
559         }*/
560
561         for (cur_page = 0; cur_page < pages_count; ++cur_page) {
562                 sprintf(out_fname, "/tmp/mobileprint_%04d.ppm", cur_page + 1);
563                 save_pdf_preview_page_image(fname,
564                                 cur_page + 1, &settings_req,
565                                 out_fname);
566         }
567
568         PGEN_TRACE_END;
569         return pages_count;
570 }
571
572
573 /**
574  * @brief      Process PDF preview generation with CUPS filters to PDF with
575  *             specific options
576  * @param[in]  fname                   input PDF file name
577  * @param[in]  printer_ppd_fname       PPD file name for current active printer
578  * @param[in]  paper_size              paper size with CUPS name
579  * @param[in]  orientation             requested printing orientation
580  * @param[in]  n_up                    number-up
581  * @param[in]  scale                   scaling of image
582  * @param[in]  is_grayscale            image must be grascaled
583  * @return     -1                      error
584  *             0                       success
585  */
586 int pdf2pdf_preview_pages(const char *fname, const char *out_pdf_fname,
587                                                   const char *printer_ppd_fname,
588                                                   const struct paper_size_pts *paper_size,
589                                                   enum page_orientation orientation, int n_up,
590                                                   const struct page_scale *scale, int is_grayscale)
591 {
592         struct pdfgen_settings pg_settings;
593
594         PGEN_TRACE_BEGIN;
595         PGEN_RETV_IF(!fname || !scale, -1, "Invalid argument");
596         PGEN_DEBUG("processing file name: %s", fname);
597
598         /* generate result pdf */
599         pg_settings.n_up = n_up;
600         pg_settings.paper_name = paper_size->name;
601         pg_settings.scale = *scale;
602         pg_settings.orientation = orientation;
603         pg_settings.ppd_filename = (char *)printer_ppd_fname;
604
605         int result = fix_pdf_page_scale(fname, &(paper_size->s), &pg_settings);
606         PGEN_RETV_IF(result < 0, -1, "ERROR in fix_pdf_page_scale()");
607
608         PGEN_DEBUG("pg_settings.paper_name = %s", pg_settings.paper_name);
609         PGEN_DEBUG("pg_settings.orientation = %d",
610                            (int)pg_settings.orientation);
611         PGEN_DEBUG("pg_settings.scale.zoom = %d", pg_settings.scale.zoom);
612         PGEN_DEBUG("pg_settings.scale.type = %d",
613                            (int)pg_settings.scale.type);
614
615         result = call_pdftopdf(fname, out_pdf_fname, &pg_settings);
616         PGEN_RETV_IF(result < 0, -1, "ERROR in call_pdftopdf()");
617
618         PGEN_TRACE_END;
619         return 0;
620 }
621
622
623 /**
624  * @brief       Process PDF preview generation with CUPS filters into temporary
625  *              pages image files (/tmp/mobileprint_xxxx.ppm)
626  * @param[in]   fname                   input PDF file name
627  * @param[in]   paper_size              paper size with CUPS name
628  * @param[in]   available_size_px       available size for image in px
629  * @param[in]   orientation             requested printing orientation
630  * @param[in]   n_up                    number-up
631  * @param[in]   scale
632  * @param[in]   is_grayscale            image must be grascaled
633  * @return      -1                      error
634  *              > 0                     generated pages count
635  */
636 int get_pdf_preview_pages(const char *fname, const char *out_pdf_fname,
637                 const char *printer_ppd_fname,
638                 const struct paper_size_pts *paper_size,
639                 const struct size_px *available_size_px,
640                 enum page_orientation orientation,
641                 int n_up, const struct page_scale *scale, int is_grayscale)
642 {
643         int res;
644         PGEN_TRACE_BEGIN;
645         pdf2pdf_preview_pages(fname, out_pdf_fname, printer_ppd_fname,
646                         paper_size, orientation,
647                         n_up, scale, is_grayscale);
648
649         res = generate_pdf_preview_pages(TEMP_PDFTOPDF_FNAME,
650                         &(paper_size->s), available_size_px,
651                         is_grayscale);
652         PGEN_TRACE_END;
653         return res;
654 }
655
656
657 int process_image_downscale(const char *fname, const char *out_fname,
658                                                         const struct size_px *available_size_px)
659 {
660         struct size_px new_size;
661         PGEN_RETV_IF(fname == NULL || out_fname == NULL || available_size_px == NULL, -1, "Invalid argument");
662         new_size.x = available_size_px->x / 2;
663         new_size.y = available_size_px->y / 2;
664         downscale_image(fname, out_fname, &new_size);
665         return 0;
666 }
667
668 int img2pdf_preview_pages(const char *fname, const char *out_pdf_fname,
669                                                   const char *printer_ppd_fname,
670                                                   const struct paper_size_pts *paper_size,
671                                                   const struct size_px *available_size_px,
672                                                   enum page_orientation orientation, int n_up,
673                                                   const struct page_scale *scale, int is_grayscale)
674 {
675         PGEN_TRACE_BEGIN;
676         PGEN_RETV_IF(!fname || !out_pdf_fname || !printer_ppd_fname ||
677                                 !paper_size || !available_size_px || !scale,
678                                 -1, "Invalid argument");
679
680         struct pdfgen_settings pg_settings;
681
682         /* generate result pdf */
683
684         /* TODO: use pdfunite for multiple files, currently only first file */
685         pg_settings.n_up = n_up;
686         pg_settings.paper_name = paper_size->name;
687         pg_settings.scale = *scale;
688         pg_settings.orientation = orientation;
689         pg_settings.ppd_filename = (char *)printer_ppd_fname;
690
691         int result = call_imagetopdf(fname, out_pdf_fname, &pg_settings);
692         PGEN_RETV_IF(result < 0, -1, "ERROR in call_imagetopdf()");
693
694         PGEN_TRACE_END;
695         return 0;
696 }
697
698
699 int img_files2pdf_preview_pages(char **const fnames,
700                 int files_count,
701                 const char *out_pdf_fname,
702                 const char *printer_ppd_fname,
703                 const struct paper_size_pts *paper_size,
704                 const struct size_px *available_size_px,
705                 enum page_orientation orientation, int n_up,
706                 const struct page_scale *scale, int is_grayscale)
707 {
708         int i;
709         struct pdfgen_settings pg_settings;
710         int out_fname_size = sizeof(PREVIEW_TEMP_DIR "/mobileprint_xxxx.pdf ");
711         int res;
712         char **out_fnames;
713         char *cur_fname;
714         int is_err = 0;
715         PGEN_TRACE_BEGIN;
716
717         PGEN_RETV_IF(files_count <= 0 || files_count > 9999,
718                         -1, "Incorrect files_count");
719
720         pg_settings.n_up = 1; /* TODO: n_up */
721         pg_settings.paper_name = paper_size->name;
722         pg_settings.scale = *scale;
723         pg_settings.orientation = orientation;
724         pg_settings.ppd_filename = (char *)printer_ppd_fname;
725
726         /* generate images pdf files and their files list */
727         out_fnames = (char **)malloc(sizeof(char*) * (files_count + 1));
728         PGEN_RETV_IF(NULL == out_fnames, -1, "Out of memory");
729         memset(out_fnames, 0, sizeof(char*) * (files_count + 1));
730         for (i = 0; i < files_count; ++i) {
731                 cur_fname = (char*)malloc(
732                                 sizeof(char) * (out_fname_size + 1));
733                 if (NULL == cur_fname) {
734                         is_err = 1;
735                         break;
736                 }
737                 out_fnames[i] = cur_fname;
738                 cur_fname[out_fname_size] = '\0';
739                 snprintf(cur_fname, out_fname_size,
740                                 PREVIEW_TEMP_DIR "/mobileprint_%04d.pdf",
741                                 i + 1);
742                 res = call_imagetopdf(fnames[i], cur_fname, &pg_settings);
743                 PGEN_DEBUG("res = %d, i = %d", res, i);
744         }
745
746         /* connect images pdf files into one file */
747         if (!is_err)
748                 res = call_pdfunite(out_fnames, out_pdf_fname);
749
750         /* free allocated memory */
751         for (i = 0; i < files_count; ++i)
752                 PGEN_IF_FREE_MEM(out_fnames[i]);
753         PGEN_IF_FREE_MEM(out_fnames);
754         if (is_err)
755                 PGEN_RETV_IF(1, -1, "Out of memory");
756
757
758         PGEN_TRACE_END;
759         return 0;
760 }
761