1 /*
2  *    This file is part of darktable,
3  *    Copyright (C) 2015-2020 darktable developers.
4  *
5  *    darktable is free software: you can redistribute it and/or modify
6  *    it under the terms of the GNU General Public License as published by
7  *    the Free Software Foundation, either version 3 of the License, or
8  *    (at your option) any later version.
9  *
10  *    darktable is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU General Public License for more details.
14  *
15  *    You should have received a copy of the GNU General Public License
16  *    along with darktable.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  *  this is a simple PDF writer, capable of creating multi page PDFs with embedded images.
21  *  it is NOT meant to be a full fledged PDF library, and shall never turn into something like that!
22  *  see the main() function in pdf.c to see an example how to use this.
23  */
24 
25 #pragma once
26 
27 #include <glib.h>
28 #include <glib/gi18n.h>
29 #include <inttypes.h>
30 #include <stdio.h>
31 
32 // clang-format off
33 
34 #define dt_pdf_inch_to_point(inch)      ((inch) * 72.0)
35 #define dt_pdf_point_to_inch(pt)        ((pt) / 72.0)
36 #define dt_pdf_mm_to_point(mm)          dt_pdf_inch_to_point((mm) / 25.4)
37 #define dt_pdf_point_to_mm(pt)          dt_pdf_point_to_inch((pt) * 25.4)
38 #define dt_pdf_point_to_pixel(pt, dpi)  (dt_pdf_point_to_inch(pt) * (dpi))
39 #define dt_pdf_pixel_to_point(px, dpi)  (dt_pdf_inch_to_point((px) / (dpi)))
40 
41 typedef enum dt_pdf_stream_encoder_t
42 {
43   DT_PDF_STREAM_ENCODER_ASCII_HEX = 0,  // inflate size by 2 -- big & fast
44   DT_PDF_STREAM_ENCODER_FLATE     = 1   // use zlib to compress -- small & slow
45 } dt_pdf_stream_encoder_t;
46 
47 typedef struct dt_pdf_t
48 {
49   FILE                    *fd;
50   int                      next_id;
51   int                      next_image;
52   size_t                   bytes_written;
53   float                    page_width, page_height, dpi;
54   dt_pdf_stream_encoder_t  default_encoder;
55 
56   char                    *title;
57 
58   size_t                  *offsets;
59   int                      n_offsets;
60 } dt_pdf_t;
61 
62 typedef struct dt_pdf_image_t
63 {
64   int       object_id;
65   int       name_id;
66   size_t    size;
67   size_t    width, height;
68   float     bb_x, bb_y, bb_width, bb_height;
69 
70   gboolean  rotate_to_fit;
71 
72   gboolean  outline_mode; // set to 1 to only draw a box instead of the image
73   gboolean  show_bb; // set to 1 to draw the bounding box. useful for debugging
74 } dt_pdf_image_t;
75 
76 typedef struct dt_pdf_page_t
77 {
78   int     object_id;
79   size_t  size;
80 } dt_pdf_page_t;
81 
82 static const struct
83 {
84   char  *name;
85   float  factor;
86 } dt_pdf_units[] =
87 {
88   {N_("mm"),   dt_pdf_mm_to_point(1.0)},
89   {N_("cm"),   dt_pdf_mm_to_point(10.0)},
90   {N_("inch"), dt_pdf_inch_to_point(1.0)},
91   {N_("\""),   dt_pdf_inch_to_point(1.0)},
92   {NULL,       0.0}
93 };
94 
95 static const int dt_pdf_units_n = sizeof(dt_pdf_units) / sizeof(dt_pdf_units[0]);
96 
97 static const struct
98 {
99   char  *name;
100   float  width;
101   float  height;
102 } dt_pdf_paper_sizes[] =
103 {
104   {N_("a4"),     dt_pdf_mm_to_point(210),   dt_pdf_mm_to_point(297)},
105   {N_("a3"),     dt_pdf_mm_to_point(297),   dt_pdf_mm_to_point(420)},
106   {N_("letter"), dt_pdf_inch_to_point(8.5), dt_pdf_inch_to_point(11.0)},
107   {N_("legal"),  dt_pdf_inch_to_point(8.5), dt_pdf_inch_to_point(14.0)},
108   {NULL,         0.0,                       0.0}
109 };
110 
111 // clang-format on
112 
113 static const int dt_pdf_paper_sizes_n = sizeof(dt_pdf_paper_sizes) / sizeof(dt_pdf_paper_sizes[0]) - 1;
114 
115 // construction of the pdf
116 dt_pdf_t *dt_pdf_start(const char *filename, float width, float height, float dpi, dt_pdf_stream_encoder_t default_encoder);
117 int dt_pdf_add_icc(dt_pdf_t *pdf, const char *filename);
118 int dt_pdf_add_icc_from_data(dt_pdf_t *pdf, const unsigned char *data, size_t size);
119 dt_pdf_image_t *dt_pdf_add_image(dt_pdf_t *pdf, const unsigned char *image, int width, int height, int bpp, int icc_id, float border);
120 dt_pdf_page_t *dt_pdf_add_page(dt_pdf_t *pdf, dt_pdf_image_t **images, int n_images);
121 void dt_pdf_finish(dt_pdf_t *pdf, dt_pdf_page_t **pages, int n_pages);
122 
123 // general helpers
124 int dt_pdf_parse_length(const char *str, float *length);
125 int dt_pdf_parse_paper_size(const char *str, float *width, float *height);
126 
127 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
128 // vim: shiftwidth=2 expandtab tabstop=2 cindent
129 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
130