summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-write.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/pdf/pdf-write.c')
-rw-r--r--source/pdf/pdf-write.c122
1 files changed, 82 insertions, 40 deletions
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c
index 4e236748..b50e5db3 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -53,7 +53,9 @@ struct pdf_write_state_s
int do_tight;
int do_ascii;
int do_expand;
- int do_deflate;
+ int do_compress;
+ int do_compress_images;
+ int do_compress_fonts;
int do_garbage;
int do_linear;
int do_clean;
@@ -1630,7 +1632,7 @@ static fz_buffer *deflatebuf(fz_context *ctx, unsigned char *p, int n)
return buf;
}
-static void copystream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, pdf_obj *obj_orig, int num, int gen)
+static void copystream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, pdf_obj *obj_orig, int num, int gen, int do_deflate)
{
fz_buffer *buf, *tmp;
pdf_obj *newlen;
@@ -1642,7 +1644,7 @@ static void copystream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts
obj = pdf_copy_dict(ctx, obj_orig);
- if (opts->do_deflate && !pdf_dict_get(ctx, obj, PDF_NAME_Filter))
+ if (do_deflate && !pdf_dict_get(ctx, obj, PDF_NAME_Filter))
{
pdf_dict_put(ctx, obj, PDF_NAME_Filter, PDF_NAME_FlateDecode);
@@ -1676,7 +1678,7 @@ static void copystream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts
pdf_drop_obj(ctx, obj);
}
-static void expandstream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, pdf_obj *obj_orig, int num, int gen)
+static void expandstream(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, pdf_obj *obj_orig, int num, int gen, int do_deflate)
{
fz_buffer *buf, *tmp;
pdf_obj *newlen;
@@ -1693,7 +1695,7 @@ static void expandstream(fz_context *ctx, pdf_document *doc, pdf_write_state *op
pdf_dict_del(ctx, obj, PDF_NAME_Filter);
pdf_dict_del(ctx, obj, PDF_NAME_DecodeParms);
- if (opts->do_deflate && !pdf_dict_get(ctx, obj, PDF_NAME_Filter))
+ if (do_deflate)
{
pdf_dict_put(ctx, obj, PDF_NAME_Filter, PDF_NAME_FlateDecode);
@@ -1738,7 +1740,7 @@ static int is_image_filter(char *s)
return 0;
}
-static int filter_implies_image(fz_context *ctx, pdf_document *doc, pdf_obj *o)
+static int filter_implies_image(fz_context *ctx, pdf_obj *o)
{
if (!o)
return 0;
@@ -1755,6 +1757,39 @@ static int filter_implies_image(fz_context *ctx, pdf_document *doc, pdf_obj *o)
return 0;
}
+static int is_image_stream(fz_context *ctx, pdf_obj *obj)
+{
+ pdf_obj *o;
+ if ((o = pdf_dict_get(ctx, obj, PDF_NAME_Type), pdf_name_eq(ctx, o, PDF_NAME_XObject)))
+ if ((o = pdf_dict_get(ctx, obj, PDF_NAME_Subtype), pdf_name_eq(ctx, o, PDF_NAME_Image)))
+ return 1;
+ if (o = pdf_dict_get(ctx, obj, PDF_NAME_Filter), filter_implies_image(ctx, o))
+ return 1;
+ if (pdf_dict_get(ctx, obj, PDF_NAME_Width) != NULL && pdf_dict_get(ctx, obj, PDF_NAME_Height) != NULL)
+ return 1;
+ return 0;
+}
+
+static int is_font_stream(fz_context *ctx, pdf_obj *obj)
+{
+ pdf_obj *o;
+ if (o = pdf_dict_get(ctx, obj, PDF_NAME_Type), pdf_name_eq(ctx, o, PDF_NAME_Font))
+ return 1;
+ if (o = pdf_dict_get(ctx, obj, PDF_NAME_Type), pdf_name_eq(ctx, o, PDF_NAME_FontDescriptor))
+ return 1;
+ if (pdf_dict_get(ctx, obj, PDF_NAME_Length1) != NULL)
+ return 1;
+ if (pdf_dict_get(ctx, obj, PDF_NAME_Length2) != NULL)
+ return 1;
+ if (pdf_dict_get(ctx, obj, PDF_NAME_Length3) != NULL)
+ return 1;
+ if (o = pdf_dict_get(ctx, obj, PDF_NAME_Subtype), pdf_name_eq(ctx, o, PDF_NAME_Type1C))
+ return 1;
+ if (o = pdf_dict_get(ctx, obj, PDF_NAME_Subtype), pdf_name_eq(ctx, o, PDF_NAME_CIDFontType0C))
+ return 1;
+ return 0;
+}
+
static void writeobject(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, int num, int gen, int skip_xrefs)
{
pdf_xref_entry *entry;
@@ -1813,39 +1848,18 @@ static void writeobject(fz_context *ctx, pdf_document *doc, pdf_write_state *opt
}
else
{
- int dontexpand = 0;
- if (opts->do_expand != 0 && opts->do_expand != PDF_EXPAND_ALL)
- {
- pdf_obj *o;
-
- if ((o = pdf_dict_get(ctx, obj, PDF_NAME_Type), pdf_name_eq(ctx, o, PDF_NAME_XObject)) &&
- (o = pdf_dict_get(ctx, obj, PDF_NAME_Subtype), pdf_name_eq(ctx, o, PDF_NAME_Image)))
- dontexpand = !(opts->do_expand & PDF_EXPAND_IMAGES);
- if (o = pdf_dict_get(ctx, obj, PDF_NAME_Type), pdf_name_eq(ctx, o, PDF_NAME_Font))
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (o = pdf_dict_get(ctx, obj, PDF_NAME_Type), pdf_name_eq(ctx, o, PDF_NAME_FontDescriptor))
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (pdf_dict_get(ctx, obj, PDF_NAME_Length1) != NULL)
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (pdf_dict_get(ctx, obj, PDF_NAME_Length2) != NULL)
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (pdf_dict_get(ctx, obj, PDF_NAME_Length3) != NULL)
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (o = pdf_dict_get(ctx, obj, PDF_NAME_Subtype), pdf_name_eq(ctx, o, PDF_NAME_Type1C))
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (o = pdf_dict_get(ctx, obj, PDF_NAME_Subtype), pdf_name_eq(ctx, o, PDF_NAME_CIDFontType0C))
- dontexpand = !(opts->do_expand & PDF_EXPAND_FONTS);
- if (o = pdf_dict_get(ctx, obj, PDF_NAME_Filter), filter_implies_image(ctx, doc, o))
- dontexpand = !(opts->do_expand & PDF_EXPAND_IMAGES);
- if (pdf_dict_get(ctx, obj, PDF_NAME_Width) != NULL && pdf_dict_get(ctx, obj, PDF_NAME_Height) != NULL)
- dontexpand = !(opts->do_expand & PDF_EXPAND_IMAGES);
- }
fz_try(ctx)
{
- if (opts->do_expand && !dontexpand && !pdf_is_jpx_image(ctx, obj))
- expandstream(ctx, doc, opts, obj, num, gen);
+ int do_deflate = opts->do_compress;
+ int do_expand = opts->do_expand;
+ if (opts->do_compress_images && is_image_stream(ctx, obj))
+ do_deflate = 1, do_expand = 0;
+ if (opts->do_compress_fonts && is_font_stream(ctx, obj))
+ do_deflate = 1, do_expand = 0;
+ if (do_expand)
+ expandstream(ctx, doc, opts, obj, num, gen, do_deflate);
else
- copystream(ctx, doc, opts, obj, num, gen);
+ copystream(ctx, doc, opts, obj, num, gen, do_deflate);
}
fz_catch(ctx)
{
@@ -2677,15 +2691,19 @@ static void initialise_write_state(fz_context *ctx, pdf_document *doc, const pdf
int xref_len = pdf_xref_len(ctx, doc);
opts->do_incremental = in_opts->do_incremental;
- opts->do_tight = (in_opts->do_expand == 0) || in_opts->do_deflate;
- opts->do_expand = in_opts->do_expand;
- opts->do_garbage = in_opts->do_garbage;
opts->do_ascii = in_opts->do_ascii;
- opts->do_deflate = in_opts->do_deflate;
+ opts->do_tight = !in_opts->do_pretty;
+ opts->do_expand = in_opts->do_decompress;
+ opts->do_compress = in_opts->do_compress;
+ opts->do_compress_images = in_opts->do_compress_images;
+ opts->do_compress_fonts = in_opts->do_compress_fonts;
+
+ opts->do_garbage = in_opts->do_garbage;
opts->do_linear = in_opts->do_linear;
opts->do_clean = in_opts->do_clean;
opts->start = 0;
opts->main_xref_offset = INT_MIN;
+
/* We deliberately make these arrays long enough to cope with
* 1 to n access rather than 0..n-1, and add space for 2 new
* extra entries that may be required for linearization. */
@@ -2730,6 +2748,30 @@ static void finalise_write_state(fz_context *ctx, pdf_write_state *opts)
fz_drop_output(ctx, opts->out);
}
+void pdf_parse_write_options(fz_context *ctx, pdf_write_options *opts, const char *args)
+{
+ int c;
+
+ memset(opts, 0, sizeof *opts);
+
+ while ((c = *args++))
+ {
+ switch (c)
+ {
+ case 'd': opts->do_decompress += 1; break;
+ case 'z': opts->do_compress += 1; break;
+ case 'f': opts->do_compress_fonts += 1; break;
+ case 'i': opts->do_compress_images += 1; break;
+ case 'p': opts->do_pretty += 1; break;
+ case 'a': opts->do_ascii += 1; break;
+ case 'g': opts->do_garbage += 1; break;
+ case 'l': opts->do_linear += 1; break;
+ case 's': opts->do_clean += 1; break;
+ default: fz_warn(ctx, "unrecognized pdf-write option: '%c'", c);
+ }
+ }
+}
+
void pdf_save_document(fz_context *ctx, pdf_document *doc, const char *filename, pdf_write_options *in_opts)
{
pdf_write_options opts_defaults = { 0 };