added missing error check
[swftools.git] / src / pdf2swf.c
1 /* pdf2swf.c
2    main routine for pdf2swf(1)
3
4    Part of the swftools package.
5    
6    Copyright (c) 2001,2002,2003 Matthias Kramm <kramm@quiss.org> 
7  
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include "../config.h"
28 #ifdef HAVE_SIGNAL_H
29 #include <signal.h>
30 #endif
31 #ifdef HAVE_DIRENT_H
32 #include <dirent.h>
33 #endif
34 #ifdef HAVE_MALLOC_H
35 #include <malloc.h>
36 #endif
37
38 #include "../lib/args.h"
39 #include "../lib/os.h"
40 #include "../lib/rfxswf.h"
41 #include "../lib/devices/swf.h"
42 #include "../lib/devices/polyops.h"
43 #include "../lib/devices/record.h"
44 #include "../lib/pdf/pdf.h"
45 #include "../lib/log.h"
46
47 #define SWFDIR concatPaths(getInstallationPath(), "swfs")
48
49 static gfxsource_t*driver = 0;
50 static gfxdevice_t*out = 0;
51
52 static char * outputname = 0;
53 static int loglevel = 3;
54 static char * pagerange = 0;
55 static char * filename = 0;
56 static char * password = 0;
57 static int zlib = 0;
58
59 static char * preloader = 0;
60 static char * viewer = 0;
61 static int xnup = 1;
62 static int ynup = 1;
63
64 static int info_only = 0;
65
66 static int max_time = 0;
67
68 static int flatten = 0;
69
70 char* fontpaths[256];
71 int fontpathpos = 0;
72
73 int move_x=0;
74 int move_y=0;
75 int custom_move = 0;
76 int clip_x1=0,clip_y1=0,clip_x2=0,clip_y2=0;
77 int custom_clip = 0;
78
79 static int system_quiet=0;
80
81 int systemf(const char* format, ...)
82 {
83     char buf[1024];
84     int ret;
85     va_list arglist;
86     va_start(arglist, format);
87     vsprintf(buf, format, arglist);
88     va_end(arglist);
89
90     if(!system_quiet) {
91         printf("%s\n", buf);
92         fflush(stdout);
93     }
94     ret = system(buf);
95     if(ret) {
96         fprintf(stderr, "system() returned %d\n", ret);
97         exit(ret);
98     }
99     return ret;
100 }
101
102 #ifdef HAVE_SIGNAL_H
103 void sigalarm(int signal)
104 {
105     msg("<fatal> Aborting rendering after %d seconds", max_time);
106 #if 0 && defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRUSAGE)
107     struct rusage usage;
108     getrusage(RUSAGE_CHILDREN, &usage);
109     msg("<fatal> Memory used: %d,%d,%d", usage.ru_maxrss, usage.ru_idrss, usage.ru_isrss);
110 #endif 
111 #if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H)
112     struct mallinfo info = mallinfo();
113     msg("<fatal> Memory used: %d Mb (%d bytes)", info.uordblks/1048576, info.uordblks);
114 #endif
115     exit(1);
116 }
117 #endif
118
119 int args_callback_option(char*name,char*val) {
120     if (!strcmp(name, "o"))
121     {
122         outputname = val;
123         return 1;
124     }
125     else if (!strcmp(name, "v"))
126     {
127         loglevel ++;
128         setConsoleLogging(loglevel);
129         return 0;
130     }
131     else if (!strcmp(name, "2"))
132     {
133         xnup = 2;
134         ynup = 1;
135         return 0;
136     }
137     else if (!strcmp(name, "4"))
138     {
139         xnup = 2;
140         ynup = 2;
141         return 0;
142     }
143     else if (!strcmp(name, "9"))
144     {
145         xnup = 3;
146         ynup = 3;
147         return 0;
148     }
149     else if (!strcmp(name, "q"))
150     {
151         loglevel --;
152         setConsoleLogging(loglevel);
153         system_quiet = 1;
154         return 0;
155     }
156     else if (name[0]=='p')
157     {
158         /* check whether the page range follows the p directly, like 
159            in -p1,2 */
160         do {
161             name++;
162         } while(*name == 32 || *name == 13 || *name == 10 || *name == '\t');
163
164         if(*name) {
165             pagerange = name;
166             return 0;
167         } 
168         pagerange = val;        
169         return 1;
170     }
171     else if (!strcmp(name, "P"))
172     {
173         password = val;
174         return 1;
175     }
176     else if (!strcmp(name, "c"))
177     {
178         char*s = strdup(val);
179         char*x1 = strtok(s, ":");
180         char*y1 = strtok(0, ":");
181         char*x2 = strtok(0, ":");
182         char*y2 = strtok(0, ":");
183         if(!(x1 && y1 && x2 && y2)) {
184             fprintf(stderr, "-c option requires four arguments, <x1>:<y1>:<x2>:<y2>\n");
185             exit(1);
186         }
187         custom_clip = 1;
188         clip_x1 = atoi(x1);
189         clip_y1 = atoi(y1);
190         clip_x2 = atoi(x2);
191         clip_y2 = atoi(y2);
192         free(s);
193         return 1;
194     }
195     else if (!strcmp(name, "m"))
196     {
197         char*s = strdup(val);
198         char*c = strchr(s, ':');
199         if(!c) {
200             fprintf(stderr, "-m option requires two arguments, <x>:<y>\n");
201             exit(1);
202         }
203         *c = 0;
204         custom_move = 1;
205         move_x = atoi(val);
206         move_y = atoi(c+1);
207         free(s);
208         return 1;
209     }
210     else if (!strcmp(name, "s"))
211     {
212         char*s = strdup(val);
213         char*c = strchr(s, '=');
214         if(c && *c && c[1])  {
215             *c = 0;
216             c++;
217             driver->set_parameter(driver, s,c);
218             out->setparameter(out, s,c);
219         } else {
220             driver->set_parameter(driver, s,"1");
221             out->setparameter(out, s,"1");
222         }
223         return 1;
224     }
225     else if (!strcmp(name, "S"))
226     {
227         driver->set_parameter(driver, "drawonlyshapes", "1");
228         return 0;
229     }
230     else if (!strcmp(name, "i"))
231     {
232         driver->set_parameter(driver, "ignoredraworder", "1");
233         return 0;
234     }
235 #ifndef WIN32
236     else if (!strcmp(name, "Q"))
237     {
238         max_time = atoi(val);
239         alarm(max_time);
240 # ifdef HAVE_SIGNAL_H
241         signal(SIGALRM, sigalarm);
242 # endif
243         return 1;
244     }
245 #endif
246     else if (!strcmp(name, "z"))
247     {
248         driver->set_parameter(driver, "enablezlib", "1");
249         zlib = 1;
250         return 0;
251     }
252     else if (!strcmp(name, "n"))
253     {
254         driver->set_parameter(driver, "opennewwindow", "1");
255         return 0;
256     }
257     else if (!strcmp(name, "I"))
258     {
259         info_only = 1;
260         return 0;
261     }
262     else if (!strcmp(name, "t"))
263     {
264         driver->set_parameter(driver, "insertstop", "1");
265         return 0;
266     }
267     else if (!strcmp(name, "T"))
268     {
269         if(!strcasecmp(val, "mx"))
270             driver->set_parameter(driver, "flashversion", "6");
271         else
272             driver->set_parameter(driver, "flashversion", val);
273
274         return 1;
275     }
276     else if (!strcmp(name, "f"))
277     {
278         driver->set_parameter(driver, "storeallcharacters", "1");
279         driver->set_parameter(driver, "extrafontdata", "1");
280         return 0;
281     }
282     else if (!strcmp(name, "w"))
283     {
284         driver->set_parameter(driver, "linksopennewwindow", "0");
285         return 0;
286     }
287     else if (!strcmp(name, "O"))
288     {
289         int level = 1;
290         int ret=0;
291         if(val&& val[0] && val[1]==0 && isdigit(val[0])) {
292             level = atoi(val);
293             ret=1;
294         }
295         if(level>=1)
296             driver->set_parameter(driver, "poly2bitmap", "1");
297         if(level>=2)
298             driver->set_parameter(driver, "bitmapfonts", "1");
299         if(level>=3)
300             driver->set_parameter(driver, "ignoredraworder", "1");
301         return ret;
302     }
303     else if (!strcmp(name, "G"))
304     {
305         //driver->set_parameter(driver, "optimize_polygons", "1");
306         flatten = 1;
307         return 0;
308     }
309     else if (!strcmp(name, "F"))
310     {
311         char *s = strdup(val);
312         int l = strlen(s);
313         while(l && s[l-1]=='/') {
314             s[l-1] = 0;
315             l--;
316         }
317         fontpaths[fontpathpos++] = s;
318         return 1;
319     }
320     else if (!strcmp(name, "l"))
321     {
322         char buf[256];
323         sprintf(buf, "%s/default_loader.swf", SWFDIR);
324         preloader = strdup(buf);
325         return 0;
326     }
327     else if (!strcmp(name, "b"))
328     {
329         char buf[256];
330         sprintf(buf, "%s/default_viewer.swf", SWFDIR);
331         viewer = strdup(buf);
332         return 0;
333     }
334     else if (!strcmp(name, "L"))
335     {
336         if(val)
337         {
338             preloader = val;
339         }
340         else
341         {
342             systemf("ls %s/*_loader.swf", SWFDIR);
343             if(!system_quiet)
344                 printf("\n");
345             exit(1);
346         }
347         return 1;
348     }
349     else if (!strcmp(name, "B"))
350     {
351         if(val)
352         {
353             viewer = val;
354         }
355         else
356         {
357             systemf("ls %s/*_viewer.swf", SWFDIR);
358             if(!system_quiet)
359                 printf("\n");
360             exit(1);
361         }
362         return 1;
363     }
364     else if (!strcmp(name, "j"))
365     {
366         if(name[1]) {
367             driver->set_parameter(driver, "jpegquality", &name[1]);
368             return 0;
369         } else {
370             driver->set_parameter(driver, "jpegquality", val);
371             return 1;
372         }
373     }
374     else if (!strcmp(name, "V"))
375     {   
376         printf("pdf2swf - part of %s %s\n", PACKAGE, VERSION);
377         exit(0);
378     }
379     else 
380     {
381         fprintf(stderr, "Unknown option: -%s\n", name);
382         exit(1);
383     }
384     return 0;
385 }
386
387 /*struct docoptions_t options[] =
388 {{"o","output","filename::Specify output file"},
389  {"V","version","Print program version"},
390  {"i","ignore","Ignore draw order (makes the SWF file smaller, but may produce graphic errors)"},
391  {"z","zlib","Use Flash 6 (MX) zlib compression (Needs at least Flash 6 Plugin to play)"},
392  {"s","shapes","Don't use SWF Fonts, but store everything as shape"},
393  {"j","jpegquality","Set quality of embedded jpeg pictures (default: 85)"},
394  {"p","pages","Convert only pages in range. (E.g. 3-85)"},
395  {"w","samewindow","Don't open a new browser window for links in the SWF"},
396  {"f","fonts","Stroe full fonts in SWF. (Don't reduce to used characters)"},
397  {"F","fontpath","path::Add directory to font search path"},
398  {"B","viewer","name::Link viewer \"name\" to the pdf"},
399  {"L","preloader","file.swf::Link preloader \"file.swf\" to the pdf"},
400  {"b","defaultviewer","Link default viewer to the pdf"},
401  {"l","defaultpreloader","Link default preloader to the pdf"}
402  {0,0}
403 };*/
404 struct options_t options[] =
405 {{"o","output"},
406  {"q","quiet"},
407  {"V","version"},
408  {"i","ignore"},
409  {"I","info"},
410  {"z","zlib"},
411  {"s","set"},
412  {"S","shapes"},
413  {"Q","maxtime"},
414  {"j","jpegquality"},
415  {"p","pages"},
416  {"w","samewindow"},
417  {"f","fonts"},
418  {"F","fontdir"},
419  {"B","viewer"},
420  {"G","flatten"},
421  {"L","preloader"},
422  {"b","defaultviewer"},
423  {"l","defaultpreloader"},
424  {"t","stop"},
425  {"T","flashversion"},
426  {0,0}
427 };
428
429 int args_callback_longoption(char*name,char*val) {
430     return args_long2shortoption(options, name, val);
431 }
432
433 int args_callback_command(char*name, char*val) {
434     if (!filename) 
435         filename = name;
436     else {
437         if(outputname)
438         {
439              fprintf(stderr, "Error: Do you want the output to go to %s or to %s?", 
440                      outputname, name);
441              exit(1);
442         }
443         outputname = name;
444     }
445     return 0;
446 }
447
448 void args_callback_usage(char*name)
449 {
450     printf("Usage: %s [Options] input.pdf [-o output.swf]\n", name);
451     printf("\nBasic options:\n");
452     printf("-p  --pages=range          Convert only pages in range\n");
453     printf("-P  --password=password    Use password for deciphering the pdf\n");
454     printf("-v  --verbose              Be verbose. Use more than one -v for greater effect\n");
455     printf("-q  --quiet                Suppress normal messages. Use -qq to suppress warnings, also.\n");
456 #ifdef HAVE_DIRENT_H
457     printf("-F  --fontdir directory    Add directory to font search path\n");
458 #endif
459     printf("-V  --version              Print program version\n");
460     printf("\nEnhanced conversion options:\n");
461     printf("-S  --shapes               Don't use SWF Fonts, but store everything as shape\n");
462     printf("-z  --zlib                 Use Flash 6 (MX) zlib compression (Needs at least Flash 6 Plugin to play)\n");
463     printf("-w  --samewindow           Don't open a new Browser Window for Links in the SWF\n");
464     printf("-f  --fonts                Store full fonts in SWF. (Don't reduce to used characters)\n");
465     printf("-T  --flashversion=num     Set the flash version in the header to num (default: 4)\n");
466     printf("-s insertstop              Insert a \"Stop\" Tag in every frame (don't turn pages automatically)\n");
467     printf("-s zoom=factor             Scale result, default: 72\n");
468     printf("-s jpegquality=quality     Set quality of embedded jpeg pictures (default:85)\n");
469     printf("-s caplinewidth=value      Set the minimum line width to trigger cap style handling to value. (3)\n");
470     printf("-s splinequality=value     Set the quality of spline convertion to value (0-100, default: 100).\n");
471     printf("-s fontquality=value       Set the quality of font convertion to value (0-100, default: 100).\n");
472     printf("-s ignoredraworder         Ignore draw order (makes the SWF file smaller and faster, but may produce\n"
473            "                           graphic errors)\n");
474     printf("-s filloverlap             Make intersecting shapes overlap, instead of canceling each\n"
475            "                           other out. (Needed for some Powerpoint PDFs)\n");
476     printf("-s transparent             Make the SWF transparent\n");
477     //deliberately undocumented (for now)
478     //printf("-2                         Put 2 pages into each frame.\n");
479     //printf("-4                         Put 4 pages into each frame.\n");
480     printf("Postprocessing options:\n");
481     printf("-b  --defaultviewer        Link default viewer to the pdf (%s)\n", concatPaths(SWFDIR, "default_viewer.swf"));
482     printf("-l  --defaultpreloader     Link default preloader the pdf (%s)\n", concatPaths(SWFDIR, "default_loader.swf"));
483     printf("-B  --viewer=filename      Link viewer \"name\" to the pdf (\"%s -B\" for list)\n", name);
484     printf("-L  --preloader=filename   Link preloader \"name\" to the pdf (\"%s -L\" for list)\n",name);
485 }
486
487 float getRate(char*filename)
488 {
489     int fi;
490     SWF swf;
491     fi = open(filename,O_RDONLY|O_BINARY);
492     if(fi<0) { 
493         char buffer[256];
494         sprintf(buffer, "Couldn't open %s", filename);
495         perror(buffer);
496         exit(1);
497     }
498     if(swf_ReadSWF(fi,&swf) < 0)
499     { 
500         fprintf(stderr, "%s is not a valid SWF file or contains errors.\n",filename);
501         close(fi);
502         exit(1);
503     }
504     swf_FreeTags(&swf);
505     return swf.frameRate / 256.0;
506 }
507
508 void show_info(gfxsource_t*driver, char*filename)
509 {
510     gfxdocument_t* pdf = driver->open(driver, filename);
511     int pagenr;
512     FILE*fo=0;
513     if(!pdf) {
514         msg("<error> Couldn't open %s", filename);
515         exit(1);
516     }
517     if(outputname) {
518         fo = fopen(outputname, "wb");
519         if(!fo) {
520             perror(outputname);exit(1);;
521         }
522     } else {
523         fo = stdout;
524     }
525
526     for(pagenr = 1; pagenr <= pdf->num_pages; pagenr++) 
527     {
528         gfxpage_t*page = pdf->getpage(pdf,pagenr);
529         if(is_in_range(pagenr, pagerange)) {
530             fprintf(fo, "page=%d width=%.2f height=%.2f\n", pagenr, page->width, page->height);
531         }
532     }
533     pdf->destroy(pdf);
534 }
535
536 int main(int argn, char *argv[])
537 {
538     int ret;
539     char buf[256];
540     int numfonts = 0;
541     int t;
542     char t1searchpath[1024];
543     int nup_pos = 0;
544     int x,y;
545     char* installPath = getInstallationPath();
546     
547     initLog(0,-1,0,0,-1,loglevel);
548
549     /* not needed anymore since fonts are embedded
550        if(installPath) {
551         fontpaths[fontpathpos++] = concatPaths(installPath, "fonts");
552     }*/
553
554 #ifdef HAVE_SRAND48
555     srand48(time(0));
556 #else
557 #ifdef HAVE_SRAND
558     srand(time(0));
559 #endif
560 #endif
561     driver = gfxsource_pdf_create();
562
563     gfxdevice_t swf,wrap;
564     gfxdevice_swf_init(&swf);
565     
566     gfxdevice_removeclippings_init(&wrap, &swf);
567
568     out = &wrap;
569     processargs(argn, argv);
570     
571     if(!flatten) {
572         out = &swf;
573     }
574     
575     if(!filename)
576     {
577         fprintf(stderr, "Please specify an input file\n");
578         exit(1);
579     }
580
581     if(info_only) {
582         show_info(driver, filename);
583         return 0;
584     }
585
586     if(!outputname)
587     {
588         if(filename) {
589             outputname = stripFilename(filename, ".swf");
590             msg("<notice> Output filename not given. Writing to %s", outputname);
591         } 
592     }
593         
594     if(!outputname)
595     {
596         fprintf(stderr, "Please use -o to specify an output file\n");
597         exit(1);
598     }
599
600     // test if the page range is o.k.
601     is_in_range(0x7fffffff, pagerange);
602
603     if(pagerange)
604         driver->set_parameter(driver, "pages", pagerange);
605
606     if (!filename) {
607         args_callback_usage(argv[0]);
608         exit(0);
609     }
610
611     /* add fonts */
612     for(t=0;t<fontpathpos;t++) {
613         driver->set_parameter(driver, "fontdir", fontpaths[t]);
614     }
615
616     char fullname[256];
617     if(password && *password) {
618         sprintf(fullname, "%s|%s", filename, password);
619         filename = fullname;
620     }
621
622     gfxdocument_t* pdf = driver->open(driver, filename);
623     if(!pdf) {
624         msg("<error> Couldn't open %s", filename);
625         exit(1);
626     }
627
628     struct mypage_t {
629         int x;
630         int y;
631         gfxpage_t*page;
632     } pages[4];
633
634     int pagenum = 0;
635     int frame = 1;
636     int pagenr;
637     
638     for(pagenr = 1; pagenr <= pdf->num_pages; pagenr++) 
639     {
640         if(is_in_range(pagenr, pagerange)) {
641             char mapping[80];
642             sprintf(mapping, "%d:%d", pagenr, frame);
643             pdf->set_parameter(pdf, "pagemap", mapping);
644             pagenum++;
645         }
646         if(pagenum == xnup*ynup || (pagenr == pdf->num_pages && pagenum>1)) {
647             pagenum = 0;
648             frame++;
649         }
650     }
651
652     pagenum = 0;
653
654     for(pagenr = 1; pagenr <= pdf->num_pages; pagenr++) 
655     {
656         if(is_in_range(pagenr, pagerange)) {
657             gfxpage_t* page = pages[pagenum].page = pdf->getpage(pdf, pagenr);
658             pages[pagenum].x = 0;
659             pages[pagenum].y = 0;
660             pages[pagenum].page = page;
661             pagenum++;
662         }
663         if(pagenum == xnup*ynup || (pagenr == pdf->num_pages && pagenum>1)) {
664
665             int t;
666             int xmax[xnup], ymax[xnup];
667             int x,y;
668             int width=0, height=0;
669
670             memset(xmax, 0, xnup*sizeof(int));
671             memset(ymax, 0, ynup*sizeof(int));
672
673             for(y=0;y<ynup;y++)
674             for(x=0;x<xnup;x++) {
675                 int t = y*xnup + x;
676
677                 if(pages[t].page->width > xmax[x])
678                     xmax[x] = (int)pages[t].page->width;
679                 if(pages[t].page->height > ymax[y])
680                     ymax[y] = (int)pages[t].page->height;
681             }
682             for(x=0;x<xnup;x++) {
683                 width += xmax[x];
684                 xmax[x] = width;
685             }
686             for(y=0;y<ynup;y++) {
687                 height += ymax[y];
688                 ymax[y] = height;
689             }
690             if(custom_clip) {
691                 out->startpage(out,clip_x2 - clip_x1, clip_y2 - clip_y1);
692             } else {
693                 out->startpage(out,width,height);
694             }
695             for(t=0;t<pagenum;t++) {
696                 int x = t%xnup;
697                 int y = t/xnup;
698                 int xpos = x>0?xmax[x-1]:0;
699                 int ypos = y>0?ymax[y-1]:0;
700                 msg("<verbose> Render (%d,%d) move:%d/%d\n",
701                         (int)(pages[t].page->width + xpos),
702                         (int)(pages[t].page->height + ypos), xpos, ypos);
703                 pages[t].page->rendersection(pages[t].page, out, custom_move? move_x : xpos, 
704                                                            custom_move? move_y : ypos,
705                                                            custom_clip? clip_x1 : 0 + xpos, 
706                                                            custom_clip? clip_y1 : 0 + ypos, 
707                                                            custom_clip? clip_x2 : pages[t].page->width + xpos, 
708                                                            custom_clip? clip_y2 : pages[t].page->height + ypos);
709             }
710             out->endpage(out);
711             for(t=0;t<pagenum;t++)  {
712                 pages[t].page->destroy(pages[t].page);
713             }
714             pagenum = 0;
715         }
716     }
717     
718     gfxresult_t*result = out->finish(out);
719
720     if(result->save(result, outputname) < 0) {
721         exit(1);
722     }
723
724     int width = (int)result->get(result, "width");
725     int height = (int)result->get(result, "height");
726     msg("<notice> SWF written");
727     
728     result->destroy(result);
729
730     pdf->destroy(pdf);
731     driver->destroy(driver);
732
733     const char*zip = "";
734     if(zlib) {
735         zip = "-z";
736     }
737     if(!preloader && viewer) {
738         systemf("swfcombine %s -X %d -Y %d \"%s\" viewport=\"%s\" -o \"%s\"",zip,width,height,
739                 viewer, outputname, outputname);
740         if(!system_quiet)
741             printf("\n");
742     }
743     if(preloader && !viewer) {
744         msg("<warning> --preloader option without --viewer option doesn't make very much sense.");
745         ret = systemf("swfcombine %s -Y %d -X %d %s/PreLoaderTemplate.swf loader=\"%s\" movie=\"%s\" -o \"%s\"",zip,width,height,
746                 SWFDIR, preloader, outputname, outputname);
747         if(!system_quiet)
748             printf("\n");
749     }
750     if(preloader && viewer) {
751 #ifdef HAVE_MKSTEMP
752         char tmpname[] = "__swf__XXXXXX";
753         mkstemp(tmpname);
754 #else 
755         char*tmpname = "__tmp__.swf";
756 #endif
757         systemf("swfcombine \"%s\" viewport=%s -o %s",
758                 viewer, outputname, tmpname);
759         systemf("swfcombine %s -X %d -Y %d -r %f %s/PreLoaderTemplate.swf loader=%s movie=%s -o \"%s\"",zip,width,height,
760                 getRate(preloader), SWFDIR, preloader, tmpname, outputname);
761         systemf("rm %s", tmpname);
762     }
763
764
765     return 0;
766 }
767