diff options
Diffstat (limited to 'devices')
34 files changed, 515 insertions, 261 deletions
diff --git a/devices/extract.mak b/devices/extract.mak index 71f30825..1ed6080b 100644 --- a/devices/extract.mak +++ b/devices/extract.mak @@ -1,4 +1,4 @@ -# Copyright (C) 2001-2021 Artifex Software, Inc. +# Copyright (C) 2001-2022 Artifex Software, Inc. # All Rights Reserved. # # This software is provided AS-IS with no warranty, either express or @@ -22,6 +22,9 @@ $(extract_out_prefix)alloc.$(OBJ): $(EXTRACT_DIR)/src/alloc.c $(MAKEDIR $(extract_out_prefix)astring.$(OBJ): $(EXTRACT_DIR)/src/astring.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/astring.c +$(extract_out_prefix)boxer.$(OBJ): $(EXTRACT_DIR)/src/boxer.c $(MAKEDIRS) + $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/boxer.c + $(extract_out_prefix)buffer.$(OBJ): $(EXTRACT_DIR)/src/buffer.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/buffer.c @@ -55,6 +58,9 @@ $(extract_out_prefix)odt_template.$(OBJ): $(EXTRACT_DIR)/src/odt_template.c $( $(extract_out_prefix)outf.$(OBJ): $(EXTRACT_DIR)/src/outf.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/outf.c +$(extract_out_prefix)rect.$(OBJ): $(EXTRACT_DIR)/src/rect.c $(MAKEDIRS) + $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/rect.c + $(extract_out_prefix)sys.$(OBJ): $(EXTRACT_DIR)/src/sys.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/sys.c @@ -70,6 +76,7 @@ $(extract_out_prefix)zip.$(OBJ): $(EXTRACT_DIR)/src/zip.c $(MAKEDIRS) EXTRACT_OBJS = \ $(extract_out_prefix)alloc.$(OBJ) \ $(extract_out_prefix)astring.$(OBJ) \ + $(extract_out_prefix)boxer.$(OBJ) \ $(extract_out_prefix)buffer.$(OBJ) \ $(extract_out_prefix)document.$(OBJ) \ $(extract_out_prefix)docx.$(OBJ) \ @@ -81,6 +88,7 @@ EXTRACT_OBJS = \ $(extract_out_prefix)odt.$(OBJ) \ $(extract_out_prefix)odt_template.$(OBJ) \ $(extract_out_prefix)outf.$(OBJ) \ + $(extract_out_prefix)rect.$(OBJ) \ $(extract_out_prefix)sys.$(OBJ) \ $(extract_out_prefix)text.$(OBJ) \ $(extract_out_prefix)xml.$(OBJ) \ diff --git a/devices/gdevclj.c b/devices/gdevclj.c index 4d4d9c71..26bf0f0e 100644 --- a/devices/gdevclj.c +++ b/devices/gdevclj.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -380,7 +380,7 @@ pack_and_compress_scanline( } /* clear to up a longword boundary */ - while ((((ulong)p_c) & (sizeof(ulong) - 1)) != 0) { + while ((((intptr_t)p_c) & (sizeof(ulong) - 1)) != 0) { *p_c++ = 0; *p_m++ = 0; *p_y++ = 0; diff --git a/devices/gdevpng.c b/devices/gdevpng.c index 554c664c..e9e776b5 100644 --- a/devices/gdevpng.c +++ b/devices/gdevpng.c @@ -632,6 +632,10 @@ do_png_print_page(gx_device_png * pdev, gp_file * file, bool monod) num_palette = 0; } /* add comment */ +#ifdef CLUSTER + strncpy(software_key, "GPL Ghostscript", sizeof(software_key)); + strncpy(software_text, "GPL Ghostscript", sizeof(software_text)); +#else strncpy(software_key, "Software", sizeof(software_key)); { int major = (int)(gs_revision / 1000); @@ -640,6 +644,7 @@ do_png_print_page(gx_device_png * pdev, gp_file * file, bool monod) gs_snprintf(software_text, sizeof(software_text), "%s %d.%02d.%d", gs_product, major, minor, patch); } +#endif text_png.compression = -1; /* uncompressed */ text_png.key = software_key; text_png.text = software_text; diff --git a/devices/gdevpsd.c b/devices/gdevpsd.c index d538b784..2a54a471 100644 --- a/devices/gdevpsd.c +++ b/devices/gdevpsd.c @@ -942,12 +942,20 @@ psd_setup(psd_write_ctx *xc, gx_devn_prn_device *dev, gp_file *file, int w, int xc->num_channels = i; if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE && strcmp(dev->dname, "psdcmykog") != 0) { + + /* Note: num_separation_order_names is only set if + SeparationColorNames was setup. If this was not set, + we need may need to make use of the ICCOutputColors + and page spot colors for our setup. */ if (dev->devn_params.num_separation_order_names == 0) { /* Page spot colors has been truncated to ensure max colorants of the target device is not exceeded. This is set if PDF file was encountered and should be used. - Also make sure PS file does not exceed limit of device. */ - if (dev->devn_params.page_spot_colors > 0) + Also make sure PS file does not exceed limit of device. + However, if ICCOutputColors was specified, that should + take precedence. */ + if (dev->devn_params.page_spot_colors > 0 && + dev->icc_struct->spotnames == NULL) xc->n_extra_channels = dev->devn_params.page_spot_colors; else { if (dev->devn_params.separations.num_separations <= (dev->color_info.max_components - NUM_CMYK_COMPONENTS)) @@ -1008,13 +1016,13 @@ psd_setup(psd_write_ctx *xc, gx_devn_prn_device *dev, gp_file *file, int w, int bool has_tags = (pdev_psd->color_model == psd_DEVICE_CMYKT); xc->num_channels += xc->n_extra_channels; - for (i=xc->base_num_channels; i < xc->num_channels; i++) { + for (i=xc->base_num_channels + has_tags; i < xc->num_channels; i++) { int j; const char *curr = "\377"; int curr_size = 1; bool compare; - for (j=xc->base_num_channels; j < (xc->num_channels - has_tags); j++) { + for (j=xc->base_num_channels + has_tags; j < xc->num_channels; j++) { devn_separation_name *separation_name; separation_name = &(dev->devn_params.separations.names[j - xc->base_num_channels]); diff --git a/devices/gdevsppr.c b/devices/gdevsppr.c index 29d34dd9..2806253d 100644 --- a/devices/gdevsppr.c +++ b/devices/gdevsppr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -101,7 +101,7 @@ err_code_string(int err_code) { if ((err_code<EMOTOR)||(err_code>ESERIAL)) { - gs_sprintf(err_buffer,"err_code out of range: %d",err_code); + gs_snprintf(err_buffer, 80, "err_code out of range: %d",err_code); return err_buffer; } return errmsg[err_code]; diff --git a/devices/gdevtfax.c b/devices/gdevtfax.c index 531eb964..5acd2626 100644 --- a/devices/gdevtfax.c +++ b/devices/gdevtfax.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -47,7 +47,7 @@ struct gx_device_tfax_s { /* The type and range of FillOrder follows TIFF 6 spec */ bool BigEndian; /* true = big endian; false = little endian*/ bool UseBigTIFF; - uint16 Compression; /* same values as TIFFTAG_COMPRESSION */ + uint16_t Compression; /* same values as TIFFTAG_COMPRESSION */ bool write_datetime; TIFF *tif; /* For TIFF output only */ }; @@ -71,7 +71,10 @@ tfax_initialize_device_procs(gx_device *dev) #define TFAX_DEVICE(dname, print_page, compr)\ {\ FAX_DEVICE_BODY(gx_device_tfax, tfax_initialize_device_procs, dname, print_page),\ - TIFF_DEFAULT_STRIP_SIZE /* strip size byte count */,\ + /* We want Fax output to be contained in one strip because apparently 'many' fax readers have\ + * problems reading TIFF images in strips (see commit 0abc209b8460396cdece8fc824c053a2662c4cbf\ + */\ + 0 /* strip size byte count */,\ ARCH_IS_BIG_ENDIAN /* default to native endian (i.e. use big endian iff the platform is so*/,\ false, /* default to not using bigtiff */\ compr,\ @@ -160,7 +163,7 @@ tfax_put_params(gx_device * dev, gs_param_list * plist) bool big_endian = tfdev->BigEndian; bool usebigtiff = tfdev->UseBigTIFF; bool write_datetime = tfdev->write_datetime; - uint16 compr = tfdev->Compression; + uint16_t compr = tfdev->Compression; gs_param_string comprstr; switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &mss)) { diff --git a/devices/gdevtifs.c b/devices/gdevtifs.c index 9c629afa..55ae5a7d 100644 --- a/devices/gdevtifs.c +++ b/devices/gdevtifs.c @@ -149,7 +149,7 @@ tiff_put_some_params(gx_device * dev, gs_param_list * plist, int which) bool big_endian = tfdev->BigEndian; bool usebigtiff = tfdev->UseBigTIFF; bool write_datetime = tfdev->write_datetime; - uint16 compr = tfdev->Compression; + uint16_t compr = tfdev->Compression; gs_param_string comprstr; long mss = tfdev->MaxStripSize; long aw = tfdev->AdjustWidth; @@ -325,11 +325,16 @@ int tiff_set_compression(gx_device_printer *pdev, TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, pdev->height); } else { - int rows = max_strip_size / + int rows = 0; + + if (pdev->width >=1) { + rows = max_strip_size / gdev_mem_bytes_per_scan_line((gx_device *)pdev); - TIFFSetField(tif, + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, max(1, rows))); + } else + return_error(gs_error_rangecheck); } return 0; @@ -355,6 +360,7 @@ int tiff_set_fields_for_printer(gx_device_printer *pdev, TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)xpi); TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)ypi); +#ifndef CLUSTER { char revs[32]; #define maxSoftware 40 @@ -372,6 +378,7 @@ int tiff_set_fields_for_printer(gx_device_printer *pdev, TIFFSetField(tif, TIFFTAG_SOFTWARE, softwareValue); } +#endif if (writedatetime) { struct tm tms; time_t t; @@ -458,7 +465,7 @@ tiff_print_page(gx_device_printer *dev, TIFF *tif, int min_feature_size) if (row - line_lag >= 0) { #if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN) if (bpc == 16) - TIFFSwabArrayOfShort((uint16 *)data, + TIFFSwabArrayOfShort((uint16_t *)data, dev->width * (long)dev->color_info.num_components); #endif @@ -565,7 +572,7 @@ tiff_downscale_and_print_page(gx_device_printer *dev, TIFF *tif, static struct compression_string { - uint16 id; + uint16_t id; const char *str; } compression_strings [] = { { COMPRESSION_NONE, "none" }, @@ -579,7 +586,7 @@ static struct compression_string { }; int -tiff_compression_param_string(gs_param_string *param, uint16 id) +tiff_compression_param_string(gs_param_string *param, uint16_t id) { struct compression_string *c; for (c = compression_strings; c->str; c++) @@ -591,7 +598,7 @@ tiff_compression_param_string(gs_param_string *param, uint16 id) } int -tiff_compression_id(uint16 *id, gs_param_string *param) +tiff_compression_id(uint16_t *id, gs_param_string *param) { struct compression_string *c; for (c = compression_strings; c->str; c++) @@ -604,7 +611,7 @@ tiff_compression_id(uint16 *id, gs_param_string *param) return_error(gs_error_undefined); } -int tiff_compression_allowed(uint16 compression, byte depth) +int tiff_compression_allowed(uint16_t compression, byte depth) { return ((depth == 1 && (compression == COMPRESSION_NONE || compression == COMPRESSION_CCITTRLE || diff --git a/devices/gdevtifs.h b/devices/gdevtifs.h index bbd01bb6..17eacb51 100644 --- a/devices/gdevtifs.h +++ b/devices/gdevtifs.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -32,7 +32,7 @@ typedef struct gx_device_tiff_s { gx_prn_device_common; bool BigEndian; /* true = big endian; false = little endian*/ bool UseBigTIFF; /* true = output big tiff file, false don't */ - uint16 Compression; /* same values as TIFFTAG_COMPRESSION */ + uint16_t Compression; /* same values as TIFFTAG_COMPRESSION */ long MaxStripSize; long AdjustWidth; /* 0 = no adjust, 1 = adjust to fax values, >1 = adjust to this */ bool write_datetime; @@ -63,7 +63,7 @@ void tiff_set_handlers (void); * Sets the compression tag for TIFF and updates the rows_per_strip tag to * reflect max_strip_size under the new compression scheme. */ -#define TIFF_DEFAULT_STRIP_SIZE 1048576 +#define TIFF_DEFAULT_STRIP_SIZE 8192 #define TIFF_DEFAULT_DOWNSCALE 1 @@ -80,17 +80,17 @@ int gdev_tiff_begin_page(gx_device_tiff *tfdev, gp_file *file); /* * Returns the gs_param_string that corresponds to the tiff COMPRESSION_* id. */ -int tiff_compression_param_string(gs_param_string *param, uint16 id); +int tiff_compression_param_string(gs_param_string *param, uint16_t id); /* * Returns the COMPRESSION_* id which corresponds to 'str'. */ -int tiff_compression_id(uint16 *id, gs_param_string *param); +int tiff_compression_id(uint16_t *id, gs_param_string *param); /* * Returns true if 'compression' can be used for encoding a data with a bit * depth of 'depth' (crle, g3, and g4 only work on 1-bit devices). */ -int tiff_compression_allowed(uint16 compression, byte depth); +int tiff_compression_allowed(uint16_t compression, byte depth); #endif /* gdevtifs_INCLUDED */ diff --git a/devices/gdevtsep.c b/devices/gdevtsep.c index fd859ddc..6d75d600 100644 --- a/devices/gdevtsep.c +++ b/devices/gdevtsep.c @@ -445,7 +445,7 @@ tiffscaled24_print_page(gx_device_printer * pdev, gp_file * file) static void tiff_set_cmyk_fields(gx_device_printer *pdev, TIFF *tif, short bits_per_sample, - uint16 compression, + uint16_t compression, long max_strip_size) { TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample); @@ -667,7 +667,7 @@ static dev_proc_decode_color(tiffsep1_decode_color); bool UseBigTIFF; /* true = output bigtiff, false don't */ \ bool write_datetime; /* true = write DATETIME tag, false = don't */ \ bool PrintSpotCMYK; /* true = print CMYK equivalents for spot inks; false = do nothing */\ - uint16 Compression; /* for the separation files, same values as TIFFTAG_COMPRESSION */\ + uint16_t Compression; /* for the separation files, same values as TIFFTAG_COMPRESSION */\ long MaxStripSize;\ long BitsPerComponent;\ int max_spots;\ @@ -678,7 +678,8 @@ static dev_proc_decode_color(tiffsep1_decode_color); bool warning_given; /* avoid issuing lots of warnings */\ gp_file *comp_file; /* Underlying file for tiff_comp */\ TIFF *tiff_comp; /* tiff file for comp file */\ - gsicc_link_t *icclink /* link profile if we are doing post rendering */ + gsicc_link_t *icclink; /* link profile if we are doing post rendering */\ + unsigned int page_num_comps /* Number of components at end of page, for cleanup */ /* * A structure definition for a DeviceN type device @@ -1224,26 +1225,16 @@ int tiffsep1_prn_close(gx_device * pdev) { tiffsep1_device * const tfdev = (tiffsep1_device *) pdev; - int num_dev_comp = tfdev->color_info.num_components; - 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; char *name= NULL; int code = gdev_prn_close(pdev); short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS]; int comp_num; - int num_comp = number_output_separations(num_dev_comp, num_std_colorants, - num_order, num_spot); const char *fmt; gs_parsed_file_name_t parsed; if (code < 0) return code; - name = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_prn_close(name)"); - if (!name) - return_error(gs_error_VMerror); - code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname, strlen(tfdev->fname), pdev->memory); if (code < 0) { @@ -1278,33 +1269,44 @@ 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]; + for (comp_num = 0; comp_num < tfdev->page_num_comps; comp_num++ ) { + const char *lname_empty = ""; + char *lname = NULL; - code = create_separation_file_name((tiffsep_device *)tfdev, name, - gp_file_name_sizeof, sep_num, true); - if (code < 0) { - goto done; - } - code = gx_device_close_output_file(pdev, name, tfdev->sep_file[comp_num]); + if (tfdev->tiff[comp_num] != NULL) { + tiff_filename_from_tiff(tfdev->tiff[comp_num], &name); + } + else { + name = (char *)lname_empty; + } + + lname = (char *)gs_alloc_bytes(tfdev->memory, strlen(name) + 1, "tiffsep1_prn_close"); + if (lname == NULL) { + code = gs_note_error(gs_error_VMerror); + goto done; + } + memcpy(lname, name, strlen(name) + 1); + + if (tfdev->tiff[comp_num]) { + void *t = TIFFClientdata(tfdev->tiff[comp_num]); + + TIFFCleanup(tfdev->tiff[comp_num]); + gs_free(pdev->memory, t, sizeof(tifs_io_private), 1, "tiffsep1_prn_close"); + tfdev->tiff[comp_num] = NULL; + } + if (tfdev->sep_file[comp_num] != NULL) { + code = gx_device_close_output_file(pdev, lname, tfdev->sep_file[comp_num]); if (code >= 0) - code = gs_remove_outputfile_control_path(pdev->memory, name); + code = gs_remove_outputfile_control_path(pdev->memory, lname); if (code < 0) { goto done; } tfdev->sep_file[comp_num] = NULL; } - if (tfdev->tiff[comp_num]) { - TIFFCleanup(tfdev->tiff[comp_num]); - tfdev->tiff[comp_num] = NULL; - } + gs_free_object(tfdev->memory, lname, "tiffsep1_prn_close"); } done: - - if (name) - gs_free_object(pdev->memory, name, "tiffsep1_prn_close(name)"); return code; } @@ -1730,26 +1732,18 @@ int tiffsep_prn_close(gx_device * pdev) { tiffsep_device * const pdevn = (tiffsep_device *) pdev; - int num_dev_comp = pdevn->color_info.num_components; - int num_std_colorants = pdevn->devn_params.num_std_colorant_names; - int num_order = pdevn->devn_params.num_separation_order_names; - int num_spot = pdevn->devn_params.separations.num_separations; short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS]; char *name = NULL; int code; int comp_num; - int num_comp = number_output_separations(num_dev_comp, num_std_colorants, - num_order, num_spot); gsicc_free_link_dev(pdevn->icclink); pdevn->icclink = NULL; - name = (char *)gs_alloc_bytes(pdevn->memory, gp_file_name_sizeof, "tiffsep_prn_close(name)"); - if (!name) - return_error(gs_error_VMerror); - if (pdevn->tiff_comp) { + void *t = TIFFClientdata(pdevn->tiff_comp); TIFFCleanup(pdevn->tiff_comp); + gs_free(pdev->memory, t, sizeof(tifs_io_private), 1, "tiffsep_prn_close"); pdevn->tiff_comp = NULL; } code = gdev_prn_close(pdev); @@ -1759,27 +1753,44 @@ tiffsep_prn_close(gx_device * pdev) 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 = pdevn->devn_params.separation_order_map[comp_num]; + for (comp_num = 0; comp_num < pdevn->page_num_comps; comp_num++ ) { + const char *lname_empty = ""; + char *lname = NULL; - code = create_separation_file_name(pdevn, name, - gp_file_name_sizeof, sep_num, true); - if (code < 0) { - goto done; - } - code = tiffsep_close_sep_file(pdevn, name, comp_num); + if (pdevn->tiff[comp_num] != NULL) { + tiff_filename_from_tiff(pdevn->tiff[comp_num], &name); + } + else { + name = (char *)lname_empty; + } + + lname = (char *)gs_alloc_bytes(pdevn->memory, strlen(name) + 1, "tiffsep1_prn_close"); + if (lname == NULL) { + code = gs_note_error(gs_error_VMerror); + goto done; + } + memcpy(lname, name, strlen(name) + 1); + + if (pdevn->tiff[comp_num]) { + void *t = TIFFClientdata(pdevn->tiff[comp_num]); + TIFFCleanup(pdevn->tiff[comp_num]); + gs_free(pdevn->memory, t, sizeof(tifs_io_private), 1, "tiffsep_prn_close"); + pdevn->tiff[comp_num] = NULL; + } + + if (pdevn->sep_file[comp_num]) { + code = gx_device_close_output_file((gx_device *)pdevn, lname, pdevn->sep_file[comp_num]); if (code >= 0) - code = gs_remove_outputfile_control_path(pdevn->memory, name); + code = gs_remove_outputfile_control_path(pdevn->memory, lname); if (code < 0) { goto done; } + pdevn->sep_file[comp_num] = NULL; } + gs_free_object(pdevn->memory, lname, "tiffsep1_prn_close"); } done: - if (name) - gs_free_object(pdev->memory, name, "tiffsep_prn_close(name)"); return code; } @@ -2123,6 +2134,7 @@ tiffsep_print_page(gx_device_printer * pdev, gp_file * file) /* Set up the separation output files */ num_comp = number_output_separations( tfdev->color_info.num_components, num_std_colorants, num_order, num_spot); + tfdev->page_num_comps = num_comp; if (!tfdev->NoSeparationFiles && !num_order && num_comp < num_std_colorants + num_spot) { dmlprintf(pdev->memory, "Warning: skipping one or more colour separations, see: Devices.htm#TIFF\n"); @@ -2493,6 +2505,8 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) /* Set up the separation output files */ num_comp = number_output_separations(tfdev->color_info.num_components, num_std_colorants, num_order, num_spot); + tfdev->page_num_comps = num_comp; + build_cmyk_map((gx_device *)tfdev, num_comp, &tfdev->equiv_cmyk_colors, cmyk_map); if (tfdev->PrintSpotCMYK) { code = print_cmyk_equivalent_colors((tiffsep_device *)tfdev, num_comp, cmyk_map); diff --git a/devices/gdevxini.c b/devices/gdevxini.c index fafcd42a..fcaab232 100644 --- a/devices/gdevxini.c +++ b/devices/gdevxini.c @@ -906,16 +906,22 @@ gdev_x_put_params(gx_device * dev, gs_param_list * plist) /* Get work area */ x_get_work_area(xdev, &area_width, &area_height); - /* Preserve screen resolution */ - dev->x_pixels_per_inch = values.x_pixels_per_inch; - dev->y_pixels_per_inch = values.y_pixels_per_inch; - dev->HWResolution[0] = values.HWResolution[0]; - dev->HWResolution[1] = values.HWResolution[1]; - - /* Recompute window size using screen resolution and available work area size*/ - /* pixels */ - dev->width = min(dev->width, area_width); - dev->height = min(dev->height, area_height); + /* Prioritize HWResolution over page size. If we can't fit the + page size at the requested resolution in the available screen + area, keep the resolution, clamp the page size. + This replaces the previous solution which refused requests to + change resolution at all. + */ + if (dev->width > area_width) { + outprintf(dev->memory, "\nWARNING: page width %f at %f dpi exceeds available area, clamping width to %f\n", + ((dev->width / 72.0) * dev->HWResolution[0]), dev->HWResolution[0], ((area_width / 72) * dev->HWResolution[0])); + dev->width = area_width; + } + if (dev->height > area_height) { + outprintf(dev->memory, "\nWARNING: page height %f at %f dpi exceeds available area, clamping height to %f\n", + ((dev->height / 72.0) * dev->HWResolution[1]), dev->HWResolution[1], ((area_height / 72) * dev->HWResolution[1])); + dev->height = area_height; + } if (dev->width <= 0 || dev->height <= 0) { emprintf3(dev->memory, "Requested pagesize %d x %d not supported by %s device\n", @@ -924,8 +930,8 @@ gdev_x_put_params(gx_device * dev, gs_param_list * plist) } /* points */ - dev->MediaSize[0] = (float)dev->width / xdev->x_pixels_per_inch * 72; - dev->MediaSize[1] = (float)dev->height / xdev->y_pixels_per_inch * 72; + dev->MediaSize[0] = (float)dev->width / dev->HWResolution[0] * 72; + dev->MediaSize[1] = (float)dev->height / dev->HWResolution[1] * 72; dw = dev->width - values.width; dh = dev->height - values.height; diff --git a/devices/gxfcopy.c b/devices/gxfcopy.c index 76f0a19e..571ff646 100644 --- a/devices/gxfcopy.c +++ b/devices/gxfcopy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -2108,6 +2108,8 @@ gs_copy_font(gs_font *font, const gs_matrix *orig_matrix, gs_memory_t *mem, gs_f copied = gs_alloc_struct(mem, gs_font, fstype, "gs_copy_font(copied font)"); if (copied) { + gs_font_base *bfont = (gs_font_base *)copied; + /* Initialize the copied font - minumum we need * so we can safely free it in the "fail:" case * below @@ -2118,6 +2120,15 @@ gs_copy_font(gs_font *font, const gs_matrix *orig_matrix, gs_memory_t *mem, gs_f copied->is_resource = false; gs_notify_init(&copied->notify_list, mem); copied->base = copied; + + bfont->FAPI = 0; + bfont->FAPI_font_data = 0; + bfont->encoding_index = ENCODING_INDEX_UNKNOWN; + code = uid_copy(&bfont->UID, mem, "gs_copy_font(UID)"); + if (code < 0) { + uid_set_invalid(&bfont->UID); + goto fail; + } } cfdata = gs_alloc_struct(mem, gs_copied_font_data_t, &st_gs_copied_font_data, @@ -2179,16 +2190,6 @@ gs_copy_font(gs_font *font, const gs_matrix *orig_matrix, gs_memory_t *mem, gs_f copied->procs.encode_char = procs->encode_char; copied->procs.glyph_info = procs->glyph_info; copied->procs.glyph_outline = procs->glyph_outline; - { - gs_font_base *bfont = (gs_font_base *)copied; - - bfont->FAPI = 0; - bfont->FAPI_font_data = 0; - bfont->encoding_index = ENCODING_INDEX_UNKNOWN; - code = uid_copy(&bfont->UID, mem, "gs_copy_font(UID)"); - if (code < 0) - goto fail; - } cfdata->procs = procs; memset(glyphs, 0, glyphs_size * sizeof(*glyphs)); diff --git a/devices/vector/doc_common.c b/devices/vector/doc_common.c index c7d38836..4575aea4 100644 --- a/devices/vector/doc_common.c +++ b/devices/vector/doc_common.c @@ -1,3 +1,18 @@ +/* Copyright (C) 2018-2022 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + Refer to licensing information at http://www.artifex.com or contact + Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, + CA 94945, U.S.A., +1(415)492-9861, for further information. +*/ + #include "doc_common.h" #include "gxfont.h" @@ -32,6 +47,7 @@ font_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat) case ft_encrypted2: case ft_CID_encrypted: case ft_user_defined: + case ft_PDF_user_defined: case ft_PCL_user_defined: case ft_GL2_stick_user_defined: case ft_GL2_531: diff --git a/devices/vector/doc_common.h b/devices/vector/doc_common.h index 24369054..08fba48b 100644 --- a/devices/vector/doc_common.h +++ b/devices/vector/doc_common.h @@ -1,3 +1,18 @@ +/* Copyright (C) 2018-2022 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + Refer to licensing information at http://www.artifex.com or contact + Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, + CA 94945, U.S.A., +1(415)492-9861, for further information. +*/ + #ifndef gdevtxtw_INCLUDED #define gdevtxtw_INCLUDED diff --git a/devices/vector/gdevdocxw.c b/devices/vector/gdevdocxw.c index b637a4c8..7783bff4 100644 --- a/devices/vector/gdevdocxw.c +++ b/devices/vector/gdevdocxw.c @@ -273,7 +273,8 @@ docxwrite_open_device(gx_device * dev) code = s_errno_to_gs(); goto end; } - if (extract_page_begin(tdev->extract)) { + /* Pass dummy page bbox for now; our simple use of extract ignores it. */ + if (extract_page_begin(tdev->extract, 0, 0, 0, 0)) { code = s_errno_to_gs(); goto end; } @@ -383,7 +384,8 @@ docxwrite_output_page(gx_device * dev, int num_copies, int flush) goto end; } } - if (extract_page_begin(tdev->extract)) { + /* Pass dummy page bbox for now; our simple use of extract ignores it. */ + if (extract_page_begin(tdev->extract, 0, 0, 0, 0)) { code = s_errno_to_gs(); goto end; } @@ -939,13 +941,16 @@ docxwrite_process_cmap_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte) txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, chr, &buffer[0]); + /* Pass dummy glyph bbox because our use of extract does not + currently cause it to be used. */ if (extract_add_char( tdev->extract, tdev->x, fixed2float(penum->origin.y) - penum->text_state->matrix.ty, buffer[0] /*ucs*/, glyph_width / penum->text_state->size /*adv*/, - 0 /*autosplit*/ + 0 /*autosplit*/, + 0, 0, 0, 0 /* bbox*/ )) { return s_errno_to_gs(); } @@ -1095,13 +1100,16 @@ docxwrite_process_plain_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte) * 'extra' code points' widths to 0. */ + /* Pass dummy glyph bbox because our use of extract does not currently + cause it to be used. */ if (extract_add_char( tdev->extract, tdev->x, fixed2float(penum->origin.y) - penum->text_state->matrix.ty, chr2[0] /*ucs*/, glyph_width / penum->text_state->size /*adv*/, - 0 /*autosplit*/ + 0 /*autosplit*/, + 0, 0, 0, 0 /*bbox*/ )) { return s_errno_to_gs(); } diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c index cb268f62..40beb06a 100644 --- a/devices/vector/gdevpdf.c +++ b/devices/vector/gdevpdf.c @@ -425,6 +425,7 @@ pdf_initialize_ids(gx_device_pdf * pdev) * date and time, rather than (for example) %%CreationDate from the * PostScript file. We think this is wrong, but we do the same. */ + if (!pdev->OmitInfoDate) { struct tm tms; time_t t; @@ -466,6 +467,7 @@ pdf_initialize_ids(gx_device_pdf * pdev) static int pdf_compute_fileID(gx_device_pdf * pdev) { + /* We compute a file identifier when beginning a document to allow its usage with PDF encryption. Due to that, in contradiction to the Adobe recommendation, our @@ -933,10 +935,14 @@ pdf_ferror(gx_device_pdf *pdev) { gp_fflush(pdev->file); gp_fflush(pdev->xref.file); - sflush(pdev->strm); - sflush(pdev->asides.strm); - sflush(pdev->streams.strm); - sflush(pdev->pictures.strm); + if (pdev->strm->file != NULL) + sflush(pdev->strm); + if (pdev->asides.strm->file != NULL) + sflush(pdev->asides.strm); + if (pdev->streams.strm->file != NULL) + sflush(pdev->streams.strm); + if (pdev->pictures.strm->file != NULL) + sflush(pdev->pictures.strm); return gp_ferror(pdev->file) || gp_ferror(pdev->xref.file) || gp_ferror(pdev->asides.file) || gp_ferror(pdev->streams.file) || gp_ferror(pdev->pictures.file); @@ -1139,13 +1145,14 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) pdf_page_t *page; double mediabox[4] = {0, 0}; stream *s; - const cos_value_t *v_mediabox; + const cos_value_t *v_mediabox = NULL; if (pdev->pages == NULL) return_error(gs_error_undefined); page = &pdev->pages[page_num - 1]; - v_mediabox = cos_dict_find_c_key(page->Page, "/MediaBox"); + if (page->Page != NULL) + v_mediabox = cos_dict_find_c_key(page->Page, "/MediaBox"); page_id = pdf_page_id(pdev, page_num); /* If we have not been given a MediaBox overriding pdfmark, use the current media size. */ @@ -1170,7 +1177,8 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) buf[l] = 0; if (sscanf(buf, "[ %g %g %g %g ]", &temp[0], &temp[1], &temp[2], &temp[3]) == 4) { - cos_dict_delete_c_key(page->Page, "/MediaBox"); + if (page->Page) + cos_dict_delete_c_key(page->Page, "/MediaBox"); } pprintg4(s, "<</Type/Page/MediaBox [%g %g %g %g]\n", temp[0], temp[1], temp[2], temp[3]); @@ -1178,13 +1186,20 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) mediabox[i] = temp[i]; } if (pdev->PDFX) { - const cos_value_t *v_trimbox = cos_dict_find_c_key(page->Page, "/TrimBox"); - const cos_value_t *v_artbox = cos_dict_find_c_key(page->Page, "/ArtBox"); - const cos_value_t *v_cropbox = cos_dict_find_c_key(page->Page, "/CropBox"); - const cos_value_t *v_bleedbox = cos_dict_find_c_key(page->Page, "/BleedBox"); - double trimbox[4] = {0, 0}, bleedbox[4] = {0, 0}; + const cos_value_t *v_trimbox = NULL; + const cos_value_t *v_artbox = NULL; + const cos_value_t *v_cropbox = NULL; + const cos_value_t *v_bleedbox = NULL; + float trimbox[4] = {0, 0}, bleedbox[4] = {0, 0}; bool print_bleedbox = false; + if (page->Page != NULL) { + v_trimbox = cos_dict_find_c_key(page->Page, "/TrimBox"); + v_artbox = cos_dict_find_c_key(page->Page, "/ArtBox"); + v_cropbox = cos_dict_find_c_key(page->Page, "/CropBox"); + v_bleedbox = cos_dict_find_c_key(page->Page, "/BleedBox"); + } + trimbox[2] = bleedbox[2] = mediabox[2]; trimbox[3] = bleedbox[3] = mediabox[3]; /* Offsets are [left right top bottom] according to the Acrobat 7.0 @@ -1203,9 +1218,10 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) trimbox[1] = temp[1]; trimbox[2] = temp[2]; trimbox[3] = temp[3]; - cos_dict_delete_c_key(page->Page, "/TrimBox"); + if (page->Page != NULL) + cos_dict_delete_c_key(page->Page, "/TrimBox"); } - if (v_artbox != NULL && v_artbox->value_type == COS_VALUE_SCALAR) + if (v_artbox != NULL && v_artbox->value_type == COS_VALUE_SCALAR && page->Page != NULL) cos_dict_delete_c_key(page->Page, "/ArtBox"); } else if (v_artbox != NULL && v_artbox->value_type == COS_VALUE_SCALAR) { @@ -1225,7 +1241,8 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) trimbox[1] = temp[1]; trimbox[2] = temp[2]; trimbox[3] = temp[3]; - cos_dict_delete_c_key(page->Page, "/ArtBox"); + if (page->Page != NULL) + cos_dict_delete_c_key(page->Page, "/ArtBox"); } } else { if (pdev->PDFXTrimBoxToMediaBoxOffset.size >= 4 && @@ -1267,7 +1284,8 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) else bleedbox[3] = temp[3]; print_bleedbox = true; - cos_dict_delete_c_key(page->Page, "/BleedBox"); + if (page->Page != NULL) + cos_dict_delete_c_key(page->Page, "/BleedBox"); } } else if (pdev->PDFXSetBleedBoxToMediaBox) print_bleedbox = true; @@ -1330,7 +1348,8 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) buf[l] = 0; if (sscanf(buf, "[ %g %g %g %g ]", &temp[0], &temp[1], &temp[2], &temp[3]) == 4) { - cos_dict_delete_c_key(page->Page, "/CropBox"); + if (page->Page != NULL) + cos_dict_delete_c_key(page->Page, "/CropBox"); /* Ensure that CropBox is no larger than MediaBox. The spec says *nothing* about * this, but Acrobat Preflight complains if it is larger. This can happen because * we apply 'round_box_coord' to the mediabox at the start of this rouinte. @@ -1386,14 +1405,16 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) } } - if (cos_dict_find_c_key(page->Page, "/TrimBox") == NULL && - cos_dict_find_c_key(page->Page, "/ArtBox") == NULL) - pprintg4(s, "/TrimBox [%g %g %g %g]\n", - trimbox[0], trimbox[1], trimbox[2], trimbox[3]); - if (print_bleedbox && - cos_dict_find_c_key(page->Page, "/BleedBox") == NULL) - pprintg4(s, "/BleedBox [%g %g %g %g]\n", - bleedbox[0], bleedbox[1], bleedbox[2], bleedbox[3]); + if (page->Page != NULL) { + if (cos_dict_find_c_key(page->Page, "/TrimBox") == NULL && + cos_dict_find_c_key(page->Page, "/ArtBox") == NULL) + pprintg4(s, "/TrimBox [%g %g %g %g]\n", + trimbox[0], trimbox[1], trimbox[2], trimbox[3]); + if (print_bleedbox && + cos_dict_find_c_key(page->Page, "/BleedBox") == NULL) + pprintg4(s, "/BleedBox [%g %g %g %g]\n", + bleedbox[0], bleedbox[1], bleedbox[2], bleedbox[3]); + } } pdf_print_orientation(pdev, page); if (page->UserUnit != 1) @@ -1480,7 +1501,8 @@ pdf_write_page(gx_device_pdf *pdev, int page_num) /* Write any elements stored by pdfmarks. */ - cos_dict_elements_write(page->Page, pdev); + if (page->Page != NULL) + cos_dict_elements_write(page->Page, pdev); stream_puts(s, ">>\n"); pdf_end_obj(pdev, resourcePage); @@ -1906,7 +1928,11 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params * +1 for the linearisation dict and +1 for the primary hint stream. */ linear_params->FirsttrailerOffset = gp_ftell(linear_params->Lin_File.file); - gs_snprintf(LDict, sizeof(LDict), "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %d>>\nstartxref\r\n0\n%%%%EOF\n \n", + if (pdev->OmitID) + gs_snprintf(LDict, sizeof(LDict), "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/Prev %d>>\nstartxref\r\n0\n%%%%EOF\n \n", + linear_params->LastResource + 3, pdev->ResourceUsage[linear_params->Info_id].NewObjectNumber, pdev->ResourceUsage[linear_params->Catalog_id].NewObjectNumber, 0); + else + gs_snprintf(LDict, sizeof(LDict), "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %d>>\nstartxref\r\n0\n%%%%EOF\n \n", linear_params->LastResource + 3, pdev->ResourceUsage[linear_params->Info_id].NewObjectNumber, pdev->ResourceUsage[linear_params->Catalog_id].NewObjectNumber, fileID, fileID, 0); gp_fwrite(LDict, strlen(LDict), 1, linear_params->Lin_File.file); @@ -2442,7 +2468,11 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params if (code != 0) return_error(gs_error_ioerror); - gs_snprintf(LDict, sizeof(LDict), "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %"PRId64">>\nstartxref\r\n0\n%%%%EOF\n", + if (pdev->OmitID) + gs_snprintf(LDict, sizeof(LDict), "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/Prev %"PRId64">>\nstartxref\r\n0\n%%%%EOF\n", + linear_params->LastResource + 3, pdev->ResourceUsage[linear_params->Info_id].NewObjectNumber, pdev->ResourceUsage[linear_params->Catalog_id].NewObjectNumber, mainxref); + else + gs_snprintf(LDict, sizeof(LDict), "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %"PRId64">>\nstartxref\r\n0\n%%%%EOF\n", linear_params->LastResource + 3, pdev->ResourceUsage[linear_params->Info_id].NewObjectNumber, pdev->ResourceUsage[linear_params->Catalog_id].NewObjectNumber, fileID, fileID, mainxref); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); @@ -2871,10 +2901,12 @@ pdf_close(gx_device * dev) COS_WRITE_OBJECT(pdev->PageLabels, pdev, resourceLabels); } - /* Write the document metadata. */ - code1 = pdf_document_metadata(pdev); - if (code >= 0) - code = code1; + if (!pdev->OmitXMP) { + /* Write the document metadata. */ + code1 = pdf_document_metadata(pdev); + if (code >= 0) + code = code1; + } /* Write the Catalog. */ @@ -3136,10 +3168,12 @@ pdf_close(gx_device * dev) stream_puts(s, "trailer\n"); pprintld3(s, "<< /Size %ld /Root %ld 0 R /Info %ld 0 R\n", pdev->next_id, Catalog_id, Info_id); - stream_puts(s, "/ID ["); - psdf_write_string(pdev->strm, pdev->fileID, sizeof(pdev->fileID), 0); - psdf_write_string(pdev->strm, pdev->fileID, sizeof(pdev->fileID), 0); - stream_puts(s, "]\n"); + if (!pdev->OmitID) { + stream_puts(s, "/ID ["); + psdf_write_string(pdev->strm, pdev->fileID, sizeof(pdev->fileID), 0); + psdf_write_string(pdev->strm, pdev->fileID, sizeof(pdev->fileID), 0); + stream_puts(s, "]\n"); + } if (pdev->OwnerPassword.size > 0) { pprintld1(s, "/Encrypt %ld 0 R ", Encrypt_id); } @@ -3429,6 +3463,27 @@ error_cleanup: } } + /* Free named objects. */ + + if (pdev->NI_stack != NULL) { + cos_release((cos_object_t *)pdev->NI_stack, "Release Name Index stack"); + gs_free_object(mem, pdev->NI_stack, "Free Name Index stack"); + pdev->NI_stack = 0; + } + + if (pdev->local_named_objects != NULL) { + cos_dict_objects_delete(pdev->local_named_objects); + COS_FREE(pdev->local_named_objects, "pdf_close(local_named_objects)"); + pdev->local_named_objects = 0; + } + + if (pdev->global_named_objects != NULL) { + /* global resources include the Catalog object and apparently the Info dict */ + cos_dict_objects_delete(pdev->global_named_objects); + COS_FREE(pdev->global_named_objects, "pdf_close(global_named_objects)"); + pdev->global_named_objects = 0; + } + code1 = pdf_free_resource_objects(pdev, resourceOther); if (code >= 0) code = code1; @@ -3477,27 +3532,6 @@ error_cleanup: pdev->last_resource = 0; } - /* Free named objects. */ - - if (pdev->NI_stack != NULL) { - cos_release((cos_object_t *)pdev->NI_stack, "Release Name Index stack"); - gs_free_object(mem, pdev->NI_stack, "Free Name Index stack"); - pdev->NI_stack = 0; - } - - if (pdev->local_named_objects != NULL) { - cos_dict_objects_delete(pdev->local_named_objects); - COS_FREE(pdev->local_named_objects, "pdf_close(local_named_objects)"); - pdev->local_named_objects = 0; - } - - if (pdev->global_named_objects != NULL) { - /* global resources include the Catalog object and apparently the Info dict */ - cos_dict_objects_delete(pdev->global_named_objects); - COS_FREE(pdev->global_named_objects, "pdf_close(global_named_objects)"); - pdev->global_named_objects = 0; - } - /* Wrap up. */ pdev->font_cache = 0; @@ -3517,7 +3551,7 @@ error_cleanup: for (i=0;i < pdev->num_pages;i++) { if (pdev->pages[i].Page != NULL) { emprintf(pdev->memory, - "Page object was reserved for an Annotation destinatio, but no such page was drawn, annotation in output will be invalid.\n"); + "Page object was reserved for an Annotation destination, but no such page was drawn, annotation in output will be invalid.\n"); gs_free_object(mem, pdev->pages[i].Page, "Free Page object"); pdev->pages[i].Page = NULL; } diff --git a/devices/vector/gdevpdfb.c b/devices/vector/gdevpdfb.c index a7b36d82..1851bab3 100644 --- a/devices/vector/gdevpdfb.c +++ b/devices/vector/gdevpdfb.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -137,7 +137,7 @@ pdf_copy_mono(gx_device_pdf *pdev, pdf_stream_position_t ipos; pdf_resource_t *pres = 0; byte invert = 0; - bool in_line = false; + bool in_line = false, char_proc_begun = false; gs_show_enum *show_enum = (gs_show_enum *)pdev->pte; int x_offset, y_offset; double width; @@ -181,6 +181,7 @@ pdf_copy_mono(gx_device_pdf *pdev, &pcp, &ipos); if (code < 0) return code; + char_proc_begun = true; y_offset = -y_offset; width = psdf_round(pdev->char_width.x, 100, 10); /* See pdf_write_Widths about rounding. We need to provide @@ -192,7 +193,7 @@ pdf_copy_mono(gx_device_pdf *pdev, pdf_image_writer_init(&writer); code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, true); if (code < 0) - return code; + goto fail; pres = (pdf_resource_t *) pcp; goto wr; } else if (pdev->pte != NULL) { @@ -216,13 +217,17 @@ pdf_copy_mono(gx_device_pdf *pdev, set_image_color(pdev, zero); } else if (zero == pdev->black && one == pdev->white) { pcs = gs_cspace_new_DeviceGray(pdev->memory); - if (pcs == NULL) - return_error(gs_error_VMerror); + if (pcs == NULL) { + code = gs_note_error(gs_error_VMerror); + goto fail; + } gs_image_t_init(&image, pcs); } else if (zero == pdev->white && one == pdev->black) { pcs = gs_cspace_new_DeviceGray(pdev->memory); - if (pcs == NULL) - return_error(gs_error_VMerror); + if (pcs == NULL) { + code = gs_note_error(gs_error_VMerror); + goto fail; + } gs_image_t_init(&image, pcs); invert = 0xff; } else { @@ -240,13 +245,14 @@ pdf_copy_mono(gx_device_pdf *pdev, code = pdf_cspace_init_Device(pdev->memory, &pcs_base, ncomp); if (code < 0) - return code; + goto fail; c[0] = psdf_adjust_color_index((gx_device_vector *)pdev, zero); c[1] = psdf_adjust_color_index((gx_device_vector *)pdev, one); pcs = gs_cspace_alloc(pdev->memory, &gs_color_space_type_Indexed); if (pcs == NULL) { rc_decrement_cs(pcs_base, "pdf_copy_mono"); - return_error(gs_error_VMerror); + code = gs_note_error(gs_error_VMerror); + goto fail; } pcs->base_space = pcs_base; pcs->params.indexed.hival = 1; @@ -267,14 +273,14 @@ pdf_copy_mono(gx_device_pdf *pdev, code = pdf_open_page(pdev, PDF_IN_STREAM); if (code < 0) - return code; + goto fail; in_line = nbytes < pdev->MaxInlineImageSize; if (in_line) pdf_put_image_matrix(pdev, &image.ImageMatrix, 1.0); pdf_image_writer_init(&writer); code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, in_line); if (code < 0) - return code; + goto fail; } wr: if (image.ImageMask) @@ -287,7 +293,7 @@ pdf_copy_mono(gx_device_pdf *pdev, code = pdf_color_space_named(pdev, NULL, &cs_value, NULL, pcs, &writer.pin->color_spaces, in_line, NULL, 0, false); if (code < 0) - return code; + goto fail; pcsvalue = &cs_value; } /* @@ -322,33 +328,37 @@ pdf_copy_mono(gx_device_pdf *pdev, code = pdf_begin_image_data(pdev, &writer, (const gs_pixel_image_t *)&image, pcsvalue, 0); if (code < 0) - return code; + goto fail; code = pdf_copy_mask_bits(writer.binary[0].strm, base, sourcex, raster, w, h, invert); if (code < 0) - return code; + goto fail; code = pdf_end_image_binary(pdev, &writer, writer.height); if (code < 0) - return code; + goto fail; if (!pres) { switch ((code = pdf_end_write_image(pdev, &writer))) { default: /* error */ - return code; + goto fail; case 1: - return 0; + code = 0; + goto fail; case 0: - return pdf_do_image(pdev, writer.pres, &image.ImageMatrix, + code = pdf_do_image(pdev, writer.pres, &image.ImageMatrix, true); + goto fail; } } writer.end_string = ""; /* no Q */ switch ((code = pdf_end_write_image(pdev, &writer))) { default: /* error */ + goto fail; return code; case 0: /* not possible */ - return_error(gs_error_Fatal); + code = gs_note_error(gs_error_Fatal); + goto fail; case 1: break; } @@ -365,6 +375,11 @@ pdf_copy_mono(gx_device_pdf *pdev, imat.yy /= h; return pdf_do_char_image(pdev, (const pdf_char_proc_t *)pres, &imat); } + +fail: + if (char_proc_begun) + (void)pdf_end_char_proc(pdev, &ipos); + return code; } int gdev_pdf_copy_mono(gx_device * dev, diff --git a/devices/vector/gdevpdfb.h b/devices/vector/gdevpdfb.h index b85dffe3..b6439f53 100644 --- a/devices/vector/gdevpdfb.h +++ b/devices/vector/gdevpdfb.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -237,7 +237,10 @@ const gx_device_pdf PDF_DEVICE_IDENT = 0, /* OCR_char_code */ 0, /* OCR_glyph */ NULL, /* ocr_glyphs */ - 0 /* initial_pattern_state */ + 0, /* initial_pattern_state */ + false, /* OmitInfoDate */ + false, /* OmitXMP */ + false /* OmitID */ }; #else diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c index ea40111b..892fc4c9 100644 --- a/devices/vector/gdevpdfd.c +++ b/devices/vector/gdevpdfd.c @@ -973,13 +973,13 @@ lcvd_close_device_with_writing(gx_device *pdev) pdf_lcvd_t *cvd = (pdf_lcvd_t *)pdev; int code, code1; - code = pdf_dump_converted_image(cvd->pdev, cvd); + code = pdf_dump_converted_image(cvd->pdev, cvd, 0); code1 = cvd->std_close_device((gx_device *)&cvd->mdev); return code < 0 ? code : code1; } static int -write_image(gx_device_pdf *pdev, gx_device_memory *mdev, gs_matrix *m) +write_image(gx_device_pdf *pdev, gx_device_memory *mdev, gs_matrix *m, int for_pattern) { gs_image_t image; pdf_image_writer writer; @@ -990,7 +990,7 @@ write_image(gx_device_pdf *pdev, gx_device_memory *mdev, gs_matrix *m) pdf_put_matrix(pdev, NULL, m, " cm\n"); code = pdf_copy_color_data(pdev, mdev->base, sourcex, mdev->raster, gx_no_bitmap_id, 0, 0, mdev->width, mdev->height, - &image, &writer, 2); + &image, &writer, for_pattern); if (code == 1) code = 0; /* Empty image. */ else if (code == 0) @@ -1176,7 +1176,7 @@ mask_to_clip(gx_device_pdf *pdev, int width, int height, } static int -write_subimage(gx_device_pdf *pdev, gx_device_memory *mdev, int x, int y, int x1, int y1) +write_subimage(gx_device_pdf *pdev, gx_device_memory *mdev, int x, int y, int x1, int y1, int for_pattern) { gs_image_t image; pdf_image_writer writer; @@ -1190,7 +1190,7 @@ write_subimage(gx_device_pdf *pdev, gx_device_memory *mdev, int x, int y, int x1 code = pdf_copy_color_data(pdev, mdev->base + mdev->raster * Y, X, mdev->raster, gx_no_bitmap_id, X, Y, X1 - X, Y1 - Y, - &image, &writer, 2); + &image, &writer, for_pattern); if (code < 0) return code; if (!writer.pres) @@ -1199,7 +1199,7 @@ write_subimage(gx_device_pdf *pdev, gx_device_memory *mdev, int x, int y, int x1 } static int -write_image_with_clip(gx_device_pdf *pdev, pdf_lcvd_t *cvd) +write_image_with_clip(gx_device_pdf *pdev, pdf_lcvd_t *cvd, int for_pattern) { int x = 0, y = 0; int code, code1; @@ -1219,7 +1219,7 @@ write_image_with_clip(gx_device_pdf *pdev, pdf_lcvd_t *cvd) if (code < 0) return code; if (code > 0) { - code1 = write_subimage(pdev, &cvd->mdev, x, y, x1, y1); + code1 = write_subimage(pdev, &cvd->mdev, x, y, x1, y1, for_pattern); if (code1 < 0) return code1; } @@ -1241,14 +1241,14 @@ write_image_with_clip(gx_device_pdf *pdev, pdf_lcvd_t *cvd) } int -pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd) +pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd, int for_pattern) { int code = 0; if (!cvd->path_is_empty || cvd->has_background) { if (!cvd->has_background) stream_puts(pdev->strm, "W n\n"); - code = write_image(pdev, &cvd->mdev, (cvd->write_matrix ? &cvd->m : NULL)); + code = write_image(pdev, &cvd->mdev, (cvd->write_matrix ? &cvd->m : NULL), for_pattern); cvd->path_is_empty = true; } else if (!cvd->mask_is_empty && pdev->PatternImagemask) { /* Convert to imagemask with a pattern color. */ @@ -1288,7 +1288,7 @@ pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd) if (code >= 0) { stream_puts(pdev->strm, "W n\n"); - code = write_image(pdev, &cvd->mdev, NULL); + code = write_image(pdev, &cvd->mdev, NULL, for_pattern); } pres = pdev->accumulating_substream_resource; if (code >= 0) { @@ -1302,7 +1302,7 @@ pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd) } if (code >= 0) code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev, - gxdso_pattern_load, &inst, id); + gxdso_pattern_load, &id, sizeof(gs_id)); if (code >= 0) code = pdf_cs_Pattern_colored(pdev, &v); if (code >= 0) { @@ -1315,7 +1315,7 @@ pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd) } else if (!cvd->mask_is_empty && !pdev->PatternImagemask) { /* Convert to image with a clipping path. */ stream_puts(pdev->strm, "q\n"); - code = write_image_with_clip(pdev, cvd); + code = write_image_with_clip(pdev, cvd, for_pattern); stream_puts(pdev->strm, "Q\n"); } if (code > 0) @@ -1338,7 +1338,7 @@ lcvd_handle_fill_path_as_shading_coverage(gx_device *dev, if (gx_path_is_null(ppath)) { /* use the mask. */ if (!cvd->path_is_empty) { - code = pdf_dump_converted_image(pdev, cvd); + code = pdf_dump_converted_image(pdev, cvd, 2); if (code < 0) return code; stream_puts(pdev->strm, "Q q\n"); @@ -1362,7 +1362,7 @@ lcvd_handle_fill_path_as_shading_coverage(gx_device *dev, gs_make_translation(cvd->path_offset.x, cvd->path_offset.y, &m); /* use the clipping. */ if (!cvd->mask_is_empty) { - code = pdf_dump_converted_image(pdev, cvd); + code = pdf_dump_converted_image(pdev, cvd, 2); if (code < 0) return code; stream_puts(pdev->strm, "Q q\n"); @@ -1685,7 +1685,7 @@ gdev_pdf_fill_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath, code = gs_shading_do_fill_rectangle(pi.templat.Shading, NULL, (gx_device *)&cvd.mdev, pgs2, !pi.shfill); if (code >= 0) - code = pdf_dump_converted_image(pdev, &cvd); + code = pdf_dump_converted_image(pdev, &cvd, 2); stream_puts(pdev->strm, "Q Q\n"); pdf_remove_masked_image_converter(pdev, &cvd, need_mask); gs_setmatrix((gs_gstate *)pgs, &save_ctm); diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c index ec011d8b..66767bd9 100644 --- a/devices/vector/gdevpdfe.c +++ b/devices/vector/gdevpdfe.c @@ -568,7 +568,7 @@ pdf_make_uuid(const byte node[6], uint64_t uuid_time, ulong time_seq, char *buf, writehex(&p, node[4], 1); writehex(&p, node[5], 1); *p = 0; - strncpy(buf, b, buf_length); + strncpy(buf, b, strlen(b) + 1); } static int @@ -696,21 +696,23 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6]) pdf_xml_attribute_name(s, "xmlns:xmp"); pdf_xml_attribute_value(s, "http://ns.adobe.com/xap/1.0/"); pdf_xml_tag_end(s); - { - pdf_xml_tag_open_beg(s, "xmp:ModifyDate"); - pdf_xml_tag_end(s); - mod_date_time[mod_date_time_len] = 0x00; - pdf_xml_copy(s, mod_date_time); - pdf_xml_tag_close(s, "xmp:ModifyDate"); - pdf_xml_newline(s); - } - { - pdf_xml_tag_open_beg(s, "xmp:CreateDate"); - pdf_xml_tag_end(s); - cre_date_time[cre_date_time_len] = 0x00; - pdf_xml_copy(s, cre_date_time); - pdf_xml_tag_close(s, "xmp:CreateDate"); - pdf_xml_newline(s); + if (!pdev->OmitInfoDate) { + { + pdf_xml_tag_open_beg(s, "xmp:ModifyDate"); + pdf_xml_tag_end(s); + mod_date_time[mod_date_time_len] = 0x00; + pdf_xml_copy(s, mod_date_time); + pdf_xml_tag_close(s, "xmp:ModifyDate"); + pdf_xml_newline(s); + } + { + pdf_xml_tag_open_beg(s, "xmp:CreateDate"); + pdf_xml_tag_end(s); + cre_date_time[cre_date_time_len] = 0x00; + pdf_xml_copy(s, cre_date_time); + pdf_xml_tag_close(s, "xmp:CreateDate"); + pdf_xml_newline(s); + } } { pdf_xml_tag_open_beg(s, "xmp:CreatorTool"); diff --git a/devices/vector/gdevpdfg.c b/devices/vector/gdevpdfg.c index d61712b0..3e2a2b6d 100644 --- a/devices/vector/gdevpdfg.c +++ b/devices/vector/gdevpdfg.c @@ -3069,7 +3069,7 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, break; default: emprintf(pdev->memory, - "\nSetting Overprint Mode to 1\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n"); + "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n"); pdev->AbortPDFAX = true; pdev->PDFA = 0; break; diff --git a/devices/vector/gdevpdfi.c b/devices/vector/gdevpdfi.c index 1e1a9daa..1de48cee 100644 --- a/devices/vector/gdevpdfi.c +++ b/devices/vector/gdevpdfi.c @@ -1872,7 +1872,7 @@ use_image_as_pattern(gx_device_pdf *pdev, pdf_resource_t *pres1, } if (code >= 0) code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev, - gxdso_pattern_load, &inst, id); + gxdso_pattern_load, &id, sizeof(gs_id)); if (code >= 0) { stream_puts(pdev->strm, "q "); code = pdf_cs_Pattern_colored(pdev, &v); @@ -2032,7 +2032,7 @@ pdf_image_end_image(gx_image_enum_common_t * info, bool draw_last) static int pdf_image_end_image_cvd(gx_image_enum_common_t * info, bool draw_last) { pdf_lcvd_t *cvd = (pdf_lcvd_t *)info->dev; - int code = pdf_dump_converted_image(cvd->pdev, cvd); + int code = pdf_dump_converted_image(cvd->pdev, cvd, 0); int code1 = gx_image1_end_image(info, draw_last); int code2 = gs_closedevice((gx_device *)cvd->mask); int code3 = gs_closedevice((gx_device *)cvd); @@ -2214,8 +2214,10 @@ pdf_image3x_make_mcde(gx_device *dev, const gs_gstate *pgs, code = pdf_begin_typed_image ((gx_device_pdf *)dev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, PDF_IMAGE_TYPE3_DATA); - if (code < 0) + if (code < 0) { + rc_decrement(*pmcdev, "pdf_image3x_make_mcde"); return code; + } if ((*pinfo)->procs != &pdf_image_enum_procs) { /* We couldn't handle the image. Bail out. */ gx_image_end(*pinfo, false); @@ -2695,7 +2697,6 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size) gs_pattern1_instance_t *pinst = param->pinst; gs_gstate *pgs = param->graphics_state; - id = param->pinst_id; code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs); if (code < 0) return code; @@ -2735,7 +2736,7 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size) memset(pdev->initial_pattern_states[pdev->PatternDepth], 0x00, sizeof(gs_gstate)); reset_gstate_for_pattern(pdev, pdev->initial_pattern_states[pdev->PatternDepth], pgs); - code = pdf_enter_substream(pdev, resourcePattern, id, &pres, false, + code = pdf_enter_substream(pdev, resourcePattern, pinst->id, &pres, false, pdev->CompressStreams); if (code < 0) { gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state"); @@ -2751,7 +2752,7 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size) * the ID is restored when we finish capturing the pattern. */ pdev->state.soft_mask_id = pgs->soft_mask_id; - pres->rid = id; + pres->rid = pinst->id; code = pdf_store_pattern1_params(pdev, pres, pinst); if (code < 0) { gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state"); @@ -2830,7 +2831,7 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size) } return 1; case gxdso_pattern_load: - pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, id); + pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, *((gx_bitmap_id *)data)); if (pres == 0) return 0; pres = pdf_substitute_pattern(pres); diff --git a/devices/vector/gdevpdfj.c b/devices/vector/gdevpdfj.c index 02692510..5888ac70 100644 --- a/devices/vector/gdevpdfj.c +++ b/devices/vector/gdevpdfj.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -348,8 +348,10 @@ pdf_begin_write_image(gx_device_pdf * pdev, pdf_image_writer * piw, } pdev->strm = pdev->streams.strm; pdev->strm = cos_write_stream_alloc(data, pdev, "pdf_begin_write_image"); - if (pdev->strm == 0) + if (pdev->strm == 0) { + pdev->strm = save_strm; return_error(gs_error_VMerror); + } if (!mask) piw->data = data; piw->height = h; diff --git a/devices/vector/gdevpdfo.c b/devices/vector/gdevpdfo.c index 3ec00f5e..e00a9258 100644 --- a/devices/vector/gdevpdfo.c +++ b/devices/vector/gdevpdfo.c @@ -1485,6 +1485,8 @@ cos_dict_find(const cos_dict_t *pcd, const byte *key_data, uint key_size) const cos_value_t * cos_dict_find_c_key(const cos_dict_t *pcd, const char *key) { + if (pcd == NULL) + return NULL; return cos_dict_find(pcd, (const byte *)key, strlen(key)); } diff --git a/devices/vector/gdevpdfp.c b/devices/vector/gdevpdfp.c index 42fa1c52..690a9e13 100644 --- a/devices/vector/gdevpdfp.c +++ b/devices/vector/gdevpdfp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -129,6 +129,9 @@ static const gs_param_item_t pdf_param_items[] = { pi("NoOutputFonts", gs_param_type_bool, FlattenFonts), pi("WantsPageLabels", gs_param_type_bool, WantsPageLabels), pi("UserUnit", gs_param_type_float, UserUnit), + pi("OmitInfoDate", gs_param_type_bool, OmitInfoDate), + pi("OmitID", gs_param_type_bool, OmitID), + pi("OmitXMP", gs_param_type_bool, OmitXMP), #undef pi gs_param_item_end }; @@ -297,6 +300,13 @@ gdev_pdf_get_param(gx_device *dev, char *Param, void *list) } #endif + if (strcmp(Param, "OmitInfoDate") == 0) + return(param_write_bool(plist, "OmitInfoDate", &pdev->OmitInfoDate)); + if (strcmp(Param, "OmitXMP") == 0) + return(param_write_bool(plist, "OmitXMP", &pdev->OmitXMP)); + if (strcmp(Param, "OmitID") == 0) + return(param_write_bool(plist, "OmitID", &pdev->OmitID)); + return gdev_psdf_get_param(dev, Param, list); } @@ -649,6 +659,25 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par param_signal_error(plist, param_name, code); } + if (pdev->OmitInfoDate && pdev->PDFX != 0) { + emprintf(pdev->memory, "\nIt is not possible to omit the CreationDate when creating PDF/X\nOmitInfoDate is being ignored.\n"); + pdev->OmitInfoDate = 0; + } + + if (pdev->OmitID && pdev->CompatibilityLevel > 1.7) { + emprintf(pdev->memory, "\nIt is not possible to omit the ID array when creating a version 2.0 or greater PDF\nOmitID is being ignored.\n"); + pdev->OmitID = 0; + } + if (pdev->OmitID && pdev->OwnerPassword.size != 0) { + emprintf(pdev->memory, "\nIt is not possible to omit the ID array when creating an encrypted PDF\nOmitID is being ignored.\n"); + pdev->OmitID = 0; + } + + if (pdev->OmitXMP && pdev->PDFA != 0) { + emprintf(pdev->memory, "\nIt is not possible to omit the XMP metadta when creating a PDF/A\nOmitXMP is being ignored.\n"); + pdev->OmitXMP = 0; + } + /* PDFA and PDFX are stored in the page device dictionary and therefore * set on every setpagedevice. However, if we have encountered a file which * can't be made this way, and the PDFACompatibilityPolicy is 1, we want to diff --git a/devices/vector/gdevpdft.c b/devices/vector/gdevpdft.c index 72f082f9..6f50df01 100644 --- a/devices/vector/gdevpdft.c +++ b/devices/vector/gdevpdft.c @@ -110,8 +110,12 @@ pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams if (pgs != NULL && pparams->group_color_type != UNKNOWN) { const gs_color_space *cs = gs_currentcolorspace_inline(pgs); - code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, cs, - &pdf_color_space_names, false, NULL, 0, false); + if (pparams->ColorSpace == NULL) + code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, cs, + &pdf_color_space_names, false, NULL, 0, false); + else + code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, pparams->ColorSpace, + &pdf_color_space_names, false, NULL, 0, false); if (code < 0) return code; code = cos_dict_put_c_key(group_dict, "/CS", &cs_value); diff --git a/devices/vector/gdevpdfu.c b/devices/vector/gdevpdfu.c index f12fa38e..9545bd58 100644 --- a/devices/vector/gdevpdfu.c +++ b/devices/vector/gdevpdfu.c @@ -1589,10 +1589,15 @@ pdf_begin_aside(gx_device_pdf * pdev, pdf_resource_t ** plist, pdf_resource_type_t type) { long id = pdf_begin_separate(pdev, type); + int code = 0; if (id < 0) return (int)id; - return pdf_alloc_aside(pdev, plist, pst, ppres, id); + code = pdf_alloc_aside(pdev, plist, pst, ppres, id); + if (code < 0) + (void)pdf_end_separate(pdev, type); + + return code; } /* Begin a resource of a given type. */ diff --git a/devices/vector/gdevpdfx.h b/devices/vector/gdevpdfx.h index 774a5156..098fc4fc 100644 --- a/devices/vector/gdevpdfx.h +++ b/devices/vector/gdevpdfx.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -946,7 +946,7 @@ struct gx_device_pdf_s { * anything in the image processing routines. */ float UserUnit; - pdf_OCR_usage UseOCR; /* Never, AsNeeded or Always */ + pdf_OCR_usage UseOCR; /* Never, AsNeeded or Always */ gs_text_enum_t* OCRSaved; /* Saved state of the text enumerator before rendering glyph bitmaps for later OCR */ pdf_OCR_stage OCRStage; /* Used to control a (sort of) state machine when using OCR to get a Unicode value for a glyph */ int *OCRUnicode; /* Used to pass back the Unicode value from the OCR engine to the text processing */ @@ -954,6 +954,9 @@ struct gx_device_pdf_s { gs_glyph OCR_glyph; /* Passes the current glyph code from text processing to the image processing code when rendering glyph bitmaps for OCR */ ocr_glyph_t *ocr_glyphs; /* Records bitmaps and other data from text processing when doing OCR */ gs_gstate **initial_pattern_states; + bool OmitInfoDate; /* If true, do not emit CreationDate and ModDate in the Infor dictionary and XMP Metadata (must not be true for PDF/X support) */ + bool OmitXMP; /* If true, do not emit an XMP /Metadata block and do not reference it from the Catalog (must not be true for PDF/A output) */ + bool OmitID; /* If true, do not emit a /ID array in the trailer dicionary (must not be true for encrypted files or PDF 2.0) */ }; #define is_in_page(pdev)\ @@ -1290,7 +1293,7 @@ typedef struct pdf_lcvd_s { int pdf_setup_masked_image_converter(gx_device_pdf *pdev, gs_memory_t *mem, const gs_matrix *m, pdf_lcvd_t **pcvd, bool need_mask, int x, int y, int w, int h, bool write_on_close); -int pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd); +int pdf_dump_converted_image(gx_device_pdf *pdev, pdf_lcvd_t *cvd, int for_pattern); void pdf_remove_masked_image_converter(gx_device_pdf *pdev, pdf_lcvd_t *cvd, bool need_mask); /* ------ Miscellaneous output ------ */ diff --git a/devices/vector/gdevpdte.c b/devices/vector/gdevpdte.c index 5e50d2cf..9760094b 100644 --- a/devices/vector/gdevpdte.c +++ b/devices/vector/gdevpdte.c @@ -382,6 +382,8 @@ pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfon if (!unicode) { unicode = (ushort *)gs_alloc_bytes(pdev->memory, length * sizeof(short), "temporary Unicode array"); + if (unicode == NULL) + return_error(gs_error_VMerror); length = font->procs.decode_glyph((gs_font *)font, glyph, ch, unicode, length); } diff --git a/devices/vector/gdevpdtt.c b/devices/vector/gdevpdtt.c index 98ce8892..9483e051 100644 --- a/devices/vector/gdevpdtt.c +++ b/devices/vector/gdevpdtt.c @@ -86,6 +86,30 @@ pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth) return gs_text_current_width(penum->pte_default, pwidth); return_error(gs_error_rangecheck); /* can't happen */ } + +static void +pdf_show_text_release(gs_text_enum_t *pte, client_name_t cname) +{ + gs_show_enum *const penum = (gs_show_enum *)pte; + gs_text_enum_procs_t *procs = (gs_text_enum_procs_t *)penum->procs; + + penum->cc = 0; + if (penum->dev_cache2) { + gx_device_retain((gx_device *)penum->dev_cache2, false); + penum->dev_cache2 = 0; + } + if (penum->dev_cache) { + gx_device_retain((gx_device *)penum->dev_cache, false); + penum->dev_cache = 0; + } + if (penum->dev_null) { + gx_device_retain((gx_device *)penum->dev_null, false); + penum->dev_null = 0; + } + gx_default_text_release(pte, cname); + gs_free_object(penum->memory->non_gc_memory, procs, "pdf_show_text_release"); +} + static int pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, gs_text_cache_control_t control) @@ -655,7 +679,7 @@ gdev_pdf_text_begin(gx_device * dev, gs_gstate * pgs, penum->output_char_code = GS_NO_CHAR; code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs, dev, pgs, text, font, pcpath, mem); - penum->k_text_release = 1; /* early release of black_text_state */ + penum->k_text_release = 1; /* early release of black_textvec_state */ if (code < 0) { gs_free_object(mem, penum, "gdev_pdf_text_begin"); @@ -3392,12 +3416,18 @@ pdf_text_process(gs_text_enum_t *pte) */ gs_show_enum psenum = *(gs_show_enum *)pte_default; gs_gstate *pgs = (gs_gstate *)penum->pgs; - gs_text_enum_procs_t special_procs = *pte_default->procs; + gs_text_enum_procs_t *special_procs; void (*save_proc)(gx_device *, gs_matrix *) = pdev->procs.get_initial_matrix; gs_matrix m, savem; - special_procs.set_cache = pdf_text_set_cache; - pte_default->procs = &special_procs; + special_procs = (gs_text_enum_procs_t *)gs_alloc_bytes(pte_default->memory->non_gc_memory, sizeof(gs_text_enum_procs_t), "pdf_text_process"); + if (special_procs == NULL) + return_error(gs_error_VMerror); + + *special_procs = *pte_default->procs; + special_procs->set_cache = pdf_text_set_cache; + special_procs->release = pdf_show_text_release; + pte_default->procs = special_procs; { /* We should not come here if we already have a cached character (except for the special case diff --git a/devices/vector/gdevpsdp.c b/devices/vector/gdevpsdp.c index fc944539..cf6933ec 100644 --- a/devices/vector/gdevpsdp.c +++ b/devices/vector/gdevpsdp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -1254,13 +1254,17 @@ gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) exit: if (!(pdev->params.LockDistillerParams && params.LockDistillerParams)) { /* Only update the device paramters if there was no error */ - /* If we have any copied param_string_arrays, start by freeing them */ - if (pdev->params.PSPageOptions.size && params.PSPageOptions.size) { - int ix; - - for (ix = 0; ix < pdev->params.PSPageOptions.size;ix++) - gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data[ix].data, "freeing old string array copy"); - gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data, "freeing old string array"); + /* Do not permit changes to pdev->Params.PSPageOptions, it doesn't make any sense */ + if (pdev->params.PSPageOptions.size != 0) { + if (params.PSPageOptions.size != 0 && params.PSPageOptions.data != pdev->params.PSPageOptions.data) { + int ix; + + for (ix = 0; ix < pdev->params.PSPageOptions.size;ix++) + gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data[ix].data, "freeing old string array copy"); + gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data, "freeing old string array"); + } + params.PSPageOptions.data = pdev->params.PSPageOptions.data; + params.PSPageOptions.size = pdev->params.PSPageOptions.size; } pdev->params = params; } else { diff --git a/devices/vector/gdevpsft.c b/devices/vector/gdevpsft.c index ae6600be..4d6384f2 100644 --- a/devices/vector/gdevpsft.c +++ b/devices/vector/gdevpsft.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -845,7 +845,6 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options, length = u32(tab + 12); /* Copy the table data now (a rudiment of old code). */ memcpy(&tables[numTables * 16], tab, 16); - switch (u32(tab)) { case W('h','e','a','d'): if (length < 54) @@ -900,13 +899,16 @@ psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options, /* falls through */ case W('c','v','t',' '): case W('f','p','g','m'): - case W('g','a','s','p'): - case W('k','e','r','n'): case W('p','r','e','p'): break; /* always copy these if present */ + case W('D','S','I','G'): case W('E','B','D','T'): case W('E','B','L','C'): case W('E','B','S','C'): + case W('G','D','E','F'): + case W('G','P','O','S'): + case W('g','a','s','p'): + case W('k','e','r','n'): continue; default: if (writing_cid) diff --git a/devices/vector/gdevpsu.c b/devices/vector/gdevpsu.c index 83b8bdbb..123dda69 100644 --- a/devices/vector/gdevpsu.c +++ b/devices/vector/gdevpsu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2021 Artifex Software, Inc. +/* Copyright (C) 2001-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -180,8 +180,12 @@ psw_begin_file_header(gp_file *f, const gx_device *dev, const gs_rect *pbbox, fputs("%...............................................................\n", f); fputs("%...............................................................\n", f); } +#ifdef CLUSTER + fprintf(f, "%%%%Creator: GPL Ghostscript (%s)\n", dev->dname); +#else fprintf(f, "%%%%Creator: %s %ld (%s)\n", gs_product, (long)gs_revision, dev->dname); +#endif { time_t t; struct tm tms; @@ -204,7 +208,9 @@ psw_begin_file_header(gp_file *f, const gx_device *dev, const gs_rect *pbbox, else if (pdpc->LanguageLevel == 1.5) fputs("%%Extensions: CMYK\n", f); psw_print_lines(f, psw_begin_prolog); +#ifndef CLUSTER fprintf(f, "%% %s\n", gs_copyright); +#endif fputs("%%BeginResource: procset ", f); fflush(f); psw_print_procset_name(f, dev, pdpc); diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c index 5c885f5f..71be58b6 100644 --- a/devices/vector/gdevtxtw.c +++ b/devices/vector/gdevtxtw.c @@ -1167,7 +1167,7 @@ txtwrite_put_params(gx_device * dev, gs_param_list * plist) if (code < 0) return code; - if (ofs.data != 0) { /* Close the file if it's open. */ + if (ofs.data != 0 && (ofs.size != strlen(tdev->fname) || strncmp((const char *)ofs.data, tdev->fname, ofs.size)) != 0) { /* Close the file if it's open. */ if (tdev->file != 0) { gp_fclose(tdev->file); tdev->file = 0; @@ -1185,10 +1185,10 @@ txtwrite_put_params(gx_device * dev, gs_param_list * plist) dev->is_open = false; code = gx_default_put_params(dev, plist); + dev->is_open = open; if (code < 0) return code; - dev->is_open = open; dev->interpolate_control = 0; @@ -1875,10 +1875,14 @@ textw_text_process(gs_text_enum_t *pte) if (!penum->SpanDeltaX) return gs_note_error(gs_error_VMerror); } +retry: { switch (font->FontType) { case ft_CID_encrypted: case ft_CID_TrueType: + errprintf(pte->memory, "\n\n*** The txtwrite device does not currently support the use of CID-Keyed fonts. ***\n\n"); + return_error(gs_error_typecheck); + break; case ft_composite: code = txtwrite_process_cmap_text(pte); break; @@ -1886,13 +1890,14 @@ textw_text_process(gs_text_enum_t *pte) case ft_encrypted2: case ft_TrueType: case ft_user_defined: + case ft_PDF_user_defined: case ft_PCL_user_defined: case ft_GL2_stick_user_defined: case ft_GL2_531: code = txtwrite_process_plain_text(pte); break; default: - return_error(gs_error_rangecheck); + return_error(gs_error_rangecheck); break; } if (code == 0) { @@ -1935,6 +1940,9 @@ textw_text_process(gs_text_enum_t *pte) penum->pte_fallback = pte_fallback; gs_text_enum_copy_dynamic(pte_fallback, pte, false); + if (font->FontType == ft_PDF_user_defined && pte->text.size != 1) + pte_fallback->text.size = pte->index + 1; + code = gs_text_process(pte_fallback); if (code != 0) { penum->returned.current_char = pte_fallback->returned.current_char; @@ -1943,6 +1951,8 @@ textw_text_process(gs_text_enum_t *pte) } gs_text_release(NULL, pte_fallback, "txtwrite_text_process"); penum->pte_fallback = 0; + if (font->FontType == ft_PDF_user_defined) + goto retry; } } return code; @@ -1954,7 +1964,11 @@ textw_text_process(gs_text_enum_t *pte) static int textw_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom) { - return gs_text_resync(pte, pfrom); + if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY) + return_error(gs_error_rangecheck); + pte->text = pfrom->text; + gs_text_enum_copy_dynamic(pte, pfrom, false); + return 0; } static bool textw_text_is_width_only(const gs_text_enum_t *pte) diff --git a/devices/vector/gdevxps.c b/devices/vector/gdevxps.c index 1ab854be..20d9dbd5 100644 --- a/devices/vector/gdevxps.c +++ b/devices/vector/gdevxps.c @@ -1790,7 +1790,7 @@ static TIFF* tiff_from_name(gx_device_xps *dev, const char *name, int big_endian static int tiff_set_values(xps_image_enum_t *pie, TIFF *tif, cmm_profile_t *profile, bool force8bit); static void xps_tiff_set_handlers(void); -static void tiff_client_release(gx_device_xps* dev, TIFF* t); +static void xps_tiff_cleanup(xps_image_enum_t *xpie); /* Check if we have the ICC profile in the package */ static xps_icc_data_t* @@ -1930,6 +1930,7 @@ xps_begin_typed_image(gx_device *dev, pie->buffer = NULL; pie->devc_buffer = NULL; pie->pgs = NULL; + pie->tif = NULL; /* Set the brush types to image */ xps_setstrokebrush(xdev, xps_imagebrush); @@ -2295,8 +2296,7 @@ xps_image_end_image(gx_image_enum_common_t * info, bool draw_last) /* N.B. Write the final strip, if any. */ code = TIFFWriteDirectory(pie->tif); - tiff_client_release((gx_device_xps*)(pie->dev), pie->tif); - TIFFCleanup(pie->tif); + xps_tiff_cleanup(pie); /* Stuff the image into the zip archive and close the file */ code = xps_add_tiff_image(pie); @@ -2573,11 +2573,14 @@ tiff_from_name(gx_device_xps *dev, const char *name, int big_endian, bool usebig return t; } -static void -tiff_client_release(gx_device_xps *dev, TIFF *t) +static void xps_tiff_cleanup(xps_image_enum_t *xpie) { - gs_free_object(dev->memory->non_gc_memory, TIFFClientdata(t), - "tiff_client_release"); + if (xpie->tif != NULL) { + void *t = TIFFClientdata(xpie->tif); + TIFFCleanup(xpie->tif); + xpie->tif = NULL; + gs_free_object(xpie->memory->non_gc_memory, t, "xps_image_enum_finalize"); + } } static void @@ -2586,6 +2589,8 @@ xps_image_enum_finalize(const gs_memory_t *cmem, void *vptr) xps_image_enum_t *xpie = (xps_image_enum_t *)vptr; gx_device_xps *xdev = (gx_device_xps *)xpie->dev; + xps_tiff_cleanup(xpie); + xpie->dev = NULL; if (xpie->pcs != NULL) rc_decrement(xpie->pcs, "xps_image_end_image (pcs)"); |