fixed mem leaks
[swftools.git] / src / pdf2swf.c
index a011db6..3b67bcc 100644 (file)
@@ -42,6 +42,8 @@
 #include "../lib/devices/swf.h"
 #include "../lib/devices/polyops.h"
 #include "../lib/devices/record.h"
+#include "../lib/devices/rescale.h"
+#include "../lib/gfxfilter.h"
 #include "../lib/pdf/pdf.h"
 #include "../lib/log.h"
 
@@ -50,6 +52,8 @@
 static gfxsource_t*driver = 0;
 static gfxdevice_t*out = 0;
 
+static int maxwidth=0, maxheight=0;
+
 static char * outputname = 0;
 static int loglevel = 3;
 static char * pagerange = 0;
@@ -68,6 +72,8 @@ static int max_time = 0;
 
 static int flatten = 0;
 
+static char* filters = 0;
+
 char* fontpaths[256];
 int fontpathpos = 0;
 
@@ -85,7 +91,7 @@ int systemf(const char* format, ...)
     int ret;
     va_list arglist;
     va_start(arglist, format);
-    vsprintf(buf, format, arglist);
+    vsnprintf(buf, sizeof(buf)-1, format, arglist);
     va_end(arglist);
 
     if(!system_quiet) {
@@ -181,6 +187,16 @@ int args_callback_option(char*name,char*val) {
         ynup = 3;
        return 0;
     }
+    else if (!strcmp(name, "X"))
+    {
+        maxwidth = atoi(val);
+       return 1;
+    }
+    else if (!strcmp(name, "Y"))
+    {
+        maxheight = atoi(val);
+       return 1;
+    }
     else if (!strcmp(name, "q"))
     {
        loglevel --;
@@ -244,7 +260,7 @@ int args_callback_option(char*name,char*val) {
     }
     else if (!strcmp(name, "s"))
     {
-       char*s = strdup(val);
+       char*s = val;
        char*c = strchr(s, '=');
        if(c && *c && c[1])  {
            *c = 0;
@@ -253,7 +269,7 @@ int args_callback_option(char*name,char*val) {
        } else if(!strcmp(s,"help")) {
            printf("PDF Parameters:\n");
            gfxsource_t*pdf = gfxsource_pdf_create();
-           pdf->set_parameter(pdf, "help", "");
+           pdf->setparameter(pdf, "help", "");
            gfxdevice_t swf;
            gfxdevice_swf_init(&swf);
            printf("SWF Parameters:\n");
@@ -321,6 +337,20 @@ int args_callback_option(char*name,char*val) {
        store_parameter("extrafontdata", "1");
        return 0;
     }
+    else if (!strcmp(name, "ff"))
+    {
+       if(filters) {
+           // append this to the current filter expression (we allow more than one --filter)
+           int l = strlen(filters);
+           int new_len = l + strlen(val) + 2;
+           filters = (char*)realloc(filters, new_len);
+           filters[l] = ':';
+           strcpy(filters+l+1, val);
+       } else {
+           filters = strdup(val);
+       }
+       return 1;
+    }
     else if (!strcmp(name, "w"))
     {
        store_parameter("linksopennewwindow", "0");
@@ -426,23 +456,6 @@ int args_callback_option(char*name,char*val) {
     return 0;
 }
 
-/*struct docoptions_t options[] =
-{{"o","output","filename::Specify output file"},
- {"V","version","Print program version"},
- {"i","ignore","Ignore draw order (makes the SWF file smaller, but may produce graphic errors)"},
- {"z","zlib","Use Flash 6 (MX) zlib compression (Needs at least Flash 6 Plugin to play)"},
- {"s","shapes","Don't use SWF Fonts, but store everything as shape"},
- {"j","jpegquality","Set quality of embedded jpeg pictures (default: 85)"},
- {"p","pages","Convert only pages in range. (E.g. 3-85)"},
- {"w","samewindow","Don't open a new browser window for links in the SWF"},
- {"f","fonts","Stroe full fonts in SWF. (Don't reduce to used characters)"},
- {"F","fontpath","path::Add directory to font search path"},
- {"B","viewer","name::Link viewer \"name\" to the pdf"},
- {"L","preloader","file.swf::Link preloader \"file.swf\" to the pdf"},
- {"b","defaultviewer","Link default viewer to the pdf"},
- {"l","defaultpreloader","Link default preloader to the pdf"}
- {0,0}
-};*/
 static struct options_t options[] = {
 {"h", "help"},
 {"V", "version"},
@@ -458,6 +471,7 @@ static struct options_t options[] = {
 {"t", "stop"},
 {"T", "flashversion"},
 {"F", "fontdir"},
+{"ff", "filter"},
 {"b", "defaultviewer"},
 {"l", "defaultloader"},
 {"B", "viewer"},
@@ -468,6 +482,8 @@ static struct options_t options[] = {
 {"G", "flatten"},
 {"I", "info"},
 {"Q", "maxtime"},
+{"X", "width"},
+{"Y", "height"},
 {0,0}
 };
 
@@ -497,7 +513,7 @@ void args_callback_usage(char *name)
     printf("\n");
     printf("-h , --help                    Print short help message and exit\n");
     printf("-V , --version                 Print version info and exit\n");
-    printf("-o , --output file.swf         Direct output to file.swf. If file.swf contains '%d' (file%d.swf), then each page \n");
+    printf("-o , --output file.swf         Direct output to file.swf. If file.swf contains '%%' (file%%.swf), then each page goes to a seperate file.\n");
     printf("-p , --pages range             Convert only pages in range with range e.g. 1-20 or 1,4,6,9-11 or\n");
     printf("-P , --password password       Use password for deciphering the pdf.\n");
     printf("-v , --verbose                 Be verbose. Use more than one -v for greater effect.\n");
@@ -572,15 +588,34 @@ void show_info(gfxsource_t*driver, char*filename)
 }
 
 
-static gfxdevice_t swf,wrap;
+static gfxdevice_t swf,wrap,rescale;
 gfxdevice_t*create_output_device()
 {
     gfxdevice_swf_init(&swf);
-    gfxdevice_removeclippings_init(&wrap, &swf);
-    out = &wrap;
-    if(!flatten) {
-       out = &swf;
+
+    /* set up filter chain */
+       
+    out = &swf;
+    if(flatten) {
+        gfxdevice_removeclippings_init(&wrap, &swf);
+        out = &wrap;
+    }
+
+    if(maxwidth || maxheight) {
+        gfxdevice_rescale_init(&rescale, out, maxwidth, maxheight, 0);
+        out = &rescale;
+    }
+
+    if(filters) {
+       gfxfilterchain_t*chain = gfxfilterchain_parse(filters);
+       if(!chain) {
+           fprintf(stderr, "Unable to parse filters: %s\n", filters);
+           exit(1);
+       }
+       out = gfxfilterchain_apply(chain, out);
+       gfxfilterchain_destroy(chain);
     }
+
     /* pass global parameters to output device */
     parameter_t*p = device_config;
     while(p) {
@@ -599,7 +634,6 @@ int main(int argn, char *argv[])
     char t1searchpath[1024];
     int nup_pos = 0;
     int x,y;
-    char* installPath = getInstallationPath();
     int one_file_per_page = 0;
     
     initLog(0,-1,0,0,-1,loglevel);
@@ -624,7 +658,7 @@ int main(int argn, char *argv[])
     /* pass global parameters to PDF driver*/
     parameter_t*p = device_config;
     while(p) {
-       driver->set_parameter(driver, p->name, p->value);
+       driver->setparameter(driver, p->name, p->value);
        p = p->next;
     }
 
@@ -634,45 +668,47 @@ int main(int argn, char *argv[])
        exit(1);
     }
 
-    if(info_only) {
-       show_info(driver, filename);
-       return 0;
-    }
-
-    if(!outputname)
-    {
-       if(filename) {
-           outputname = stripFilename(filename, ".swf");
-           msg("<notice> Output filename not given. Writing to %s", outputname);
-       } 
-    }
-       
-    if(!outputname)
-    {
-       fprintf(stderr, "Please use -o to specify an output file\n");
-       exit(1);
+    if (!info_only) {
+        if(!outputname)
+        {
+            if(filename) {
+                outputname = stripFilename(filename, ".swf");
+                msg("<notice> Output filename not given. Writing to %s", outputname);
+            } 
+        }
+            
+        if(!outputname)
+        {
+            fprintf(stderr, "Please use -o to specify an output file\n");
+            exit(1);
+        }
     }
 
     // test if the page range is o.k.
     is_in_range(0x7fffffff, pagerange);
 
-    if(pagerange)
-       driver->set_parameter(driver, "pages", pagerange);
-
     if (!filename) {
        args_callback_usage(argv[0]);
        exit(0);
     }
+    
+    char fullname[256];
+    if(password && *password) {
+       sprintf(fullname, "%s|%s", filename, password);
+       filename = fullname;
+    }
+    
+    if(pagerange)
+       driver->setparameter(driver, "pages", pagerange);
 
     /* add fonts */
     for(t=0;t<fontpathpos;t++) {
-       driver->set_parameter(driver, "fontdir", fontpaths[t]);
+       driver->setparameter(driver, "fontdir", fontpaths[t]);
     }
 
-    char fullname[256];
-    if(password && *password) {
-       sprintf(fullname, "%s|%s", filename, password);
-       filename = fullname;
+    if(info_only) {
+       show_info(driver, filename);
+       return 0;
     }
 
     char*u = 0;
@@ -705,7 +741,7 @@ int main(int argn, char *argv[])
     /* pass global parameters document */
     p = device_config;
     while(p) {
-       pdf->set_parameter(pdf, p->name, p->value);
+       pdf->setparameter(pdf, p->name, p->value);
        p = p->next;
     }
 
@@ -724,7 +760,7 @@ int main(int argn, char *argv[])
        if(is_in_range(pagenr, pagerange)) {
            char mapping[80];
            sprintf(mapping, "%d:%d", pagenr, frame);
-           pdf->set_parameter(pdf, "pagemap", mapping);
+           pdf->setparameter(pdf, "pagemap", mapping);
            pagenum++;
        }
        if(pagenum == xnup*ynup || (pagenr == pdf->num_pages && pagenum>1)) {
@@ -732,10 +768,16 @@ int main(int argn, char *argv[])
            frame++;
        }
     }
+    if(pagerange && !pagenum && frame==1) {
+       fprintf(stderr, "No pages in range %s", pagerange);
+       exit(1);
+    }
 
     pagenum = 0;
 
     gfxdevice_t*out = create_output_device();;
+    pdf->prepare(pdf, out);
+
     for(pagenr = 1; pagenr <= pdf->num_pages; pagenr++) 
     {
        if(is_in_range(pagenr, pagerange)) {
@@ -801,7 +843,7 @@ int main(int argn, char *argv[])
            if(one_file_per_page) {
                gfxresult_t*result = out->finish(out);out=0;
                char buf[1024];
-               sprintf(buf, outputname, one_file_per_page++);
+               sprintf(buf, outputname, pagenr);
                if(result->save(result, buf) < 0) {
                    return 1;
                }
@@ -822,8 +864,8 @@ int main(int argn, char *argv[])
        if(result->save(result, outputname) < 0) {
            exit(1);
        }
-       int width = (int)result->get(result, "width");
-       int height = (int)result->get(result, "height");
+       int width = (int)(ptroff_t)result->get(result, "width");
+       int height = (int)(ptroff_t)result->get(result, "height");
        result->destroy(result);result=0;
 
        if(preloader || viewer) {
@@ -873,6 +915,9 @@ int main(int argn, char *argv[])
        p->next = 0;free(p);
        p = next;
     }
+    if(filters) {
+       free(filters);
+    }
 
     return 0;
 }