Fix: Bug 687560 "Invalid PDF if /BP pdfmarks with non-unique /_objdef"
"SaGS" <[email protected]> Mon, 30 Aug 2004 00:22:23 +0300
| Newsgroups | gmane.comp.printing.ghostscript.patches |
|---|---|
| Message-ID | <[email protected]> |
Hi all, Attached is a proposed fix for bug 687560. I added rather extensive comments to the bug report; for details on this patch, please see http://bugs.ghostscript.com/show_bug.cgi?id=687560, especially comment #6. _______________________________________________ gs-code-review mailing list [email protected] http://www.ghostscript.com/mailman/listinfo/gs-code-review
Bug687560.diff
(application/octet-stream, 22.8 KB)
Index: src/gdevpdfi.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfi.c,v
retrieving revision 1.56
diff -u -r1.56 gdevpdfi.c
--- src/gdevpdfi.c 4 Aug 2004 19:36:12 -0000 1.56
+++ src/gdevpdfi.c 29 Aug 2004 20:53:56 -0000
@@ -893,7 +893,7 @@
return 1;
case pattern_manage__start_accum:
code = pdf_enter_substream(pdev, resourcePattern, id, &pres, true,
- pdev->CompressFonts/* Have no better switch.*/);
+ pdev->CompressFonts/* Have no better switch.*/, NULL);
if (code < 0)
return code;
pres->rid = id;
Index: src/gdevpdfm.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfm.c,v
retrieving revision 1.45
diff -u -r1.45 gdevpdfm.c
--- src/gdevpdfm.c 15 Jul 2004 16:39:08 -0000 1.45
+++ src/gdevpdfm.c 29 Aug 2004 20:54:04 -0000
@@ -1040,6 +1040,31 @@
return size + 1;
}
+/* Create a unique distill-time objname for driver's internal use */
+private int
+pdf_unique_objname (char *objname)
+{
+ static long n_objname = 0; /* (no need to be context-specific) */
+ /* Notes:
+ * - Names generated by different pdf_unique_objname() calls are different because
+ * n_objname is incremented with each call.
+ * - All names generated by pdf_unique_objname() are different from all names coming
+ * from PostScript code because they are not enclosed in "{}".
+ */
+ return sprintf (objname,"?%ld",n_objname++);
+}
+
+/* Contants that define various methods to deal with duplicate distill-time names */
+#define PDF_NAMECOLLISION_NONAME 0x0001 /* not a named object (so no collision possible) */
+#define PDF_NAMECOLLISION_NONE 0x0002 /* no name collision */
+#define PDF_NAMECOLLISION_ERRCODE 0x0004 /* error, "return code" */
+#define PDF_NAMECOLLISION_ERRTYPE 0x0008 /* "return_error(gs_error_typecheck)" */
+#define PDF_NAMECOLLISION_ERRRANGE 0x0010 /* "return_error(gs_error_rangecheck)" */
+#define PDF_NAMECOLLISION_REBUILD 0x0020 /* "rebuid" the same object, discard old copy */
+#define PDF_NAMECOLLISION_KEEPOLD 0x0040 /* keep old copy, discard new one */
+#define PDF_NAMECOLLISION_BACKUP 0x0080 /* "backup" previous copy, then create a new obj */
+#define PDF_NAMECOLLISION_FWDOBJ 0x0100 /* false collision due to a forward reference */
+
/* Start a XObject. */
private int
start_XObject(gx_device_pdf * pdev, bool compress, cos_stream_t **ppcs,
@@ -1048,27 +1073,175 @@
cos_stream_t *pcs;
cos_value_t value;
int code;
+ int oper; /* one or more of the PDF_NAMECOLLISION_* values */
+ cos_object_t *pcoprev;
code = pdf_open_page(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
- code = pdf_enter_substream(pdev, resourceXObject, gs_no_id, &pres, true,
- pdev->CompressFonts /* Have no better switch*/);
- if (code < 0)
- return code;
- pcs = (cos_stream_t *)pres->object;
- pdev->substream_Resources = cos_dict_alloc(pdev, "start_XObject");
- if (!pdev->substream_Resources)
- return_error(gs_error_VMerror);
- code = cos_dict_put(pdev->local_named_objects, objname->data,
- objname->size, cos_object_value(&value, pres->object));
- if (code < 0)
- return code;
- pres->named = true;
- pres->where_used = 0; /* initially not used */
- pcs->pres = pres;
- *ppcs = pcs;
- return 0;
+
+ oper = 0;
+ if (objname) {
+ /* check for duplicate name and see which methods are suitable for resolving the conflict */
+ switch (code = pdf_find_named(pdev, objname, &pcoprev)) {
+ case gs_error_undefined: /* new name */
+ oper = PDF_NAMECOLLISION_NONE;
+ break;
+ case 0: /* duplicate name */
+ if (cos_type(pcoprev) == cos_type_generic)
+ /* (assumes named generic objects in pdev->local_named_objects are
+ created only as a result of finding forward references) */
+ oper = PDF_NAMECOLLISION_FWDOBJ | PDF_NAMECOLLISION_REBUILD;
+ else if (cos_type(pcoprev) != cos_type_stream)
+ /* do not accept changing the type of an object */
+ oper = PDF_NAMECOLLISION_ERRTYPE;
+ else if (pcoprev->is_graphics && pcoprev->is_open)
+ /* do not accept redefining a Form XObject while it is being built */
+ oper = PDF_NAMECOLLISION_ERRRANGE;
+ else
+ oper = PDF_NAMECOLLISION_KEEPOLD | PDF_NAMECOLLISION_REBUILD | PDF_NAMECOLLISION_BACKUP;
+ break;
+ default: /* misc errors */
+ oper = PDF_NAMECOLLISION_ERRCODE;
+ break;
+ }
+ } else
+ oper = PDF_NAMECOLLISION_NONAME;
+ /* cannot rebuild an object that is already written */
+ if ((oper &PDF_NAMECOLLISION_REBUILD) && pcoprev->written)
+ oper &= ~PDF_NAMECOLLISION_REBUILD;
+ /* favor PDF_NAMECOLLISION_FWDOBJ over PDF_NAMECOLLISION_REBUILD */
+ if (oper &PDF_NAMECOLLISION_FWDOBJ)
+ oper &= ~PDF_NAMECOLLISION_REBUILD;
+ /* favor PDF_NAMECOLLISION_REBUILD over PDF_NAMECOLLISION_KEEPOLD over PDF_NAMECOLLISION_BACKUP */
+ if (oper &PDF_NAMECOLLISION_REBUILD)
+ oper &= ~(PDF_NAMECOLLISION_BACKUP|PDF_NAMECOLLISION_KEEPOLD);
+ if (oper &PDF_NAMECOLLISION_BACKUP)
+ oper &= ~(PDF_NAMECOLLISION_KEEPOLD);
+ /* the various methods of resolving name conflicts */
+ switch (oper) {
+ case PDF_NAMECOLLISION_ERRCODE:
+ return code;
+ case PDF_NAMECOLLISION_ERRTYPE:
+ return_error(gs_error_typecheck);
+ case PDF_NAMECOLLISION_ERRRANGE:
+ return_error(gs_error_rangecheck);
+ default:
+ /* should never happen; if it does, the decision code above is incomplete */
+ return_error(gs_error_unknownerror);
+ case PDF_NAMECOLLISION_REBUILD: {
+ pdf_resource_t *presprev = pcoprev->pres;
+ long oldid = pcoprev->id;
+ /* "rebuid" the same object, discarding the old copy
+ * - create a new generic object, as if encountering a forward reference
+ * - assign this object the same id as the old copy and reuse the resource
+ * - the old object gets freed while the new one is inserted into
+ * pdev->local_named_objects by pdf_create_named()
+ * - continue as if we have to create an object that was forward referenced
+ */
+ if (presprev)
+ presprev->object = NULL; /* diconnect resource from old object... */
+ pcoprev->pres = NULL; /* ... (prevent it to be freed) */
+ code = pdf_create_named(pdev,objname,cos_type_generic,&pcoprev,oldid);
+ if (code < 0)
+ return code;
+ pcoprev->pres = presprev;
+ pdf_obj_ref_reused(pdev,oldid);
+ pcoprev->is_graphics = true;
+ pcoprev->pres->named = true;
+ }
+ oper = PDF_NAMECOLLISION_FWDOBJ; /* continue as for a "forward" object...*/
+ case PDF_NAMECOLLISION_FWDOBJ:
+ /* false collision due to a forward reference, resolved by "continuing" with
+ * the old object from where pdf_replace_names() left off
+ * - pass the old object to pdf_enter_substream() so it will "continue"
+ * with it instead of creating a new one
+ * - do not add the object to pdev->local_named_objects, it's already there
+ * - pcoprev->named/where_used already in place
+ */
+ code = pdf_enter_substream(pdev, resourceXObject, gs_no_id, &pres, true,
+ pdev->CompressFonts /* Have no better switch*/, pcoprev);
+ if (code < 0)
+ return code;
+ pcs = (cos_stream_t *)pres->object;
+ pdev->substream_Resources = cos_dict_alloc(pdev, "start_XObject(FWDOBJ)");
+ if (!pdev->substream_Resources)
+ return_error(gs_error_VMerror);
+ if (code < 0)
+ return code;
+ pcs->pres = pres;
+ *ppcs = pcs;
+ return 0;
+ case PDF_NAMECOLLISION_KEEPOLD:
+ /* keep old copy, discard new one
+ * - create a "temporary object" without an ID
+ * - do not add the object to pdev->local_named_objects, because:
+ * - adding it removes the old object
+ * - it does not have an ID, so it must not be accessible by name since
+ * we cannot create references ("n 0 R") to it
+ * - pdfmark_EP() will discard the object
+ */
+ code = pdf_enter_substream(pdev, resourceXObject, gs_no_id, &pres, false,
+ pdev->CompressFonts /* Have no better switch*/, NULL);
+ if (code < 0)
+ return code;
+ pcs = (cos_stream_t *)pres->object;
+ pdev->substream_Resources = cos_dict_alloc(pdev, "start_XObject(KEEPOLD)");
+ if (!pdev->substream_Resources)
+ return_error(gs_error_VMerror);
+ pres->named = true;
+ pres->where_used = 0; /* initially not used */
+ pcs->pres = pres;
+ *ppcs = pcs;
+ return 0;
+ case PDF_NAMECOLLISION_BACKUP:
+ /* "backup" previous copy, then create a new object
+ * (an object name is treated like a variable: pdfmarks that create objects
+ * "assign" a (new) value to it, and each reference to the object takes
+ * into account the most recent value (in execution order))
+ * - replace the key in pdev->local_named_objects with a unique one
+ * - continue as if no name conflict
+ */
+ { char unique[1+10+1]; /* '?' + long + '\0' */
+ code = cos_dict_rename(pdev->local_named_objects,
+ objname->data,objname->size,
+ (const byte *)unique,pdf_unique_objname(unique));
+ if (code < 0)
+ return code;
+ }
+ oper = PDF_NAMECOLLISION_NONE; /* continue as for PDF_NAMECOLLISION_NONE... */
+ case PDF_NAMECOLLISION_NONAME:
+ /* object does not have a name
+ * - same as PDF_NAMECOLLISION_NONE, except the object is not registered
+ * in pdev->local_named_objects.
+ */
+ case PDF_NAMECOLLISION_NONE:
+ /* no name conflict
+ * - create the object normally and initialize all its fields
+ * - do assign the object an id
+ * - register the object in pdev->local_named_objects
+ */
+ code = pdf_enter_substream(pdev, resourceXObject, gs_no_id, &pres, true,
+ pdev->CompressFonts /* Have no better switch*/, NULL);
+ if (code < 0)
+ return code;
+ pcs = (cos_stream_t *)pres->object;
+ pdev->substream_Resources = cos_dict_alloc(pdev, "start_XObject(NONAMECOLLISION)");
+ if (!pdev->substream_Resources)
+ return_error(gs_error_VMerror);
+ if (!(oper &PDF_NAMECOLLISION_NONAME))
+ code = cos_dict_put(pdev->local_named_objects, objname->data,
+ objname->size, cos_object_value(&value, pres->object));
+ else
+ DO_NOTHING;
+ if (code < 0)
+ return code;
+ pres->named = !(oper &PDF_NAMECOLLISION_NONAME);
+ pres->where_used = 0; /* initially not used */
+ pcs->pres = pres;
+ *ppcs = pcs;
+ return 0;
+ }
}
/* PS pdfmark */
@@ -1108,7 +1281,7 @@
code = pdf_enter_substream(pdev,
resourceXObject /* A stub. Actually it's not a resource. */,
gs_no_id, &pres, true,
- pdev->CompressFonts /* Have no better switch*/);
+ pdev->CompressFonts /* Have no better switch*/, NULL);
if (code < 0)
return code;
pcs = (cos_stream_t *)pres->object;
@@ -1458,13 +1631,23 @@
const gs_matrix * pctm, const gs_param_string * no_objname)
{
int code;
+ pdf_resource_t *pres_cancel;
- code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
- if (code < 0)
- return code;
+ pres_cancel = pdev->accumulating_substream_resource;
+ if (pres_cancel->object->id > 0) pres_cancel = NULL;
+ if (!pres_cancel) {
+ code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
+ if (code < 0)
+ return code;
+ }
code = pdf_exit_substream(pdev);
if (code < 0)
return code;
+ if (pres_cancel) {
+ code = pdf_cancel_resource(pdev, pres_cancel, resourceXObject);
+ if (code < 0)
+ return code;
+ }
return 0;
}
@@ -1478,10 +1661,31 @@
if (count != 1)
return_error(gs_error_rangecheck);
- if ((code = pdf_get_named(pdev, &pairs[0], cos_type_stream, &pco)) < 0)
+ if ((code = pdf_refer_named(pdev, &pairs[0], &pco)) < 0)
+ /* misc errors */
return code;
- if (pco->is_open || !pco->is_graphics)
- return_error(gs_error_rangecheck);
+ if (cos_type(pco) == cos_type_generic) {
+ /* forward reference
+ * - use the object without additional checks
+ * - be sure it has an associated resource structure, since we need to
+ * store some information in object->pres->where_used
+ * - don't turn it into a stream object (let it remain a generic one), since
+ * the object is not yet finalized and references to it are still "forward"
+ */
+ if (pco->pres == 0) {
+ code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, resourceXObject, gs_no_id),
+ pdf_resource_type_structs[resourceXObject], &pco->pres, 0, pco);
+ if (pco->pres == 0)
+ return_error(gs_error_VMerror);
+ }
+ pco->pres->named = true;
+ pco->is_graphics = true;
+ } else if (cos_type(pco) == cos_type_stream) {
+ /* object exists as a stream */
+ if (!pco->is_graphics || pco->is_open)
+ return_error(gs_error_rangecheck);
+ } else
+ return_error(gs_error_typecheck);
code = pdf_open_contents(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
Index: src/gdevpdfo.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfo.c,v
retrieving revision 1.30
diff -u -r1.30 gdevpdfo.c
--- src/gdevpdfo.c 8 Jun 2004 11:43:03 -0000 1.30
+++ src/gdevpdfo.c 29 Aug 2004 20:54:09 -0000
@@ -986,6 +986,36 @@
return cos_dict_put_c_key(pcd, key, cos_c_string_value(&cvalue, value));
}
+/* "Rename" a dict entry by changing the key without affecting the value */
+int
+cos_dict_rename(cos_dict_t *pcd, const byte *oldkey_data, uint oldkey_size,
+ const byte *newkey_data, uint newkey_size)
+{
+ gs_memory_t *mem = COS_OBJECT_MEMORY(pcd);
+ cos_dict_element_t **ppcde = &pcd->elements;
+ cos_dict_element_t *next;
+ byte *copied_key_data;
+ int code;
+
+ while ((next = *ppcde) != 0)
+ if (bytes_compare(next->key.data, next->key.size, oldkey_data, oldkey_size))
+ ppcde = &next->next;
+ else {
+ copied_key_data = gs_alloc_string(mem, newkey_size,"cos_dict_rename(new key)");
+ if (copied_key_data == 0)
+ return_error(gs_error_VMerror);
+ memcpy(copied_key_data, newkey_data, newkey_size);
+ if (next->owns_key)
+ gs_free_const_string(mem, next->key.data, next->key.size,
+ "cos_dict_rename(old key)");
+ next->key.data = copied_key_data;
+ next->key.size = newkey_size;
+ next->owns_key = true;
+ return 0;
+ }
+ return_error(gs_error_undefined);
+}
+
/* Move all the elements from one dict to another. */
int
cos_dict_move_all(cos_dict_t *pcdto, cos_dict_t *pcdfrom)
Index: src/gdevpdfo.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfo.h,v
retrieving revision 1.19
diff -u -r1.19 gdevpdfo.h
--- src/gdevpdfo.h 8 Jun 2004 11:43:04 -0000 1.19
+++ src/gdevpdfo.h 29 Aug 2004 20:54:11 -0000
@@ -251,6 +251,9 @@
int cos_dict_put_string(cos_dict_t *, const byte *, uint, const byte *, uint);
int cos_dict_put_string_copy(cos_dict_t *pcd, const char *key, const char *value);
int cos_dict_put_c_strings(cos_dict_t *, const char *, const char *);
+/* rename an entry by changing the key without affecting the value */
+int cos_dict_rename(cos_dict_t *pcd, const byte *oldkey_data, uint oldkey_size,
+ const byte *newkey_data, uint newkey_size);
/* move all the elements from one dict to another */
int cos_dict_move_all(cos_dict_t *, cos_dict_t *);
/* stream */
Index: src/gdevpdfu.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfu.c,v
retrieving revision 1.58
diff -u -r1.58 gdevpdfu.c
--- src/gdevpdfu.c 24 Aug 2004 17:51:31 -0000 1.58
+++ src/gdevpdfu.c 29 Aug 2004 20:54:17 -0000
@@ -140,6 +140,21 @@
fwrite(&pos, sizeof(pos), 1, pdev->xref.file);
return id;
}
+/* Reuse an ID from an existing object.
+ Similar to pdf_obj_ref(), but receives an ID to reuse instead of allocating a new one */
+long
+pdf_obj_ref_reused(gx_device_pdf * pdev, long id)
+{
+ long pos = pdf_stell(pdev);
+ FILE *tfile = pdev->xref.file;
+ long tpos = ftell(tfile);
+
+ fseek(tfile, (id - pdev->FirstObjectNumber) * sizeof(pos),
+ SEEK_SET);
+ fwrite(&pos, sizeof(pos), 1, tfile);
+ fseek(tfile, tpos, SEEK_SET);
+ return id;
+}
/* Begin an object, optionally allocating an ID. */
long
@@ -281,7 +296,7 @@
pdf_resource_t *pres;
code = pdf_enter_substream(pdev, resourcePage, gs_no_id, &pres,
- true, pdev->params.CompressPages);
+ true, pdev->params.CompressPages, NULL);
if (code < 0)
return code;
pdev->contents_id = pres->object->id;
@@ -572,16 +587,35 @@
int
pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
const gs_memory_struct_type_t * pst, pdf_resource_t **ppres,
- long id)
+ long id, cos_object_t *pcofwd)
{
pdf_resource_t *pres;
cos_object_t *object;
if (pst == NULL)
pst = &st_pdf_resource;
- pres = gs_alloc_struct(pdev->pdf_memory, pdf_resource_t, pst,
- "pdf_alloc_aside(resource)");
- object = cos_object_alloc(pdev, "pdf_alloc_aside(object)");
+ if (pcofwd) {
+ /* received a "forward" object to use instead of allocating a new object */
+ object = pcofwd;
+ id = object->id; /* "forward" objects already have ids */
+ pres = object->pres;
+ } else {
+ object = cos_object_alloc(pdev, "pdf_alloc_aside(object)");
+ pres = 0;
+ }
+ if (pres == 0) {
+ pres = gs_alloc_struct(pdev->pdf_memory, pdf_resource_t, pst,
+ "pdf_alloc_aside(resource)");
+ if (pres) {
+ pres->next = *plist;
+ *plist = pres;
+ pres->prev = pdev->last_resource;
+ pdev->last_resource = pres;
+ pres->named = false;
+ pres->where_used = pdev->used_mask;
+ }
+ } else
+ DO_NOTHING; /* "forward" object already has an associated resource */
if (pres == 0 || object == 0) {
return_error(gs_error_VMerror);
}
@@ -591,12 +625,6 @@
pres->rname[0] = 0;
} else
pdf_reserve_object_id(pdev, pres, id);
- pres->next = *plist;
- *plist = pres;
- pres->prev = pdev->last_resource;
- pdev->last_resource = pres;
- pres->named = false;
- pres->where_used = pdev->used_mask;
*ppres = pres;
return 0;
}
@@ -608,7 +636,7 @@
if (id < 0)
return (int)id;
- return pdf_alloc_aside(pdev, plist, pst, ppres, id);
+ return pdf_alloc_aside(pdev, plist, pst, ppres, id, NULL);
}
/* Begin a resource of a given type. */
@@ -644,7 +672,7 @@
pdf_resource_t ** ppres, long id)
{
int code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, rid),
- pdf_resource_type_structs[rtype], ppres, id);
+ pdf_resource_type_structs[rtype], ppres, id, NULL);
if (code >= 0)
(*ppres)->rid = rid;
@@ -1321,7 +1349,7 @@
pdw->binary.dev = (gx_device_psdf *)pdev;
pdw->binary.strm = 0; /* for GC in case of failure */
code = pdf_open_aside(pdev, resourceOther, gs_no_id, &pdw->pres, !object_id,
- (options & DATA_STREAM_COMPRESS ? true : false));
+ (options & DATA_STREAM_COMPRESS ? true : false), NULL);
if (object_id != 0)
pdf_reserve_object_id(pdev, pdw->pres, object_id);
pdw->binary.strm = pdev->strm;
Index: src/gdevpdfx.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdfx.h,v
retrieving revision 1.100
diff -u -r1.100 gdevpdfx.h
--- src/gdevpdfx.h 24 Aug 2004 17:51:31 -0000 1.100
+++ src/gdevpdfx.h 29 Aug 2004 20:54:22 -0000
@@ -700,6 +700,9 @@
/* Allocate an ID for a future object. */
long pdf_obj_ref(gx_device_pdf * pdev);
+/* Reuse an ID from an existing object.
+ Similar to pdf_obj_ref(), but receives an ID to reuse instead of allocating a new one */
+long pdf_obj_ref_reused(gx_device_pdf * pdev, long id);
/* Read the current position in the output stream. */
long pdf_stell(gx_device_pdf * pdev);
@@ -743,7 +746,7 @@
/* Begin an aside (resource, annotation, ...). */
int pdf_alloc_aside(gx_device_pdf * pdev, pdf_resource_t ** plist,
const gs_memory_struct_type_t * pst, pdf_resource_t **ppres,
- long id);
+ long id, cos_object_t *pcofwd);
/* Begin an aside (resource, annotation, ...). */
int pdf_begin_aside(gx_device_pdf * pdev, pdf_resource_t **plist,
const gs_memory_struct_type_t * pst,
@@ -1116,15 +1119,15 @@
int pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font);
/* Open a stream object in the temporary file. */
-int pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
- gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress);
+int pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype, gs_id id,
+ pdf_resource_t **ppres, bool reserve_object_id, bool compress, cos_object_t *pcofwd);
/* Close a stream object in the temporary file. */
int pdf_close_aside(gx_device_pdf *pdev);
/* Enter the substream accumulation mode. */
-int pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
- gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress);
+int pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype, gs_id id,
+ pdf_resource_t **ppres, bool reserve_object_id, bool compress, cos_object_t *pcofwd);
/* Exit the substream accumulation mode. */
int pdf_exit_substream(gx_device_pdf *pdev);
Index: src/gdevpdti.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdti.c,v
retrieving revision 1.36
diff -u -r1.36 gdevpdti.c
--- src/gdevpdti.c 4 Aug 2004 19:36:12 -0000 1.36
+++ src/gdevpdti.c 29 Aug 2004 20:54:25 -0000
@@ -386,7 +386,7 @@
pdf_char_proc_t *pcp;
pdf_resource_t *pres;
int code = pdf_enter_substream(pdev, resourceCharProc, gs_next_ids(pdev->memory, 1),
- &pres, false, pdev->CompressFonts);
+ &pres, false, pdev->CompressFonts, NULL);
if (code < 0)
return code;
@@ -447,8 +447,8 @@
*/
int
-pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
- gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
+pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype, gs_id id,
+ pdf_resource_t **ppres, bool reserve_object_id, bool compress, cos_object_t *pcofwd)
{
int code;
pdf_resource_t *pres;
@@ -460,7 +460,7 @@
pdev->streams.save_strm = pdev->strm;
code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, id),
- pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1);
+ pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1, pcofwd);
if (code < 0)
return code;
cos_become(pres->object, cos_type_stream);
@@ -517,8 +517,8 @@
* Enter the substream accumulation mode.
*/
int
-pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
- gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
+pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype, gs_id id,
+ pdf_resource_t **ppres, bool reserve_object_id, bool compress, cos_object_t *pcofwd)
{
int sbstack_ptr = pdev->sbstack_depth;
pdf_resource_t *pres;
@@ -532,7 +532,7 @@
if (pdev->sbstack[sbstack_ptr].text_state == 0)
return_error(gs_error_VMerror);
}
- code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id, compress);
+ code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id, compress, pcofwd);
if (code < 0)
return code;
code = pdf_save_viewer_state(pdev, NULL);