summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/pdfobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pdfobj.c')
-rw-r--r--Build/source/texk/dvipdfm-x/pdfobj.c443
1 files changed, 325 insertions, 118 deletions
diff --git a/Build/source/texk/dvipdfm-x/pdfobj.c b/Build/source/texk/dvipdfm-x/pdfobj.c
index be799cc2290..a1acf1b5e25 100644
--- a/Build/source/texk/dvipdfm-x/pdfobj.c
+++ b/Build/source/texk/dvipdfm-x/pdfobj.c
@@ -1,6 +1,6 @@
/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
- Copyright (C) 2007-2018 by Jin-Hwan Cho and Shunsaku Hirata,
+ Copyright (C) 2007-2019 by Jin-Hwan Cho and Shunsaku Hirata,
the dvipdfmx project team.
Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
@@ -2223,48 +2223,9 @@ pdf_add_stream (pdf_obj *stream, const void *stream_data, int length)
#if HAVE_ZLIB
#define WBUF_SIZE 4096
-int
-pdf_add_stream_flate (pdf_obj *dst, const void *data, int len)
-{
- z_stream z;
- Bytef wbuf[WBUF_SIZE];
-
- z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL;
-
- z.next_in = (z_const Bytef *) data; z.avail_in = len;
- z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE;
-
- if (inflateInit(&z) != Z_OK) {
- WARN("inflateInit() failed.");
- return -1;
- }
-
- for (;;) {
- int status;
- status = inflate(&z, Z_NO_FLUSH);
- if (status == Z_STREAM_END)
- break;
- else if (status != Z_OK) {
- WARN("inflate() failed. Broken PDF file?");
- inflateEnd(&z);
- return -1;
- }
-
- if (z.avail_out == 0) {
- pdf_add_stream(dst, wbuf, WBUF_SIZE);
- z.next_out = wbuf;
- z.avail_out = WBUF_SIZE;
- }
- }
-
- if (WBUF_SIZE - z.avail_out > 0)
- pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out);
-
- return (inflateEnd(&z) == Z_OK ? 0 : -1);
-}
static int
-get_decode_parms (struct decode_parms *parms, pdf_obj *dict)
+filter_get_DecodeParms_FlateDecode (struct decode_parms *parms, pdf_obj *dict)
{
pdf_obj *tmp;
@@ -2278,18 +2239,25 @@ get_decode_parms (struct decode_parms *parms, pdf_obj *dict)
parms->columns = 1;
tmp = pdf_deref_obj(pdf_lookup_dict(dict, "Predictor"));
- if (tmp)
+ if (tmp) {
parms->predictor = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ }
tmp = pdf_deref_obj(pdf_lookup_dict(dict, "Colors"));
- if (tmp)
+ if (tmp) {
parms->colors = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ }
tmp = pdf_deref_obj(pdf_lookup_dict(dict, "BitsPerComponent"));
- if (tmp)
+ if (tmp) {
parms->bits_per_component = pdf_number_value(tmp);
+ pdf_release_obj(tmp);
+ }
tmp = pdf_deref_obj(pdf_lookup_dict(dict, "Columns"));
- if (tmp)
+ if (tmp) {
parms->columns = pdf_number_value(tmp);
-
+ pdf_release_obj(tmp);
+ }
if (parms->bits_per_component != 1 &&
parms->bits_per_component != 2 &&
parms->bits_per_component != 4 &&
@@ -2354,17 +2322,19 @@ filter_row_TIFF2 (unsigned char *dst, const unsigned char *src,
* Especially, calling pdf_add_stream() for each 4 bytes append is highly
* inefficient.
*/
-static int
-filter_decoded (pdf_obj *dst, const void *src, int srclen,
- struct decode_parms *parms)
+static pdf_obj *
+filter_stream_decode_Predictor (const void *src, size_t srclen, struct decode_parms *parms)
{
+ pdf_obj *dst;
const unsigned char *p = (const unsigned char *) src;
const unsigned char *endptr = p + srclen;
- unsigned char *prev, *buf;
- int bits_per_pixel = parms->colors * parms->bits_per_component;
- int bytes_per_pixel = (bits_per_pixel + 7) / 8;
- int length = (parms->columns * bits_per_pixel + 7) / 8;
- int i, error = 0;
+ unsigned char *prev, *buf;
+ int bits_per_pixel = parms->colors * parms->bits_per_component;
+ int bytes_per_pixel = (bits_per_pixel + 7) / 8;
+ int length = (parms->columns * bits_per_pixel + 7) / 8;
+ int i, error = 0;
+
+ dst = pdf_new_stream(0);
prev = NEW(length, unsigned char);
buf = NEW(length, unsigned char);
@@ -2491,16 +2461,21 @@ filter_decoded (pdf_obj *dst, const void *src, int srclen,
RELEASE(prev);
RELEASE(buf);
- return error;
+ if (error) {
+ pdf_release_obj(dst);
+ dst = NULL;
+ }
+
+ return dst;
}
-static int
-pdf_add_stream_flate_filtered (pdf_obj *dst, const void *data, int len, struct decode_parms *parms)
+static pdf_obj *
+filter_stream_decode_FlateDecode (const void *data, size_t len, struct decode_parms *parms)
{
- pdf_obj *tmp;
- z_stream z;
- Bytef wbuf[WBUF_SIZE];
- int error;
+ pdf_obj *dst;
+ pdf_obj *tmp;
+ z_stream z;
+ Bytef wbuf[WBUF_SIZE];
z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL;
@@ -2509,7 +2484,7 @@ pdf_add_stream_flate_filtered (pdf_obj *dst, const void *data, int len, struct d
if (inflateInit(&z) != Z_OK) {
WARN("inflateInit() failed.");
- return -1;
+ return NULL;
}
tmp = pdf_new_stream(0);
@@ -2521,7 +2496,8 @@ pdf_add_stream_flate_filtered (pdf_obj *dst, const void *data, int len, struct d
else if (status != Z_OK) {
WARN("inflate() failed. Broken PDF file?");
inflateEnd(&z);
- return -1;
+ pdf_release_obj(tmp);
+ return NULL;
}
if (z.avail_out == 0) {
@@ -2534,79 +2510,310 @@ pdf_add_stream_flate_filtered (pdf_obj *dst, const void *data, int len, struct d
if (WBUF_SIZE - z.avail_out > 0)
pdf_add_stream(tmp, wbuf, WBUF_SIZE - z.avail_out);
- error = filter_decoded(dst, pdf_stream_dataptr(tmp), pdf_stream_length(tmp), parms);
+ if (inflateEnd(&z) == Z_OK) {
+ if (parms) {
+ dst = filter_stream_decode_Predictor(pdf_stream_dataptr(tmp), pdf_stream_length(tmp), parms);
+ } else {
+ dst = pdf_link_obj(tmp);
+ }
+ } else {
+ dst = NULL;
+ }
pdf_release_obj(tmp);
- return ((!error && inflateEnd(&z) == Z_OK) ? 0 : -1);
+ return dst;
}
#endif
-int
-pdf_concat_stream (pdf_obj *dst, pdf_obj *src)
+static pdf_obj *
+filter_stream_decode_ASCIIHexDecode (const void *data, size_t len)
+{
+ pdf_obj *dst;
+ int eod, error;
+ const char *p = (const char *) data;
+ const char *endptr = p + len;
+ unsigned char *buf, ch;
+ size_t pos, n;
+
+ buf = NEW((len+1)/2, unsigned char);
+ skip_white(&p, endptr);
+ ch = 0; n = 0; pos = 0; eod = 0; error = 0;
+ while (p < endptr && !error && !eod) {
+ char c1, val;
+ c1 = p[0];
+ if (c1 >= 'A' && c1 <= 'F') {
+ val = c1 - 'A' + 10;
+ } else if (c1 >= 'a' && c1 <= 'f') {
+ val = c1 - 'a' + 10;
+ } else if (c1 >= '0' && c1 <= '9') {
+ val = c1 - '0';
+ } else if (c1 == '>') {
+ val = 0;
+ eod = 1;
+ if ((pos % 2) == 0)
+ break;
+ } else {
+ error = -1;
+ break;
+ }
+ if (pos % 2) {
+ buf[n] = ch + val;
+ n++;
+ ch = 0;
+ } else {
+ ch = val << 4;
+ }
+ pos++; p++;
+ skip_white(&p, endptr);
+ }
+ if (error || !eod) {
+ WARN("Invalid ASCIIHex data seen: %s", error ? "Invalid character" : "No EOD marker");
+ dst = NULL;
+ } else {
+ dst = pdf_new_stream(0);
+ pdf_add_stream(dst, buf, n);
+ }
+ RELEASE(buf);
+
+ return dst;
+}
+
+/* Percent sign is not start of comment here.
+ * We need this for reading Ascii85 encoded data.
+ */
+#define is_space(c) ((c) == ' ' || (c) == '\t' || (c) == '\f' || \
+ (c) == '\r' || (c) == '\n' || (c) == '\0')
+static void
+skip_white_a85 (const char **p, const char *endptr)
{
+ while (*p < endptr && (is_space(**p))) {
+ (*p)++;
+ }
+}
+
+static pdf_obj *
+filter_stream_decode_ASCII85Decode (const void *data, size_t len)
+{
+ pdf_obj *dst;
+ int eod, error;
+ const char *p = (const char *) data;
+ const char *endptr = p + len;
+ unsigned char *buf;
+ size_t n;
+
+ buf = NEW(((len+4)/5)*4, unsigned char);
+ skip_white_a85(&p, endptr);
+ n = 0; eod = 0; error = 0;
+ while (p < endptr && !error && !eod) {
+ char q[5] = {'u', 'u', 'u', 'u', 'u'};
+ int m;
+ char ch;
+
+ ch = p[0];
+ p++;
+ skip_white_a85(&p, endptr);
+ if (ch == 'z') {
+ memset(buf+n, 0, 4);
+ n += 4;
+ continue;
+ } else if (ch == '~') {
+ if (p < endptr && p[0] == '>') {
+ eod = 1;
+ p++;
+ } else {
+ error = -1;
+ }
+ break;
+ }
+ q[0] = ch;
+ for (m = 1; m < 5 && p < endptr; m++) {
+ ch = p[0];
+ p++;
+ skip_white_a85(&p, endptr);
+ if (ch == '~') {
+ if (p < endptr && p[0] == '>') {
+ eod = 1;
+ p++;
+ } else {
+ error = -1;
+ }
+ break;
+ } else if (ch < '!' || ch > 'u') {
+ error = -1;
+ break;
+ } else {
+ q[m] = ch;
+ }
+ }
+ if (!error) {
+ uint32_t val = 0;
+ int i;
+ if (m <= 1) {
+ error = -1;
+ break;
+ }
+ val = 85*85*85*(q[0] - '!') + 85*85*(q[1] - '!')
+ + 85*(q[2] - '!') + (q[3] - '!');
+ /* Check overflow */
+ if (val > UINT32_MAX / 85) {
+ error = -1;
+ break;
+ } else {
+ val = 85 * val;
+ if (val > UINT32_MAX - (q[4] - '!')) {
+ error = -1;
+ break;
+ }
+ val += (q[4] - '!');
+ }
+ if (!error) {
+ for (i = 3; i >= 0; i--) {
+ buf[n + i] = val & 0xff;
+ val /= 256;
+ }
+ n += m - 1;
+ }
+ }
+ }
+
+ if (error) {
+ WARN("Error in reading ASCII85 data.");
+ dst = NULL;
+ } else if (!eod) {
+ WARN("Error in reading ASCII85 data: No EOD");
+ dst = NULL;
+ } else {
+ dst = pdf_new_stream(0);
+ pdf_add_stream(dst, buf, n);
+ }
+ RELEASE(buf);
+
+ return dst;
+}
+
+static pdf_obj *
+filter_stream_decode (const char *filter_name, pdf_obj *src, pdf_obj *parm)
+{
+ pdf_obj *dec;
const char *stream_data;
- int stream_length;
- pdf_obj *stream_dict;
- pdf_obj *filter;
- int error = 0;
+ size_t stream_length;
- if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src))
- ERROR("Invalid type.");
+ if (!filter_name)
+ return pdf_link_obj(src);
stream_data = pdf_stream_dataptr(src);
- stream_length = pdf_stream_length (src);
- stream_dict = pdf_stream_dict (src);
+ stream_length = pdf_stream_length(src);
- filter = pdf_lookup_dict(stream_dict, "Filter");
- if (!filter)
- pdf_add_stream(dst, stream_data, stream_length);
+ if (!strcmp(filter_name, "ASCIIHexDecode")) {
+ dec = filter_stream_decode_ASCIIHexDecode(stream_data, stream_length);
+ } else if (!strcmp(filter_name, "ASCII85Decode")) {
+ dec = filter_stream_decode_ASCII85Decode(stream_data, stream_length);
#if HAVE_ZLIB
- else {
- struct decode_parms parms;
- int have_parms = 0;
+ } else if (!strcmp(filter_name, "FlateDecode")) {
+ struct decode_parms decode_parm;
+ if (parm)
+ filter_get_DecodeParms_FlateDecode(&decode_parm, parm);
+ dec = filter_stream_decode_FlateDecode(stream_data, stream_length, parm ? &decode_parm : NULL);
+#endif /* HAVE_ZLIB */
+ } else {
+ WARN("DecodeFilter \"%s\" not supported.", filter_name);
+ dec = NULL;
+ }
- if (pdf_lookup_dict(stream_dict, "DecodeParms")) {
- pdf_obj *tmp;
+ return dec;
+}
- /* Dictionary or array */
- tmp = pdf_deref_obj(pdf_lookup_dict(stream_dict, "DecodeParms"));
- if (PDF_OBJ_ARRAYTYPE(tmp)) {
- if (pdf_array_length(tmp) > 1) {
- WARN("Unexpected size for DecodeParms array.");
- return -1;
- }
- tmp = pdf_deref_obj(pdf_get_array(tmp, 0));
- }
- if (!PDF_OBJ_DICTTYPE(tmp)) {
- WARN("PDF dict expected for DecodeParms...");
- return -1;
- }
- error = get_decode_parms(&parms, tmp);
- if (error)
- ERROR("Invalid value(s) in DecodeParms dictionary.");
- have_parms = 1;
- }
- if (PDF_OBJ_ARRAYTYPE(filter)) {
- if (pdf_array_length(filter) > 1) {
- WARN("Multiple DecodeFilter not supported.");
+int
+pdf_concat_stream (pdf_obj *dst, pdf_obj *src)
+{
+ pdf_obj *filtered;
+ pdf_obj *stream_dict;
+ pdf_obj *filter, *parms;
+ int error = 0;
+
+ if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) {
+ WARN("Passed invalid type in pdf_concat_stream().");
+ return -1;
+ }
+
+ stream_dict = pdf_stream_dict(src);
+
+ filter = pdf_lookup_dict(stream_dict, "Filter");
+ if (!filter) {
+ pdf_add_stream(dst, pdf_stream_dataptr(src), pdf_stream_length(src));
+ return 0;
+ }
+ if (pdf_lookup_dict(stream_dict, "DecodeParms")) {
+ /* Dictionary or array */
+ parms = pdf_deref_obj(pdf_lookup_dict(stream_dict, "DecodeParms"));
+ if (!parms) {
+ WARN("Failed to deref DeocdeParms...");
+ return -1;
+ } else if (!PDF_OBJ_ARRAYTYPE(parms) && !PDF_OBJ_DICTTYPE(parms)) {
+ WARN("PDF dict or array expected for DecodeParms...");
+ pdf_release_obj(parms);
+ return -1;
+ }
+ } else {
+ parms = NULL;
+ }
+ if (PDF_OBJ_ARRAYTYPE(filter)) {
+ int i, num;
+ pdf_obj *prev = NULL;
+
+ num = pdf_array_length(filter);
+ if (parms) {
+ if (!PDF_OBJ_ARRAYTYPE(parms) || pdf_array_length(parms) != num) {
+ WARN("Invalid DecodeParam object found.");
+ pdf_release_obj(parms);
return -1;
}
- filter = pdf_get_array(filter, 0);
}
- if (PDF_OBJ_NAMETYPE(filter)) {
- char *filter_name = pdf_name_value(filter);
- if (filter_name && !strcmp(filter_name, "FlateDecode")) {
- if (have_parms)
- error = pdf_add_stream_flate_filtered(dst, stream_data, stream_length, &parms);
- else
- error = pdf_add_stream_flate(dst, stream_data, stream_length);
- } else {
- WARN("DecodeFilter \"%s\" not supported.", filter_name);
- error = -1;
+ if (num == 0) {
+ filtered = pdf_link_obj(src);
+ } else {
+ filtered = NULL;
+ prev = pdf_link_obj(src);
+ for (i = 0; i < num && prev != NULL; i++) {
+ pdf_obj *tmp1, *tmp2;
+
+ tmp1 = pdf_deref_obj(pdf_get_array(filter, i));
+ if (parms) {
+ tmp2 = pdf_deref_obj(pdf_get_array(parms, i));
+ } else {
+ tmp2 = NULL;
+ }
+ if (PDF_OBJ_NAMETYPE(tmp1)) {
+ filtered = filter_stream_decode(pdf_name_value(tmp1), prev, tmp2);
+ } else if (PDF_OBJ_NULLTYPE(tmp1)) {
+ filtered = pdf_link_obj(prev);
+ } else {
+ WARN("Unexpected object found for /Filter...");
+ filtered = NULL;
+ }
+ if (prev)
+ pdf_release_obj(prev);
+ if (tmp1)
+ pdf_release_obj(tmp1);
+ if (tmp2)
+ pdf_release_obj(tmp2);
+ prev = filtered;
}
- } else
- ERROR("Broken PDF file?");
-#endif /* HAVE_ZLIB */
+ }
+ } else if (PDF_OBJ_NAMETYPE(filter)) {
+ filtered = filter_stream_decode(pdf_name_value(filter), src, parms);
+ } else {
+ WARN("Invalid value for /Filter found.");
+ filtered = NULL;
+ }
+ if (parms)
+ pdf_release_obj(parms);
+ if (filtered) {
+ pdf_add_stream(dst, pdf_stream_dataptr(filtered), pdf_stream_length(filtered));
+ pdf_release_obj(filtered);
+ error = 0;
+ } else {
+ error = -1;
}
return error;