Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / pngxpdf / main.c
blob208d2a640438e729fa087973dbd8f2dca7ba2a47
1 /*
3 * pngxpdf copyright (C) 2008 Monty <monty@xiph.org>
5 * pngxpdf 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 2, or (at your option)
8 * any later version.
9 *
10 * pngxpdf 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.
15 * You should have received a copy of the GNU General Public License
16 * along with pngxpdf; see the file COPYING. If not, write to the
17 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define _GNU_SOURCE
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <getopt.h>
28 #include <cairo.h>
29 #include <cairo-ft.h>
30 #include <cairo-pdf.h>
32 const char *optstring = "W:H:r:t:mhvx:y:f:";
34 struct option options [] = {
35 {"width",required_argument,NULL,'W'},
36 {"height",required_argument,NULL,'H'},
37 {"resolution",required_argument,NULL,'r'},
38 {"text",required_argument,NULL,'t'},
39 {"help",no_argument,NULL,'h'},
40 {"version",no_argument,NULL,'v'},
41 {"x-offset",required_argument,NULL,'x'},
42 {"y-offset",required_argument,NULL,'y'},
43 {"font-size",required_argument,NULL,'f'},
45 {NULL,0,NULL,0}
48 cairo_status_t pdf_write(void *closure,
49 const unsigned char *data,
50 unsigned int length){
51 if(fwrite(data, 1, length, stdout)<length)
52 return CAIRO_STATUS_WRITE_ERROR;
53 return CAIRO_STATUS_SUCCESS;
56 void usage(FILE *f){
57 fprintf(f,"pngxpdf "VERSION"\n"
58 "(C) 2008 Monty <monty@xiph.org>\n\n"
59 "USAGE:\n\n"
60 " pnxpdf [options] file1.png [file2.png...] > output.pdf\n\n"
61 "OPTIONS:\n\n"
62 " -h --help : Display this usage information\n\n"
63 " -f --font-size <n> : Font size (points)\n"
64 " -H --height <n> : Height of each output page; suffix with mm, cm,\n"
65 " in or pt to use various units. default is 11.0in\n\n"
66 " -r --resolution <n> : Specify input resolution of each image. Each\n"
67 " image is centered on the page and either cropped\n"
68 " to fit or placed within a border. Suffix with\n"
69 " dpi, dpcm, dpmm, or dpp to specify different\n"
70 " units. 150dpi default.\n\n"
71 " -t --text <string> : string comment to add as a footer to each page\n\n"
72 " -v --version : Output version string and exit\n\n"
73 " -W --width <n> : Width of each output page; suffix with mm, cm,\n"
74 " in or pt to use various units. default is 8.5in\n"
75 " -x --x-offset <n> : Left or right offset of image center; suffix with\n"
76 " mm, cm, in or pt to use various units.\n\n"
77 " -y --y-offset <n> : Up or down offset of image center; suffix with\n"
78 " mm, cm, in or pt to use various units. Use -y 0\n"
79 " to eliminate text footer from shifting default\n"
80 " center upwards.\n\n");
83 int main(int argc, char **argv){
84 float width=8.5*72.0;
85 float height=11.0*72.0;
86 float xoff=0;
87 float yoff=0;
88 float fontsize=-1;
89 int havey=0;
90 float dpp=300.0/72.0;
91 char *text=NULL;
93 int c,long_option_index;
95 cairo_surface_t *cs;
96 cairo_t *ct;
97 cairo_text_extents_t extents;
99 while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
100 switch(c){
101 case 'W':
102 case 'H':
103 case 'x':
104 case 'y':
106 float temp;
107 if(strstr(optarg,"cm")){
108 temp=atof(optarg)*28.3464566929;
109 }else if (strstr(optarg,"mm")){
110 temp=atof(optarg)*2.83464566929;
111 }else if (strstr(optarg,"pt")){
112 temp=atof(optarg);
113 }else{
114 temp=atof(optarg)*72.0;
116 switch(c){
117 case 'W':
118 width=temp;
119 break;
120 case 'H':
121 height=temp;
122 break;
123 case 'x':
124 xoff=temp;
125 break;
126 case 'y':
127 yoff=temp;
128 havey=1;
129 break;
132 break;
133 case 'r':
134 if(strstr(optarg,"dpcm")){
135 dpp=atof(optarg)*.03527777777778;
136 }else if (strstr(optarg,"dpmm")){
137 dpp=atof(optarg)*.35277777777778;
138 }else if (strstr(optarg,"dpp")){
139 dpp=atof(optarg);
140 }else{
141 dpp=atof(optarg)*.01388888888889;
143 break;
144 case 'f':
145 fontsize=atof(optarg);
146 break;
147 case 't':
148 text=strdup(optarg);
149 break;
150 case 'h':
151 usage(stdout);
152 exit(0);
153 case 'v':
154 fprintf(stderr,"pngxpdf "VERSION"\n");
155 default:
156 usage(stderr);
160 /* set up our surface */
161 cs = cairo_pdf_surface_create_for_stream (pdf_write, NULL, width, height);
162 if(!cs || cairo_surface_status(cs)!=CAIRO_STATUS_SUCCESS){
163 fprintf(stderr,"CAIRO ERROR: Unable to create PDF surface.\n\n");
164 exit(1);
166 ct = cairo_create(cs);
167 if(fontsize<=0){
168 fontsize=height*15./792.;
169 if(fontsize<5)fontsize=5;
171 cairo_set_font_size(ct, fontsize);
172 if(text){
173 cairo_text_extents(ct, text, &extents);
174 if(!havey)
175 yoff = -extents.height-fontsize*4;
178 /* Iterate through PNG files inline */
179 while(optind<argc){
180 int ww, hh;
181 char *filename = argv[optind];
182 cairo_pattern_t *pattern;
183 cairo_surface_t *ps=cairo_image_surface_create_from_png(filename);
184 cairo_status_t status = cairo_surface_status(ps);
185 if(!ps || status!=CAIRO_STATUS_SUCCESS){
186 fprintf(stderr,"CAIRO ERROR: Unable to load PNG file %s: %s\n\n",filename,cairo_status_to_string(status));
187 exit(1);
189 ww = cairo_image_surface_get_width(ps);
190 hh = cairo_image_surface_get_height(ps);
192 cairo_save(ct);
193 cairo_scale(ct, 1./dpp, 1./dpp);
194 pattern = cairo_pattern_create_for_surface(ps);
195 cairo_translate(ct,(width*dpp - (ww-1))*.5,((height+yoff)*dpp - (hh-1))*.5);
196 cairo_pattern_set_filter(pattern, CAIRO_FILTER_BEST);
197 cairo_set_source(ct,pattern);
198 cairo_paint(ct);
199 cairo_restore(ct);
201 /* draw comment text */
202 if(text){
203 cairo_set_source_rgba(ct, 1,1,1,.75);
204 cairo_move_to(ct, width-extents.width-fontsize*1.5, height-fontsize*1.5);
205 cairo_text_path (ct, text);
206 cairo_set_line_width(ct,3.);
207 cairo_set_line_join(ct,CAIRO_LINE_JOIN_ROUND);
208 cairo_stroke(ct);
210 cairo_set_source_rgb(ct, 0,0,0);
211 cairo_move_to(ct, width-extents.width-fontsize*1.5, height-fontsize*1.5);
212 cairo_show_text(ct, text);
217 cairo_surface_show_page(cs);
220 cairo_surface_destroy(ps);
221 optind++;
224 cairo_destroy(ct);
225 cairo_surface_destroy(cs);