summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2012-04-30 15:27:30 +0100
committerChris Liddell <chris.liddell@artifex.com>2012-04-30 15:27:30 +0100
commit3cde6d6d3d24a0930d591df9914ddda194d13b37 (patch)
tree82552a7c14b6362c1852a059f17439782f3c39b6
parent60640aeb33b18f9a9fcd76fc6f1083d7c7635f24 (diff)
Bug 692459: stop tiffsep(1) overwriting pages already written
The tiffsep and tiffsep1 devices both get closed and reopen when the separations change (communicated by put_params). Previously this caused the output files to be closed and reopened - not a problem when writing each page to its own set of files, but when writing multipage tiffs, it resulted in all pages up to that point to be overwritten. We now have tiffsep and tiffsep1 handle their own file "management", and prevent output files from being closed and reopened when the device is closed and reopened due to a put_params call. No cluster differences.
-rw-r--r--gs/base/gdevtsep.c266
1 files changed, 189 insertions, 77 deletions
diff --git a/gs/base/gdevtsep.c b/gs/base/gdevtsep.c
index 15e276a22..a50557a41 100644
--- a/gs/base/gdevtsep.c
+++ b/gs/base/gdevtsep.c
@@ -406,6 +406,10 @@ static dev_proc_put_params(tiffsep1_put_params);
static dev_proc_print_page(tiffsep1_print_page);
static dev_proc_fill_path(sep1_fill_path);
+/* common to tiffsep and tiffsepo1 */
+static dev_proc_print_page_copies(tiffseps_print_page_copies);
+static dev_proc_output_page(tiffseps_output_page);
+
#define tiffsep_devices_common\
gx_device_common;\
gx_prn_device_common;\
@@ -415,6 +419,7 @@ static dev_proc_fill_path(sep1_fill_path);
bool BigEndian; /* true = big endian; false = little endian */\
uint16 Compression; /* for the separation files, same values as
TIFFTAG_COMPRESSION */\
+ bool close_files; \
long MaxStripSize;\
gs_devn_params devn_params; /* DeviceN generated parameters */\
equivalent_cmyk_color_params equiv_cmyk_colors\
@@ -424,6 +429,7 @@ static dev_proc_fill_path(sep1_fill_path);
*/
typedef struct tiffsep_device_s {
tiffsep_devices_common;
+ FILE *comp_file; /* Underlying file for tiff_comp */
TIFF *tiff_comp; /* tiff file for comp file */
bool warning_given;
} tiffsep_device;
@@ -479,6 +485,11 @@ RELOC_PTRS_END
static void
tiffsep_device_finalize(const gs_memory_t *cmem, void *vpdev)
{
+ tiffsep_device * const pdevn = (tiffsep_device *) vpdev;
+
+ /* for safety */
+ pdevn->close_files = true;
+
/* We need to deallocate the compressed_color_list.
and the names. */
devn_free_params((gx_device*) vpdev);
@@ -496,7 +507,7 @@ gs_private_st_composite_final(st_tiffsep_device, tiffsep_device,
{ open,\
gx_default_get_initial_matrix,\
NULL, /* sync_output */\
- tiff_output_page, /* output_page */\
+ tiffseps_output_page, /* output_page */\
close, /* close */\
NULL, /* map_rgb_color - not used */\
tiffsep_decode_color, /* map_color_rgb */\
@@ -557,7 +568,7 @@ gs_private_st_composite_final(st_tiffsep_device, tiffsep_device,
}
-#define tiffsep_devices_body(dtype, procs, dname, ncomp, pol, depth, mg, mc, sl, cn, print_page, compr)\
+#define tiffsep_devices_body(dtype, procs, dname, ncomp, pol, depth, mg, mc, sl, cn, print_page, print_page_copies, compr)\
std_device_full_body_type_extended(dtype, &procs, dname,\
&st_tiffsep_device,\
(int)((long)(DEFAULT_WIDTH_10THS) * (X_DPI) / 10),\
@@ -574,11 +585,12 @@ gs_private_st_composite_final(st_tiffsep_device, tiffsep_device,
0, 0, /* offsets */\
0, 0, 0, 0 /* margins */\
),\
- prn_device_body_rest_(print_page),\
+ prn_device_body_rest2_(print_page, print_page_copies, -1),\
{ 0 }, /* tiff state for separation files */\
{ 0 }, /* separation files */\
arch_is_big_endian /* true = big endian; false = little endian */,\
compr /* COMPRESSION_* */,\
+ true, /* close_files */ \
TIFF_DEFAULT_STRIP_SIZE /* MaxStripSize */
/*
@@ -614,7 +626,7 @@ static const gx_device_procs spot1_cmyk_procs =
const tiffsep_device gs_tiffsep_device =
{
- tiffsep_devices_body(tiffsep_device, spot_cmyk_procs, "tiffsep", NC, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, SL, "DeviceCMYK", tiffsep_print_page, COMPRESSION_LZW),
+ tiffsep_devices_body(tiffsep_device, spot_cmyk_procs, "tiffsep", NC, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, SL, "DeviceCMYK", tiffsep_print_page, tiffseps_print_page_copies, COMPRESSION_LZW),
/* devn_params specific parameters */
{ 8, /* Not used - Bits per color */
DeviceCMYKComponents, /* Names of color model colorants */
@@ -630,7 +642,7 @@ const tiffsep_device gs_tiffsep_device =
const tiffsep1_device gs_tiffsep1_device =
{
- tiffsep_devices_body(tiffsep1_device, spot1_cmyk_procs, "tiffsep1", NC, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, SL, "DeviceCMYK", tiffsep1_print_page, COMPRESSION_CCITTFAX4),
+ tiffsep_devices_body(tiffsep1_device, spot1_cmyk_procs, "tiffsep1", NC, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, SL, "DeviceCMYK", tiffsep1_print_page, tiffseps_print_page_copies, COMPRESSION_CCITTFAX4),
/* devn_params specific parameters */
{ 1, /* Not used - Bits per color */
DeviceCMYKComponents, /* Names of color model colorants */
@@ -838,6 +850,7 @@ tiffsep_put_params(gx_device * pdev, gs_param_list * plist)
int code;
const char *param_name;
gs_param_string comprstr;
+ bool save_close_files = pdevn->close_files;
/* Read BigEndian option as bool */
switch (code = param_read_bool(plist, (param_name = "BigEndian"), &pdevn->BigEndian)) {
@@ -882,8 +895,14 @@ tiffsep_put_params(gx_device * pdev, gs_param_list * plist)
break;
}
- return devn_printer_put_params(pdev, plist,
+ pdevn->close_files = false;
+
+ code = devn_printer_put_params(pdev, plist,
&(pdevn->devn_params), &(pdevn->equiv_cmyk_colors));
+
+ pdevn->close_files = save_close_files;
+
+ return(code);
}
static int
@@ -903,6 +922,52 @@ tiffsep1_put_params(gx_device * pdev, gs_param_list * plist)
return code;
}
+
+/* common print_page_copies method for both tiff separation devices */
+static int
+tiffseps_print_page_copies(gx_device_printer * pdev, FILE * prn_stream, int num_copies)
+{
+ int i = 1;
+ int code = 0;
+ (void) prn_stream;
+
+ for (; i < num_copies; ++i) {
+ code = (*pdev->printer_procs.print_page) (pdev, NULL);
+ if (code < 0)
+ return code;
+
+ pdev->PageCount++;
+
+ }
+ /* Print the last (or only) page. */
+ pdev->PageCount -= num_copies - 1;
+ return (*pdev->printer_procs.print_page) (pdev, NULL);
+}
+
+int
+tiffseps_output_page(gx_device *pdev, int num_copies, int flush)
+{
+ gx_device_printer * const ppdev = (gx_device_printer *)pdev;
+ int outcode = 0, closecode = 0, endcode;
+
+ if (num_copies > 0 || !flush) {
+ /* Print the accumulated page description. */
+ outcode = (*ppdev->printer_procs.print_page_copies)(ppdev, ppdev->file, num_copies);
+ }
+ endcode = (ppdev->buffer_space && !ppdev->is_async_renderer ?
+ clist_finish_page(pdev, flush) : 0);
+
+ if (outcode < 0)
+ return (outcode);
+ if (closecode < 0)
+ return (closecode);
+ if (endcode < 0)
+ return (endcode);
+
+ endcode = gx_finish_output_page(pdev, num_copies, flush);
+ return (endcode);
+}
+
static void build_comp_to_sep_map(tiffsep_device *, short *);
static int number_output_separations(int, int, int, int);
static int create_separation_file_name(tiffsep_device *, char *, uint, int, bool);
@@ -932,6 +997,7 @@ tiffsep1_prn_open(gx_device * pdev)
tfdev->fill_path = pdev->procs.fill_path;
pdev->procs.fill_path = sep1_fill_path;
}
+
return code;
}
@@ -979,26 +1045,28 @@ tiffsep1_prn_close(gx_device * pdev)
}
- build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
- /* Close the separation files */
- for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
- if (tfdev->sep_file[comp_num] != NULL) {
- int sep_num = map_comp_to_sep[comp_num];
-
- code = create_separation_file_name((tiffsep_device *)tfdev, name,
- MAX_FILE_NAME_SIZE, sep_num, true);
- if (code < 0)
- return code;
- code = gx_device_close_output_file(pdev, name, tfdev->sep_file[comp_num]);
- if (code < 0)
- return code;
- tfdev->sep_file[comp_num] = NULL;
+ if (tfdev->close_files) {
+ build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
+ /* Close the separation files */
+ for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
+ if (tfdev->sep_file[comp_num] != NULL) {
+ int sep_num = map_comp_to_sep[comp_num];
+
+ code = create_separation_file_name((tiffsep_device *)tfdev, name,
+ MAX_FILE_NAME_SIZE, sep_num, true);
+ if (code < 0)
+ return code;
+ code = gx_device_close_output_file(pdev, name, tfdev->sep_file[comp_num]);
+ if (code < 0)
+ return code;
+ tfdev->sep_file[comp_num] = NULL;
+ }
+ if (tfdev->tiff[comp_num]) {
+ TIFFCleanup(tfdev->tiff[comp_num]);
+ tfdev->tiff[comp_num] = NULL;
+ }
}
- if (tfdev->tiff[comp_num]) {
- TIFFCleanup(tfdev->tiff[comp_num]);
- tfdev->tiff[comp_num] = NULL;
}
- }
/* If we have thresholds, free them and clear the pointers */
if( tfdev->thresholds[0].dstart != NULL) {
sep1_free_thresholds(tfdev);
@@ -1238,11 +1306,11 @@ build_comp_to_sep_map(tiffsep_device * pdev, short * map_comp_to_sep)
int
tiffsep_prn_open(gx_device * pdev)
{
-
-#if TIFFSEP_PLANAR
gx_device_printer * const ppdev = (gx_device_printer *)pdev;
tiffsep_device *pdev_sep = (tiffsep_device *) pdev;
int code;
+
+#if TIFFSEP_PLANAR
/* With planar the depth can be more than 64. Update the color
info to reflect the proper depth and number of planes */
@@ -1268,15 +1336,11 @@ tiffsep_prn_open(gx_device * pdev)
pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
code = gdev_prn_open_planar(pdev, true);
ppdev->file = NULL;
- if (ppdev->OpenOutputFile)
- code = gdev_prn_open_printer_seekable(pdev, 1, true);
+
pdev->icc_struct->supports_devn = true;
- return code;
#else
- int code = tiff_open(pdev);
- tiffsep_device *pdev_sep = (tiffsep_device *) pdev;
+ code = tiff_open(pdev);
pdev_sep->warning_given = false;
-#endif
#if !USE_COMPRESSED_ENCODING
/*
@@ -1286,6 +1350,8 @@ tiffsep_prn_open(gx_device * pdev)
set_linear_color_bits_mask_shift(pdev);
pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
#endif
+#endif
+
return code;
}
@@ -1308,6 +1374,24 @@ tiffsep_close_sep_file(tiffsep_device *tfdev, const char *fn, int comp_num)
return code;
}
+static int
+tiffsep_close_comp_file(tiffsep_device *tfdev, const char *fn)
+{
+ int code;
+
+ if (tfdev->tiff_comp) {
+ TIFFCleanup(tfdev->tiff_comp);
+ tfdev->tiff_comp = NULL;
+ }
+
+ code = gx_device_close_output_file((gx_device *)tfdev,
+ fn,
+ tfdev->comp_file);
+ tfdev->comp_file = NULL;
+
+ return code;
+}
+
/* Close the tiffsep device */
int
tiffsep_prn_close(gx_device * pdev)
@@ -1324,7 +1408,7 @@ tiffsep_prn_close(gx_device * pdev)
int num_comp = number_output_separations(num_dev_comp, num_std_colorants,
num_order, num_spot);
- if (pdevn->tiff_comp) {
+ if (pdevn->tiff_comp && pdevn->close_files) {
TIFFCleanup(pdevn->tiff_comp);
pdevn->tiff_comp = NULL;
}
@@ -1332,19 +1416,21 @@ tiffsep_prn_close(gx_device * pdev)
if (code < 0)
return code;
- build_comp_to_sep_map(pdevn, map_comp_to_sep);
- /* Close the separation files */
- for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
- if (pdevn->sep_file[comp_num] != NULL) {
- int sep_num = map_comp_to_sep[comp_num];
-
- code = create_separation_file_name(pdevn, name,
- MAX_FILE_NAME_SIZE, sep_num, false);
- if (code < 0)
- return code;
- code = tiffsep_close_sep_file(pdevn, name, comp_num);
- if (code < 0)
- return code;
+ if (pdevn->close_files) {
+ build_comp_to_sep_map(pdevn, map_comp_to_sep);
+ /* Close the separation files */
+ for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
+ if (pdevn->sep_file[comp_num] != NULL) {
+ int sep_num = map_comp_to_sep[comp_num];
+
+ code = create_separation_file_name(pdevn, name,
+ MAX_FILE_NAME_SIZE, sep_num, false);
+ if (code < 0)
+ return code;
+ code = tiffsep_close_sep_file(pdevn, name, comp_num);
+ if (code < 0)
+ return code;
+ }
}
}
@@ -1655,7 +1741,7 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
int num_order = tfdev->devn_params.num_separation_order_names;
int num_spot = tfdev->devn_params.separations.num_separations;
- int num_comp, comp_num, sep_num, code = 0;
+ int num_comp, comp_num, sep_num, code = 0, code1 = 0;
short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
char name[MAX_FILE_NAME_SIZE];
@@ -1689,12 +1775,18 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
dprintf("CMYK composite file would be too large! Reduce resolution or enable compression.\n");
return_error(gs_error_rangecheck); /* this will overflow 32 bits */
}
-
- if (gdev_prn_file_is_new(pdev)) {
- tfdev->tiff_comp = tiff_from_filep(pdev->dname, file, tfdev->BigEndian);
+
+ if (!tfdev->comp_file) {
+ code = gx_device_open_output_file((gx_device *)pdev, pdev->fname, true, true, &(tfdev->comp_file));
+ if (code < 0)
+ return code;
+
+ tfdev->tiff_comp = tiff_from_filep(pdev->dname, tfdev->comp_file, tfdev->BigEndian);
if (!tfdev->tiff_comp)
return_error(gs_error_invalidfileaccess);
+
}
+
code = tiff_set_fields_for_printer(pdev, tfdev->tiff_comp, 1, 0);
if (tfdev->Compression==COMPRESSION_NONE || tfdev->Compression==COMPRESSION_LZW || tfdev->Compression==COMPRESSION_PACKBITS)
tiff_set_cmyk_fields(pdev, tfdev->tiff_comp, 8, tfdev->Compression, tfdev->MaxStripSize);
@@ -1719,15 +1811,7 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
sep_num, false);
if (code < 0)
return code;
- /*
- * Close the old separation file if we are creating individual files
- * for each page.
- */
- if (tfdev->sep_file[comp_num] != NULL && fmt != NULL) {
- code = tiffsep_close_sep_file(tfdev, name, comp_num);
- if (code < 0)
- return code;
- }
+
/* Open the separation file, if not already open */
if (tfdev->sep_file[comp_num] == NULL) {
code = gx_device_open_output_file((gx_device *)pdev, name,
@@ -1867,9 +1951,32 @@ tiffsep_print_page(gx_device_printer * pdev, FILE * file)
gs_free_object(pdev->memory, line, "tiffsep_print_page");
gs_free_object(pdev->memory, sep_line, "tiffsep_print_page");
#endif
- for (comp_num = 0; comp_num < num_comp; comp_num++ )
+
+ code1 = 0;
+ for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
TIFFWriteDirectory(tfdev->tiff[comp_num]);
+ if (fmt) {
+ int sep_num = map_comp_to_sep[comp_num];
+
+ code = create_separation_file_name(tfdev, name, MAX_FILE_NAME_SIZE, sep_num, false);
+ if (code < 0) {
+ code1 = code;
+ continue;
+ }
+ code = tiffsep_close_sep_file(tfdev, name, comp_num);
+ if (code < 0) {
+ code1 = code;
+ }
+ }
+ }
+
TIFFWriteDirectory(tfdev->tiff_comp);
+ if (fmt) {
+ code = tiffsep_close_comp_file(tfdev, pdev->fname);
+ }
+ if (code1 < 0) {
+ code = code1;
+ }
}
#if defined(DEBUG) && 0
@@ -1905,7 +2012,7 @@ tiffsep1_print_page(gx_device_printer * pdev, FILE * file)
int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
int num_order = tfdev->devn_params.num_separation_order_names;
int num_spot = tfdev->devn_params.separations.num_separations;
- int num_comp, comp_num, code = 0;
+ int num_comp, comp_num, code = 0, code1 = 0;
short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
char name[MAX_FILE_NAME_SIZE];
int save_depth = pdev->color_info.depth;
@@ -1957,21 +2064,7 @@ tiffsep1_print_page(gx_device_printer * pdev, FILE * file)
MAX_FILE_NAME_SIZE, sep_num, true);
if (code < 0)
return code;
- /*
- * Close the old separation file if we are creating individual files
- * for each page.
- */
- if (tfdev->sep_file[comp_num] != NULL && fmt != NULL) {
- code = gx_device_close_output_file((const gx_device *)tfdev, name,
- tfdev->sep_file[comp_num]);
- if (code < 0)
- return code;
- tfdev->sep_file[comp_num] = NULL;
- if (tfdev->tiff[comp_num]) {
- TIFFCleanup(tfdev->tiff[comp_num]);
- tfdev->tiff[comp_num] = NULL;
- }
- }
+
/* Open the separation file, if not already open */
if (tfdev->sep_file[comp_num] == NULL) {
code = gx_device_open_output_file((gx_device *)pdev, name,
@@ -2096,9 +2189,28 @@ tiffsep1_print_page(gx_device_printer * pdev, FILE * file)
TIFFWriteScanline(tfdev->tiff[comp_num], (tdata_t)dithered_line, y, 0);
} /* end component loop */
}
+
/* Update the strip data */
- for (comp_num = 0; comp_num < num_comp; comp_num++ )
+ code1 = 0;
+ for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
TIFFWriteDirectory(tfdev->tiff[comp_num]);
+
+ if (fmt) {
+ int sep_num = map_comp_to_sep[comp_num];
+
+ code = create_separation_file_name((tiffsep_device *)tfdev, name, MAX_FILE_NAME_SIZE, sep_num, false);
+ if (code < 0) {
+ code1 = code;
+ continue;
+ }
+ code = tiffsep_close_sep_file((tiffsep_device *)tfdev, name, comp_num);
+ if (code < 0) {
+ code1 = code;
+ }
+ }
+ }
+ code = code1;
+
gs_free_object(pdev->memory, line, "tiffsep1_print_page");
gs_free_object(pdev->memory, dithered_line, "tiffsep1_print_page");
}