summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-write.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-04-27 14:14:52 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-04-27 17:01:06 +0200
commit4355fda4abe7e7022e3e258c276ccba9e4713d91 (patch)
tree7a21c614bad51f8157c56db60d658f77ad6273b6 /source/pdf/pdf-write.c
parenta1c86cfcea30b18734488935c636a5d7198b3983 (diff)
downloadmupdf-4355fda4abe7e7022e3e258c276ccba9e4713d91.tar.xz
Tweak pdf-write option handling.
The handling of not-decompressing images/fonts was geared towards pdfclean usage; but now that we can create new PDF files, it makes more sense to ask for images and fonts to be compressed, rather than asking for them not to be decompressed with quirky interaction with the 'expand' and 'deflate' flags. If -f or -i are set, we will never decompress images, and we will compress them if they are uncompressed. If -d is set, we will first decompress all streams (module -f or -i). If -z is set, we will then compress all uncompressed streams.
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 };