diff options
author | Sam James <sam@gentoo.org> | 2022-03-29 10:27:10 +0100 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2022-04-17 12:53:05 +0100 |
commit | 085bde903b9e684c3c1160e4df912bea9a660997 (patch) | |
tree | c4f5e6e9f2422e869ca5bc0b944520d451001282 /devices | |
parent | Import Ghostscript 9.55 (diff) | |
download | ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.tar.gz ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.tar.bz2 ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.zip |
Import Ghostscript 9.56.0ghostscript-9.56
Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to 'devices')
50 files changed, 1717 insertions, 844 deletions
diff --git a/devices/devs.mak b/devices/devs.mak index 484e0e36..bfe2903a 100644 --- a/devices/devs.mak +++ b/devices/devs.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 @@ -180,7 +180,8 @@ DEVGEN=$(DEVGENDIR)$(D) # png16 4-bit color Portable Network Graphics (PNG) # png256 8-bit color Portable Network Graphics (PNG) # png16m 24-bit color Portable Network Graphics (PNG) -# pngalpha 32-bit RGBA color Portable Network Graphics (PNG) +# pngalpha 32-bit RGBA color Portable Network Graphics (PNG) (aa) +# png16malpha 32-bit RGBA color Portable Network Graphics (PNG) # tiffgray TIFF 8-bit gray, no compression # tiff12nc TIFF 12-bit RGB, no compression # tiff24nc TIFF 24-bit RGB, no compression (NeXT standard format) @@ -1165,7 +1166,7 @@ $(DD)chameleon.dev : $(chameleon_) $(GLD)page.dev $(GLD)cielib.dev $(GDEV) \ $(DEVOBJ)gdevchameleon.$(OBJ) : $(DEVSRC)gdevchameleon.c $(PDEVH)\ $(gsparam_h) $(gdevdcrd_h) $(gscrd_h) $(gscrdp_h) $(gxlum_h) $(gxdcconv_h)\ - $(gsutil_h) $(DEVS_MAK) $(MAKEDIRS) + $(gsutil_h) $(gsicc_manage_h) $(DEVS_MAK) $(MAKEDIRS) $(DEVCC) $(DEVO_)gdevchameleon.$(OBJ) $(C_) $(DEVSRC)gdevchameleon.c ### ------------------------- .BMP file formats ------------------------- ### @@ -1243,12 +1244,18 @@ $(DD)psdrgb.dev : $(psd_) $(GLD)page.dev $(GDEV) $(DEVS_MAK) $(MAKEDIRS) $(DD)psdcmyk.dev : $(psd_) $(GLD)page.dev $(GDEV) $(DEVS_MAK) $(MAKEDIRS) $(SETDEV) $(DD)psdcmyk $(psd_) +$(DD)psdcmyktags.dev : $(psd_) $(GLD)page.dev $(GDEV) $(DEVS_MAK) $(MAKEDIRS) + $(SETDEV) $(DD)psdcmyktags $(psd_) + $(DD)psdrgb16.dev : $(DEVS_MAK) $(psd_) $(GLD)page.dev $(GDEV) $(SETDEV) $(DD)psdrgb16 $(psd_) $(DD)psdcmyk16.dev : $(DEVS_MAK) $(psd_) $(GLD)page.dev $(GDEV) $(SETDEV) $(DD)psdcmyk16 $(psd_) +$(DD)psdcmyktags16.dev : $(DEVS_MAK) $(psd_) $(GLD)page.dev $(GDEV) + $(SETDEV) $(DD)psdcmyktags16 $(psd_) + $(DEVOBJ)gdevpsd.$(OBJ) : $(DEVSRC)gdevpsd.c $(PDEVH) $(math__h)\ $(gdevdcrd_h) $(gscrd_h) $(gscrdp_h) $(gsparam_h) $(gxlum_h)\ $(gstypes_h) $(gxdcconv_h) $(gdevdevn_h) $(gxdevsop_h) $(gsequivc_h)\ @@ -1516,6 +1523,11 @@ $(DD)pngalpha.dev : $(libpng_dev) $(png_) $(GLD)page.dev $(GDEV) \ $(SETPDEV2) $(DD)pngalpha $(png_) $(ADDMOD) $(DD)pngalpha $(png_i_) +$(DD)png16malpha.dev : $(libpng_dev) $(png_) $(GLD)page.dev $(GDEV) \ + $(DEVS_MAK) $(MAKEDIRS) + $(SETPDEV2) $(DD)png16malpha $(png_) + $(ADDMOD) $(DD)png16malpha $(png_i_) + ### --------------- Portable Network Graphics file format --------------- ### ### Requires zlib 0.95 (or more recent versions). ### ### See zlib.mak for more details. ### @@ -1799,8 +1811,8 @@ $(DD)tiffsep1.dev : $(tiffsep_) $(DD)tiffs.dev $(minftrsz_h)\ plan_=$(DEVOBJ)gdevplan.$(OBJ) $(DEVOBJ)gdevppla.$(OBJ) $(DEVOBJ)gdevmpla.$(OBJ) -$(DEVOBJ)gdevplan.$(OBJ) : $(DEVSRC)gdevplan.c $(PDEVH)\ - $(gdevmpla_h) $(gdevplnx_h) $(gdevppla_h)\ +$(DEVOBJ)gdevplan.$(OBJ) : $(DEVSRC)gdevplan.c $(PDEVH) $(gxdevsop_h)\ + $(gdevmpla_h) $(gdevplnx_h) $(gdevppla_h) $(gxdownscale_h) $(gsicc_cache_h)\ $(gscdefs_h) $(gscspace_h) $(gxgetbit_h) $(gxiparam_h) $(gxlum_h) \ $(DEVS_MAK) $(MAKEDIRS) $(DEVCC) $(DEVO_)gdevplan.$(OBJ) $(C_) $(DEVSRC)gdevplan.c @@ -1888,12 +1900,26 @@ $(DD)pwgraster.dev : $(lcups_dev) $(lcupsi_dev) $(cups_) $(GDEV) $(GLD)page.dev $(ADDMOD) $(DD)pwgraster -include $(lcupsi_dev) $(ADDMOD) $(DD)pwgraster -include $(GLD)page +$(DD)appleraster.dev : $(lcups_dev) $(lcupsi_dev) $(cups_) $(GDEV) $(GLD)page.dev \ + $(DEVS_MAK) $(MAKEDIRS) + $(SETPDEV2) $(DD)appleraster $(cups_) + $(ADDMOD) $(DD)appleraster -include $(lcups_dev) + $(ADDMOD) $(DD)appleraster -include $(lcupsi_dev) + $(ADDMOD) $(DD)appleraster -include $(GLD)page + +$(DD)urf.dev : $(lcups_dev) $(lcupsi_dev) $(cups_) $(GDEV) $(GLD)page.dev \ + $(DEVS_MAK) $(MAKEDIRS) + $(SETPDEV2) $(DD)urf $(cups_) + $(ADDMOD) $(DD)urf -include $(lcups_dev) + $(ADDMOD) $(DD)urf -include $(lcupsi_dev) + $(ADDMOD) $(DD)urf -include $(GLD)page + $(DEVOBJ)gdevcups.$(OBJ) : $(LCUPSSRCDIR)$(D)gdevcups.c $(std_h) $(gxdevsop_h) $(DEVS_MAK) $(MAKEDIRS) $(CUPS_CC) $(DEVO_)gdevcups.$(OBJ) $(C_) $(CFLAGS) $(CUPSCFLAGS) \ - $(I_)$(GLSRC) \ - $(I_)$(DEVSRC) \ - $(I_)$(DEVOBJ) $(I_)$(LCUPSSRCDIR)$(D)libs \ - $(LCUPSSRCDIR)$(D)gdevcups.c + $(I_)$(GLSRC)$(_I) \ + $(I_)$(DEVSRC)$(_I) $(I_)$(LIBCUPSSRCDIR)$(D)libs$(_I) \ + $(I_)$(DEVOBJ)$(_I) \ + $(LCUPSSRCDIR)$(D)gdevcups.c ### ---------------------------- Tracing -------------------------------- ### @@ -1943,6 +1969,10 @@ $(DD)PCLm.dev : $(DEVOBJ)gdevpdfimg.$(OBJ) $(GLD)page.dev $(GDEV) $(DEVS_MAK) $( $(SETPDEV2) $(DD)PCLm $(DEVOBJ)gdevpdfimg.$(OBJ) $(ADDMOD) $(DD)PCLm -include $(GLD)page +$(DD)PCLm8.dev : $(DEVOBJ)gdevpdfimg.$(OBJ) $(GLD)page.dev $(GDEV) $(DEVS_MAK) $(MAKEDIRS) + $(SETPDEV2) $(DD)PCLm8 $(DEVOBJ)gdevpdfimg.$(OBJ) + $(ADDMOD) $(DD)PCLm8 -include $(GLD)page + $(DEVOBJ)gdevpdfimg.$(OBJ) : $(DEVSRC)gdevpdfimg.c $(AK) $(gdevkrnlsclass_h) \ $(DEVS_MAK) $(arch_h) $(stdint__h) $(gdevprn_h) $(gxdownscale_h) \ $(stream_h) $(spprint_h) $(time__h) $(smd5_h) $(sstring_h) $(strimpl_h) \ diff --git a/devices/extract.mak b/devices/extract.mak index 74f1f29c..71f30825 100644 --- a/devices/extract.mak +++ b/devices/extract.mak @@ -13,7 +13,7 @@ # CA 94945, U.S.A., +1(415)492-9861, for further information. # -extract_cc = $(CC) $(CCFLAGS) $(I_)$(EXTRACT_DIR)/include$(_I) $(I_)$(ZSRCDIR)$(_I) $(O_) +extract_cc = $(CC) $(CCFLAGS) -DEXTRACT_CV=0 $(I_)$(EXTRACT_DIR)/include$(_I) $(I_)$(ZSRCDIR)$(_I) $(O_) extract_out_prefix = $(GLOBJDIR)$(D)extract_ $(extract_out_prefix)alloc.$(OBJ): $(EXTRACT_DIR)/src/alloc.c $(MAKEDIRS) @@ -25,6 +25,9 @@ $(extract_out_prefix)astring.$(OBJ): $(EXTRACT_DIR)/src/astring.c $(MAKED $(extract_out_prefix)buffer.$(OBJ): $(EXTRACT_DIR)/src/buffer.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/buffer.c +$(extract_out_prefix)document.$(OBJ): $(EXTRACT_DIR)/src/document.c $(MAKEDIRS) + $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/document.c + $(extract_out_prefix)docx.$(OBJ): $(EXTRACT_DIR)/src/docx.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/docx.c @@ -37,6 +40,9 @@ $(extract_out_prefix)extract.$(OBJ): $(EXTRACT_DIR)/src/extract.c $(MAKED $(extract_out_prefix)join.$(OBJ): $(EXTRACT_DIR)/src/join.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/join.c +$(extract_out_prefix)html.$(OBJ): $(EXTRACT_DIR)/src/html.c $(MAKEDIRS) + $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/html.c + $(extract_out_prefix)mem.$(OBJ): $(EXTRACT_DIR)/src/mem.c $(MAKEDIRS) $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/mem.c @@ -65,9 +71,11 @@ EXTRACT_OBJS = \ $(extract_out_prefix)alloc.$(OBJ) \ $(extract_out_prefix)astring.$(OBJ) \ $(extract_out_prefix)buffer.$(OBJ) \ + $(extract_out_prefix)document.$(OBJ) \ $(extract_out_prefix)docx.$(OBJ) \ $(extract_out_prefix)docx_template.$(OBJ) \ $(extract_out_prefix)extract.$(OBJ) \ + $(extract_out_prefix)html.$(OBJ) \ $(extract_out_prefix)join.$(OBJ) \ $(extract_out_prefix)mem.$(OBJ) \ $(extract_out_prefix)odt.$(OBJ) \ diff --git a/devices/gdev8510.c b/devices/gdev8510.c index 534435c0..40c9ab80 100644 --- a/devices/gdev8510.c +++ b/devices/gdev8510.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 @@ -134,7 +134,7 @@ m8510_output_run(gx_device_printer *pdev, /* Transfer the line of data. */ count = out_end - out; if (count > 0) { - gs_sprintf(tmp, "\033g%03d", count/8); + gs_snprintf(tmp, sizeof(tmp), "\033g%03d", count/8); gp_fwrite(tmp, 1, 5, prn_stream); gp_fwrite(out, 1, count, prn_stream); gp_fwrite("\r", 1, 1, prn_stream); diff --git a/devices/gdevccr.c b/devices/gdevccr.c index 03fcfa59..4f138659 100644 --- a/devices/gdevccr.c +++ b/devices/gdevccr.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 @@ -220,9 +220,9 @@ static int alloc_rb( gs_memory_t *mem, cmyrow **rb, int rows) int r; for(r=0; r<rows; r++) { - gs_sprintf((*rb)[r].cname, "C%02x", r); - gs_sprintf((*rb)[r].mname, "M%02x", r); - gs_sprintf((*rb)[r].yname, "Y%02x", r); + gs_snprintf((*rb)[r].cname, sizeof((*rb)[r].cname), "C%02x", r); + gs_snprintf((*rb)[r].mname, sizeof((*rb)[r].mname), "M%02x", r); + gs_snprintf((*rb)[r].yname, sizeof((*rb)[r].yname), "Y%02x", r); (*rb)[r].is_used=0; } return 0; diff --git a/devices/gdevcdj.c b/devices/gdevcdj.c index 6908067b..cb2160ee 100644 --- a/devices/gdevcdj.c +++ b/devices/gdevcdj.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 @@ -2040,7 +2040,7 @@ hp_colour_print_page(gx_device_printer * pdev, gp_file * prn_stream, int ptype) int outbuff_size = 0; int compression = 0; int scan = 0; - int *errors[2]; + int *errors[2] = { 0 }; /* Shut up coverity */ int code = 0; const char *cid_string = (const char*) 0; byte *data[4], *plane_data[4][4], *out_data; diff --git a/devices/gdevchameleon.c b/devices/gdevchameleon.c index 6d7ba87c..789a5b01 100644 --- a/devices/gdevchameleon.c +++ b/devices/gdevchameleon.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 @@ -25,6 +25,7 @@ #include "gdevdcrd.h" #include "gxdownscale.h" #include "gxdevsop.h" +#include "gsicc_manage.h" /* Define the device parameters. */ #ifndef X_DPI @@ -45,6 +46,13 @@ static dev_proc_get_params(chameleon_get_params); static dev_proc_put_params(chameleon_put_params); static dev_proc_print_page(chameleon_print_page); static dev_proc_dev_spec_op(chameleon_spec_op); +static dev_proc_close_device(chameleon_close); + +typedef enum { + linktype_none = 0, + linktype_postrender, + linktype_device +} linktype_t; struct gx_device_chameleon_s { gx_device_common; @@ -56,10 +64,21 @@ struct gx_device_chameleon_s { int output_as_pxm; bool language_uses_rops; gx_downscaler_params downscale; + gsicc_link_t *icclink; + linktype_t linktype; + cmm_profile_t *default_device_profile; }; typedef struct gx_device_chameleon_s gx_device_chameleon; static void +chameleon_finalize(gx_device *dev) +{ + gx_device_chameleon *pcdev = (gx_device_chameleon *)dev; + + gsicc_adjust_profile_rc(pcdev->default_device_profile, -1, "chameleon_finalize"); +} + +static void chameleon_initialize_device_procs(gx_device *dev) { gdev_prn_initialize_device_procs_bg(dev); @@ -72,6 +91,8 @@ chameleon_initialize_device_procs(gx_device *dev) set_dev_proc(dev, encode_color, chameleon_rgb_encode_color); set_dev_proc(dev, decode_color, chameleon_rgb_decode_color); set_dev_proc(dev, dev_spec_op, chameleon_spec_op); + set_dev_proc(dev, close_device, chameleon_close); + dev->finalize = chameleon_finalize; } const gx_device_chameleon gs_chameleon_device = @@ -208,62 +229,143 @@ chameleon_cmyk_decode_color(gx_device * dev, gx_color_index color, gx_color_valu #undef cvalue } -/* # So long, oh, I hate to see you go */ +static int +fixup_icc_struct(gx_device_chameleon *pcdev, gsicc_colorbuffer_t cs, char *profile) +{ + if (pcdev->icc_struct && + pcdev->icc_struct->device_profile[gsDEFAULTPROFILE] && + pcdev->icc_struct->device_profile[gsDEFAULTPROFILE]->data_cs == cs) + return 0; /* Already the right profile type */ + + rc_decrement(pcdev->icc_struct, "fixup_icc_struct(chameleon)"); + + pcdev->icc_struct = gsicc_new_device_profile_array((gx_device *)pcdev); + if (pcdev->icc_struct == NULL) + return gs_error_VMerror; + + return gsicc_set_device_profile((gx_device *)pcdev, pcdev->memory, + profile, gsDEFAULTPROFILE); +} + +static void reset_icclink(gx_device_chameleon *pcdev) +{ + gsicc_free_link_dev(pcdev->icclink); + pcdev->icclink = NULL; + pcdev->linktype = linktype_none; +} + static void +stash_default_device_profile(gx_device_chameleon *pcdev) +{ + if (pcdev->default_device_profile != NULL) + return; + + pcdev->default_device_profile = pcdev->icc_struct->device_profile[gsDEFAULTPROFILE]; + gsicc_adjust_profile_rc(pcdev->default_device_profile, 1, "stash_default_device_profile"); +} + +/* # So long, oh, I hate to see you go */ +static int reconfigure_baby(gx_device_chameleon *pcdev) { int bpc = pcdev->dst_bpc; int num_comps = pcdev->dst_num_components; + int code; + + stash_default_device_profile(pcdev); if (pcdev->language_uses_rops) { bpc = 8; num_comps = 3; } - if (pcdev->bpc != bpc || - pcdev->num_components != num_comps) { - - gs_closedevice((gx_device *)pcdev); - - pcdev->bpc = bpc; - pcdev->num_components = num_comps; - - switch (num_comps * bpc) { - case 1*1: case 1*2: case 1*4: case 1*8: - case 4*4: case 4*8: - pcdev->color_info.depth = bpc * num_comps; - break; - case 3*1: - pcdev->color_info.depth = 4; - break; - case 3*2: - pcdev->color_info.depth = 8; - break; - case 3*4: - pcdev->color_info.depth = 16; - break; - } - pcdev->color_info.max_gray = pcdev->color_info.max_color = - (pcdev->color_info.dither_grays = pcdev->color_info.dither_colors = 1<<bpc) - 1; - - set_dev_proc(pcdev, map_cmyk_color, NULL); - set_dev_proc(pcdev, map_rgb_color, NULL); - set_dev_proc(pcdev, map_color_rgb, NULL); - set_dev_proc(pcdev, encode_color, - num_comps == 1 ? chameleon_mono_encode_color : - num_comps == 4 ? chameleon_cmyk_encode_color : - chameleon_rgb_encode_color); - set_dev_proc(pcdev, decode_color, - num_comps == 1 ? chameleon_mono_decode_color : - num_comps == 4 ? chameleon_cmyk_decode_color : - chameleon_rgb_decode_color); - - /* Reset the separable and linear shift, masks, bits. */ - set_linear_color_bits_mask_shift((gx_device *)pcdev); - pcdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN; - pcdev->bpc = bpc; - pcdev->num_components = num_comps; + if (pcdev->bpc == bpc && pcdev->num_components == num_comps) + return 0; /* Nothing needs to change! */ + + gs_closedevice((gx_device *)pcdev); + + pcdev->bpc = bpc; + pcdev->num_components = num_comps; + + switch (num_comps * bpc) { + case 1*1: case 1*2: case 1*4: case 1*8: + case 3*8: + case 4*4: case 4*8: + pcdev->color_info.depth = bpc * num_comps; + break; + case 3*1: + pcdev->color_info.depth = 4; + break; + case 3*2: + pcdev->color_info.depth = 8; + break; + case 3*4: + pcdev->color_info.depth = 16; + break; } + pcdev->color_info.num_components = num_comps; + pcdev->color_info.max_components = num_comps; + pcdev->color_info.max_gray = pcdev->color_info.max_color = + (pcdev->color_info.dither_grays = pcdev->color_info.dither_colors = 1<<bpc) - 1; + + switch (num_comps) { + case 1: + set_dev_proc(pcdev, encode_color, chameleon_mono_encode_color); + set_dev_proc(pcdev, decode_color, chameleon_mono_decode_color); + set_dev_proc(pcdev, get_color_mapping_procs, + gx_default_DevGray_get_color_mapping_procs); + set_dev_proc(pcdev, get_color_comp_index, + gx_default_DevGray_get_color_comp_index); + pcdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE; + pcdev->color_info.cm_name = "DeviceGray"; + pcdev->color_info.gray_index = 0; + code = fixup_icc_struct(pcdev, gsGRAY, DEFAULT_GRAY_ICC); + if (code < 0) + return code; + break; + case 3: + set_dev_proc(pcdev, encode_color, chameleon_rgb_encode_color); + set_dev_proc(pcdev, decode_color, chameleon_rgb_decode_color); + set_dev_proc(pcdev, get_color_mapping_procs, + gx_default_DevRGB_get_color_mapping_procs); + set_dev_proc(pcdev, get_color_comp_index, + gx_default_DevRGB_get_color_comp_index); + pcdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE; + pcdev->color_info.cm_name = "DeviceRGB"; + pcdev->color_info.gray_index = GX_CINFO_COMP_NO_INDEX; + code = fixup_icc_struct(pcdev, gsRGB, DEFAULT_RGB_ICC); + if (code < 0) + return code; + break; + case 4: + set_dev_proc(pcdev, encode_color, chameleon_cmyk_encode_color); + set_dev_proc(pcdev, decode_color, chameleon_cmyk_decode_color); + set_dev_proc(pcdev, get_color_mapping_procs, + gx_default_DevCMYK_get_color_mapping_procs); + set_dev_proc(pcdev, get_color_comp_index, + gx_default_DevCMYK_get_color_comp_index); + pcdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE; + pcdev->color_info.cm_name = "DevicCMYK"; + pcdev->color_info.gray_index = 3; + code = fixup_icc_struct(pcdev, gsCMYK, DEFAULT_CMYK_ICC); + if (code < 0) + return code; + break; + } + set_dev_proc(pcdev, map_color_rgb, dev_proc(pcdev, decode_color)); + set_dev_proc(pcdev, map_cmyk_color, dev_proc(pcdev, encode_color)); + set_dev_proc(pcdev, map_rgb_color, dev_proc(pcdev, encode_color)); + + /* Reset the separable and linear shift, masks, bits. */ + set_linear_color_bits_mask_shift((gx_device *)pcdev); + pcdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN; + pcdev->bpc = bpc; + pcdev->num_components = num_comps; + + /* Invalidate the link. */ + reset_icclink(pcdev); + + return 0; } /* Get parameters. We provide a default CRD. */ @@ -357,9 +459,7 @@ chameleon_put_params(gx_device * pdev, gs_param_list * plist) pcdev->output_as_pxm = pxm; pcdev->language_uses_rops = language_uses_rops; - reconfigure_baby(pcdev); - - return 0; + return reconfigure_baby(pcdev); } static int @@ -374,35 +474,6 @@ chameleon_spec_op(gx_device *dev_, int op, void *data, int datasize) } static int -craprgbtocmyk(void *arg, - byte **dst, - byte **src, - int w, - int h, - int raster) -{ - byte *d = *dst; - byte *s = *src; - - while (w--) { - int c = 255-*s++; - int m = 255-*s++; - int y = 255-*s++; - int k = c; - if (k > m) - k = m; - if (k > y) - k = y; - *d++ = c - k; - *d++ = m - k; - *d++ = y - k; - *d++ = k; - } - - return 0; -} - -static int header_4x1(gp_file *file, gx_device_chameleon *pcdev) { gp_fprintf(file, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE CMYK\nENDHDR\n", @@ -448,12 +519,20 @@ header_3x8(gp_file *file, gx_device_chameleon *pcdev) } static int +header_4x8(gp_file *file, gx_device_chameleon *pcdev) +{ + gp_fprintf(file, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE CMYK\nENDHDR\n", + pcdev->width, pcdev->height); + return 0; +} + +static int do_fwrite(const byte *data, int n, gp_file *file) { return gp_fwrite(data, 1, (n+7)>>3, file); } -static int tiff_chunky_post_cm(void *arg, byte **dst, byte **src, int w, int h, +static int chunky_post_cm(void *arg, byte **dst, byte **src, int w, int h, int raster) { gsicc_bufferdesc_t input_buffer_desc, output_buffer_desc; @@ -517,8 +596,6 @@ chameleon_print_page(gx_device_printer * pdev, gp_file * prn_stream) int (*write)(const byte *, int, gp_file *) = do_fwrite; int (*header)(gp_file *, gx_device_chameleon *) = NULL; int bitwidth; - gx_downscale_cm_fn *col_convert = NULL; - void *col_convert_arg = NULL; switch (pcdev->dst_num_components * pcdev->dst_bpc) { case 1*1: case 1*2: case 1*4: case 1*8: @@ -552,6 +629,8 @@ chameleon_print_page(gx_device_printer * pdev, gp_file * prn_stream) case 4: if (pcdev->dst_bpc == 1) header = header_4x1, write = write_4x1; + else if (pcdev->dst_bpc == 8) + header = header_4x8; break; case 3: if (pcdev->dst_bpc == 8) @@ -565,18 +644,48 @@ chameleon_print_page(gx_device_printer * pdev, gp_file * prn_stream) * components, then use that. */ if (pcdev->icc_struct->postren_profile && pcdev->icc_struct->postren_profile->num_comps == pcdev->dst_num_components) { - col_convert = tiff_chunky_post_cm; - col_convert_arg = pcdev->icc_struct->postren_profile; - } - /* Can we get away with no conversion? */ - else if (pcdev->num_components == pcdev->dst_num_components && - pcdev->bpc == pcdev->dst_bpc) { + if (pcdev->linktype != linktype_postrender) { + reset_icclink(pcdev); + code = gx_downscaler_create_post_render_link((gx_device *)pdev, + &pcdev->icclink); + if (code < 0) + return code; + pcdev->linktype = linktype_postrender; + } + } else if (pcdev->num_components == pcdev->dst_num_components && + pcdev->bpc == pcdev->dst_bpc) { /* Nothing to do */ - } - /* Otherwise, use some inbuilt crap conversions */ - else if (pcdev->num_components == 3 && pcdev->bpc == 8 && pcdev->dst_num_components == 4) { - col_convert = craprgbtocmyk; - col_convert_arg = NULL; + reset_icclink(pcdev); + } else if (pcdev->bpc == 8 && pcdev->dst_num_components == 4) { + if (pcdev->linktype != linktype_device) { + reset_icclink(pcdev); + code = gx_downscaler_create_icc_link((gx_device *)pdev, + &pcdev->icclink, + pcdev->default_device_profile); + if (code < 0) + return code; + pcdev->linktype = linktype_device; + } + } else if (pcdev->bpc == 8 && pcdev->dst_num_components == 3) { + if (pcdev->linktype != linktype_device) { + reset_icclink(pcdev); + code = gx_downscaler_create_icc_link((gx_device *)pdev, + &pcdev->icclink, + pcdev->default_device_profile); + if (code < 0) + return code; + pcdev->linktype = linktype_device; + } + } else if (pcdev->bpc == 8 && pcdev->dst_num_components == 1) { + if (pcdev->linktype != linktype_device) { + reset_icclink(pcdev); + code = gx_downscaler_create_icc_link((gx_device *)pdev, + &pcdev->icclink, + pcdev->default_device_profile); + if (code < 0) + return code; + pcdev->linktype = linktype_device; + } } else { emprintf(pdev->memory, "Chameleon device doesn't support this color conversion.\n"); return gs_error_rangecheck; @@ -589,7 +698,8 @@ chameleon_print_page(gx_device_printer * pdev, gp_file * prn_stream) pcdev->num_components, &pcdev->downscale, NULL, 0, /* Adjust width */ - col_convert, col_convert_arg, /* Color Management */ + pcdev->icclink ? chunky_post_cm : NULL, + pcdev->icclink, /* Color Management */ pcdev->dst_num_components, default_ht); if (code < 0) @@ -613,3 +723,13 @@ cleanup: gs_free_object(pdev->memory, in_alloc, "chameleon_print_page(in)"); return code; } + +static int +chameleon_close(gx_device *pdev) +{ + gx_device_chameleon *pcdev = (gx_device_chameleon *)pdev; + + gsicc_free_link_dev(pcdev->icclink); + pcdev->icclink = NULL; + return gdev_prn_close(pdev); +} diff --git a/devices/gdevdjet.c b/devices/gdevdjet.c index 1ded0813..d2f936d1 100644 --- a/devices/gdevdjet.c +++ b/devices/gdevdjet.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 @@ -330,7 +330,7 @@ ljet4pjl_close(gx_device *pdev) init string is stored in buf, so make sure that buf is at least 5 bytes larger than str. */ static void -hpjet_make_init(gx_device_printer *pdev, char *buf, const char *str) +hpjet_make_init(gx_device_printer *pdev, char buf[80], const char *str) { gx_device_hpjet *dev = (gx_device_hpjet *)pdev; int paper_source = -1; @@ -339,9 +339,9 @@ hpjet_make_init(gx_device_printer *pdev, char *buf, const char *str) else if (dev->MediaPosition_set && dev->MediaPosition >= 0) paper_source = dev->MediaPosition; if (paper_source >= 0) - gs_sprintf(buf, "%s\033&l%dH", str, paper_source); + gs_snprintf(buf, 80, "%s\033&l%dH", str, paper_source); else - gs_sprintf(buf, "%s", str); + gs_snprintf(buf, 80, "%s", str); } /* The DeskJet can compress (mode 2) */ @@ -377,7 +377,7 @@ fs600_print_page_copies(gx_device_printer * pdev, gp_file * prn_stream, char base_init[60]; char init[80]; - gs_sprintf(base_init, "\033*r0F\033&u%dD", dots_per_inch); + gs_snprintf(base_init, sizeof(base_init), "\033*r0F\033&u%dD", dots_per_inch); hpjet_make_init(pdev, init, base_init); return dljet_mono_print_page_copies(pdev, prn_stream, num_copies, dots_per_inch, PCL_FS600_FEATURES, @@ -441,7 +441,7 @@ ljet3d_print_page_copies(gx_device_printer * pdev, gp_file * prn_stream, bool tumble=dev->Tumble; hpjet_make_init(pdev, init, "\033&l-180u36Z\033*r0F"); - gs_sprintf(even_init, "\033&l180u36Z\033*r0F"); + gs_snprintf(even_init, sizeof(even_init), "\033&l180u36Z\033*r0F"); return dljet_mono_print_page_copies(pdev, prn_stream, num_copies, 300, PCL_LJ3D_FEATURES, init, even_init, tumble); } @@ -456,9 +456,9 @@ ljet4_print_page_copies(gx_device_printer * pdev, gp_file * prn_stream, char base_init[60]; char init[80]; - gs_sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch); + gs_snprintf(base_init, sizeof(base_init), "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch); if (gdev_pcl_page_orientation((gx_device *) pdev) == PAGE_ORIENTATION_LANDSCAPE) - gs_sprintf(base_init, "\033&l0u140Z\033*r0F\033&u%dD", dots_per_inch); + gs_snprintf(base_init, sizeof(base_init), "\033&l0u140Z\033*r0F\033&u%dD", dots_per_inch); hpjet_make_init(pdev, init, base_init); return dljet_mono_print_page_copies(pdev, prn_stream, num_copies, @@ -490,9 +490,9 @@ ljet4d_print_page_copies(gx_device_printer * pdev, gp_file * prn_stream, in duplex mode we set this parameters for each odd page (paper tray is set by "hpjet_make_init") */ - gs_sprintf(base_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch); + gs_snprintf(base_init, sizeof(base_init), "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch); hpjet_make_init(pdev, init, base_init); - gs_sprintf(even_init, "\033&l180u36Z\033*r0F\033&u%dD", dots_per_inch); + gs_snprintf(even_init, sizeof(even_init), "\033&l180u36Z\033*r0F\033&u%dD", dots_per_inch); return dljet_mono_print_page_copies(pdev, prn_stream, num_copies, dots_per_inch, PCL_LJ4D_FEATURES, init,even_init,tumble); @@ -507,7 +507,7 @@ ljet4pjl_print_page_copies(gx_device_printer *pdev, gp_file *prn_stream, { int dots_per_inch = (int)pdev->y_pixels_per_inch; char real_init[60]; - gs_sprintf(real_init, "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch); + gs_snprintf(real_init, sizeof(real_init), "\033&l-180u36Z\033*r0F\033&u%dD", dots_per_inch); return dljet_mono_print_page_copies(pdev, prn_stream, num_copies, dots_per_inch, PCL_LJ4PJL_FEATURES, real_init, real_init, false); diff --git a/devices/gdevdsp.c b/devices/gdevdsp.c index d772ccfd..f757666a 100644 --- a/devices/gdevdsp.c +++ b/devices/gdevdsp.c @@ -372,7 +372,7 @@ display_output_page(gx_device * dev, int copies, int flush) } if (code >= 0) - code = gx_finish_output_page(dev, copies, flush); + code = gx_finish_output_page((gx_device *)ddev, copies, flush); return code; } @@ -1276,12 +1276,12 @@ display_separation_decode_color(gx_device * dev, gx_color_index color, * Device proc for updating the equivalent CMYK color for spot colors. */ static int -display_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs) +display_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs, const gs_color_space *pcs) { gx_device_display * ddev = (gx_device_display *)dev; if ((ddev->nFormat & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_SEPARATION) - update_spot_equivalent_cmyk_colors(dev, pgs, + update_spot_equivalent_cmyk_colors(dev, pgs, pcs, &ddev->devn_params, &ddev->equiv_cmyk_colors); return 0; } @@ -1810,6 +1810,10 @@ display_set_separations(gx_device_display *dev) int sep_num; int sep_name_size; unsigned int c, m, y, k; + gx_device_display *head = dev; + + while(head->parent) + head = (gx_device_display *)head->parent; /* Map the separation numbers to component numbers */ memset(comp_map, 0, sizeof(comp_map)); @@ -1858,10 +1862,7 @@ display_set_separations(gx_device_display *dev) * 65535 / frac_1; } } - while(dev->parent) - dev = (gx_device_display *)dev->parent; - - (*dev->callback->display_separation)(dev->pHandle, dev, + (*head->callback->display_separation)(dev->pHandle, head, comp_num, name, (unsigned short)c, (unsigned short)m, (unsigned short)y, (unsigned short)k); diff --git a/devices/gdevfpng.c b/devices/gdevfpng.c index d57df8f8..f533d777 100644 --- a/devices/gdevfpng.c +++ b/devices/gdevfpng.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 @@ -301,6 +301,8 @@ static int fpng_process(void *arg, gx_device *dev, gx_device *bdev, const gs_int p = params.data[0]; stream.next_out = &buffer->data[0]; stream.avail_out = buffer->size; + stream.total_out = 0; + stream.total_in = 0; /* Nasty zlib hackery here. Zlib always outputs a 'start of stream' * marker at the beginning. We just want a block, so for all blocks @@ -311,7 +313,9 @@ static int fpng_process(void *arg, gx_device *dev, gx_device *bdev, const gs_int { stream.next_in = ⊂ stream.avail_in = 1; - deflate(&stream, Z_FULL_FLUSH); + err = deflate(&stream, Z_FULL_FLUSH); + if (err != Z_OK) + return_error(gs_error_VMerror); stream.next_out = &buffer->data[0]; stream.avail_out = buffer->size; stream.total_out = 0; @@ -321,15 +325,19 @@ static int fpng_process(void *arg, gx_device *dev, gx_device *bdev, const gs_int for (y = h-1; y >= 0; y--) { stream.avail_in = 1; - deflate(&stream, Z_NO_FLUSH); + err = deflate(&stream, Z_NO_FLUSH); + if (err != Z_OK) + return_error(gs_error_VMerror); stream.next_in = p; stream.avail_in = w*3; - deflate(&stream, (y == 0 ? (lastband ? Z_FINISH : Z_FULL_FLUSH) : Z_NO_FLUSH)); + err = deflate(&stream, (y == 0 ? (lastband ? Z_FINISH : Z_FULL_FLUSH) : Z_NO_FLUSH)); + if (err != Z_OK) + return_error(gs_error_VMerror); p += raster; stream.next_in = &paeth; } /* Ignore errors given here */ - deflateEnd(&stream); + (void)deflateEnd(&stream); buffer->compressed = stream.total_out; diff --git a/devices/gdevijs.c b/devices/gdevijs.c index 0252e3b5..3851f911 100644 --- a/devices/gdevijs.c +++ b/devices/gdevijs.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 @@ -633,7 +633,7 @@ gsijs_set_margin_params(gx_device_ijs *ijsdev) } if (code == 0) { - gs_sprintf (buf, "%gx%g", ijsdev->MediaSize[0] * (1.0 / 72), + gs_snprintf (buf, sizeof(buf), "%gx%g", ijsdev->MediaSize[0] * (1.0 / 72), ijsdev->MediaSize[1] * (1.0 / 72)); code = ijs_client_set_param(ijsdev->ctx, 0, "PaperSize", buf, strlen(buf)); @@ -678,7 +678,7 @@ gsijs_set_margin_params(gx_device_ijs *ijsdev) m[1] = ijsdev->MediaSize[1] * (1.0 / 72) - printable_top - printable_height; gx_device_set_margins((gx_device *)ijsdev, m, true); - gs_sprintf (buf, "%gx%g", printable_left, printable_top); + gs_snprintf (buf, sizeof(buf), "%gx%g", printable_left, printable_top); code = ijs_client_set_param(ijsdev->ctx, 0, "TopLeft", buf, strlen(buf)); } @@ -848,7 +848,7 @@ gsijs_open(gx_device *dev) /* Note: dup() may not be portable to all interesting IJS platforms. In that case, this branch should be #ifdef'ed out. */ - gs_sprintf(buf, "%d", fd); + gs_snprintf(buf, sizeof(buf), "%d", fd); ijs_client_set_param(ijsdev->ctx, 0, "OutputFD", buf, strlen(buf)); close(fd); } else { @@ -1013,9 +1013,9 @@ gsijs_output_page(gx_device *dev, int num_copies, int flush) } /* Required page parameters */ - gs_sprintf(buf, "%d", n_chan); + gs_snprintf(buf, sizeof(buf), "%d", n_chan); gsijs_client_set_param(ijsdev, "NumChan", buf); - gs_sprintf(buf, "%d", ijsdev->BitsPerSample); + gs_snprintf(buf, sizeof(buf), "%d", ijsdev->BitsPerSample); gsijs_client_set_param(ijsdev, "BitsPerSample", buf); /* This needs to become more sophisticated for DeviceN. */ @@ -1023,12 +1023,12 @@ gsijs_output_page(gx_device *dev, int num_copies, int flush) ((n_chan == 3) ? (krgb_mode ? ((k_bits == 1) ? "KRGB" : "KxRGB") : "DeviceRGB") : "DeviceGray")); gsijs_client_set_param(ijsdev, "ColorSpace", buf); - gs_sprintf(buf, "%d", ijs_width); + gs_snprintf(buf, sizeof(buf), "%d", ijs_width); gsijs_client_set_param(ijsdev, "Width", buf); - gs_sprintf(buf, "%d", ijs_height); + gs_snprintf(buf, sizeof(buf), "%d", ijs_height); gsijs_client_set_param(ijsdev, "Height", buf); - gs_sprintf(buf, "%gx%g", xres, yres); + gs_snprintf(buf, sizeof(buf), "%gx%g", xres, yres); gsijs_client_set_param(ijsdev, "Dpi", buf); #ifdef KRGB_DEBUG diff --git a/devices/gdevl31s.c b/devices/gdevl31s.c index 8832c13a..5532ec5e 100644 --- a/devices/gdevl31s.c +++ b/devices/gdevl31s.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 @@ -191,9 +191,9 @@ lj3100sw_print_page_copies(gx_device_printer *pdev, gp_file *prn_stream, int num if (gdev_prn_file_is_new(pdev)) { lj3100sw_output_section_header(prn_stream, 1, 0, 0); lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0x1b, 12); - ptr += gs_sprintf(ptr, "\r\nBD"); + ptr += gs_snprintf(ptr, sizeof(buffer) - (ptr - buffer), "\r\nBD"); lj3100sw_output_repeated_data_bytes(prn_stream, buffer, &ptr, 0, 5520); - ptr += gs_sprintf(ptr, "%s\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n", + ptr += gs_snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n%s %d\r\n", "NJ", "PQ", -1, "RE", high_resolution ? 6 : 2, @@ -205,7 +205,7 @@ lj3100sw_print_page_copies(gx_device_printer *pdev, gp_file *prn_stream, int num } lj3100sw_output_section_header(prn_stream, 3, ppdev->NumCopies, 0); - ptr += gs_sprintf(ptr, "%s %d\r\n%s\r\n", + ptr += gs_snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s %d\r\n%s\r\n", "CM", 1, "PD"); *ptr++ = 0; diff --git a/devices/gdevpdfimg.c b/devices/gdevpdfimg.c index 81e7a48e..d0b412ec 100644 --- a/devices/gdevpdfimg.c +++ b/devices/gdevpdfimg.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 @@ -200,8 +200,6 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev, gp_file *file) { gx_device_printer *const pdev = (gx_device_printer *)pdf_dev; - cmm_dev_profile_t *profile_struct; - gsicc_rendering_param_t rendering_params; int code; pdfimage_page *page; @@ -213,39 +211,11 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev, if (gdev_prn_file_is_new(pdev)) { /* Set up the icc link settings at this time */ - code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct); - if (code < 0) - return_error(gs_error_undefined); - if (profile_struct->postren_profile != NULL) { - rendering_params.black_point_comp = gsBLACKPTCOMP_ON; - rendering_params.graphics_type_tag = GS_UNKNOWN_TAG; - rendering_params.override_icc = false; - rendering_params.preserve_black = gsBLACKPRESERVE_OFF; - rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC; - rendering_params.cmm = gsCMM_DEFAULT; - if (profile_struct->oi_profile != NULL) { - pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->oi_profile, profile_struct->postren_profile, - &rendering_params); - } else if (profile_struct->link_profile != NULL) { - pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->link_profile, profile_struct->postren_profile, - &rendering_params); - } else { - pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], profile_struct->postren_profile, - &rendering_params); - } - if (pdf_dev->icclink == NULL) { - gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page"); - return_error(gs_error_VMerror); - } - /* If it is identity, release it now and set link to NULL */ - if (pdf_dev->icclink->is_identity) { - pdf_dev->icclink->procs.free_link(pdf_dev->icclink); - gsicc_free_link_dev(pdev->memory, pdf_dev->icclink); - pdf_dev->icclink = NULL; - } + code = gx_downscaler_create_post_render_link((gx_device *)pdev, + &pdf_dev->icclink); + if (code < 0) { + gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page"); + return code; } /* Set up the stream and insert the file header */ @@ -603,7 +573,7 @@ pdf_image_downscale_and_print_page(gx_device_printer *dev, pprintd1(pdf_dev->strm, "%d 0 obj\n", page->PageDictObjectNumber); pprintd1(pdf_dev->strm, "<<\n/Contents %d 0 R\n", page->PageStreamObjectNumber); stream_puts(pdf_dev->strm, "/Type /Page\n/Parent 2 0 R\n"); - gs_sprintf(Buffer, "/MediaBox [0 0 %f %f]\n", ((double)pdf_dev->width / pdf_dev->HWResolution[0]) * 72, ((double)pdf_dev->height / pdf_dev->HWResolution[1]) * 72); + gs_snprintf(Buffer, sizeof(Buffer), "/MediaBox [0 0 %f %f]\n", ((double)pdf_dev->width / pdf_dev->HWResolution[0]) * 72, ((double)pdf_dev->height / pdf_dev->HWResolution[1]) * 72); stream_puts(pdf_dev->strm, Buffer); pprintd1(pdf_dev->strm, "/Resources <<\n/XObject <<\n/Im1 %d 0 R\n>>\n", page->ImageObjectNumber); if (pdf_dev->ocr.file_init) @@ -699,7 +669,7 @@ static void write_xref_entry (stream *s, gs_offset_t Offset) if (Offset > 9999999999){ Offset = 0; } - gs_sprintf(O, "%d", Offset); + gs_snprintf(O, sizeof(O), "%d", Offset); for (i=0; i< (10 - strlen(O)); i++) stream_puts(s, "0"); stream_puts(s, O); @@ -707,13 +677,13 @@ static void write_xref_entry (stream *s, gs_offset_t Offset) } static void -pdf_store_default_Producer(char *buf) +pdf_store_default_Producer(char buf[256]) { int major = (int)(gs_revision / 1000); int minor = (int)(gs_revision - (major * 1000)) / 10; int patch = gs_revision % 10; - gs_sprintf(buf, "(%s %d.%02d.%d)", gs_product, major, minor, patch); + gs_snprintf(buf, 256, "(%s %d.%02d.%d)", gs_product, major, minor, patch); } static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm) @@ -759,7 +729,7 @@ static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm) tms = *localtime(&t); #endif - gs_sprintf(CreationDate, "(D:%04d%02d%02d%02d%02d%02d%c%02d\'%02d\')", + gs_snprintf(CreationDate, sizeof(CreationDate), "(D:%04d%02d%02d%02d%02d%02d%c%02d\'%02d\')", tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, tms.tm_hour, tms.tm_min, tms.tm_sec, timesign, timeoffset / 60, timeoffset % 60); @@ -851,12 +821,8 @@ static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm) pdf_dev->Pages = NULL; pdf_dev->NumPages = 0; } - if (pdf_dev->icclink != NULL) - { - pdf_dev->icclink->procs.free_link(pdf_dev->icclink); - gsicc_free_link_dev(pdf_dev->memory, pdf_dev->icclink); - pdf_dev->icclink = NULL; - } + gsicc_free_link_dev(pdf_dev->icclink); + pdf_dev->icclink = NULL; pdf_dev->RootOffset = 0; pdf_dev->PagesOffset = 0; pdf_dev->xrefOffset = 0; @@ -1095,10 +1061,7 @@ pdf_image_put_some_params(gx_device * dev, gs_param_list * plist, int which) (which & 2 ? GX_DOWNSCALER_PARAMS_TRAP : 0) | (which & 4 ? GX_DOWNSCALER_PARAMS_ETS : 0))); if (code < 0) - { ecode = code; - param_signal_error(plist, param_name, ecode); - } } if (ecode < 0) return ecode; @@ -1127,7 +1090,7 @@ pdf_image_put_params_downscale_cmyk_ets(gx_device * dev, gs_param_list * plist) return pdf_image_put_some_params(dev, plist, 7); } -void +static void PCLm_get_initial_matrix(gx_device * dev, register gs_matrix * pmat) { gx_device_pdf_image *pdev = (gx_device_pdf_image *)dev; @@ -1176,6 +1139,21 @@ PCLm_initialize_device_procs(gx_device *dev) set_dev_proc(dev, put_params, pdf_image_put_params_downscale); } +static void +PCLm8_initialize_device_procs(gx_device *dev) +{ + gdev_prn_initialize_device_procs_rgb(dev); + + set_dev_proc(dev, open_device, PCLm_open); + set_dev_proc(dev, output_page, gdev_prn_output_page); + set_dev_proc(dev, get_initial_matrix, PCLm_get_initial_matrix); + set_dev_proc(dev, close_device, PCLm_close); + set_dev_proc(dev, get_params, pdf_image_get_params_downscale); + set_dev_proc(dev, put_params, pdf_image_put_params_downscale); + set_dev_proc(dev, encode_color, gx_default_8bit_map_gray_color); + set_dev_proc(dev, decode_color, gx_default_8bit_map_color_gray); +} + static dev_proc_print_page(PCLm_print_page); const gx_device_pdf_image gs_PCLm_device = { @@ -1196,6 +1174,24 @@ const gx_device_pdf_image gs_PCLm_device = { 0 /* JPEGQ */ }; +const gx_device_pdf_image gs_PCLm8_device = { + prn_device_body_duplex(gx_device_pdf_image, + PCLm8_initialize_device_procs, + "pclm8", + DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, + 600, 600, /* 600 dpi by default */ + 0, 0, 0, 0, /* Margins */ + 1, /* num components */ + 8, /* bits per sample */ + 255, 0, 256, 0, + PCLm_print_page), + 3, + GX_DOWNSCALER_PARAMS_DEFAULTS, + 16, /* StripHeight */ + 0.0, /* QFactor */ + 0 /* JPEGQ */ +}; + /* Open a temporary file, with or without a stream. */ static int PCLm_open_temp_file(gx_device_pdf_image *pdev, PCLm_temp_file_t *ptf) @@ -1328,8 +1324,6 @@ static int gdev_PCLm_begin_page(gx_device_pdf_image *pdf_dev, gp_file *file) { gx_device_printer *const pdev = (gx_device_printer *)pdf_dev; - cmm_dev_profile_t *profile_struct; - gsicc_rendering_param_t rendering_params; int code; pdfimage_page *page; @@ -1341,39 +1335,11 @@ static int gdev_PCLm_begin_page(gx_device_pdf_image *pdf_dev, if (gdev_prn_file_is_new(pdev)) { /* Set up the icc link settings at this time */ - code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct); - if (code < 0) - return_error(gs_error_undefined); - if (profile_struct->postren_profile != NULL) { - rendering_params.black_point_comp = gsBLACKPTCOMP_ON; - rendering_params.graphics_type_tag = GS_UNKNOWN_TAG; - rendering_params.override_icc = false; - rendering_params.preserve_black = gsBLACKPRESERVE_OFF; - rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC; - rendering_params.cmm = gsCMM_DEFAULT; - if (profile_struct->oi_profile != NULL) { - pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->oi_profile, profile_struct->postren_profile, - &rendering_params); - } else if (profile_struct->link_profile != NULL) { - pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->link_profile, profile_struct->postren_profile, - &rendering_params); - } else { - pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], profile_struct->postren_profile, - &rendering_params); - } - if (pdf_dev->icclink == NULL) { - gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page"); - return_error(gs_error_VMerror); - } - /* If it is identity, release it now and set link to NULL */ - if (pdf_dev->icclink->is_identity) { - pdf_dev->icclink->procs.free_link(pdf_dev->icclink); - gsicc_free_link_dev(pdev->memory, pdf_dev->icclink); - pdf_dev->icclink = NULL; - } + code = gx_downscaler_create_post_render_link((gx_device *)pdev, + &pdf_dev->icclink); + if (code < 0) { + gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page"); + return code; } /* Set up the stream and insert the file header */ @@ -1475,7 +1441,7 @@ PCLm_downscale_and_print_page(gx_device_printer *dev, pprintd1(pdf_dev->strm, "%d 0 obj\n", page->PageDictObjectNumber); pprintd1(pdf_dev->strm, "<<\n/Contents %d 0 R\n", page->PageStreamObjectNumber); stream_puts(pdf_dev->strm, "/Type /Page\n/Parent 2 0 R\n"); - gs_sprintf(Buffer, "/MediaBox [0 0 %.3f %.3f]\n", ((double)pdf_dev->width / pdf_dev->HWResolution[0]) * 72, ((double)pdf_dev->height / pdf_dev->HWResolution[1]) * 72); + gs_snprintf(Buffer, sizeof(Buffer), "/MediaBox [0 0 %.3f %.3f]\n", ((double)pdf_dev->width / pdf_dev->HWResolution[0]) * 72, ((double)pdf_dev->height / pdf_dev->HWResolution[1]) * 72); stream_puts(pdf_dev->strm, Buffer); stream_puts(pdf_dev->strm, "/Resources <<\n/XObject <<\n"); @@ -1494,9 +1460,9 @@ PCLm_downscale_and_print_page(gx_device_printer *dev, double adjusted; adjusted = height - (row * pdf_dev->StripHeight); adjusted = adjusted / (pdf_dev->HWResolution[1] / (factor * 72)); - gs_sprintf(Buffer, "%.3f 0 0 %.3f 0 0 cm\n/Im%d Do Q\n", (width / (pdf_dev->HWResolution[0] / 72)) * factor, adjusted, row); + gs_snprintf(Buffer, sizeof(Buffer), "%.3f 0 0 %.3f 0 0 cm\n/Im%d Do Q\n", (width / (pdf_dev->HWResolution[0] / 72)) * factor, adjusted, row); } else - gs_sprintf(Buffer, "%.3f 0 0 %.3f 0 %f cm\n/Im%d Do Q\n", (width / (pdf_dev->HWResolution[0] / 72)) * factor, StripDecrement, ((height / (pdf_dev->HWResolution[1] / 72)) * factor) - (StripDecrement * (row + 1)), row); + gs_snprintf(Buffer, sizeof(Buffer), "%.3f 0 0 %.3f 0 %f cm\n/Im%d Do Q\n", (width / (pdf_dev->HWResolution[0] / 72)) * factor, StripDecrement, ((height / (pdf_dev->HWResolution[1] / 72)) * factor) - (StripDecrement * (row + 1)), row); stream_puts(pdf_dev->temp_stream.strm, Buffer); pprintd2(pdf_dev->strm, "/Im%d %d 0 R\n", row, page->ImageObjectNumber + (row * 2)); } @@ -1574,7 +1540,10 @@ PCLm_downscale_and_print_page(gx_device_printer *dev, stream_puts(pdf_dev->strm, "/Subtype /Image\n"); pprintd1(pdf_dev->strm, "/Width %d\n", width); pprintd1(pdf_dev->strm, "/Height %d\n", Read); - stream_puts(pdf_dev->strm, "/ColorSpace /DeviceRGB\n"); + if (dev->color_info.max_components == 1) + stream_puts(pdf_dev->strm, "/ColorSpace /DeviceGray\n"); + else + stream_puts(pdf_dev->strm, "/ColorSpace /DeviceRGB\n"); stream_puts(pdf_dev->strm, "/BitsPerComponent 8\n"); switch (pdf_dev->Compression) { case COMPRESSION_FLATE: @@ -1674,7 +1643,10 @@ PCLm_downscale_and_print_page(gx_device_printer *dev, stream_puts(pdf_dev->strm, "/Subtype /Image\n"); pprintd1(pdf_dev->strm, "/Width %d\n", width); pprintd1(pdf_dev->strm, "/Height %d\n", Read); - stream_puts(pdf_dev->strm, "/ColorSpace /DeviceRGB\n"); + if (dev->color_info.max_components == 1) + stream_puts(pdf_dev->strm, "/ColorSpace /DeviceGray\n"); + else + stream_puts(pdf_dev->strm, "/ColorSpace /DeviceRGB\n"); stream_puts(pdf_dev->strm, "/BitsPerComponent 8\n"); switch (pdf_dev->Compression) { case COMPRESSION_FLATE: diff --git a/devices/gdevpdfocr.c b/devices/gdevpdfocr.c index 8dd5a599..ff60c120 100644 --- a/devices/gdevpdfocr.c +++ b/devices/gdevpdfocr.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 @@ -544,20 +544,20 @@ flush_word(gx_device_pdf_image *dev) size = bbox[3]-bbox[1]; if (dev->ocr.cur_size != size) { - gs_sprintf(buffer, "/Ft0 %.3f Tf", size); + gs_snprintf(buffer, sizeof(buffer), "/Ft0 %.3f Tf", size); stream_puts(dev->strm, buffer); dev->ocr.cur_size = size; } scale = (bbox[2]-bbox[0]) / size / len * 200; if (dev->ocr.cur_scale != scale) { - gs_sprintf(buffer, " %.3f Tz", scale); + gs_snprintf(buffer, sizeof(buffer), " %.3f Tz", scale); stream_puts(dev->strm, buffer); dev->ocr.cur_scale = scale; } - gs_sprintf(buffer, " 1 0 0 1 %.3f %.3f Tm[<", bbox[0], bbox[1]); + gs_snprintf(buffer, sizeof(buffer), " 1 0 0 1 %.3f %.3f Tm[<", bbox[0], bbox[1]); stream_puts(dev->strm, buffer); for (i = 0; i < len; i++) { - gs_sprintf(buffer, "%04x", dev->ocr.word_chars[i]); + gs_snprintf(buffer, sizeof(buffer), "%04x", dev->ocr.word_chars[i]); stream_puts(dev->strm, buffer); } stream_puts(dev->strm, ">]TJ\n"); @@ -607,19 +607,19 @@ ocr_callback(void *arg, const char *rune_, size = bbox[3]-bbox[1]; if (ppdev->ocr.cur_size != size) { - gs_sprintf(buffer, "/Ft0 %f Tf ", size); + gs_snprintf(buffer, sizeof(buffer), "/Ft0 %f Tf ", size); stream_puts(ppdev->strm, buffer); ppdev->ocr.cur_size = size; } scale = (bbox[2]-bbox[0]) / size * 200; if (ppdev->ocr.cur_scale != scale) { - gs_sprintf(buffer, " %f Tz ", scale); + gs_snprintf(buffer, sizeof(buffer), " %f Tz ", scale); stream_puts(ppdev->strm, buffer); ppdev->ocr.cur_scale = scale; } - gs_sprintf(buffer, "1 0 0 1 %f %f Tm ", bbox[0], bbox[1]); + gs_snprintf(buffer, sizeof(buffer), "1 0 0 1 %f %f Tm ", bbox[0], bbox[1]); stream_puts(ppdev->strm, buffer); - gs_sprintf(buffer, "<%04x>Tj\n", unicode); + gs_snprintf(buffer, sizeof(buffer), "<%04x>Tj\n", unicode); stream_puts(ppdev->strm, buffer); #else bbox[0] = word_bbox[0] * scale / ppdev->ocr.xres; diff --git a/devices/gdevplan.c b/devices/gdevplan.c index 0ce82cda..abef8295 100644 --- a/devices/gdevplan.c +++ b/devices/gdevplan.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 @@ -24,6 +24,9 @@ #include "gdevplnx.h" #include "gdevppla.h" #include "gdevmem.h" +#include "gxdownscale.h" +#include "gsicc_cache.h" +#include "gxdevsop.h" /* This file defines 5 different devices: * @@ -48,6 +51,13 @@ /* ------ The device descriptors ------ */ +typedef struct { + gx_device_common; + gx_prn_device_common; + gx_downscaler_params downscale; + gsicc_link_t *icclink; +} gx_device_plan; + /* * Default X and Y resolution. */ @@ -61,6 +71,7 @@ static dev_proc_decode_color(plang_decode_color); static dev_proc_encode_color(planc_encode_color); static dev_proc_decode_color(planc_decode_color); static dev_proc_map_color_rgb(planc_map_color_rgb); +static dev_proc_dev_spec_op(plan_spec_op); static dev_proc_open_device(plan_open); static dev_proc_close_device(plan_close); @@ -77,6 +88,31 @@ static int planr_print_page(gx_device_printer * pdev, gp_file * pstream); /* The device procedures */ +static int +plan_get_params(gx_device * dev, gs_param_list * plist) +{ + gx_device_plan *pdev = (gx_device_plan *)dev; + int code = gdev_prn_get_params(dev, plist); + + if (code < 0) + return code; + + return gx_downscaler_write_params(plist, &pdev->downscale, 0); +} + +static int +plan_put_params(gx_device *dev, gs_param_list * plist) +{ + gx_device_plan *pdev = (gx_device_plan *)dev; + int code; + + code = gx_downscaler_read_params(plist, &pdev->downscale, 0); + if (code < 0) + return code; + + return gdev_prn_put_params(dev, plist); +} + static void plan_base_initialize_device_procs(gx_device *dev, dev_proc_map_color_rgb(map_color_rgb), @@ -91,6 +127,8 @@ plan_base_initialize_device_procs(gx_device *dev, set_dev_proc(dev, get_page_device, gx_page_device_get_page_device); set_dev_proc(dev, encode_color, encode_color); set_dev_proc(dev, decode_color, decode_color); + set_dev_proc(dev, get_params, plan_get_params); + set_dev_proc(dev, put_params, plan_put_params); } static void @@ -109,6 +147,7 @@ plang_initialize_device_procs(gx_device *dev) plang_decode_color, plang_encode_color, plang_decode_color); + set_dev_proc(dev, dev_spec_op, plan_spec_op); } static void @@ -118,6 +157,7 @@ plan_initialize_device_procs(gx_device *dev) plan_decode_color, gx_default_rgb_map_rgb_color, plan_decode_color); + set_dev_proc(dev, dev_spec_op, plan_spec_op); } static void @@ -127,6 +167,7 @@ planc_initialize_device_procs(gx_device *dev) planc_map_color_rgb, planc_encode_color, planc_decode_color); + set_dev_proc(dev, dev_spec_op, plan_spec_op); } static void @@ -149,30 +190,31 @@ planr_initialize_device_procs(gx_device *dev) /* Macro for generating device descriptors. */ #define plan_prn_device(init, dev_name, num_comp, depth, max_gray, max_rgb, print_page) \ -{ prn_device_body(gx_device_printer, init, dev_name,\ +{ prn_device_body(gx_device_plan, init, dev_name,\ DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, X_DPI, Y_DPI,\ 0, 0, 0, 0,\ num_comp, depth, max_gray, max_rgb, max_gray + 1, max_rgb + 1,\ - print_page)\ + print_page),\ + GX_DOWNSCALER_PARAMS_DEFAULTS\ } /* The device descriptors themselves */ -const gx_device_printer gs_plan_device = +const gx_device_plan gs_plan_device = plan_prn_device(plan_initialize_device_procs, "plan", 3, 24, 255, 255, plan_print_page); -const gx_device_printer gs_plang_device = +const gx_device_plan gs_plang_device = plan_prn_device(plang_initialize_device_procs, "plang", 1, 8, 255, 0, plang_print_page); -const gx_device_printer gs_planm_device = +const gx_device_plan gs_planm_device = plan_prn_device(planm_initialize_device_procs, "planm", 1, 1, 1, 0, planm_print_page); -const gx_device_printer gs_plank_device = +const gx_device_plan gs_plank_device = plan_prn_device(plank_initialize_device_procs, "plank", 4, 4, 1, 1, plank_print_page); -const gx_device_printer gs_planc_device = +const gx_device_plan gs_planc_device = plan_prn_device(planc_initialize_device_procs, "planc", 4, 32, 255, 255, planc_print_page); -const gx_device_printer gs_planr_device = +const gx_device_plan gs_planr_device = plan_prn_device(planr_initialize_device_procs, "planr", 3, 3, 1, 1, planr_print_page); @@ -363,10 +405,14 @@ plan_open(gx_device * pdev) static int plan_close(gx_device *pdev) { + gx_device_plan *dev = (gx_device_plan *)pdev; + #ifdef DEBUG_PRINT emprintf(pdev->memory, "plan_close\n"); #endif + gsicc_free_link_dev(dev->icclink); + dev->icclink = NULL; return gdev_prn_close(pdev); } @@ -486,26 +532,75 @@ planc_encode_color(gx_device * dev, const gx_color_value cv[]) return (color == gx_no_color_index ? color ^ 1 : color); } +static int +plan_spec_op(gx_device *dev, int op, void *data, int datasize) +{ + if (op == gxdso_supports_iccpostrender) { + int bpc = dev->color_info.depth / dev->color_info.num_components; + return bpc == 8; + } + if (op == gxdso_skip_icc_component_validation) { + int bpc = dev->color_info.depth / dev->color_info.num_components; + return bpc == 8; + } + return gdev_prn_dev_spec_op(dev, op, data, datasize); +} + /* ------ Internal routines ------ */ +static int post_cm(void *arg, + byte **dst, + byte **src, + int w, + int h, + int raster) +{ + gsicc_bufferdesc_t input_buffer_desc, output_buffer_desc; + gsicc_link_t *icclink = (gsicc_link_t*)arg; + + gsicc_init_buffer(&input_buffer_desc, icclink->num_input, 1, false, + false, true, src[1] - src[0], raster, h, w); + gsicc_init_buffer(&output_buffer_desc, icclink->num_output, 1, false, + false, true, dst[1] - dst[0], raster, h, w); + icclink->procs.map_buffer(NULL, icclink, &input_buffer_desc, &output_buffer_desc, + src[0], dst[0]); + return 0; +} + /* Print a page using a given row printing routine. */ static int -plan_print_page_loop(gx_device_printer * pdev, int log2bits, int numComps, +plan_print_page_loop(gx_device_printer *pdev, int log2bits, int numComps, gp_file *pstream) { - int lnum; + gx_device_plan *dev = (gx_device_plan *)pdev; + int i, lnum; int code = 0; gs_get_bits_options_t options; + gx_downscaler_t ds; + gs_get_bits_params_t params; + int post_cm_comps; + byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS]; + int factor = dev->downscale.downscale_factor; + int width = gx_downscaler_scale(pdev->width, factor); + int height = gx_downscaler_scale(pdev->height, factor); + int raster_plane = bitmap_raster(width << log2bits); + #ifdef DEBUG_DUMP dump_row row_proc = NULL; int output_is_nul = !strncmp(pdev->fname, "nul:", min(strlen(pdev->fname), 4)) || !strncmp(pdev->fname, "/dev/null", min(strlen(pdev->fname), 9)); - - if (!output_is_nul) - row_proc = dump_start(pdev->width, pdev->height, numComps, log2bits, pstream); #endif + + if (gdev_prn_file_is_new(pdev)) { + code = gx_downscaler_create_post_render_link((gx_device *)pdev, + &dev->icclink); + if (code < 0) + return code; + } + options = GB_ALIGN_ANY | GB_RETURN_POINTER | + GB_RETURN_COPY | GB_OFFSET_0 | GB_RASTER_STANDARD | GB_COLORS_NATIVE | @@ -514,25 +609,54 @@ plan_print_page_loop(gx_device_printer * pdev, int log2bits, int numComps, options |= GB_PACKING_CHUNKY; else options |= GB_PACKING_PLANAR; - for (lnum = 0; lnum < pdev->height; lnum++) { - gs_int_rect rect; - gs_get_bits_params_t params; - - rect.p.x = 0; - rect.p.y = lnum; - rect.q.x = pdev->width; - rect.q.y = lnum+1; - memset(¶ms, 0, sizeof(params)); - params.options = options; - params.x_offset = 0; - code = (*dev_proc(pdev, get_bits_rectangle))((gx_device *)pdev, &rect, ¶ms); + + memset(¶ms, 0, sizeof(params)); + params.options = options; + params.x_offset = 0; + post_cm_comps = dev->icclink ? dev->icclink->num_output : numComps; + + planes[0] = gs_alloc_bytes(pdev->memory, raster_plane * post_cm_comps, + "plan_print_page_loop"); + if (planes[0] == NULL) + return_error(gs_error_VMerror); + for (i = 1; i < post_cm_comps; i++) { + planes[i] = planes[i-1] + raster_plane; + params.data[i] = planes[i]; + } + + code = gx_downscaler_init_planar_cm(&ds, + (gx_device *)dev, + 1<<log2bits, /* src_bpc */ + 1<<log2bits, /* dst_bpc */ + numComps, + &dev->downscale, + ¶ms, + dev->icclink ? post_cm : NULL, + dev->icclink, + post_cm_comps); + if (code < 0) + goto fail; + +#ifdef DEBUG_DUMP + if (!output_is_nul) + row_proc = dump_start(width, height, post_cm_comps, log2bits, pstream); +#endif + + for (lnum = 0; lnum < height; lnum++) { + for (i = 0; i < post_cm_comps; i++) + params.data[i] = planes[i]; + code = gx_downscaler_get_bits_rectangle(&ds, ¶ms, lnum); if (code < 0) break; #ifdef DEBUG_DUMP if (row_proc) - (*row_proc)(pdev->width, params.data, pstream); + (*row_proc)(width, params.data, pstream); #endif } + + gx_downscaler_fin(&ds); +fail: + gs_free_object(pdev->memory, planes[0], "plan_print_page_loop"); return (code < 0 ? code : 0); } diff --git a/devices/gdevpng.c b/devices/gdevpng.c index 5d353a12..554c664c 100644 --- a/devices/gdevpng.c +++ b/devices/gdevpng.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 @@ -317,6 +317,41 @@ const gx_device_pngalpha gs_pngalpha_device = { 0xffffff /* white background */ }; +const gx_device_pngalpha gs_png16malpha_device = { + std_device_part1_(gx_device_pngalpha, + pngalpha_initialize_device_procs, "png16malpha", + &st_device_printer, open_init_closed), + /* color_info */ + {3 /* max components */, + 3 /* number components */, + GX_CINFO_POLARITY_ADDITIVE /* polarity */, + 32 /* depth */, + -1 /* gray index */, + 255 /* max gray */, + 255 /* max color */, + 256 /* dither grays */, + 256 /* dither colors */, + { 1, 1 } /* antialias info text, graphics */, + GX_CINFO_UNKNOWN_SEP_LIN /* separable_and_linear */, + { 0 } /* component shift */, + { 0 } /* component bits */, + { 0 } /* component mask */, + "DeviceRGB" /* process color name */, + GX_CINFO_OPMSUPPORTED_UNKNOWN /* opmsupported */, + 0 /* process_cmps */, + 0 /* icc_locations */ + }, + std_device_part2_( + (int)((float)(DEFAULT_WIDTH_10THS) * (X_DPI) / 10 + 0.5), + (int)((float)(DEFAULT_HEIGHT_10THS) * (Y_DPI) / 10 + 0.5), + X_DPI, Y_DPI), + offset_margin_values(0, 0, 0, 0, 0, 0), + std_device_part3_(), + prn_device_body_rest_(png_print_page), + GX_DOWNSCALER_PARAMS_DEFAULTS, + 0xffffff /* white background */ +}; + /* ------ Private definitions ------ */ static int @@ -603,7 +638,7 @@ do_png_print_page(gx_device_png * pdev, gp_file * file, bool monod) int minor = (int)(gs_revision - (major * 1000)) / 10; int patch = gs_revision % 10; - gs_sprintf(software_text, "%s %d.%02d.%d", gs_product, major, minor, patch); + gs_snprintf(software_text, sizeof(software_text), "%s %d.%02d.%d", gs_product, major, minor, patch); } text_png.compression = -1; /* uncompressed */ text_png.key = software_key; @@ -821,6 +856,7 @@ pngalpha_create_buf_device(gx_device **pbdev, gx_device *target, int y, ptarget= (gx_device_printer *)target; set_dev_proc(*pbdev, copy_alpha, ptarget->orig_procs.copy_alpha); + set_dev_proc(*pbdev, dev_spec_op, ptarget->orig_procs.dev_spec_op); set_dev_proc(*pbdev, fillpage, pngalpha_fillpage); return code; } diff --git a/devices/gdevpsd.c b/devices/gdevpsd.c index 3c9f6b01..d538b784 100644 --- a/devices/gdevpsd.c +++ b/devices/gdevpsd.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 @@ -57,6 +57,7 @@ static dev_proc_get_params(psd_get_params); static dev_proc_put_params(psd_put_params); static dev_proc_get_params(psd_get_params_cmyk); static dev_proc_put_params(psd_put_params_cmyk); +static dev_proc_put_params(psd_put_params_cmyktag); static dev_proc_print_page(psd_print_page); static dev_proc_map_color_rgb(psd_map_color_rgb); static dev_proc_get_color_mapping_procs(get_psdrgb_color_mapping_procs); @@ -69,9 +70,19 @@ typedef enum { psd_DEVICE_GRAY, psd_DEVICE_RGB, psd_DEVICE_CMYK, + psd_DEVICE_CMYKT, psd_DEVICE_N } psd_color_model; +fixed_colorant_name DevCMYKTComponents[] = { + "Cyan", + "Magenta", + "Yellow", + "Black", + "Tags", + 0 /* List terminator */ +}; + /* * A structure definition for a DeviceN type device */ @@ -205,7 +216,7 @@ const psd_device gs_psdrgb_device = { true }, /* equivalent CMYK colors for spot colors */ /* PSD device specific parameters */ psd_DEVICE_RGB, /* Color model */ - GS_SOFT_MAX_SPOTS, /* max_spots */ + GS_SOFT_MAX_SPOTS, /* max_spots */ false, /* colorants not locked */ GX_DOWNSCALER_PARAMS_DEFAULTS }; @@ -215,13 +226,13 @@ const psd_device gs_psdrgb16_device = psd_device_body(psd_initialize_device_procs, "psdrgb16", 3, GX_CINFO_POLARITY_ADDITIVE, 48, 65535, 65535, GX_CINFO_SEP_LIN, "DeviceRGB"), /* devn_params specific parameters */ { 16, /* Bits per color - must match ncomp, depth, etc. above */ - DeviceRGBComponents, /* Names of color model colorants */ - 3, /* Number colorants for RGB */ - 0, /* MaxSeparations has not been specified */ - -1, /* PageSpotColors has not been specified */ - { 0 }, /* SeparationNames */ - 0, /* SeparationOrder names */ - { 0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ + DeviceRGBComponents, /* Names of color model colorants */ + 3, /* Number colorants for RGB */ + 0, /* MaxSeparations has not been specified */ + -1, /* PageSpotColors has not been specified */ + { 0 }, /* SeparationNames */ + 0, /* SeparationOrder names */ + {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ }, { true }, /* equivalent CMYK colors for spot colors */ /* PSD device specific parameters */ @@ -244,6 +255,19 @@ psdcmyk_initialize_device_procs(gx_device *dev) set_dev_proc(dev, get_color_mapping_procs, get_psd_color_mapping_procs); } +/* + * PSD device with CMYK process color model, spot color support, and tags. + */ +static void +psdcmyktag_initialize_device_procs(gx_device *dev) +{ + psd_initialize_device_procs(dev); + + set_dev_proc(dev, get_params, psd_get_params_cmyk); + set_dev_proc(dev, put_params, psd_put_params_cmyktag); + set_dev_proc(dev, get_color_mapping_procs, get_psd_color_mapping_procs); +} + const psd_device gs_psdcmyk_device = { psd_device_body(psdcmyk_initialize_device_procs, "psdcmyk", @@ -269,22 +293,47 @@ const psd_device gs_psdcmyk_device = GX_DOWNSCALER_PARAMS_DEFAULTS }; +const psd_device gs_psdcmyktags_device = +{ + psd_device_body(psdcmyktag_initialize_device_procs, "psdcmyktags", + ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */ + GX_CINFO_POLARITY_SUBTRACTIVE, + ARCH_SIZEOF_GX_COLOR_INDEX * 8, /* 8 bits per component (albeit in planes) */ + 255, 255, GX_CINFO_SEP_LIN, "DeviceCMYK"), + /* devn_params specific parameters */ + { 8, /* Bits per color - must match ncomp, depth, etc. above */ + DevCMYKTComponents, /* Names of color model colorants */ + 4, /* Number colorants for CMYK. Tags added to extra in DevCMYKTComponents */ + 0, /* MaxSeparations has not been specified */ + -1, /* PageSpotColors has not been specified */ + {0}, /* SeparationNames */ + 0, /* SeparationOrder names */ + {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ + }, + { true }, /* equivalent CMYK colors for spot colors */ + /* PSD device specific parameters */ + psd_DEVICE_CMYKT, /* Color model */ + GS_SOFT_MAX_SPOTS, /* max_spots */ + false, /* colorants not locked */ + GX_DOWNSCALER_PARAMS_DEFAULTS +}; + const psd_device gs_psdcmyk16_device = { psd_device_body(psdcmyk_initialize_device_procs, "psdcmyk16", - ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */ - GX_CINFO_POLARITY_SUBTRACTIVE, - ARCH_SIZEOF_GX_COLOR_INDEX * 16, /* 8 bits per component (albeit in planes) */ - 65535, 65535, GX_CINFO_SEP_LIN, "DeviceCMYK"), + ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */ + GX_CINFO_POLARITY_SUBTRACTIVE, + ARCH_SIZEOF_GX_COLOR_INDEX * 16, /* 8 bits per component (albeit in planes) */ + 65535, 65535, GX_CINFO_SEP_LIN, "DeviceCMYK"), /* devn_params specific parameters */ { 16, /* Bits per color - must match ncomp, depth, etc. above */ - DeviceCMYKComponents, /* Names of color model colorants */ - 4, /* Number colorants for CMYK */ - 0, /* MaxSeparations has not been specified */ - -1, /* PageSpotColors has not been specified */ - { 0 }, /* SeparationNames */ - 0, /* SeparationOrder names */ - { 0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ + DeviceCMYKComponents, /* Names of color model colorants */ + 4, /* Number colorants for CMYK */ + 0, /* MaxSeparations has not been specified */ + -1, /* PageSpotColors has not been specified */ + { 0 }, /* SeparationNames */ + 0, /* SeparationOrder names */ + {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ }, { true }, /* equivalent CMYK colors for spot colors */ /* PSD device specific parameters */ @@ -294,6 +343,31 @@ const psd_device gs_psdcmyk16_device = GX_DOWNSCALER_PARAMS_DEFAULTS }; +const psd_device gs_psdcmyktags16_device = +{ + psd_device_body(psdcmyktag_initialize_device_procs, "psdcmyktags16", + ARCH_SIZEOF_GX_COLOR_INDEX, /* Number of components - need a nominal 1 bit for each */ + GX_CINFO_POLARITY_SUBTRACTIVE, + ARCH_SIZEOF_GX_COLOR_INDEX * 16, /* 8 bits per component (albeit in planes) */ + 65535, 65535, GX_CINFO_SEP_LIN, "DeviceCMYK"), + /* devn_params specific parameters */ + { 16, /* Bits per color - must match ncomp, depth, etc. above */ + DevCMYKTComponents, /* Names of color model colorants */ + 4, /* Number colorants for CMYK. Tags added to extra in DevCMYKTComponents */ + 0, /* MaxSeparations has not been specified */ + -1, /* PageSpotColors has not been specified */ + { 0 }, /* SeparationNames */ + 0, /* SeparationOrder names */ + {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ + }, + { true }, /* equivalent CMYK colors for spot colors */ + /* PSD device specific parameters */ + psd_DEVICE_CMYKT, /* Color model */ + GS_SOFT_MAX_SPOTS, /* max_spots */ + false, /* colorants not locked */ + GX_DOWNSCALER_PARAMS_DEFAULTS +}; + /* Open the psd devices */ int psd_prn_open(gx_device * pdev) @@ -302,6 +376,7 @@ psd_prn_open(gx_device * pdev) int code; int k; cmm_dev_profile_t *profile_struct; + bool has_tags = (pdev_psd->color_model == psd_DEVICE_CMYKT); #ifdef TEST_PAD_AND_ALIGN pdev->pad = 5; @@ -340,7 +415,7 @@ psd_prn_open(gx_device * pdev) } pdev->color_info.num_components = (profile_struct->spotnames->count - + pdev_psd->devn_params.page_spot_colors); + + pdev_psd->devn_params.page_spot_colors + has_tags); if (pdev->color_info.num_components > pdev->color_info.max_components) pdev->color_info.num_components = pdev->color_info.max_components; } else { @@ -351,7 +426,7 @@ psd_prn_open(gx_device * pdev) if (!(pdev_psd->lock_colorants)) { pdev->color_info.num_components = (pdev_psd->devn_params.page_spot_colors - + pdev_psd->devn_params.num_std_colorant_names); + + pdev_psd->devn_params.num_std_colorant_names + has_tags); if (pdev->color_info.num_components > pdev->color_info.max_components) pdev->color_info.num_components = pdev->color_info.max_components; } @@ -369,7 +444,7 @@ psd_prn_open(gx_device * pdev) was set (Default is GS_SOFT_MAX_SPOTS which is 10), it is made use of here. */ if (!(pdev_psd->lock_colorants)) { - int num_comp = pdev_psd->max_spots + 4; /* Spots + CMYK */ + int num_comp = pdev_psd->max_spots + 4 + has_tags; /* Spots + CMYK */ if (num_comp > GS_CLIENT_COLOR_MAX_COMPONENTS) num_comp = GS_CLIENT_COLOR_MAX_COMPONENTS; pdev->color_info.num_components = num_comp; @@ -474,6 +549,49 @@ rgb_cs_to_psdcmyk_cm(const gx_device * dev, const gs_gstate *pgs, } static void +cmyk_cs_to_psdcmyktags_cm(const gx_device *dev, + frac c, frac m, frac y, frac k, frac out[]) +{ + const gs_devn_params *devn = gx_devn_prn_ret_devn_params_const(dev); + const int *map = devn->separation_order_map; + int j; + + if (devn->num_separation_order_names > 0) { + /* This is to set only those that we are using */ + int ncomps = dev->color_info.num_components; + for (j = 0; j < ncomps; j++) + out[j] = 0; + for (j = 0; j < devn->num_separation_order_names; j++) { + switch (map[j]) { + case 0: + out[0] = c; + break; + case 1: + out[1] = m; + break; + case 2: + out[2] = y; + break; + case 3: + out[3] = k; + break; + default: + break; + } + } + } else { + cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out); + } + /* And set the tags. At this point, the color values + are frac representation for the range [0.0 1.0]. We + need to encode the graphics type, which is 0 to 255 + accordingly, as it goes through the same mappings on + its way to devn and then eventually to 8 or 16 bit values */ + if (map[4] != GX_DEVICE_COLOR_MAX_COMPONENTS) + out[4] = byte2frac(dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS); +} + +static void cmyk_cs_to_psdcmyk_cm(const gx_device * dev, frac c, frac m, frac y, frac k, frac out[]) { @@ -602,6 +720,10 @@ static const gx_cm_color_map_procs psdCMYK_procs = { gray_cs_to_psdcmyk_cm, rgb_cs_to_psdcmyk_cm, cmyk_cs_to_psdcmyk_cm }; +static const gx_cm_color_map_procs psdCMYKtags_procs = { + gray_cs_to_psdcmyk_cm, rgb_cs_to_psdcmyk_cm, cmyk_cs_to_psdcmyktags_cm +}; + static const gx_cm_color_map_procs psdN_procs = { gray_cs_to_spotn_cm, rgb_cs_to_spotn_cm, cmyk_cs_to_spotn_cm }; @@ -627,6 +749,8 @@ get_psd_color_mapping_procs(const gx_device * dev, const gx_device **map_dev) return &psdRGB_procs; else if (xdev->color_model == psd_DEVICE_CMYK) return &psdCMYK_procs; + else if (xdev->color_model == psd_DEVICE_CMYKT) + return &psdCMYKtags_procs; else if (xdev->color_model == psd_DEVICE_N) return &psdN_procs; else if (xdev->color_model == psd_DEVICE_GRAY) @@ -744,6 +868,13 @@ psd_put_params_cmyk(gx_device * pdev, gs_param_list * plist) return psd_put_params_generic(pdev, plist, 1); } +static int +psd_put_params_cmyktag(gx_device *pdev, gs_param_list* plist) +{ + pdev->graphics_type_tag |= GS_DEVICE_ENCODES_TAGS; + return psd_put_params_generic(pdev, plist, 1); +} + /* * This routine will check to see if the color component name match those * that are available amoung the current device's color components. @@ -812,7 +943,18 @@ psd_setup(psd_write_ctx *xc, gx_devn_prn_device *dev, gp_file *file, int w, int if (dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE && strcmp(dev->dname, "psdcmykog") != 0) { if (dev->devn_params.num_separation_order_names == 0) { - xc->n_extra_channels = dev->devn_params.separations.num_separations; + /* 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) + 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)) + xc->n_extra_channels = dev->devn_params.separations.num_separations; + else + xc->n_extra_channels = dev->color_info.max_components - NUM_CMYK_COMPONENTS; + } } else { /* Have to figure out how many in the order list were not std colorants */ @@ -856,24 +998,33 @@ psd_setup(psd_write_ctx *xc, gx_devn_prn_device *dev, gp_file *file, int w, int /* No order specified, map them alpabetically */ /* This isn't at all speed critical -- only runs once per page and */ /* there are never very many spot colors, so just search in a loop */ - byte *prev = " "; + + /* If the device has tags, then that goes at the end, after all the + spot colors */ + + const char *prev = " "; int prev_size = 1; + psd_device *pdev_psd = (psd_device*)dev; + 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++) { int j; - byte* curr = "\377"; + const char *curr = "\377"; int curr_size = 1; + bool compare; - for (j=xc->base_num_channels; j < xc->num_channels; j++) { - const devn_separation_name *separation_name; + for (j=xc->base_num_channels; j < (xc->num_channels - has_tags); j++) { + devn_separation_name *separation_name; separation_name = &(dev->devn_params.separations.names[j - xc->base_num_channels]); - if (strncmp(separation_name->data, curr, min(curr_size, separation_name->size)) < 0) { - if (strncmp(separation_name->data, prev, min(prev_size, separation_name->size)) > 0) { + compare = strncmp((const char*) separation_name->data, curr, min(curr_size, separation_name->size)); + if (compare < 0 || (compare == 0 && separation_name->size < curr_size)) { + compare = strncmp((const char*) separation_name->data, prev, min(prev_size, separation_name->size)); + if (compare > 0 || (compare == 0 && separation_name->size > prev_size)) { xc->chnl_to_position[i] = j; xc->chnl_to_orig_sep[i] = j; - curr = separation_name->data; + curr = (const char*) separation_name->data; curr_size = separation_name->size; } } @@ -934,8 +1085,36 @@ get_sep_name(gx_devn_prn_device *pdev, int n) return p; } +static inline void +psd_write_src_spot_names(psd_write_ctx *xc, gx_devn_prn_device *pdev, int chan_idx, bool has_tags) +{ + int sep_num; + const devn_separation_name *separation_name; + + for (; chan_idx < xc->num_channels; chan_idx++) { + sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS - has_tags; + separation_name = &(pdev->devn_params.separations.names[sep_num]); + psd_write_8(xc, (byte)separation_name->size); + psd_write(xc, separation_name->data, separation_name->size); + } +} + +static inline void +psd_write_std_extra_names(psd_write_ctx *xc, gx_devn_prn_device *pdev, int chan_idx) +{ + for (; chan_idx < xc->num_channels; chan_idx++) { + int len; + fixed_colorant_name n = pdev->devn_params.std_colorant_names[chan_idx]; + if (n == NULL) + break; + len = strlen(n); + psd_write_8(xc, (byte)len); + psd_write(xc, (const byte*)n, len); + } +} + int -psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev) +psd_write_header(psd_write_ctx* xc, gx_devn_prn_device* pdev) { int code = 0; int num_channels = xc->num_channels; @@ -944,8 +1123,14 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev) int chan_names_len = 0; int sep_num; const devn_separation_name *separation_name; + cmm_dev_profile_t *profile_struct; + cmm_profile_t *dev_profile; + int profile_resource_size; + psd_device *pdev_psd = (psd_device*)pdev; + bool has_tags = (pdev_psd->color_model == psd_DEVICE_CMYKT); + int extra_std_colors = 0; - psd_write(xc, (const byte *)"8BPS", 4); /* Signature */ + psd_write(xc, (const byte*)"8BPS", 4); /* Signature */ psd_write_16(xc, 1); /* Version - Always equal to 1*/ /* Reserved 6 Bytes - Must be zero */ psd_write_32(xc, 0); @@ -955,51 +1140,71 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev) psd_write_32(xc, xc->width); /* Columns */ psd_write_16(xc, bpc); /* Depth - 1, 8 and 16 */ /* Modes: Bitmap=0, Grayscale=1, RGB=3, CMYK=4 MultiChannel=7 Lab=9 */ - psd_write_16(xc, (bits16) xc->base_num_channels); /* We use 1, 3 or 4. */ + psd_write_16(xc, (bits16)xc->base_num_channels); /* We use 1, 3 or 4. */ - /* Color Mode Data */ - psd_write_32(xc, 0); /* No color mode data */ + /* Color Mode Data. Only used for indexed and duotone */ + psd_write_32(xc, 0); - /* Image Resources */ + /* Resources */ - /* Channel Names */ + /* ICC profile */ + code = dev_proc(pdev, get_profile)((gx_device*)pdev, &profile_struct); + if (code < 0) { + dev_profile = NULL; + profile_resource_size = 0; + } else { + dev_profile = profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; + + /* Resource has to be padded to even size */ + profile_resource_size = dev_profile->buffer_size + dev_profile->buffer_size % 2; + } + + /* Channel Names size computation -- this will get the "Tags" name */ for (chan_idx = NUM_CMYK_COMPONENTS; chan_idx < xc->num_channels; chan_idx++) { fixed_colorant_name n = pdev->devn_params.std_colorant_names[chan_idx]; if (n == NULL) break; chan_names_len += strlen(n) + 1; } + extra_std_colors = chan_idx - NUM_CMYK_COMPONENTS; + for (; chan_idx < xc->num_channels; chan_idx++) { - sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS; + sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS - has_tags; separation_name = &(pdev->devn_params.separations.names[sep_num]); chan_names_len += (separation_name->size + 1); } + + /* Length of resource section */ psd_write_32(xc, 12 + (chan_names_len + (chan_names_len % 2)) + (12 + (14 * (xc->num_channels - xc->base_num_channels))) - + 28); + + (profile_resource_size ? (12 + profile_resource_size) : 0) + 28); + + /* Channel names resource */ psd_write(xc, (const byte *)"8BIM", 4); psd_write_16(xc, 1006); /* 0x03EE */ psd_write_16(xc, 0); /* PString */ psd_write_32(xc, chan_names_len + (chan_names_len % 2)); - for (chan_idx = NUM_CMYK_COMPONENTS; chan_idx < xc->num_channels; chan_idx++) { - int len; - fixed_colorant_name n = pdev->devn_params.std_colorant_names[chan_idx]; - if (n == NULL) - break; - len = strlen(n); - psd_write_8(xc, (byte)len); - psd_write(xc, (const byte *)n, len); - } - for (; chan_idx < xc->num_channels; chan_idx++) { - sep_num = xc->chnl_to_orig_sep[chan_idx] - NUM_CMYK_COMPONENTS; - separation_name = &(pdev->devn_params.separations.names[sep_num]); - psd_write_8(xc, (byte) separation_name->size); - psd_write(xc, separation_name->data, separation_name->size); + + /* If it has tags, do the spots first (if there are any), + then the tags. We will need to rework this if we were + to add tags to psdcmykog or similar such device that + has pre-defined spots with the tags plane */ + if (has_tags) { + chan_idx = NUM_CMYK_COMPONENTS + extra_std_colors; + psd_write_src_spot_names(xc, pdev, chan_idx, has_tags); + chan_idx = NUM_CMYK_COMPONENTS; + psd_write_std_extra_names(xc, pdev, chan_idx); + + } else { + chan_idx = NUM_CMYK_COMPONENTS; + psd_write_std_extra_names(xc, pdev, chan_idx); + chan_idx = NUM_CMYK_COMPONENTS + extra_std_colors; + psd_write_src_spot_names(xc, pdev, chan_idx, has_tags); } if (chan_names_len % 2) psd_write_8(xc, 0); /* pad */ - /* DisplayInfo - Colors for each spot channels */ + /* DisplayInfo - Colors for each spot channels resource*/ psd_write(xc, (const byte *)"8BIM", 4); psd_write_16(xc, 1007); /* 0x03EF */ psd_write_16(xc, 0); /* PString */ @@ -1044,7 +1249,7 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev) psd_write_8(xc, 0); /* Padding - Always Zero */ } - /* Image resolution */ + /* Image resolution resource */ psd_write(xc, (const byte *)"8BIM", 4); psd_write_16(xc, 1005); /* 0x03ED */ psd_write_16(xc, 0); /* PString */ @@ -1057,6 +1262,17 @@ psd_write_header(psd_write_ctx *xc, gx_devn_prn_device *pdev) psd_write_16(xc, 1); /* height: 1 --> resolution is pixels per inch */ psd_write_16(xc, 1); /* height: 1 --> resolution is pixels per inch */ + /* ICC Profile resource */ + if (profile_resource_size) { + psd_write(xc, (const byte*)"8BIM", 4); + psd_write_16(xc, 1039); /* 0x040F */ + psd_write_16(xc, 0); /* PString */ + psd_write_32(xc, profile_resource_size); + psd_write(xc, dev_profile->buffer, dev_profile->buffer_size); + if (dev_profile->buffer_size % 2) + psd_write_8(xc, 0); + } + /* Layer and Mask information */ psd_write_32(xc, 0); /* No layer or mask information */ diff --git a/devices/gdevtifs.c b/devices/gdevtifs.c index b937d0e3..9c629afa 100644 --- a/devices/gdevtifs.c +++ b/devices/gdevtifs.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 @@ -76,12 +76,9 @@ tiff_close(gx_device * pdev) if (tfdev->tif) TIFFClose(tfdev->tif); - if (tfdev->icclink != NULL) - { - tfdev->icclink->procs.free_link(tfdev->icclink); - gsicc_free_link_dev(pdev->memory, tfdev->icclink); - tfdev->icclink = NULL; - } + gsicc_free_link_dev(tfdev->icclink); + tfdev->icclink = NULL; + return gdev_prn_close(pdev); } @@ -298,8 +295,6 @@ int gdev_tiff_begin_page(gx_device_tiff *tfdev, gp_file *file) { gx_device_printer *const pdev = (gx_device_printer *)tfdev; - cmm_dev_profile_t *profile_struct; - gsicc_rendering_param_t rendering_params; int code; if (gdev_prn_file_is_new(pdev)) { @@ -308,39 +303,10 @@ int gdev_tiff_begin_page(gx_device_tiff *tfdev, if (!tfdev->tif) return_error(gs_error_invalidfileaccess); /* Set up the icc link settings at this time */ - code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct); + code = gx_downscaler_create_post_render_link((gx_device *)pdev, + &tfdev->icclink); if (code < 0) - return_error(gs_error_undefined); - if (profile_struct->postren_profile != NULL) { - rendering_params.black_point_comp = gsBLACKPTCOMP_ON; - rendering_params.graphics_type_tag = GS_UNKNOWN_TAG; - rendering_params.override_icc = false; - rendering_params.preserve_black = gsBLACKPRESERVE_OFF; - rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC; - rendering_params.cmm = gsCMM_DEFAULT; - if (profile_struct->oi_profile != NULL) { - tfdev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->oi_profile, profile_struct->postren_profile, - &rendering_params); - } else if (profile_struct->link_profile != NULL) { - tfdev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->link_profile, profile_struct->postren_profile, - &rendering_params); - } else { - tfdev->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], - profile_struct->postren_profile, &rendering_params); - } - if (tfdev->icclink == NULL) { - return_error(gs_error_VMerror); - } - /* If it is identity, release it now and set link to NULL */ - if (tfdev->icclink->is_identity) { - tfdev->icclink->procs.free_link(tfdev->icclink); - gsicc_free_link_dev(pdev->memory, tfdev->icclink); - tfdev->icclink = NULL; - } - } + return code; } return tiff_set_fields_for_printer(pdev, tfdev->tif, tfdev->downscale.downscale_factor, @@ -400,7 +366,7 @@ int tiff_set_fields_for_printer(gx_device_printer *pdev, strncpy(softwareValue, gs_product, maxSoftware); softwareValue[maxSoftware - 1] = 0; - gs_sprintf(revs, " %d.%2d.%d", major, minor, patch); + gs_snprintf(revs, sizeof(revs), " %d.%2d.%d", major, minor, patch); strncat(softwareValue, revs, maxSoftware - strlen(softwareValue) - 1); @@ -418,7 +384,7 @@ int tiff_set_fields_for_printer(gx_device_printer *pdev, time(&t); tms = *localtime(&t); #endif - gs_sprintf(dateTimeValue, "%04d:%02d:%02d %02d:%02d:%02d", + gs_snprintf(dateTimeValue, sizeof(dateTimeValue), "%04d:%02d:%02d %02d:%02d:%02d", tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, tms.tm_hour, tms.tm_min, tms.tm_sec); @@ -438,8 +404,6 @@ int tiff_set_fields_for_printer(gx_device_printer *pdev, if (pdev->icc_struct->postren_profile != NULL) icc_profile = pdev->icc_struct->postren_profile; - else if (pdev->icc_struct->oi_profile != NULL) - icc_profile = pdev->icc_struct->oi_profile; else icc_profile = pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; diff --git a/devices/gdevtsep.c b/devices/gdevtsep.c index 10d3b633..fd859ddc 100644 --- a/devices/gdevtsep.c +++ b/devices/gdevtsep.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 @@ -395,8 +395,6 @@ tiff_set_rgb_fields(gx_device_tiff *tfdev) if (tfdev->icc_struct->postren_profile != NULL) icc_profile = tfdev->icc_struct->postren_profile; - else if (tfdev->icc_struct->oi_profile != NULL) - icc_profile = tfdev->icc_struct->oi_profile; else icc_profile = tfdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; @@ -956,11 +954,11 @@ tiffsep_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out * Device proc for updating the equivalent CMYK color for spot colors. */ static int -tiffsep_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs) +tiffsep_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs, const gs_color_space *pcs) { tiffsep_device * pdev = (tiffsep_device *)dev; - update_spot_equivalent_cmyk_colors(dev, pgs, + update_spot_equivalent_cmyk_colors(dev, pgs, pcs, &pdev->devn_params, &pdev->equiv_cmyk_colors); return 0; } @@ -1267,9 +1265,9 @@ tiffsep1_prn_close(gx_device * pdev) while (*fmt != 'l' && *fmt != '%') --fmt; if (*fmt == 'l') - gs_sprintf(compname, parsed.fname, count1); + gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, count1); else - gs_sprintf(compname, parsed.fname, (int)count1); + gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, (int)count1); parsed.iodev->procs.delete_file(parsed.iodev, compname); } else { parsed.iodev->procs.delete_file(parsed.iodev, tfdev->fname); @@ -1368,7 +1366,9 @@ copy_separation_name(tiffsep_device * pdev, { int sep_size = pdev->devn_params.separations.names[sep_num].size; const byte *p = pdev->devn_params.separations.names[sep_num].data; - int r, w; + int r, w, use_sep_num = 0; + const char *stdnames[4] = {"CYAN", "MAGENTA", "YELLOW", "BLACK"}; + char sep_num_str[16] = ""; /* Previously the code here would simply replace any char that wasn't * passed by gp_file_name_good_char (and %) with '_'. The grounds for @@ -1378,13 +1378,28 @@ copy_separation_name(tiffsep_device * pdev, * the file handling routines as they assume the filenames are in * utf-8 format. */ + for (r=0;r<4;r++) + { + if (strlen(stdnames[r]) == pdev->devn_params.separations.names[sep_num].size) { + use_sep_num = 1; + for (w=0;w<strlen(stdnames[r]);w++) { + if (toupper(pdev->devn_params.separations.names[sep_num].data[w]) != stdnames[r][w]) { + use_sep_num = 0; + break; + } + } + } + } + if (use_sep_num != 0) + gs_snprintf(sep_num_str, sizeof(sep_num_str), "%d", sep_num); + /* New code: Copy the name, escaping non gp_file_name_good_char chars, * % and top bit set chars using %02x format. In addition, if 'escape' * is set, output % as %% to allow for printf later. */ r = 0; w = 0; - while (r < sep_size && w < max_size-1) + while (r < sep_size && w < max_size-1 - strlen(sep_num_str)) { int c = p[r++]; if (c >= 127 || @@ -1393,7 +1408,7 @@ copy_separation_name(tiffsep_device * pdev, { /* Top bit set, backspace, or char we can't represent on the * filesystem. */ - if (w + 2 + escape >= max_size-1) + if (w + 2 + escape >= max_size-1 - strlen(sep_num_str)) break; buffer[w++] = '%'; if (escape) @@ -1406,6 +1421,10 @@ copy_separation_name(tiffsep_device * pdev, buffer[w++] = c; } } + if (use_sep_num) { + for (r = 0;r < strlen(sep_num_str);r++) + buffer[w++] = sep_num_str[r]; + } buffer[w] = 0; /* Terminate string */ } @@ -1479,7 +1498,7 @@ create_separation_file_name(tiffsep_device * pdev, char * buffer, /* Max of 10 chars in %d format */ if (max_size < base_filename_length + 11) return_error(gs_error_rangecheck); - gs_sprintf(buffer + base_filename_length, "s%d", sep_num); + gs_snprintf(buffer + base_filename_length, max_size - base_filename_length, "s%d", sep_num); } } if (use_sep_name) @@ -1575,12 +1594,13 @@ tiffsep_prn_open(gx_device * pdev) tiffsep_device *pdev_sep = (tiffsep_device *) pdev; int code, k; cmm_dev_profile_t *profile_struct; - gsicc_rendering_param_t rendering_params; /* Use our own warning and error message handlers in libtiff */ tiff_set_handlers(); code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct); + if (code < 0) + return code; /* For the planar device we need to set up the bit depth of each plane. For other devices this is handled in check_device_separable where @@ -1653,6 +1673,8 @@ tiffsep_prn_open(gx_device * pdev) pdev_sep->devn_params.bitspercomponent; pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN; code = gdev_prn_open_planar(pdev, true); + if (code < 0) + return code; while (pdev->child) pdev = pdev->child; ppdev = (gx_device_printer *)pdev; @@ -1662,42 +1684,8 @@ tiffsep_prn_open(gx_device * pdev) /* Set up the icc link settings at this time. Only CMYK post render profiles are allowed */ - code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct); - if (code < 0) - return_error(gs_error_undefined); - - if (profile_struct->postren_profile != NULL && - profile_struct->postren_profile->data_cs == gsCMYK) { - rendering_params.black_point_comp = gsBLACKPTCOMP_ON; - rendering_params.graphics_type_tag = GS_UNKNOWN_TAG; - rendering_params.override_icc = false; - rendering_params.preserve_black = gsBLACKPRESERVE_OFF; - rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC; - rendering_params.cmm = gsCMM_DEFAULT; - if (profile_struct->oi_profile != NULL) { - pdev_sep->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->oi_profile, profile_struct->postren_profile, - &rendering_params); - } else if (profile_struct->link_profile != NULL) { - pdev_sep->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->link_profile, profile_struct->postren_profile, - &rendering_params); - } else { - pdev_sep->icclink = gsicc_alloc_link_dev(pdev->memory, - profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], - profile_struct->postren_profile, &rendering_params); - } - if (pdev_sep->icclink == NULL) { - return_error(gs_error_VMerror); - } - /* If it is identity, release it now and set link to NULL */ - if (pdev_sep->icclink->is_identity) { - pdev_sep->icclink->procs.free_link(pdev_sep->icclink); - gsicc_free_link_dev(pdev->memory, pdev_sep->icclink); - pdev_sep->icclink = NULL; - } - } - return code; + return gx_downscaler_create_post_render_link((gx_device *)pdev, + &pdev_sep->icclink); } static int @@ -1752,11 +1740,9 @@ tiffsep_prn_close(gx_device * pdev) int comp_num; int num_comp = number_output_separations(num_dev_comp, num_std_colorants, num_order, num_spot); - if (pdevn->icclink != NULL) { - pdevn->icclink->procs.free_link(pdevn->icclink); - gsicc_free_link_dev(pdevn->memory, pdevn->icclink); - pdevn->icclink = NULL; - } + + 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) @@ -2066,7 +2052,6 @@ tiffsep_print_page(gx_device_printer * pdev, gp_file * file) int num_comp, comp_num, code = 0, code1 = 0; cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS]; char *name = NULL; - bool double_f = false; int save_depth = pdev->color_info.depth; int save_numcomps = pdev->color_info.num_components; const char *fmt; @@ -2490,9 +2475,9 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) while (*fmt != 'l' && *fmt != '%') --fmt; if (*fmt == 'l') - gs_sprintf(compname, parsed.fname, count1); + gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, count1); else - gs_sprintf(compname, parsed.fname, (int)count1); + gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, (int)count1); parsed.iodev->procs.delete_file(parsed.iodev, compname); } #endif /* PPM_COMBINED_OUTPUT */ diff --git a/devices/gdevupd.c b/devices/gdevupd.c index 66359847..179c400d 100644 --- a/devices/gdevupd.c +++ b/devices/gdevupd.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 @@ -216,6 +216,7 @@ static int upd_procs_map( upd_device *udev); static void upd_initialize_device_procs(gx_device *dev) { + set_dev_proc(dev, initialize_device, gx_init_non_threadsafe_device); set_dev_proc(dev, open_device, upd_open); set_dev_proc(dev, output_page, gdev_prn_output_page); set_dev_proc(dev, close_device, upd_close); @@ -6483,7 +6484,7 @@ upd_open_wrtrtl(upd_device *udev) if( (B_PAGEWIDTH & upd->flags) && ((c == 0x73) || (c == 0x53)) ) { /* esc * r # S */ - gs_sprintf(cv,"%d",upd->pwidth); + gs_snprintf(cv,sizeof(cv),"%d",upd->pwidth); ncv = strlen(cv); nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i); @@ -6501,7 +6502,7 @@ upd_open_wrtrtl(upd_device *udev) } else if((B_PAGELENGTH & upd->flags) && ((c == 0x74) || (c == 0x54)) ) { /* esc * r # T */ - gs_sprintf(cv,"%d",upd->pheight); + gs_snprintf(cv,sizeof(cv),"%d",upd->pheight); ncv = strlen(cv); nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i); @@ -6530,7 +6531,7 @@ upd_open_wrtrtl(upd_device *udev) if( (B_RESOLUTION & upd->flags) && ((c == 0x72) || (c == 0x52)) ) { /* esc * t # R */ - gs_sprintf(cv,"%d",(int) + gs_snprintf(cv,sizeof(cv),"%d",(int) ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ? udev->x_pixels_per_inch : udev->y_pixels_per_inch) +0.5)); @@ -6737,7 +6738,7 @@ upd_open_wrtrtl(upd_device *udev) if(B_PAGELENGTH & upd->flags) { /* insert new number */ - gs_sprintf(cv,"%d",(int) + gs_snprintf(cv,sizeof(cv),"%d",(int) (720.0 * udev->height / udev->y_pixels_per_inch + 0.5)); ncv = strlen(cv); @@ -6802,7 +6803,7 @@ upd_open_wrtrtl(upd_device *udev) if(B_PAGEWIDTH & upd->flags) { /* insert new number */ - gs_sprintf(cv,"%d",(int) + gs_snprintf(cv,sizeof(cv),"%d",(int) (720.0 * udev->width / udev->x_pixels_per_inch + 0.5)); ncv = strlen(cv); @@ -6897,7 +6898,7 @@ upd_open_wrtrtl(upd_device *udev) if(B_RESOLUTION & upd->flags) { /* insert new number */ - gs_sprintf(cv,"%d",(int) + gs_snprintf(cv,sizeof(cv),"%d",(int) ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ? udev->x_pixels_per_inch : udev->y_pixels_per_inch) +0.5)); @@ -6952,7 +6953,7 @@ It must hold: char tmp[16]; if(0 < upd->strings[S_YMOVE].size) { - gs_sprintf(tmp,"%d",upd->pheight); + gs_snprintf(tmp,sizeof(tmp),"%d",upd->pheight); ny = upd->strings[S_YMOVE].size + strlen(tmp); } else { ny = 1 + upd->string_a[SA_WRITECOMP].data[upd->ocomp-1].size; @@ -7013,14 +7014,14 @@ upd_wrtrtl(upd_p upd, gp_file *out) */ if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */ if(1 < upd->strings[S_YMOVE].size) { - gs_sprintf((char *)upd->outbuf+ioutbuf, + gs_snprintf((char *)upd->outbuf+ioutbuf, upd->noutbuf-ioutbuf, (const char *) upd->strings[S_YMOVE].data, upd->yscan - upd->yprinter); ioutbuf += strlen((char *)upd->outbuf+ioutbuf); } else { while(upd->yscan > upd->yprinter) { for(icomp = 0; icomp < upd->ocomp; ++icomp) { - gs_sprintf((char *)upd->outbuf+ioutbuf, + gs_snprintf((char *)upd->outbuf+ioutbuf, upd->noutbuf-ioutbuf, (const char *) upd->string_a[SA_WRITECOMP].data[icomp].data,0); ioutbuf += strlen((char *)upd->outbuf+ioutbuf); } diff --git a/devices/gdevwpr2.c b/devices/gdevwpr2.c index eeb94896..a8e812f6 100644 --- a/devices/gdevwpr2.c +++ b/devices/gdevwpr2.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 @@ -574,7 +574,7 @@ win_pr2_print_page(gx_device_printer * pdev, gp_file * file) } if (!wdev->nocancel) { - gs_sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1); + gs_snprintf(dlgtext, sizeof(dlgtext), "Printing page %d", (int)(pdev->PageCount) + 1); SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext); ShowWindow(wdev->hDlgModeless, SW_SHOW); } @@ -606,7 +606,7 @@ win_pr2_print_page(gx_device_printer * pdev, gp_file * file) if (!wdev->nocancel) { /* inform user of progress */ - gs_sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines)); + gs_snprintf(dlgtext, sizeof(dlgtext), "%d%% done", (int)(y * 100L / scan_lines)); SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext); } /* process message loop */ @@ -1080,11 +1080,11 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER); /* now find out what paper sizes are available */ - devcapsize = DeviceCapabilities(device, output, DC_PAPERSIZE, NULL, NULL); + devcapsize = DeviceCapabilities(podevmode->dmDeviceName, output, DC_PAPERSIZE, NULL, NULL); devcapsize *= sizeof(POINT); if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL) return FALSE; - n = DeviceCapabilities(device, output, DC_PAPERSIZE, devcap, NULL); + n = DeviceCapabilities(podevmode->dmDeviceName, output, DC_PAPERSIZE, devcap, NULL); paperwidth = (int)(wdev->MediaSize[0] * 254 / 72); paperheight = (int)(wdev->MediaSize[1] * 254 / 72); papername[0] = '\0'; @@ -1119,21 +1119,21 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc"); /* get the dmPaperSize */ - devcapsize = DeviceCapabilities(device, output, DC_PAPERS, NULL, NULL); + devcapsize = DeviceCapabilities(podevmode->dmDeviceName, output, DC_PAPERS, NULL, NULL); devcapsize *= sizeof(WORD); if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL) return FALSE; - n = DeviceCapabilities(device, output, DC_PAPERS, devcap, NULL); + n = DeviceCapabilities(podevmode->dmDeviceName, output, DC_PAPERS, devcap, NULL); if ((paperindex >= 0) && (paperindex < n)) papersize = ((WORD *) devcap)[paperindex]; gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc"); /* get the paper name */ - devcapsize = DeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL); + devcapsize = DeviceCapabilities(podevmode->dmDeviceName, output, DC_PAPERNAMES, NULL, NULL); devcapsize *= 64; if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL) return FALSE; - n = DeviceCapabilities(device, output, DC_PAPERNAMES, devcap, NULL); + n = DeviceCapabilities(podevmode->dmDeviceName, output, DC_PAPERNAMES, devcap, NULL); if ((paperindex >= 0) && (paperindex < n)) strcpy(papername, devcap + paperindex * 64); gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc"); @@ -1175,7 +1175,7 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) wdev->user_media_size[1] = paperheight / 254.0 * 72.0; } - if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) { + if (DeviceCapabilities(podevmode->dmDeviceName, output, DC_DUPLEX, NULL, NULL)) { wdev->Duplex_set = 1; } @@ -1186,7 +1186,7 @@ win_pr2_getdc(gx_device_win_pr2 * wdev) ClosePrinter(hprinter); /* now get a DC */ - wdev->hdcprn = CreateDC(driver, device, NULL, podevmode); + wdev->hdcprn = CreateDC(driver, podevmode->dmDeviceName, NULL, podevmode); if (wdev->win32_hdevmode == NULL) wdev->win32_hdevmode = GlobalAlloc(0, devmode_size); @@ -1505,9 +1505,9 @@ win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev, int mode) wdev->user_changed_settings = TRUE; if (wdev->use_old_spool_name) { - gs_sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset)); + gs_snprintf(wdev->fname, prn_fname_sizeof, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset)); } else { - gs_sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset)); + gs_snprintf(wdev->fname, prn_fname_sizeof, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset)); } if (mode == 3) { diff --git a/devices/gdevxini.c b/devices/gdevxini.c index 1944c9a9..fafcd42a 100644 --- a/devices/gdevxini.c +++ b/devices/gdevxini.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 @@ -88,7 +88,7 @@ gdev_x_open(gx_device_X * xdev) XSizeHints sizehints; char *window_id; XEvent event; - XVisualInfo xvinfo; + XVisualInfo xvinfo = { 0 }; int nitems; XtAppContext app_con; Widget toplevel; @@ -385,7 +385,7 @@ gdev_x_open(gx_device_X * xdev) char gstr[40]; int bitmask; - gs_sprintf(gstr, "%dx%d+%d+%d", sizehints.width, + gs_snprintf(gstr, sizeof(gstr), "%dx%d+%d+%d", sizehints.width, sizehints.height, sizehints.x, sizehints.y); bitmask = XWMGeometry(xdev->dpy, DefaultScreen(xdev->dpy), xdev->geometry, gstr, xdev->borderWidth, @@ -589,9 +589,9 @@ x_set_buffer(gx_device_X * xdev) * *But* if we run buffered, we have to use the real specs of the real x11 device. * Hence, the real color_info is saved into orig_color_info, and we use that here. */ - if (mdev == 0 || mdev->color_info.depth != xdev->orig_color_info.depth) { + if (mdev == 0 || mdev->color_info.depth != xdev->color_info.depth) { const gx_device_memory *mdproto = - gdev_mem_device_for_bits(xdev->orig_color_info.depth); + gdev_mem_device_for_bits(xdev->color_info.depth); if (!mdproto) { buffered = false; @@ -643,7 +643,7 @@ x_set_buffer(gx_device_X * xdev) rc_decrement(mdev->icc_struct, "x_set_buffer"); mdev->icc_struct = xdev->icc_struct; rc_increment(xdev->icc_struct); - mdev->color_info = xdev->orig_color_info; + mdev->color_info = xdev->color_info; mdev->base = xdev->buffer; gdev_mem_open_scan_lines(mdev, xdev->height); } @@ -762,6 +762,10 @@ static int x_initialize_device(gx_device *dev) { gx_device_X *xdev = (gx_device_X *) dev; + int code = gx_init_non_threadsafe_device(dev); + + if (code < 0) + return code; /* Mark the new instance as closed. */ xdev->is_open = false; @@ -984,7 +988,8 @@ gdev_x_close(gx_device_X *xdev) xdev->gc = NULL; } if (xdev->dpy && xdev->bpixmap != (Pixmap)0) { - XFreePixmap(xdev->dpy, xdev->bpixmap); + /* Only free the pixmap if we created it */ + if (xdev->ghostview == 0) XFreePixmap(xdev->dpy, xdev->bpixmap); xdev->bpixmap = (Pixmap)0; xdev->dest = (Pixmap)0; } diff --git a/devices/gxfcopy.c b/devices/gxfcopy.c index 72235693..76f0a19e 100644 --- a/devices/gxfcopy.c +++ b/devices/gxfcopy.c @@ -1735,6 +1735,10 @@ copy_font_cid0(gs_font *font, gs_font *copied) subdata->glyphs = cfdata->glyphs; subdata->glyphs_size = cfdata->glyphs_size; subdata->names = 0; + if (subdata->global_subrs.data != NULL) + gs_free_object(copied->memory, subdata->global_subrs.data, "copy parent global subrs to child, free child global subrs"); + if (subdata->global_subrs.starts != NULL) + gs_free_object(copied->memory, subdata->global_subrs.starts, "copy parent global subrs to child, free child global subrs"); subdata->global_subrs = cfdata->global_subrs; FDArray[i] = subcopy1; } @@ -2236,7 +2240,7 @@ gs_copy_font(gs_font *font, const gs_matrix *orig_matrix, gs_memory_t *mem, gs_f return code; } -/* We only need this because the ddescndant(s) share the parent +/* We only need this because the descendant(s) share the parent * CIDFont glyph space, so we can't free that if we are a descendant. */ static int gs_free_copied_descendant_font(gs_font *font) @@ -2257,6 +2261,13 @@ static int gs_free_copied_descendant_font(gs_font *font) gs_free_object(mem, cfdata->Encoding, "gs_free_copied_font(Encoding)"); gs_free_object(mem, cfdata->names, "gs_free_copied_font(names)"); gs_free_object(mem, cfdata->data, "gs_free_copied_font(data)"); + if (cfdata->subrs.data != NULL) + gs_free_object(mem, cfdata->subrs.data, "gs_free_copied_font(subrs->data)"); + if (cfdata->subrs.starts != NULL) + gs_free_object(mem, cfdata->subrs.starts, "gs_free_copied_font(subrs->starts)"); + /* global subrs are 'shared with the parent', see copy_font_cid0() + * so we don't want to free them here, they are freed by the parent font. + */ gs_free_object(mem, cfdata, "gs_free_copied_font(wrapper data)"); } gs_free_object(mem, font, "gs_free_copied_font(copied font)"); @@ -2295,6 +2306,10 @@ int gs_free_copied_font(gs_font *font) if (copied2->subst_CID_on_WMode) rc_decrement(copied2->subst_CID_on_WMode, "gs_free_copied_font(subst_CID_on_WMode"); + gs_free_string(mem, (byte *)copied2->cidata.common.CIDSystemInfo.Registry.data, copied2->cidata.common.CIDSystemInfo.Registry.size, "Free copied Registry"); + gs_free_string(mem, (byte *)copied2->cidata.common.CIDSystemInfo.Ordering.data, copied2->cidata.common.CIDSystemInfo.Ordering.size, "Free copied Registry"); + copied2->cidata.common.CIDSystemInfo.Registry.data = copied2->cidata.common.CIDSystemInfo.Ordering.data = NULL; + copied2->cidata.common.CIDSystemInfo.Registry.size = copied2->cidata.common.CIDSystemInfo.Ordering.size = 0; } if (cfdata) { diff --git a/devices/vector/gdevdocxw.c b/devices/vector/gdevdocxw.c index 54ab5be7..b637a4c8 100644 --- a/devices/vector/gdevdocxw.c +++ b/devices/vector/gdevdocxw.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 @@ -241,6 +241,12 @@ docxwrite_open_device(gx_device * dev) gs_parsed_file_name_t parsed; int code = 0; + if (tdev->extract) { + /* We can be called multiple times; nothing to do after the first time. + */ + return 0; + } + gx_device_fill_in_procs(dev); if (tdev->fname[0] == 0) return_error(gs_error_undefinedfilename); @@ -728,7 +734,8 @@ docx_update_text_state(docx_list_entry_t *ppts, font->font_name.size + 1, "txtwrite alloc font name"); if (!ppts->FontName) return gs_note_error(gs_error_VMerror); - memcpy(ppts->FontName, font->font_name.chars, font->font_name.size + 1); + memcpy(ppts->FontName, font->font_name.chars, font->font_name.size); + ppts->FontName[font->font_name.size] = 0; if (font->PaintType == 2 && penum->pgs->text_rendering_mode == 0) { @@ -980,7 +987,7 @@ docxwrite_process_plain_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte) ch = pte->text.data.chars[pte->index]; } else if (operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH)) { if (operation & TEXT_FROM_GLYPHS) { - gdata = pte->text.data.glyphs + (pte->index++ * sizeof (gs_glyph)); + gdata = pte->text.data.glyphs + pte->index++; } else { gdata = &pte->text.data.d_glyph; } @@ -1031,14 +1038,36 @@ docxwrite_process_plain_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte) return s_errno_to_gs(); } } + + /* Calculate glyph_width from the **original** glyph metrics, not the overriding + * advance width (if TEXT_REPLACE_WIDTHS is set below) + */ txt_char_widths_to_uts(pte->orig_font, &widths); /* convert design->text space */ + glyph_width = widths.real_width.xy.x * penum->text_state->size; + + if (pte->text.operation & TEXT_REPLACE_WIDTHS) + { + gs_point tpt; + + /* We are applying a width override, from x/y/xyshow. This could be from + * a PostScript file, or it could be from a PDF file where we have a font + * with a FontMatrix which is neither horizontal nor vertical. + */ + code = gs_text_replaced_width(&pte->text, pte->xy_index++, &tpt); + if (code < 0) + return_error(gs_error_unregistered); + + widths.Width.w = widths.real_width.w = tpt.x; + widths.Width.xy.x = widths.real_width.xy.x = tpt.x; + widths.Width.xy.y = widths.real_width.xy.y = tpt.y; + } + gs_distance_transform(widths.real_width.xy.x * penum->text_state->size, widths.real_width.xy.y * penum->text_state->size, &penum->text_state->matrix, &wanted); pte->returned.total_width.x += wanted.x; pte->returned.total_width.y += wanted.y; span_delta_x = widths.real_width.xy.x * penum->text_state->size; - glyph_width = widths.real_width.xy.x * penum->text_state->size; if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) { gs_point tpt; @@ -1061,7 +1090,7 @@ docxwrite_process_plain_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte) span_delta_x += dpt.x; - code = txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, ch, &chr2[0]); + (void) txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, ch, &chr2[0]); /* If a single text code returned multiple Unicode values, then we need to set the * 'extra' code points' widths to 0. */ diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c index 9ab562c7..cb268f62 100644 --- a/devices/vector/gdevpdf.c +++ b/devices/vector/gdevpdf.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 @@ -447,7 +447,7 @@ pdf_initialize_ids(gx_device_pdf * pdev) tms = *localtime(&t); #endif - gs_sprintf(buf, "(D:%04d%02d%02d%02d%02d%02d%c%02d\'%02d\')", + gs_snprintf(buf, sizeof(buf), "(D:%04d%02d%02d%02d%02d%02d%c%02d\'%02d\')", tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, tms.tm_hour, tms.tm_min, tms.tm_sec, timesign, timeoffset / 60, timeoffset % 60); @@ -1600,7 +1600,7 @@ static int write_xref_section(gx_device_pdf *pdev, gp_file *tfile, int64_t start * chances of needing to write white space to pad the file out. */ if (!pdev->Linearise) { - gs_sprintf(str, "%010"PRId64" 00000 n \n", pos); + gs_snprintf(str, sizeof(str), "%010"PRId64" 00000 n \n", pos); stream_puts(pdev->strm, str); } if (Offsets) @@ -1633,7 +1633,7 @@ rewrite_object(gx_device_pdf *const pdev, pdf_linearisation_t *linear_params, in code = gp_fread(&c, 1, 1, linear_params->sfile); read++; } while (c != '\n' && code > 0); - gs_sprintf(Scratch, "%d 0 obj\n", pdev->ResourceUsage[object].NewObjectNumber); + gs_snprintf(Scratch, ScratchSize, "%d 0 obj\n", pdev->ResourceUsage[object].NewObjectNumber); gp_fwrite(Scratch, strlen(Scratch), 1, linear_params->Lin_File.file); code = gp_fread(&c, 1, 1, linear_params->sfile); @@ -1685,7 +1685,7 @@ rewrite_object(gx_device_pdf *const pdev, pdf_linearisation_t *linear_params, in target++; (void)sscanf(target, "%d 0 R", &ID); gp_fwrite(source, target - source, 1, linear_params->Lin_File.file); - gs_sprintf(Buf, "%d 0 R", pdev->ResourceUsage[ID].NewObjectNumber); + gs_snprintf(Buf, sizeof(Buf), "%d 0 R", pdev->ResourceUsage[ID].NewObjectNumber); gp_fwrite(Buf, strlen(Buf), 1, linear_params->Lin_File.file); source = next; } else { @@ -1874,7 +1874,7 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params } #endif /* Linearisation. Part 1, file header */ - gs_sprintf(Header, "%%PDF-%d.%d\n", level / 10, level % 10); + gs_snprintf(Header, sizeof(Header), "%%PDF-%d.%d\n", level / 10, level % 10); gp_fwrite(Header, strlen(Header), 1, linear_params->Lin_File.file); if (pdev->binary_ok) gp_fwrite(Binary, strlen(Binary), 1, linear_params->Lin_File.file); @@ -1887,16 +1887,16 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params /* Linearisation. Part 2, the Linearisation dictioanry */ linear_params->LDictOffset = gp_ftell(linear_params->Lin_File.file); - gs_sprintf(LDict, "%d 0 obj\n<< \n", + gs_snprintf(LDict, sizeof(LDict), "%d 0 obj\n<< \n", LDictObj); gp_fwrite(LDict, strlen(LDict), 1, linear_params->Lin_File.file); /* First page cross-reference table here (Part 3) */ linear_params->FirstxrefOffset = gp_ftell(linear_params->Lin_File.file); - gs_sprintf(Header, "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */ + gs_snprintf(Header, sizeof(Header), "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */ gp_fwrite(Header, strlen(Header), 1, linear_params->Lin_File.file); - gs_sprintf(Header, "0000000000 00000 n \n"); + gs_snprintf(Header, sizeof(Header), "0000000000 00000 n \n"); for (i = LDictObj;i <= linear_params->LastResource + 2; i++) { gp_fwrite(Header, 20, 1, linear_params->Lin_File.file); @@ -1906,7 +1906,7 @@ 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_sprintf(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", + 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); @@ -2024,7 +2024,7 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params } } /* insert the primary hint stream */ - gs_sprintf(LDict, "%d 0 obj\n<</Length \n/S >>\nstream\n", HintStreamObj); + gs_snprintf(LDict, sizeof(LDict), "%d 0 obj\n<</Length \n/S >>\nstream\n", HintStreamObj); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); HintStreamStart = gp_ftell(linear_params->sfile); @@ -2338,7 +2338,7 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params flush_hint_stream(linear_params); HintLength = gp_ftell(linear_params->sfile) - HintStreamStart; - gs_sprintf(LDict, "\nendstream\nendobj\n"); + gs_snprintf(LDict, sizeof(LDict), "\nendstream\nendobj\n"); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); /* Calculate the length of the primary hint stream */ HintStreamLen = gp_ftell(linear_params->sfile) - pdev->ResourceUsage[HintStreamObj].LinearisedOffset; @@ -2371,23 +2371,23 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params /* Now the file is long enough, write the xref */ mainxref = gp_ftell(linear_params->sfile); - gs_sprintf(Header, "xref\n0 %d\n", LDictObj); + gs_snprintf(Header, sizeof(Header), "xref\n0 %d\n", LDictObj); gp_fwrite(Header, strlen(Header), 1, linear_params->sfile); linear_params->T = gp_ftell(linear_params->sfile) - 1; - gs_sprintf(Header, "0000000000 65535 f \n"); + gs_snprintf(Header, sizeof(Header), "0000000000 65535 f \n"); gp_fwrite(Header, strlen(Header), 1, linear_params->sfile); for (i = 1;i < LDictObj; i++) { for (j = 0; j < pdev->ResourceUsageSize;j++) { if (pdev->ResourceUsage[j].NewObjectNumber == i) { - gs_sprintf(Header, "%010"PRId64" 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset + HintStreamLen); + gs_snprintf(Header, sizeof(Header), "%010"PRId64" 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset + HintStreamLen); gp_fwrite(Header, 20, 1, linear_params->sfile); } } } - gs_sprintf(LDict, "trailer\n<</Size %d>>\nstartxref\n%"PRId64"\n%%%%EOF\n", + gs_snprintf(LDict, sizeof(LDict), "trailer\n<</Size %d>>\nstartxref\n%"PRId64"\n%%%%EOF\n", LDictObj, linear_params->FirstxrefOffset); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); @@ -2401,19 +2401,19 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params * versions. */ gp_fseek(linear_params->sfile, linear_params->LDictOffset, SEEK_SET); - gs_sprintf(LDict, "%d 0 obj\n<</Linearized 1/L %"PRId64"/H[ ", LDictObj, linear_params->FileLength); + gs_snprintf(LDict, sizeof(LDict), "%d 0 obj\n<</Linearized 1/L %"PRId64"/H[ ", LDictObj, linear_params->FileLength); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); - gs_sprintf(LDict, "%"PRId64"", pdev->ResourceUsage[HintStreamObj].LinearisedOffset); + gs_snprintf(LDict, sizeof(LDict), "%"PRId64"", pdev->ResourceUsage[HintStreamObj].LinearisedOffset); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); - gs_sprintf(LDict, " %"PRId64"]", HintStreamLen); + gs_snprintf(LDict, sizeof(LDict), " %"PRId64"]", HintStreamLen); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); /* Implementation Note 180 in hte PDF Reference 1.7 says that Acrobat * gets the 'E' value wrong. So its probably not important.... */ - gs_sprintf(LDict, "/O %d/E %"PRId64"",pdev->ResourceUsage[pdev->pages[0].Page->id].NewObjectNumber, linear_params->E); + gs_snprintf(LDict, sizeof(LDict), "/O %d/E %"PRId64"",pdev->ResourceUsage[pdev->pages[0].Page->id].NewObjectNumber, linear_params->E); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); - gs_sprintf(LDict, "/N %d/T %"PRId64">>\nendobj\n", pdev->next_page, linear_params->T); + gs_snprintf(LDict, sizeof(LDict), "/N %d/T %"PRId64">>\nendobj\n", pdev->next_page, linear_params->T); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); /* Return to the secondary xref and write it again filling @@ -2423,13 +2423,13 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params code = gs_error_ioerror; goto error; } - gs_sprintf(Header, "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */ + gs_snprintf(Header, sizeof(Header), "xref\n%d %d\n", LDictObj, Part1To6 - LDictObj + 1); /* +1 for the primary hint stream */ gp_fwrite(Header, strlen(Header), 1, linear_params->sfile); for (i = LDictObj;i <= linear_params->LastResource + 2; i++) { for (j = 0; j < pdev->ResourceUsageSize;j++) { if (pdev->ResourceUsage[j].NewObjectNumber == i) { - gs_sprintf(Header, "%010"PRId64" 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset); + gs_snprintf(Header, sizeof(Header), "%010"PRId64" 00000 n \n", pdev->ResourceUsage[j].LinearisedOffset); gp_fwrite(Header, 20, 1, linear_params->sfile); } } @@ -2442,7 +2442,7 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params if (code != 0) return_error(gs_error_ioerror); - gs_sprintf(LDict, "\ntrailer\n<</Size %ld/Info %d 0 R/Root %d 0 R/ID[%s%s]/Prev %"PRId64">>\nstartxref\r\n0\n%%%%EOF\n", + 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); @@ -2450,9 +2450,9 @@ static int pdf_linearise(gx_device_pdf *pdev, pdf_linearisation_t *linear_params if (code != 0) return_error(gs_error_ioerror); - gs_sprintf(LDict, "%d 0 obj\n<</Length %10"PRId64"", HintStreamObj, HintLength); + gs_snprintf(LDict, sizeof(LDict), "%d 0 obj\n<</Length %10"PRId64"", HintStreamObj, HintLength); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); - gs_sprintf(LDict, "\n/S %10"PRId64">>\nstream\n", SharedHintOffset); + gs_snprintf(LDict, sizeof(LDict), "\n/S %10"PRId64">>\nstream\n", SharedHintOffset); gp_fwrite(LDict, strlen(LDict), 1, linear_params->sfile); error: @@ -2648,11 +2648,21 @@ pdf_close(gx_device * dev) char str[256]; pdf_linearisation_t linear_params; bool file_per_page = false; + int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0); if (!dev->is_open) return_error(gs_error_undefined); dev->is_open = false; + if (pdev->sbstack_depth > bottom) { + emprintf(pdev->pdf_memory, "Error closing device; open substreams detected!\n"); + emprintf(pdev->pdf_memory, "Probably due to errors in the input. Output file is incorrect/invalid.\n"); + } + + while(pdev->sbstack_depth > bottom) + /* This is an error, and we are trying to recover, so ignore any further errors */ + (void)pdf_exit_substream(pdev); + if (pdev->initial_pattern_states != NULL) { int pdepth = 0; @@ -3093,12 +3103,12 @@ pdf_close(gx_device * dev) linear_params.xref = xref; if (pdev->FirstObjectNumber == 1) { - gs_sprintf(str, "xref\n0 %"PRId64"\n0000000000 65535 f \n", + gs_snprintf(str, sizeof(str), "xref\n0 %"PRId64"\n0000000000 65535 f \n", end_section); stream_puts(s, str); } else { - gs_sprintf(str, "xref\n0 1\n0000000000 65535 f \n%"PRId64" %"PRId64"\n", + gs_snprintf(str, sizeof(str), "xref\n0 1\n0000000000 65535 f \n%"PRId64" %"PRId64"\n", start_section, end_section - start_section); stream_puts(s, str); @@ -3107,7 +3117,7 @@ pdf_close(gx_device * dev) do { code = write_xref_section(pdev, tfile, start_section, end_section, resource_pos, linear_params.Offsets); if (code < 0) - return code; + goto error_cleanup; if (end_section >= pdev->next_id) break; @@ -3115,7 +3125,7 @@ pdf_close(gx_device * dev) end_section = find_end_xref_section(pdev, tfile, start_section, resource_pos); if (end_section < 0) return end_section; - gs_sprintf(str, "%"PRId64" %"PRId64"\n", start_section, end_section - start_section); + gs_snprintf(str, sizeof(str), "%"PRId64" %"PRId64"\n", start_section, end_section - start_section); stream_puts(s, str); } while (1); @@ -3134,7 +3144,7 @@ pdf_close(gx_device * dev) pprintld1(s, "/Encrypt %ld 0 R ", Encrypt_id); } stream_puts(s, ">>\n"); - gs_sprintf(xref_str, "startxref\n%"PRId64"\n%%%%EOF\n", xref); + gs_snprintf(xref_str, sizeof(xref_str), "startxref\n%"PRId64"\n%%%%EOF\n", xref); stream_puts(s, xref_str); } } @@ -3150,6 +3160,7 @@ pdf_close(gx_device * dev) gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->ResourceUsage, "Free linearisation resource usage records"); } +error_cleanup: /* Require special handling for Fonts, ColorSpace and Pattern resources * These are tracked in pdev->last_resource, and are complex structures which may * contain other memory allocations. All other resource types can be simply dicarded @@ -3501,6 +3512,15 @@ pdf_close(gx_device * dev) gs_free_object(mem, pdev->pages[i].Annots, "Free Annots dict"); } gs_free_object(mem, pdev->pages[i].Page, "Free Page object"); + pdev->pages[i].Page = NULL; + } + 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"); + gs_free_object(mem, pdev->pages[i].Page, "Free Page object"); + pdev->pages[i].Page = NULL; + } } } gs_free_object(mem, pdev->pages, "pages"); @@ -3562,6 +3582,8 @@ pdf_close(gx_device * dev) code = gs_error_ioerror; } + pdf_free_pdf_font_cache(pdev); + code1 = gdev_vector_close_file((gx_device_vector *) pdev); if (code >= 0) code = code1; @@ -3588,6 +3610,5 @@ pdf_close(gx_device * dev) code = gs_note_error(gs_error_ioerror); } - pdf_free_pdf_font_cache(pdev); return code; } diff --git a/devices/vector/gdevpdfb.h b/devices/vector/gdevpdfb.h index daa6ba0a..b85dffe3 100644 --- a/devices/vector/gdevpdfb.h +++ b/devices/vector/gdevpdfb.h @@ -184,6 +184,7 @@ const gx_device_pdf PDF_DEVICE_IDENT = {{0, 0}, {0, 0}}, /* Charproc BBox */ 0, /* charproc_just_accumulated */ 1, /* PS_accumulator */ + 0, /* Scaled_accumulator */ 0, /* accumulating_a_global_object */ 0, /* cgp */ 0, /* substituted_pattern_count */ diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c index c7cad3e5..ea40111b 100644 --- a/devices/vector/gdevpdfd.c +++ b/devices/vector/gdevpdfd.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 @@ -499,7 +499,7 @@ static int pdf_write_path(gx_device_pdf * pdev, gs_path_enum *cenum, gdev_vector buffering = 0; seg_index = -1; } - if (type & gx_path_type_optimize) { + if (type & gx_path_type_optimize && seg_index > 0) { if (segments[seg_index - 1].op == gs_pe_lineto) { if (segments[seg_index].vs[0].x == segments[seg_index - 1].vs[0].x && segments[seg_index].vs[0].x == line_start.x) { if (segments[seg_index - 1].vs[0].y > line_start.y && segments[seg_index].vs[0].y >= segments[seg_index - 1].vs[0].y) { diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c index e083ee11..ec011d8b 100644 --- a/devices/vector/gdevpdfe.c +++ b/devices/vector/gdevpdfe.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 @@ -209,7 +209,7 @@ pdf_xmp_time(char *buf, int buf_length) time(&t); tms = *localtime(&t); #endif - gs_sprintf(buf1, + gs_snprintf(buf1, sizeof(buf1), "%04d-%02d-%02d", tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday); strncpy(buf, buf1, buf_length); @@ -489,8 +489,11 @@ pdf_xmp_write_translated(gx_device_pdf *pdev, stream *s, const byte *data, int d /* Skip the Byte Order Mark (0xfe 0xff) */ buf0b = (short *)(buf0 + 2); code = gs_ConvertUTF16((unsigned char *)buf0b, j - 2, (unsigned char **)&buf1b, data_length * 2 * sizeof(unsigned char)); - if (code < 0) + if (code < 0) { + gs_free_object(pdev->memory, buf0, "pdf_xmp_write_translated"); + gs_free_object(pdev->memory, buf1, "pdf_xmp_write_translated"); return code; + } write(s, (const byte *)buf1, buf1b - buf1); gs_free_object(pdev->memory, buf1, "pdf_xmp_write_translated"); } @@ -881,7 +884,7 @@ pdf_document_metadata(gx_device_pdf *pdev) code = COS_WRITE_OBJECT(pres->object, pdev, resourceNone); if (code < 0) return code; - gs_sprintf(buf, "%ld 0 R", pres->object->id); + gs_snprintf(buf, sizeof(buf), "%ld 0 R", pres->object->id); pdf_record_usage(pdev, pres->object->id, resource_usage_part9_structure); code = cos_dict_put_c_key_object(pdev->Catalog, "/Metadata", pres->object); diff --git a/devices/vector/gdevpdfg.c b/devices/vector/gdevpdfg.c index 6feec8b0..d61712b0 100644 --- a/devices/vector/gdevpdfg.c +++ b/devices/vector/gdevpdfg.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 @@ -2083,7 +2083,7 @@ transfer_map_access_signed(const gs_data_source_t *psrc, static int pdf_write_transfer_map(gx_device_pdf *pdev, const gx_transfer_map *map, int range0, bool check_identity, - const char *key, char *ids) + const char *key, char *ids, int id_max) { gs_memory_t *mem = pdev->pdf_memory; gs_function_Sd_params_t params; @@ -2152,14 +2152,14 @@ pdf_write_transfer_map(gx_device_pdf *pdev, const gx_transfer_map *map, gs_function_free(pfn, false, mem); if (code < 0) return code; - gs_sprintf(ids, "%s%s%ld 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id); + gs_snprintf(ids, id_max, "%s%s%ld 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id); return 0; } static int pdf_write_transfer(gx_device_pdf *pdev, const gx_transfer_map *map, - const char *key, char *ids) + const char *key, char *ids, int id_max) { - return pdf_write_transfer_map(pdev, map, 0, true, key, ids); + return pdf_write_transfer_map(pdev, map, 0, true, key, ids, id_max); } /* ------ Halftones ------ */ @@ -2395,7 +2395,7 @@ pdf_write_spot_halftone(gx_device_pdf *pdev, const gs_spot_halftone *psht, if (pdev->CompatibilityLevel <= 1.7) { code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction", - trs); + trs, sizeof(trs)); if (code < 0) return code; } @@ -2515,7 +2515,7 @@ pdf_write_threshold_halftone(gx_device_pdf *pdev, memset(trs, 0x00, 17 + MAX_FN_CHARS + 1); if (pdev->CompatibilityLevel <= 1.7) { code = pdf_write_transfer(pdev, porder->transfer, "", - trs); + trs, sizeof(trs)); if (code < 0) return code; @@ -2549,7 +2549,7 @@ pdf_write_threshold2_halftone(gx_device_pdf *pdev, memset(trs, 0x00, 17 + MAX_FN_CHARS + 1); if (pdev->CompatibilityLevel <= 1.7) { code = pdf_write_transfer(pdev, porder->transfer, "", - trs); + trs, sizeof(trs)); if (code < 0) return code; @@ -2710,7 +2710,7 @@ pdf_write_multiple_halftone(gx_device_pdf *pdev, gs_gstate *pgs, */ static int pdf_update_halftone(gx_device_pdf *pdev, const gs_gstate *pgs, - char *hts) + char *hts, int hts_max) { const gs_halftone *pht = pgs->halftone; const gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT]; @@ -2748,7 +2748,7 @@ pdf_update_halftone(gx_device_pdf *pdev, const gs_gstate *pgs, } if (code < 0) return code; - gs_sprintf(hts, "%ld 0 R", id); + gs_snprintf(hts, hts_max, "%ld 0 R", id); pdev->halftone_id = pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id; return code; } @@ -2816,7 +2816,7 @@ pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres) */ static int pdf_update_transfer(gx_device_pdf *pdev, const gs_gstate *pgs, - char *trs) + char *trs, int trs_max) { int i, pi = -1; bool multiple = false, update = false; @@ -2842,7 +2842,7 @@ pdf_update_transfer(gx_device_pdf *pdev, const gs_gstate *pgs, int mask; if (!multiple) { - code = pdf_write_transfer(pdev, tm[pi], "", trs); + code = pdf_write_transfer(pdev, tm[pi], "", trs, trs_max); if (code < 0) return code; mask = code == 0; @@ -2851,9 +2851,10 @@ pdf_update_transfer(gx_device_pdf *pdev, const gs_gstate *pgs, mask = 0; for (i = 0; i < 4; ++i) if (tm[i] != NULL) { + int len = (int)strlen(trs); code = pdf_write_transfer_map(pdev, tm[i], - 0, true, " ", trs + strlen(trs)); + 0, true, " ", trs + len, trs_max - len); if (code < 0) return code; mask |= (code == 0) << i; @@ -2891,7 +2892,7 @@ pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs, } } else{ - gs_sprintf(buf, "%ld 0 R", pgs->soft_mask_id); + gs_snprintf(buf, sizeof(buf), "%ld 0 R", pgs->soft_mask_id); code = pdf_open_gstate(pdev, ppres); if (code < 0) return code; @@ -2941,6 +2942,9 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, int bottom; if (pdev->CompatibilityLevel >= 1.4) { + code = pdf_update_alpha(pdev, pgs, ppres, for_text); + if (code < 0) + return code; if (pdev->state.blend_mode != pgs->blend_mode) { static const char *const bm_names[] = { GS_BLEND_MODE_NAMES }; char buf[20]; @@ -2955,9 +2959,6 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, return code; pdev->state.blend_mode = pgs->blend_mode; } - code = pdf_update_alpha(pdev, pgs, ppres, for_text); - if (code < 0) - return code; } else { /* * If the graphics state calls for any transparency functions, @@ -2991,28 +2992,28 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, pdev->halftone_id != pgs->dev_ht[HT_OBJTYPE_DEFAULT]->id && !pdev->PDFX ) { - code = pdf_update_halftone(pdev, pgs, hts); + code = pdf_update_halftone(pdev, pgs, hts, sizeof(hts)); if (code < 0) return code; } if (pdev->params.TransferFunctionInfo != tfi_Remove && !pdev->PDFX && pdev->PDFA == 0 ) { - code = pdf_update_transfer(pdev, pgs, trs); + code = pdf_update_transfer(pdev, pgs, trs, sizeof(trs)); if (code < 0) return code; } if (pdev->params.UCRandBGInfo == ucrbg_Preserve) { if (pgs->black_generation && pdev->black_generation_id != pgs->black_generation->id) { code = pdf_write_transfer_map(pdev, pgs->black_generation, - 0, false, "", bgs); + 0, false, "", bgs, sizeof(bgs)); if (code < 0) return code; pdev->black_generation_id = pgs->black_generation->id; } if (pgs->undercolor_removal && pdev->undercolor_removal_id != pgs->undercolor_removal->id) { code = pdf_write_transfer_map(pdev, pgs->undercolor_removal, - -1, false, "", ucrs); + -1, false, "", ucrs, sizeof(ucrs)); if (code < 0) return code; pdev->undercolor_removal_id = pgs->undercolor_removal->id; @@ -3046,14 +3047,45 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, if (!pdev->PDFX) { gs_currentscreenphase(pgs, &phase, 0); gs_currentscreenphase(&pdev->state, &dev_phase, 0); + if ((dev_phase.x != phase.x || dev_phase.y != phase.y) && pdev->PDFA != 0) { + switch (pdev->PDFACompatibilityPolicy) { + case 0: + emprintf(pdev->memory, + "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, reverting to normal PDF output\n"); + pdev->AbortPDFAX = true; + pdev->PDFA = 0; + break; + case 1: + emprintf(pdev->memory, + "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, values not set\n\n"); + /* Deliberately breaking const here in order to force the graphics state overprint mode to be unchanged */ + dev_phase.x = phase.x; + dev_phase.y = phase.y; + break; + case 2: + emprintf(pdev->memory, + "\nSetting Halftone Phase or Halftone Offset\n not permitted in PDF/A, aborting conversion\n"); + return_error(gs_error_undefined); + break; + default: + emprintf(pdev->memory, + "\nSetting Overprint Mode to 1\n not permitted in PDF/A, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n"); + pdev->AbortPDFAX = true; + pdev->PDFA = 0; + break; + } + } if (dev_phase.x != phase.x || dev_phase.y != phase.y) { char buf[sizeof(int) * 3 + 5]; code = pdf_open_gstate(pdev, ppres); if (code < 0) return code; - gs_sprintf(buf, "[%d %d]", phase.x, phase.y); - code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTP", buf); + gs_snprintf(buf, sizeof(buf), "[%d %d]", phase.x, phase.y); + if (pdev->CompatibilityLevel >= 1.999) + code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTO", buf); + else + code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTP", buf); if (code < 0) return code; gx_gstate_setscreenphase(&pdev->state, phase.x, phase.y, diff --git a/devices/vector/gdevpdfi.c b/devices/vector/gdevpdfi.c index 82e8f7a2..1e1a9daa 100644 --- a/devices/vector/gdevpdfi.c +++ b/devices/vector/gdevpdfi.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 @@ -1923,7 +1923,7 @@ pdf_end_and_do_image(gx_device_pdf *pdev, pdf_image_writer *piw, if (pdev->image_mask_id != gs_no_id) { char buf[20]; - gs_sprintf(buf, "%ld 0 R", pdev->image_mask_id); + gs_snprintf(buf, sizeof(buf), "%ld 0 R", pdev->image_mask_id); code = cos_dict_put_string_copy((cos_dict_t *)pres->object, pdev->image_mask_is_SMask ? "/SMask" : "/Mask", buf); (*(pres->object)).md5_valid = 0; @@ -2372,6 +2372,8 @@ static int reset_gstate_for_pattern(gx_device_pdf * pdev, gs_gstate *destination source->line_params.dot_length_absolute = pdev->vg_initial.line_params.dot_length_absolute; destination->line_params.dot_orientation = source->line_params.dot_orientation; source->line_params.dot_orientation = pdev->vg_initial.line_params.dot_orientation; + if (destination->line_params.dash.pattern != NULL && destination->line_params.dash.pattern != source->line_params.dash.pattern) + gs_free_object(destination->memory, destination->line_params.dash.pattern, "free dash assigned during pattern accumulation"); memcpy(&destination->line_params.dash, &source->line_params.dash, sizeof(source->line_params.dash)); memcpy(&source->line_params.dash, &pdev->vg_initial.line_params.dash, sizeof(source->line_params.dash)); } diff --git a/devices/vector/gdevpdfm.c b/devices/vector/gdevpdfm.c index 902c17ac..f6b6c51f 100644 --- a/devices/vector/gdevpdfm.c +++ b/devices/vector/gdevpdfm.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 @@ -171,12 +171,12 @@ pdfmark_make_dest(char dstr[MAX_DEST_STRING], gx_device_pdf * pdev, else if (pdfmark_find_key("/Action", pairs, count, &action) && pdf_key_eq(&action, "/GoToR") ) - gs_sprintf(dstr, "[%d ", page - 1); + gs_snprintf(dstr, MAX_DEST_STRING, "[%d ", page - 1); else { code = update_max_page_reference(pdev, &page); if (code < 0) return code; - gs_sprintf(dstr, "[%ld 0 R ", pdf_page_id(pdev, page)); + gs_snprintf(dstr, MAX_DEST_STRING, "[%ld 0 R ", pdf_page_id(pdev, page)); } len = strlen(dstr); if (len + view_string.size > MAX_DEST_STRING) @@ -912,7 +912,7 @@ pdfmark_put_ao_pairs(gx_device_pdf * pdev, cos_dict_t *pcd, char dstr[1 + (sizeof(long) * 8 / 3 + 1) + 25 + 1]; long page_id = pdf_page_id(pdev, pdev->next_page + 1); - gs_sprintf(dstr, "[%ld 0 R /XYZ null null null]", page_id); + gs_snprintf(dstr, MAX_DEST_STRING, "[%ld 0 R /XYZ null null null]", page_id); cos_dict_put_c_key_string(pcd, "/Dest", (const unsigned char*) dstr, strlen(dstr)); } @@ -1769,7 +1769,7 @@ pdfmark_PS(gx_device_pdf * pdev, gs_param_string * pairs, uint count, if (level1_id != gs_no_id) { char r[MAX_DEST_STRING]; - gs_sprintf(r, "%ld 0 R", level1_id); + gs_snprintf(r, sizeof(r), "%ld 0 R", level1_id); code = cos_dict_put_c_key_string(cos_stream_dict(pcs), "/Level1", (byte *)r, strlen(r)); if (code < 0) @@ -1933,7 +1933,7 @@ pdfmark_PAGELABEL(gx_device_pdf * pdev, gs_param_string * pairs, uint count, return 0; } -static int is_XMP_Key(gs_param_string *param) +static int is_XMP_Key(const gs_param_string *param) { if (pdf_key_eq(param, "/Title")) return 1; @@ -2450,7 +2450,23 @@ static int pdfmark_MP(gx_device_pdf *pdev, gs_param_string *pairs, uint count, const gs_matrix *pctm, const gs_param_string *objname) { - return 0; /****** NOT IMPLEMENTED YET ******/ + int code; + char *tag; + + if (count != 1) return_error(gs_error_rangecheck); + + tag = (char *)gs_alloc_bytes(pdev->memory, (pairs[0].size + 1) * sizeof(unsigned char), + "pdfmark_MP"); + memcpy(tag, pairs[0].data, pairs[0].size); + tag[pairs[0].size] = 0x00; + + code = pdf_open_contents(pdev, PDF_IN_STREAM); + if (code < 0) return code; + + pprints1(pdev->strm, "%s MP\n", tag); + + gs_free_object(pdev->memory, tag, "pdfmark_MP"); + return 0; } /* [ tag propdict /DP pdfmark */ @@ -2458,7 +2474,87 @@ static int pdfmark_DP(gx_device_pdf *pdev, gs_param_string *pairs, uint count, const gs_matrix *pctm, const gs_param_string *objname) { - return 0; /****** NOT IMPLEMENTED YET ******/ + int code; + cos_object_t *pco; + char *cstring; + pdf_resource_t *pres; + + if (count != 2) return_error(gs_error_rangecheck); + + /* check tag for /Name object syntax */ + if ((pairs[0].data)[0] != '/') return_error(gs_error_rangecheck); + + /* check propdict for {object name} syntax */ + if (pdf_objname_is_valid(pairs[1].data, pairs[1].size)) + { + code = pdf_refer_named(pdev, &pairs[1], &pco); + if(code < 0) return code; + } + else /* << inline prop dict >> */ + { + /* strip << and >> */ + if ((pairs[1].data)[0]=='<'&&(pairs[1].data)[1]=='<') + { + int ix = 0; + byte *p = (byte *)pairs[1].data; + + /* Fortunately we don't use the 'size' when freeing the memory + * so we can quickly copy the string content up two places and reduce + * the size by 2 to remove the '<<'. This saves an alloc and free of the + * string data. + */ + for (ix = 0; ix < pairs[1].size - 2;ix++) + p[ix] = pairs[1].data[ix + 2]; + pairs[1].size-=2; + } + else + return_error(gs_error_rangecheck); + + if ((pairs[1].data)[pairs[1].size-1]=='>'&&(pairs[1].data)[pairs[1].size-2]=='>') + pairs[1].size-=2; + + /* convert inline propdict to C string with object names replaced by refs */ + code = pdf_replace_names(pdev, &pairs[1], &pairs[1]); + if (code<0) return code; + cstring = (char *)gs_alloc_bytes(pdev->memory, (pairs[1].size + 1) * sizeof(unsigned char), + "pdfmark_DP"); + memcpy(cstring, pairs[1].data, pairs[1].size); + cstring[pairs[1].size] = 0x00; + + code = pdf_make_named_dict(pdev, NULL, (cos_dict_t**) &pco, true); + if (code<0) return code; + + /* copy inline propdict to new object */ + code = cos_dict_put_c_strings((cos_dict_t*) pco, cstring, ""); + if(code < 0) return code; + COS_WRITE_OBJECT(pco, pdev, resourceProperties); + COS_RELEASE(pco, "pdfmark_DP"); + gs_free_object(pdev->memory, cstring, "pdfmark_DP"); + } + + pres = pdf_find_resource_by_resource_id(pdev, resourceProperties, pco->id); + if (pres==0){ + if ((code = pdf_alloc_resource(pdev, resourceProperties, pco->id, &(pco->pres), pco->id))<0) + return code; + } + + cstring = (char *)gs_alloc_bytes(pdev->memory, (pairs[0].size + 1) * sizeof(unsigned char), + "pdfmark_DP"); + memcpy(cstring, pairs[0].data, pairs[0].size); + cstring[pairs[0].size] = 0x00; + + /* make sure we write to the correct stream */ + code = pdf_open_contents(pdev, PDF_IN_STREAM); + if (code < 0) return code; + + pprints1(pdev->strm, "%s", cstring); /* write tag */ + pprintld1(pdev->strm, "/R%ld DP\n", pco->id); + pco->pres->where_used |= pdev->used_mask; + if ((code = pdf_add_resource(pdev, pdev->substream_Resources, "/Properties", pco->pres))<0) + return code; + + gs_free_object(pdev->memory, cstring, "pdfmark_DP"); + return 0; } /* [ tag /BMC pdfmark */ diff --git a/devices/vector/gdevpdfo.c b/devices/vector/gdevpdfo.c index a1c18012..3ec00f5e 100644 --- a/devices/vector/gdevpdfo.c +++ b/devices/vector/gdevpdfo.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 @@ -701,7 +701,7 @@ cos_array_add_int(cos_array_t *pca, int i) char str[sizeof(int) * 8 / 3 + 3]; /* sign, rounding, 0 terminator */ cos_value_t v; - gs_sprintf(str, "%d", i); + gs_snprintf(str, sizeof(str), "%d", i); return cos_array_add(pca, cos_string_value(&v, (byte *)str, strlen(str))); } int @@ -1380,7 +1380,7 @@ cos_dict_put_c_key_int(cos_dict_t *pcd, const char *key, int value) { char str[sizeof(int) * 8 / 3 + 3]; /* sign, rounding, 0 terminator */ - gs_sprintf(str, "%d", value); + gs_snprintf(str, sizeof(str), "%d", value); return cos_dict_put_c_key_string(pcd, key, (byte *)str, strlen(str)); } int diff --git a/devices/vector/gdevpdfr.c b/devices/vector/gdevpdfr.c index 7aca15a6..fd641aef 100644 --- a/devices/vector/gdevpdfr.c +++ b/devices/vector/gdevpdfr.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 @@ -140,7 +140,7 @@ pdf_refer_named(gx_device_pdf * pdev, const gs_param_string * pname_orig, } if (page_number <= 0) return code; - gs_sprintf(page_name_chars, "{Page%d}", page_number); + gs_snprintf(page_name_chars, sizeof(page_name_chars), "{Page%d}", page_number); param_string_from_string(pnstr, page_name_chars); pname = &pnstr; code = pdf_find_named(pdev, pname, ppco); @@ -470,7 +470,7 @@ pdf_replace_names(gx_device_pdf * pdev, const gs_param_string * from, size += sname - scan; if (pco) { - gs_sprintf(ref, " %ld 0 R ", pco->id); + gs_snprintf(ref, sizeof(ref), " %ld 0 R ", pco->id); size += strlen(ref); /* Special 'name' escaping convention (see gs_pdfwr.ps, /.pdf===dict * the /nametype procedure). We do not want to write out the NULL @@ -509,7 +509,7 @@ pdf_replace_names(gx_device_pdf * pdev, const gs_param_string * from, memcpy(sto, scan, copy); sto += copy; if (pco) { - gs_sprintf(ref, " %ld 0 R ", pco->id); + gs_snprintf(ref, sizeof(ref), " %ld 0 R ", pco->id); rlen = strlen(ref); if (sname >= (start + 2) && sname[-1] == 0x00 && sname[-2] == 0x00 && next[0] == 0x00) { sto -= 2; diff --git a/devices/vector/gdevpdft.c b/devices/vector/gdevpdft.c index 5b8af68d..72f082f9 100644 --- a/devices/vector/gdevpdft.c +++ b/devices/vector/gdevpdft.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 @@ -63,7 +63,7 @@ pdf_make_soft_mask_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * ppa code = pdf_write_function(pdev, pparams->transfer_function, &id); if (code < 0) return code; - gs_sprintf(buf, " %ld 0 R", id); + gs_snprintf(buf, sizeof(buf), " %ld 0 R", id); code = cos_dict_put_c_key_string(soft_mask_dict, "/TR", (const byte *)buf, strlen(buf)); if (code < 0) return code; @@ -365,7 +365,7 @@ pdf_end_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev, return 0; /* We need to update the 'where_used' field, in case we substituted a resource */ pres->where_used |= pdev->used_mask; - gs_sprintf(buf, "%ld 0 R", pdf_resource_id(pres)); + gs_snprintf(buf, sizeof(buf), "%ld 0 R", pdf_resource_id(pres)); if (pdev->pres_soft_mask_dict == 0L) { /* something went horribly wrong, we have an 'end' wihtout a matching 'begin' * Give up, throw an error. diff --git a/devices/vector/gdevpdfu.c b/devices/vector/gdevpdfu.c index ec4a8165..f12fa38e 100644 --- a/devices/vector/gdevpdfu.c +++ b/devices/vector/gdevpdfu.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 @@ -335,14 +335,14 @@ static int write_tt_encodings(stream *s, bool HaveTrueTypes) char Buffer[256]; single_glyph_list_t *entry = SingleGlyphList; - gs_sprintf(Buffer, "/AdobeGlyphList mark\n"); + gs_snprintf(Buffer, sizeof(Buffer), "/AdobeGlyphList mark\n"); stream_write(s, Buffer, strlen(Buffer)); while (entry->Glyph) { - gs_sprintf(Buffer, "/%s 16#%04x\n", entry->Glyph, entry->Unicode); + gs_snprintf(Buffer, sizeof(Buffer), "/%s 16#%04x\n", entry->Glyph, entry->Unicode); stream_write(s, Buffer, strlen(Buffer)); entry++; }; - gs_sprintf(Buffer, ".dicttomark readonly def\n"); + gs_snprintf(Buffer, sizeof(Buffer), ".dicttomark readonly def\n"); stream_write(s, Buffer, strlen(Buffer)); index = 0; @@ -523,29 +523,29 @@ int ps2write_dsc_header(gx_device_pdf * pdev, int pages) } } if (!pdev->Eps2Write || pdev->BBox.p.x > pdev->BBox.q.x || pdev->BBox.p.y > pdev->BBox.q.y) - gs_sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\n", (int)urx, (int)ury); + gs_snprintf(BBox, sizeof(BBox), "%%%%BoundingBox: 0 0 %d %d\n", (int)urx, (int)ury); else - gs_sprintf(BBox, "%%%%BoundingBox: %d %d %d %d\n", (int)floor(pdev->BBox.p.x), (int)floor(pdev->BBox.p.y), (int)ceil(pdev->BBox.q.x), (int)ceil(pdev->BBox.q.y)); + gs_snprintf(BBox, sizeof(BBox), "%%%%BoundingBox: %d %d %d %d\n", (int)floor(pdev->BBox.p.x), (int)floor(pdev->BBox.p.y), (int)ceil(pdev->BBox.q.x), (int)ceil(pdev->BBox.q.y)); stream_write(s, (byte *)BBox, strlen(BBox)); if (!pdev->Eps2Write || pdev->BBox.p.x > pdev->BBox.q.x || pdev->BBox.p.y > pdev->BBox.q.y) - gs_sprintf(BBox, "%%%%HiResBoundingBox: 0 0 %.2f %.2f\n", urx, ury); + gs_snprintf(BBox, sizeof(BBox), "%%%%HiResBoundingBox: 0 0 %.2f %.2f\n", urx, ury); else - gs_sprintf(BBox, "%%%%HiResBoundingBox: %.2f %.2f %.2f %.2f\n", pdev->BBox.p.x, pdev->BBox.p.y, pdev->BBox.q.x, pdev->BBox.q.y); + gs_snprintf(BBox, sizeof(BBox), "%%%%HiResBoundingBox: %.2f %.2f %.2f %.2f\n", pdev->BBox.p.x, pdev->BBox.p.y, pdev->BBox.q.x, pdev->BBox.q.y); stream_write(s, (byte *)BBox, strlen(BBox)); } cre_date_time_len = pdf_get_docinfo_item(pdev, "/CreationDate", cre_date_time, sizeof(cre_date_time) - 1); cre_date_time[cre_date_time_len] = 0; - gs_sprintf(BBox, "%%%%Creator: %s %d (%s)\n", gs_product, (int)gs_revision, + gs_snprintf(BBox, sizeof(BBox), "%%%%Creator: %s %d (%s)\n", gs_product, (int)gs_revision, pdev->dname); stream_write(s, (byte *)BBox, strlen(BBox)); stream_puts(s, "%%LanguageLevel: 2\n"); - gs_sprintf(BBox, "%%%%CreationDate: %s\n", cre_date_time); + gs_snprintf(BBox, sizeof(BBox), "%%%%CreationDate: %s\n", cre_date_time); stream_write(s, (byte *)BBox, strlen(BBox)); - gs_sprintf(BBox, "%%%%Pages: %d\n", pages); + gs_snprintf(BBox, sizeof(BBox), "%%%%Pages: %d\n", pages); stream_write(s, (byte *)BBox, strlen(BBox)); - gs_sprintf(BBox, "%%%%EndComments\n"); + gs_snprintf(BBox, sizeof(BBox), "%%%%EndComments\n"); stream_write(s, (byte *)BBox, strlen(BBox)); - gs_sprintf(BBox, "%%%%BeginProlog\n"); + gs_snprintf(BBox, sizeof(BBox), "%%%%BeginProlog\n"); stream_write(s, (byte *)BBox, strlen(BBox)); if (pdev->params.CompressPages) { /* When CompressEntireFile is true and ASCII85EncodePages is false, @@ -605,7 +605,7 @@ pdfwrite_pdf_open_document(gx_device_pdf * pdev) pdev->CompressEntireFile = 0; else { stream_write(s, (byte *)"%!\r", 3); - gs_sprintf(BBox, "%%%%BoundingBox: 0 0 %d %d\n", width, height); + gs_snprintf(BBox, sizeof(BBox), "%%%%BoundingBox: 0 0 %d %d\n", width, height); stream_write(s, (byte *)BBox, strlen(BBox)); if (pdev->params.CompressPages || pdev->CompressEntireFile) { /* When CompressEntireFile is true and ASCII85EncodePages is false, @@ -1544,7 +1544,7 @@ void pdf_reserve_object_id(gx_device_pdf * pdev, pdf_resource_t *pres, long id) { pres->object->id = (id == 0 ? pdf_obj_ref(pdev) : id); - gs_sprintf(pres->rname, "R%ld", pres->object->id); + gs_snprintf(pres->rname, sizeof(pres->rname), "R%ld", pres->object->id); } /* Begin an aside (resource, annotation, ...). */ @@ -2006,7 +2006,7 @@ pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER]) int minor = (int)(gs_revision - (major * 1000)) / 10; int patch = gs_revision % 10; - gs_sprintf(buf, "(%s %d.%02d.%d)", gs_product, major, minor, patch); + gs_snprintf(buf, PDF_MAX_PRODUCER, "(%s %d.%02d.%d)", gs_product, major, minor, patch); } /* Write matrix values. */ @@ -2053,7 +2053,7 @@ pdf_put_name_chars_1_2(stream *s, const byte *nstr, uint size) case '[': case ']': case '{': case '}': case '/': - gs_sprintf(hex, "#%02x", c); + gs_snprintf(hex, sizeof(hex), "#%02x", c); stream_puts(s, hex); break; case 0: diff --git a/devices/vector/gdevpdfv.c b/devices/vector/gdevpdfv.c index 0159169c..8a44dcce 100644 --- a/devices/vector/gdevpdfv.c +++ b/devices/vector/gdevpdfv.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 @@ -157,7 +157,7 @@ pdf_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc, if (pcd_XObject == 0) return_error(gs_error_VMerror); - gs_sprintf(key, "/R%ld", pcs_image->id); + gs_snprintf(key, sizeof(key), "/R%ld", pcs_image->id); /* This is non-obvious code. Previously we would put the image object (pcs_image) * into the Resources dit. When we come to write out the Resources dict * that code writes a reference (index 0 R) using the ID from the object. @@ -203,7 +203,7 @@ pdf_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc, { char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */ - gs_sprintf(buf, "/R%ld Do\n", pcs_image->id); + gs_snprintf(buf, sizeof(buf), "/R%ld Do\n", pcs_image->id); cos_stream_add_bytes(pdev, pcos, (const byte *)buf, strlen(buf)); } @@ -231,6 +231,14 @@ pdf_store_pattern1_params(gx_device_pdf *pdev, pdf_resource_t *pres, bbox[1] = t->BBox.p.y; bbox[2] = t->BBox.q.x; bbox[3] = t->BBox.q.y; + if (pdev->accumulating_charproc) { + /* Assume here we can only be installing a pattern while acumulating a + * charproc if the font is a coloured type 3 font. In this case we will + * have set the CTM to be the identity scaled by 100 (!). See gdevpdtt.c + * install_PS_charproc_accumulator() for details. + */ + gs_make_identity(&smat2); + } /* The graphics library assumes a shifted origin to provide positive bitmap pixel indices. Compensate it now. */ smat2.tx += pinst->step_matrix.tx; @@ -242,7 +250,7 @@ pdf_store_pattern1_params(gx_device_pdf *pdev, pdf_resource_t *pres, * form is nested inside a form, the default space is the space of the * first form, and therefore we do *not* remove the resolution scaling. */ - if (pdev->FormDepth == 0 || (pdev->FormDepth > 0 && pdev->PatternsSinceForm > 0)) { + if ((pdev->FormDepth == 0 || (pdev->FormDepth > 0 && pdev->PatternsSinceForm > 0)) && !pdev->accumulating_charproc) { gs_matrix scaled; gs_make_scaling(1 / scale_x, 1 / scale_y, &scaled); @@ -614,7 +622,7 @@ pdf_put_linear_shading(gx_device_pdf *pdev, cos_dict_t *pscd, const float *Coord if (Extend[0] | Extend[1]) { char extend_str[1 + 5 + 1 + 5 + 1 + 1]; /* [bool bool] */ - gs_sprintf(extend_str, "[%s %s]", + gs_snprintf(extend_str, sizeof(extend_str), "[%s %s]", (Extend[0] ? "true" : "false"), (Extend[1] ? "true" : "false")); code = cos_dict_put_c_key_string(pscd, "/Extend", diff --git a/devices/vector/gdevpdfx.h b/devices/vector/gdevpdfx.h index d5dfd756..774a5156 100644 --- a/devices/vector/gdevpdfx.h +++ b/devices/vector/gdevpdfx.h @@ -856,6 +856,7 @@ struct gx_device_pdf_s { Used only with uncached charprocs. */ bool PS_accumulator; /* A flag to determine whether a given accumulator is for a PostScript type 3 font or not. */ + bool Scaled_accumulator; /* We scale teh CTM when accumulating type 3 fonts */ bool accumulating_a_global_object; /* ps2write only. Accumulating a global object (such as a named Form, so that resources used in it must also be global. diff --git a/devices/vector/gdevpdtb.c b/devices/vector/gdevpdtb.c index 42ef43e4..5c8fb8d8 100644 --- a/devices/vector/gdevpdtb.c +++ b/devices/vector/gdevpdtb.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 @@ -371,7 +371,7 @@ pdf_base_font_alloc(gx_device_pdf *pdev, pdf_base_font_t **ppbfont, font_name.size -= SUBSET_PREFIX_SIZE; } } else { - gs_sprintf(fnbuf, ".F" PRI_INTPTR, (intptr_t)copied); + gs_snprintf(fnbuf, sizeof(fnbuf), ".F" PRI_INTPTR, (intptr_t)copied); font_name.data = (byte *)fnbuf; font_name.size = strlen(fnbuf); } @@ -572,7 +572,7 @@ pdf_adjust_font_name(gx_device_pdf *pdev, long id, pdf_base_font_t *pbfont) size = i + 1; } /* Create a unique name. */ - gs_sprintf(suffix, "%c%lx", SUFFIX_CHAR, id); + gs_snprintf(suffix, sizeof(suffix), "%c%lx", SUFFIX_CHAR, id); suffix_size = strlen(suffix); data = gs_resize_string(pdev->pdf_memory, chars, size, size + suffix_size, diff --git a/devices/vector/gdevpdtc.c b/devices/vector/gdevpdtc.c index 81d66dd5..7ad7dec4 100644 --- a/devices/vector/gdevpdtc.c +++ b/devices/vector/gdevpdtc.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 @@ -341,31 +341,52 @@ attach_cmap_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, } } if (pcmres || is_identity) { - uint size = pcmap->CMapName.size; - byte *chars = gs_alloc_string(pdev->pdf_memory, size, - "pdf_font_resource_t(CMapName)"); - - if (chars == 0) - return_error(gs_error_VMerror); - memcpy(chars, pcmap->CMapName.data, size); + if (pdfont->u.type0.CMapName_data == NULL || pcmap->CMapName.size != pdfont->u.type0.CMapName_size || + memcmp(pdfont->u.type0.CMapName_data, pcmap->CMapName.data, pcmap->CMapName.size)) + { + byte *chars = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, pcmap->CMapName.size, + "pdf_font_resource_t(CMapName)"); + + if (chars == 0) + return_error(gs_error_VMerror); + memcpy(chars, pcmap->CMapName.data, pcmap->CMapName.size); + if (pdfont->u.type0.CMapName_data != NULL) + gs_free_object(pdev->pdf_memory->non_gc_memory, pdfont->u.type0.CMapName_data, "rewriting CMapName"); + pdfont->u.type0.CMapName_data = chars; + pdfont->u.type0.CMapName_size = pcmap->CMapName.size; + } if (is_identity) strcpy(pdfont->u.type0.Encoding_name, (pcmap->WMode ? "/Identity-V" : "/Identity-H")); else - gs_sprintf(pdfont->u.type0.Encoding_name, "%ld 0 R", - pdf_resource_id(pcmres)); - pdfont->u.type0.CMapName.data = chars; - pdfont->u.type0.CMapName.size = size; + gs_snprintf(pdfont->u.type0.Encoding_name, sizeof(pdfont->u.type0.Encoding_name), + "%ld 0 R", pdf_resource_id(pcmres)); } else { + uint size = 0; + if (!*pcmn) /* Should not be possible, if *pcmn is NULL then either * is_identity is true or we create pcmres. */ return_error(gs_error_invalidfont); - gs_sprintf(pdfont->u.type0.Encoding_name, "/%s", *pcmn); - pdfont->u.type0.CMapName.data = (const byte *)*pcmn; - pdfont->u.type0.CMapName.size = strlen(*pcmn); + size = strlen(*pcmn); + if (pdfont->u.type0.CMapName_data == NULL || size != pdfont->u.type0.CMapName_size || + memcmp(pdfont->u.type0.CMapName_data, *pcmn, size) != 0) + { + byte *chars = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, size, "pdf_font_resource_t(CMapName)"); + if (chars == 0) + return_error(gs_error_VMerror); + + memcpy(chars, *pcmn, size); + + if (pdfont->u.type0.CMapName_data != NULL) + gs_free_object(pdev->pdf_memory->non_gc_memory, pdfont->u.type0.CMapName_data, "rewriting CMapName"); + pdfont->u.type0.CMapName_data = chars; + pdfont->u.type0.CMapName_size = size; + } + + gs_snprintf(pdfont->u.type0.Encoding_name, sizeof(pdfont->u.type0.Encoding_name), "/%s", *pcmn); pdfont->u.type0.cmap_is_standard = true; } pdfont->u.type0.WMode = pcmap->WMode; diff --git a/devices/vector/gdevpdte.c b/devices/vector/gdevpdte.c index 592205fd..5e50d2cf 100644 --- a/devices/vector/gdevpdte.c +++ b/devices/vector/gdevpdte.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 @@ -485,14 +485,14 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_ : *gdata); if (glyph == GS_NO_GLYPH || glyph == pet->glyph) { if((pdfont->cmap_ToUnicode == NULL || !gs_cmap_ToUnicode_check_pair(pdfont->cmap_ToUnicode, ch)) && pdev->UseOCR != UseOCRNever) - (void)pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr); + (void)pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, NULL); return 0; } if (pet->glyph != GS_NO_GLYPH) { /* encoding conflict */ return_error(gs_error_rangecheck); /* Must not happen because pdf_obtain_font_resource - * checks for encoding compatibility. - */ + * checks for encoding compatibility. + */ } code = font->procs.glyph_name(font, glyph, &gnstr); if (code < 0) @@ -547,13 +547,13 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_ /* PS font has no such glyph. */ if (bytes_compare(gnstr.data, gnstr.size, (const byte *)".notdef", 7)) { pet->glyph = glyph; - pet->str = gnstr; + pdf_copy_string_to_encoding(pdev, &gnstr, pet); pet->is_difference = true; } } else if (pdfont->base_font == NULL && ccfont != NULL && (gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1 || gs_copied_font_add_encoding((gs_font *)ccfont, ch, glyph) < 0)) { - /* + /* * The "complete" copy of the font appears incomplete * due to incrementally added glyphs. Drop the "complete" * copy now and continue with subset font only. @@ -566,7 +566,7 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_ * We also check whether the encoding is compatible. * It must be compatible here due to the pdf_obtain_font_resource * and ccfont logics, but we want to ensure for safety reason. - */ + */ ccfont = NULL; pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor); } @@ -584,16 +584,15 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_ pdfont->used[ch >> 3] |= 0x80 >> (ch & 7); } /* - * We always generate ToUnicode for simple fonts, because - * we can't detemine in advance, which glyphs the font actually uses. - * The decision about writing it out is deferred until pdf_write_font_resource. - */ + * We always generate ToUnicode for simple fonts, because + * we can't detemine in advance, which glyphs the font actually uses. + * The decision about writing it out is deferred until pdf_write_font_resource. + */ code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr); if(code < 0) return code; pet->glyph = glyph; - pet->str = gnstr; - return 0; + return pdf_copy_string_to_encoding(pdev, &gnstr, pet); } /* @@ -725,7 +724,10 @@ process_text_estimate_bbox(pdf_text_enum_t *pte, gs_font_base *font, return code; } if (pte->text.operation & TEXT_REPLACE_WIDTHS) { - gs_text_replaced_width(&pte->text, xy_index++, &tpt); + code = gs_text_replaced_width(&pte->text, xy_index++, &tpt); + if (code < 0) + return code; + gs_distance_transform(tpt.x, tpt.y, &ctm_only(pte->pgs), &wanted); } else { gs_distance_transform(info.width[WMode].x, diff --git a/devices/vector/gdevpdtf.c b/devices/vector/gdevpdtf.c index 0972e02d..0b714198 100644 --- a/devices/vector/gdevpdtf.c +++ b/devices/vector/gdevpdtf.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 @@ -39,8 +39,6 @@ /* GC descriptors */ public_st_pdf_font_resource(); -private_st_pdf_encoding1(); -private_st_pdf_encoding_element(); private_st_pdf_standard_font(); private_st_pdf_standard_font_element(); private_st_pdf_outline_fonts(); @@ -66,9 +64,6 @@ case 7: switch (pdfont->FontType) { ENUM_RETURN(pdfont->u.simple.Encoding); } case 8: switch (pdfont->FontType) { - case ft_composite: - return (pdfont->u.type0.cmap_is_standard ? ENUM_OBJ(0) : - ENUM_CONST_STRING(&pdfont->u.type0.CMapName)); case ft_encrypted: case ft_encrypted2: case ft_TrueType: @@ -82,6 +77,7 @@ case 8: switch (pdfont->FontType) { case ft_CID_encrypted: case ft_CID_TrueType: ENUM_RETURN(pdfont->u.cidfont.v); + case ft_composite: default: ENUM_RETURN(0); } @@ -141,8 +137,6 @@ RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs, pdf_font_resource_t *pdfont) RELOC_VAR(pdfont->cmap_ToUnicode); switch (pdfont->FontType) { case ft_composite: - if (!pdfont->u.type0.cmap_is_standard) - RELOC_CONST_STRING_VAR(pdfont->u.type0.CMapName); RELOC_VAR(pdfont->u.type0.DescendantFont); break; case ft_PCL_user_defined: @@ -456,6 +450,11 @@ int font_resource_free(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) } switch(pdfont->FontType) { case ft_composite: + if (pdfont->u.type0.CMapName_data != NULL) { + gs_free_object(pdev->memory->non_gc_memory, (byte *)pdfont->u.type0.CMapName_data, "font_resource_free(CMapName)"); + pdfont->u.type0.CMapName_data = NULL; + pdfont->u.type0.CMapName_size = 0; + } break; case ft_PCL_user_defined: case ft_MicroType: @@ -464,6 +463,9 @@ int font_resource_free(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) case ft_PDF_user_defined: case ft_GL2_531: if(pdfont->u.simple.Encoding) { + int ix; + for (ix = 0; ix <= 255;ix++) + gs_free_object(pdev->pdf_memory->non_gc_memory, pdfont->u.simple.Encoding[ix].data, "Free copied glyph name string"); gs_free_object(pdev->pdf_memory, pdfont->u.simple.Encoding, "Free simple Encoding"); pdfont->u.simple.Encoding = 0; } @@ -486,6 +488,14 @@ int font_resource_free(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) break; case ft_CID_encrypted: case ft_CID_TrueType: + if(pdfont->u.cidfont.Widths2) { + gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.Widths2, "Free CIDFont Widths2 array"); + pdfont->u.cidfont.Widths2 = NULL; + } + if(pdfont->u.cidfont.v) { + gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.v, "Free CIDFont v array"); + pdfont->u.cidfont.v = NULL; + } if(pdfont->u.cidfont.used2) { gs_free_object(pdev->pdf_memory, pdfont->u.cidfont.used2, "Free CIDFont used2"); pdfont->u.cidfont.used2 = 0; @@ -497,6 +507,9 @@ int font_resource_free(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) break; default: if(pdfont->u.simple.Encoding) { + int ix; + for (ix = 0; ix <= 255;ix++) + gs_free_object(pdev->pdf_memory->non_gc_memory, pdfont->u.simple.Encoding[ix].data, "Free copied glyph name string"); gs_free_object(pdev->pdf_memory, pdfont->u.simple.Encoding, "Free simple Encoding"); pdfont->u.simple.Encoding = 0; } @@ -593,10 +606,7 @@ font_resource_encoded_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, gs_id rid, font_type ftype, pdf_font_write_contents_proc_t write_contents) { - pdf_encoding_element_t *Encoding = - gs_alloc_struct_array(pdev->pdf_memory, 256, pdf_encoding_element_t, - &st_pdf_encoding_element, - "font_resource_encoded_alloc"); + pdf_encoding_element_t *Encoding = (pdf_encoding_element_t *)gs_alloc_bytes(pdev->pdf_memory, 256 * sizeof(pdf_encoding_element_t), "font_resource_encoded_alloc"); gs_point *v = (gs_point *)gs_alloc_byte_array(pdev->pdf_memory, 256, sizeof(gs_point), "pdf_font_simple_alloc"); pdf_font_resource_t *pdfont; @@ -953,6 +963,7 @@ pdf_compute_BaseFont(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, bool fini pdf_font_descriptor_embedding(pdfont->FontDescriptor) ) { int code; + gs_font_base *pbfont = pdf_font_resource_font(pdfont, false); if (pdfont->FontDescriptor) code = pdf_add_subset_prefix(pdev, &fname, pdfont->used, pdfont->count, pdf_fontfile_hash(pdfont->FontDescriptor)); @@ -962,8 +973,12 @@ pdf_compute_BaseFont(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, bool fini if (code < 0) return code; pdfont->BaseFont = fname; + /* Don't write a UID for subset fonts. */ - uid_set_invalid(&pdf_font_resource_font(pdfont, false)->UID); + if (uid_is_XUID(&pbfont->UID)) { + uid_free(&pbfont->UID, pbfont->memory, "gs_font_finalize"); + } + uid_set_invalid(&pbfont->UID); } if (pdfont->FontType != ft_composite && pdsubf->FontDescriptor) *pdf_font_descriptor_name(pdsubf->FontDescriptor) = fname; @@ -982,8 +997,17 @@ pdf_font_type0_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, ft_composite, 0, pdf_write_contents_type0); if (code >= 0) { + byte *chars = NULL; + (*ppfres)->u.type0.DescendantFont = DescendantFont; - (*ppfres)->u.type0.CMapName = *CMapName; + + chars = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, CMapName->size, "pdf_font_resource_t(CMapName)"); + if (chars == 0) + return_error(gs_error_VMerror); + memcpy(chars, CMapName->data, CMapName->size); + (*ppfres)->u.type0.CMapName_data = chars; + (*ppfres)->u.type0.CMapName_size = CMapName->size; + (*ppfres)->u.type0.font_index = 0; code = pdf_compute_BaseFont(pdev, *ppfres, false); } @@ -1206,7 +1230,8 @@ pdf_convert_truetype_font(gx_device_pdf *pdev, pdf_resource_t *pres) if (code < 0) return 0; pdfont->u.cidfont.CIDSystemInfo_id = pdev->IdentityCIDSystemInfo_id; - gs_sprintf(pdfont0->u.type0.Encoding_name, "%ld 0 R", pdf_resource_id(pdev->OneByteIdentityH)); + gs_snprintf(pdfont0->u.type0.Encoding_name, sizeof(pdfont0->u.type0.Encoding_name), + "%ld 0 R", pdf_resource_id(pdev->OneByteIdentityH)); /* Move ToUnicode : */ pdfont0->res_ToUnicode = pdfont->res_ToUnicode; pdfont->res_ToUnicode = 0; pdfont0->cmap_ToUnicode = pdfont->cmap_ToUnicode; pdfont->cmap_ToUnicode = 0; diff --git a/devices/vector/gdevpdtf.h b/devices/vector/gdevpdtf.h index f13c0eac..5a1a57dd 100644 --- a/devices/vector/gdevpdtf.h +++ b/devices/vector/gdevpdtf.h @@ -117,13 +117,30 @@ typedef int (*pdf_font_write_contents_proc_t) */ typedef struct pdf_encoding_element_s { gs_glyph glyph; - gs_const_string str; + byte *data; + uint size; bool is_difference; /* true if must be written in Differences */ } pdf_encoding_element_t; + +static inline int pdf_copy_string_to_encoding(gx_device_pdf *pdev, gs_const_string *gnstr, pdf_encoding_element_t *pet) +{ + byte *p = NULL; + + p = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, gnstr->size, "pdf_copy_string_to_encoding"); + if (p == NULL) + return_error(gs_error_VMerror); + memcpy(p, gnstr->data, gnstr->size); + if (pet->data != NULL) + gs_free_object(pdev->pdf_memory->non_gc_memory, pet->data, "pdf_copy_string_to_encoding free existing glyph name"); + pet->data = p; + pet->size = gnstr->size; + return 0; +} + #define private_st_pdf_encoding1() /* gdevpdtf.c */\ gs_private_st_const_strings1(st_pdf_encoding1,\ pdf_encoding_element_t, "pdf_encoding_element_t",\ - pdf_encoding1_enum_ptrs, pdf_encoding1_reloc_ptrs, str) + pdf_encoding1_enum_ptrs, pdf_encoding1_reloc_ptrs, bah) #define private_st_pdf_encoding_element() /* gdevpdtf.c */\ gs_private_st_element(st_pdf_encoding_element, pdf_encoding_element_t,\ "pdf_encoding_element_t[]", pdf_encoding_elt_enum_ptrs,\ @@ -227,8 +244,8 @@ struct pdf_font_resource_s { sizeof(long) * 8 / 3 + 1 + 4 /* <id> 0 R */ ) + 1 /* \0 terminator */ ]; - gs_const_string CMapName; /* copied from the original CMap, */ - /* or references the table of standard names */ + byte *CMapName_data; + uint CMapName_size; uint font_index; /* The index of the descendent font in the source CMap. */ bool cmap_is_standard; int WMode; /* of CMap */ diff --git a/devices/vector/gdevpdti.c b/devices/vector/gdevpdti.c index d1b39e99..45a56082 100644 --- a/devices/vector/gdevpdti.c +++ b/devices/vector/gdevpdti.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 @@ -292,10 +292,11 @@ pdf_attach_charproc(gx_device_pdf * pdev, pdf_font_resource_t *pdfont, pdf_char_ pcpo->char_name.data = 0; pcpo->char_name.size = 0; } else { - pcpo->char_name.data = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, gnstr->size, "storage for charproc name"); - memcpy(pcpo->char_name.data, gnstr->data, gnstr->size); + if (gnstr->size > 0) { + pcpo->char_name.data = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, gnstr->size, "storage for charproc name"); + memcpy(pcpo->char_name.data, gnstr->data, gnstr->size); + } pcpo->char_name.size = gnstr->size; -// pcpo->char_name = *gnstr; } pcpo->duplicate_char_name = duplicate_char_name; return 0; @@ -335,7 +336,7 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, int code; /* This code added to store PCL bitmap glyphs in type 3 fonts where possible */ gs_glyph glyph = GS_NO_GLYPH; - gs_const_string *str = NULL; + gs_const_string str2, *str = NULL; gs_show_enum *show_enum = (gs_show_enum *)pdev->pte; pdf_encoding_element_t *pet = 0; /* Since this is for text searching, its only useful if the character code @@ -406,15 +407,17 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, * then we need to give up, something about the font or text is not acceptable * (see various comments above). */ - if (pet && pet->glyph != GS_NO_GLYPH && !(pet->str.size == 7 && - !strncmp((const char *)pet->str.data, ".notdef", 7))) { + if (pet && pet->glyph != GS_NO_GLYPH && !(pet->size == 7 && + !strncmp((const char *)pet->data, ".notdef", 7))) { if (char_code < font->u.simple.FirstChar) font->u.simple.FirstChar = char_code; if ((int)char_code > font->u.simple.LastChar) font->u.simple.LastChar = char_code; base->FontBBox.q.x = max(base->FontBBox.q.x, w); base->FontBBox.q.y = max(base->FontBBox.q.y, y_offset + h); - str = &pet->str; + str2.data = pet->data; + str2.size = pet->size; + str = &str2; glyph = pet->glyph; /* This is to work around a weird Acrobat bug. If the Encoding of a type 3 * (possibly other types) is simply a standard encoding (eg WinAnsiEncoding) @@ -1065,13 +1068,12 @@ complete_adding_char(gx_device_pdf *pdev, gs_font *font, pdfont->u.simple.v[ch].y = pcp->v.x; } pet->glyph = glyph; - pet->str = *gnstr; pet->is_difference = true; if (pdfont->u.simple.LastChar < (int)ch) pdfont->u.simple.LastChar = (int)ch; if (pdfont->u.simple.FirstChar > (int)ch) pdfont->u.simple.FirstChar = (int)ch; - return 0; + return pdf_copy_string_to_encoding(pdev, (gs_const_string *)gnstr, pet); } static int @@ -1212,7 +1214,7 @@ pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_reso if (code < 0) return code; } - gs_sprintf(buf, "%ld 0 R\n", pres->object->id); + gs_snprintf(buf, sizeof(buf), "%ld 0 R\n", pres->object->id); if (v != NULL) { if (v->value_type != COS_VALUE_OBJECT && v->value_type != COS_VALUE_RESOURCE) diff --git a/devices/vector/gdevpdtt.c b/devices/vector/gdevpdtt.c index 3091a18d..98ce8892 100644 --- a/devices/vector/gdevpdtt.c +++ b/devices/vector/gdevpdtt.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 @@ -114,7 +114,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, * NOT the identity, but we want the cache device values to be in * font co-ordinate space, so we need to undo that scale here. */ - if (pdev->PS_accumulator){ + if (pdev->PS_accumulator || pdev->Scaled_accumulator){ gs_matrix_scale(&ctm_only(pte->pgs), .01, .01, &m); gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width); } else { @@ -133,7 +133,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, * NOT the identity, but we want the cache device values to be in * font co-ordinate space, so we need to undo that scale here. */ - if (pdev->PS_accumulator){ + if (pdev->PS_accumulator || pdev->Scaled_accumulator){ gs_matrix_scale(&ctm_only(pte->pgs), .01, .01, &m); gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width); } else { @@ -214,7 +214,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, * needs to be in the 100x100 space so that it doesn't clip * out marking operations. */ - if (pdev->PS_accumulator) + if (pdev->PS_accumulator || pdev->Scaled_accumulator) gs_matrix_scale(&ctm_only(penum_s->pgs), .01, .01, &m); else m = ctm_only(penum_s->pgs); @@ -225,7 +225,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, pw1[i] = p.x; pw1[i + 1] = p.y; } - if (!pdev->PS_accumulator) + if (!pdev->PS_accumulator && !pdev->Scaled_accumulator) code = pdf_set_charproc_attrs(pdev, pte->current_font, pw1, narg, control, penum->returned.current_char, false); else @@ -1114,11 +1114,10 @@ pdf_is_compatible_encoding(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, if (pfont->data.FMapType == fmap_CMap) { const gs_cmap_t *pcmap = pfont->data.CMap; - const gs_const_string *s0 = &pdfont->u.type0.CMapName; const gs_const_string *s1 = &pcmap->CMapName; - return (s0->size == s1->size && - !memcmp(s0->data, s1->data, s0->size)); + return (pdfont->u.type0.CMapName_size == s1->size && + !memcmp(pdfont->u.type0.CMapName_data, s1->data, pdfont->u.type0.CMapName_size)); } } return false; @@ -1283,9 +1282,9 @@ pdf_find_type0_font_resource(gx_device_pdf *pdev, const pdf_font_resource_t *pds */ if (pdfont->BaseFont.size != pdsubf->BaseFont.size) continue; - if (pdfont->u.type0.CMapName.size != CMapName->size) + if (pdfont->u.type0.CMapName_size != CMapName->size) continue; - if (memcmp(pdfont->u.type0.CMapName.data, CMapName->data, CMapName->size)) + if (memcmp(pdfont->u.type0.CMapName_data, CMapName->data, CMapName->size)) continue; } @@ -2290,9 +2289,16 @@ int pdf_obtain_parent_type0_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdsubf, uint font_index, const gs_const_string *CMapName, pdf_font_resource_t **pdfont) { + gs_const_string s1; + + if (pdsubf->u.cidfont.parent != 0) { + s1.data = pdsubf->u.cidfont.parent->u.type0.CMapName_data; + s1.size = pdsubf->u.cidfont.parent->u.type0.CMapName_size; + } + if (pdsubf->u.cidfont.parent != 0 && font_index == pdsubf->u.cidfont.parent->u.type0.font_index && - strings_equal(CMapName, &pdsubf->u.cidfont.parent->u.type0.CMapName)) + strings_equal(CMapName, &s1)) *pdfont = pdsubf->u.cidfont.parent; else { /* @@ -2868,7 +2874,7 @@ pdf_choose_output_char_code(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_char } static int -pdf_choose_output_glyph_name(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_const_string *gnstr, gs_glyph glyph) +pdf_choose_output_glyph_name(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_const_string *gnstr, gs_glyph glyph, bool *cleanup) { if (penum->orig_font->FontType == ft_composite || penum->orig_font->procs.glyph_name(penum->orig_font, glyph, gnstr) < 0 || (penum->orig_font->FontType > 42 && gnstr->size == 7 && strcmp((const char *)gnstr->data, ".notdef")== 0)) { @@ -2887,9 +2893,10 @@ pdf_choose_output_glyph_name(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_con p = (byte *)gs_alloc_string(pdev->pdf_memory, gnstr->size, "pdf_text_set_cache"); if (p == NULL) return_error(gs_error_VMerror); - gs_sprintf(buf, "g%04x", (unsigned int)(glyph & 0xFFFF)); + gs_snprintf(buf, sizeof(buf), "g%04x", (unsigned int)(glyph & 0xFFFF)); memcpy(p, buf, 5); gnstr->data = p; + *cleanup = true; } return 0; } @@ -3041,6 +3048,12 @@ static int install_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte executed gsave, so we are safe to change CTM now. Note that BuildChar may change CTM before calling setcachedevice. */ gs_make_identity(&m); + if (penum->current_font->FontType == ft_PDF_user_defined) { + pdev->width *= 100; + pdev->height *= 100; + gs_matrix_scale(&m, 100, 100, &m); + pdev->Scaled_accumulator = 1; + } gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m); /* Choose a character code to use with the charproc. */ @@ -3074,10 +3087,11 @@ static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte, { gs_const_string gnstr; int code; + bool cleanup = false; if (pte_default->returned.current_glyph == GS_NO_GLYPH) return_error(gs_error_undefined); - code = pdf_choose_output_glyph_name(pdev, penum, &gnstr, pte_default->returned.current_glyph); + code = pdf_choose_output_glyph_name(pdev, penum, &gnstr, pte_default->returned.current_glyph, &cleanup); if (code < 0) { return code; } @@ -3109,26 +3123,30 @@ static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte, stream_puts(pdev->strm, "0 0 0 0 0 0 d1\n"); } - if (was_PS_type3) { + if (was_PS_type3 || pdev->Scaled_accumulator) { /* See below, we scaled the device height and width to prevent * clipping of the CharProc operations, now we need to undo that. */ pdev->width /= 100; pdev->height /= 100; + pdev->Scaled_accumulator = 0; } code = pdf_end_charproc_accum(pdev, penum->current_font, penum->cgp, pte_default->returned.current_glyph, penum->output_char_code, &gnstr); if (code < 0) - return code; + goto exit; pdev->accumulating_charproc = false; penum->charproc_accum = false; code = gx_default_text_restore_state(pte_default); if (code < 0) - return code; + goto exit; gs_text_release(NULL, pte_default, "pdf_text_process"); penum->pte_default = 0; - return 0; +exit: + if (cleanup) + gs_free_string(pdev->pdf_memory, (byte *)gnstr.data, gnstr.size, "pdf_text_set_cache free working name"); + return code; } /* Nasty hackery. The PCL 'stick font' is drawn by constructing a path, and then stroking it. @@ -3449,7 +3467,8 @@ pdf_text_process(gs_text_enum_t *pte) /* We need a special 'initial matrix' method for stick fonts, * See pdf_type3_get_initial_matrix above. */ - pdev->procs.get_initial_matrix = pdf_type3_get_initial_matrix; + if (penum->current_font->FontType != ft_PDF_user_defined) + pdev->procs.get_initial_matrix = pdf_type3_get_initial_matrix; pdev->pte = (gs_text_enum_t *)penum; /* CAUTION: See comment in gdevpdfx.h . */ /* In case of error, text_process will restore back to the enumerator 'level' @@ -3524,7 +3543,7 @@ pdf_text_process(gs_text_enum_t *pte) /* end of code copied from show_cache_setup */ /* This copied from set_cache */ - code = gx_alloc_char_bits(pte->current_font->dir, dev, NULL, + code = gx_alloc_char_bits(pte->current_font->dir, dev, 0, 0, &log2_scale, 1, &cc); if (code < 0) return code; diff --git a/devices/vector/gdevpdtv.c b/devices/vector/gdevpdtv.c index 47b9d798..a9df5e82 100644 --- a/devices/vector/gdevpdtv.c +++ b/devices/vector/gdevpdtv.c @@ -12,7 +12,6 @@ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, CA 94945, U.S.A., +1(415)492-9861, for further information. */ - /* * This file contains substantial parts of toolbin/encs2c.ps, * which generated the remainder of the file mechanically from @@ -23,6 +22,9 @@ * This source file is maintained manually under source code control, * however its content should be regenerated by using encs2c.ps * if changes are required. + * You should not manually alter this file! If you regenerate it using + * encs2c.ps you must regenerate all 4 files; base/gscedata.[c|h] + * and devices/vector/gdevpdtv.[c|h] */ #include "gdevpdtv.h" @@ -65,7 +67,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 28, -3, +0, 0, 0, 0, @@ -89,7 +91,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 12, -192, +0, 0, 0, 0, @@ -97,7 +99,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 60, -1, +0, 3, 0, 0, @@ -129,7 +131,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 92, -49, +51, 0, 0, 0, @@ -153,7 +155,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 76, -4, +0, 0, 192, 0, @@ -161,7 +163,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 12, -0, +1, 1, 0, 3, @@ -193,7 +195,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 12, -4, +5, 48, 0, 0, @@ -313,7 +315,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 12, -4, +192, 0, 0, 0, @@ -354,7 +356,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 60, 4, -1, +0, 0, 0, 0, @@ -369,7 +371,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 60, -64, +0, 0, 48, 0, @@ -393,7 +395,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 12, -12, +0, 12, 0, 0, @@ -418,7 +420,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 28, 48, -3, +1, 0, 3, 0, @@ -433,7 +435,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 28, -0, +4, 48, 0, 0, @@ -473,7 +475,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, 192, 0, 0, @@ -513,7 +515,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, +12, +0, 0, 0, 0, @@ -537,7 +540,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, 12, 0, 0, @@ -553,7 +555,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, +0, 0, 4, 0, @@ -593,7 +595,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, +76, 48, 48, 0, @@ -633,7 +635,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, +0, 0, 0, 0, @@ -649,7 +652,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, 192, 0, 0, @@ -673,7 +675,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, 51, 0, 0, @@ -713,7 +715,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, 0, 0, 0, @@ -761,7 +763,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +192, 0, 4, 0, @@ -802,7 +804,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 48, -1, +3, 1, 0, 0, @@ -817,7 +819,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, +0, 0, 48, 0, @@ -833,7 +835,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, +12, 16, 0, 0, @@ -866,14 +868,14 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, +1, 4, 0, 0, 0, 0, 0, -12, +76, 0, 0, 0, @@ -930,7 +932,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -1, +3, 16, 0, 0, @@ -953,7 +955,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +4, 0, 0, 0, @@ -985,7 +987,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, 0, 0, 0, @@ -993,7 +994,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -52, +0, +60, 17, 1, 0, @@ -1041,7 +1043,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -112, +48, 12, 16, 0, @@ -1073,7 +1075,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, +0, 48, 12, 0, @@ -1097,7 +1099,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, +64, 0, 0, 0, @@ -1122,7 +1124,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, +1, 0, 0, 0, @@ -1153,7 +1155,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -68, +12, 48, 16, 0, @@ -1186,7 +1188,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 48, -13, +15, 1, 0, 0, @@ -1233,7 +1235,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, 16, 0, 0, @@ -1250,7 +1252,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, +1, 0, 0, 0, @@ -1313,7 +1315,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, 51, 0, 0, @@ -1377,7 +1379,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +240, 3, 17, 0, @@ -1433,7 +1435,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, +76, 0, 0, 0, @@ -1442,7 +1444,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, +195, 0, 0, 0, @@ -1473,7 +1475,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -60, +12, 60, 1, 0, @@ -1489,7 +1491,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, +0, 0, 28, 0, @@ -1506,15 +1508,14 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, -12, 0, +4, 0, 0, 0, @@ -1522,6 +1523,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +48, 0, 0, 0, @@ -1545,7 +1547,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, +64, 12, 0, 0, @@ -1553,7 +1555,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -12, +4, 48, 0, 0, @@ -1570,7 +1572,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -1, +3, 3, 0, 0, @@ -1593,15 +1595,15 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -4, -0, 12, 0, +12, 0, 0, 0, 0, 0, +64, 0, 48, 0, @@ -1617,9 +1619,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, -204, 0, +204, 0, 0, 0, @@ -1634,7 +1635,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +12, +49, 0, 0, 0, @@ -1673,7 +1675,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +12, 0, 0, 0, @@ -1713,7 +1715,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -112, +52, 16, 48, 0, @@ -1769,7 +1771,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +64, 0, 0, 0, @@ -1825,7 +1827,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +192, 0, 48, 0, @@ -1881,7 +1883,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, +0, 192, 0, 0, @@ -1937,7 +1939,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, +0, 0, 48, 0, @@ -1993,7 +1995,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, +64, 0, 0, 0, @@ -2049,7 +2051,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, +48, 12, 51, 0, @@ -2105,7 +2107,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, +0, 0, 0, 0, @@ -2145,7 +2147,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 192, -48, +0, 192, 3, 0, @@ -2161,7 +2163,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -192, +64, 0, 48, 0, @@ -2193,7 +2195,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 192, -0, +48, 52, 0, 0, @@ -2217,7 +2219,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -64, +192, 0, 12, 0, @@ -2241,7 +2243,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 192, -48, +0, 0, 3, 0, @@ -2273,7 +2275,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +192, 48, 48, 0, @@ -2329,7 +2331,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +64, 0, 0, 0, @@ -2337,7 +2339,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 192, -0, +48, 12, 3, 0, @@ -2385,7 +2387,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 192, -112, +64, 0, 48, 0, @@ -2441,7 +2443,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +192, 0, 0, 0, @@ -2497,7 +2499,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +64, 192, 48, 0, @@ -2665,7 +2667,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +64, 0, 0, 0, @@ -2817,7 +2819,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +48, 0, 1, 0, @@ -2865,7 +2867,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +0, 0, 0, 0, @@ -3009,7 +3011,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +48, 0, 0, 0, @@ -3057,7 +3059,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +0, 12, 16, 0, @@ -3201,7 +3203,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +48, 68, 3, 0, @@ -3297,10 +3299,9 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, 0, -3, 0, +3, 0, 0, 0, @@ -3346,6 +3347,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +48, 12, 0, 0, @@ -3393,7 +3395,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -1, +0, 0, 3, 0, @@ -3425,7 +3427,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, 0, 0, 0, @@ -3441,7 +3442,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +0, +0, 0, 0, 0, @@ -3521,7 +3523,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, +1, 0, 0, 0, @@ -3553,7 +3555,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -1, +3, 192, 0, 0, @@ -3617,8 +3619,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, -0, +1, 0, 0, 0, @@ -3634,6 +3635,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +48, 12, 0, 0, @@ -3649,7 +3651,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -1, +3, 0, 0, 0, @@ -3681,7 +3683,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -51, +3, 0, 1, 0, @@ -3713,7 +3715,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -3, +1, 0, 0, 0, @@ -3777,7 +3779,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -49, +51, 12, 1, 0, @@ -3809,7 +3811,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +3, 0, 0, 0, @@ -3841,7 +3843,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +1, 0, 0, 0, @@ -3921,7 +3923,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +48, 4, 0, 0, @@ -3969,7 +3971,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +0, 0, 1, 0, @@ -4113,6 +4115,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +48, 0, 0, 0, @@ -4161,7 +4164,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -16, 0, 3, 0, @@ -4209,6 +4211,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +16, 0, 0, 0, @@ -4257,7 +4260,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, 192, 3, 0, @@ -4353,8 +4355,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -16, -0, +48, 0, 0, 0, @@ -4402,6 +4403,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +16, 0, 0, 0, @@ -4497,7 +4499,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +0, 0, 0, 0, @@ -4689,7 +4691,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -16, +48, 0, 0, 0, @@ -4737,7 +4739,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, +16, 0, 3, 0, @@ -4881,7 +4883,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +48, 0, 0, 0, @@ -4977,7 +4979,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, 0, 0, 0, @@ -5026,6 +5027,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +48, 0, 3, 0, @@ -5073,7 +5075,6 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -48, 0, 0, 0, @@ -5121,7 +5122,8 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -16, +0, +48, 0, 3, 0, @@ -5217,7 +5219,7 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, -0, +16, 0, 3, 0, @@ -5265,6 +5267,54 @@ const unsigned char gs_c_pdf_glyph_type[] = { 0, 0, 0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, 16, 0, 0, diff --git a/devices/vector/gdevpdtv.h b/devices/vector/gdevpdtv.h index 54db170c..0cccd412 100644 --- a/devices/vector/gdevpdtv.h +++ b/devices/vector/gdevpdtv.h @@ -12,7 +12,6 @@ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, CA 94945, U.S.A., +1(415)492-9861, for further information. */ - /* * This file contains substantial parts of toolbin/encs2c.ps, * which generated the remainder of the file mechanically from @@ -23,12 +22,15 @@ * This source file is maintained manually under source code control, * however its content should be regenerated by using encs2c.ps * if changes are required. + * You should not manually alter this file! If you regenerate it using + * encs2c.ps you must regenerate all 4 files; base/gscedata.[c|h] + * and devices/vector/gdevpdtv.[c|h] */ #ifndef gdevpdtv_INCLUDED #define gdevpdtv_INCLUDED -#define GS_C_PDF_MAX_GOOD_GLYPH 21894 +#define GS_C_PDF_MAX_GOOD_GLYPH 22086 #define GS_C_PDF_GOOD_GLYPH_MASK 1 #define GS_C_PDF_GOOD_NON_SYMBOL_MASK 2 diff --git a/devices/vector/gdevpdtw.c b/devices/vector/gdevpdtw.c index 0647db66..907c7f0c 100644 --- a/devices/vector/gdevpdtw.c +++ b/devices/vector/gdevpdtw.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 @@ -78,9 +78,13 @@ pdf_different_encoding_element(const pdf_font_resource_t *pdfont, int ch, int en if (code < 0) return code; /* Must not happen */ - if (glyph1 != GS_NO_GLYPH) - if (!strings_equal(&str, &pdfont->u.simple.Encoding[ch].str)) + if (glyph1 != GS_NO_GLYPH) { + gs_const_string str2; + str2.data = pdfont->u.simple.Encoding[ch].data; + str2.size = pdfont->u.simple.Encoding[ch].size; + if (!strings_equal(&str, &str2)) return 1; + } } return 0; } @@ -120,7 +124,7 @@ pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t *pdfont) */ return true; if (!pdfont->TwoByteToUnicode) - return true; + return false; for (ch = 0; ch < 256; ++ch) { pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; @@ -129,9 +133,9 @@ pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t *pdfont) if (glyph == GS_NO_GLYPH) continue; if (glyph < gs_c_min_std_encoding_glyph || glyph >= GS_MIN_CID_GLYPH) { - if (pet->str.size == 0) + if (pet->size == 0) return true; - glyph = gs_c_name_glyph(pet->str.data, pet->str.size); + glyph = gs_c_name_glyph(pet->data, pet->size); if (glyph == GS_NO_GLYPH) return true; } @@ -176,12 +180,12 @@ pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long * Enforce writing differences against that. */ if (pdfont->used[ch >> 3] & 0x80 >> (ch & 7)) - if (pdfont->u.simple.Encoding[ch].str.size) + if (pdfont->u.simple.Encoding[ch].size) code = 1; } if (code) { - const byte *d = pdfont->u.simple.Encoding[ch].str.data; - int i, l = pdfont->u.simple.Encoding[ch].str.size; + const byte *d = pdfont->u.simple.Encoding[ch].data; + int i, l = pdfont->u.simple.Encoding[ch].size; if (pdev->HavePDFWidths) { for (i = 0; i + sl < l; i++) @@ -881,7 +885,7 @@ pdf_write_OneByteIdentityH(gx_device_pdf *pdev) code = cos_dict_put_string_copy(pcd, "/CMapName", "/OneByteIdentityH"); if (code < 0) return code; - gs_sprintf(buf, "%ld 0 R", pdev->IdentityCIDSystemInfo_id); + gs_snprintf(buf, sizeof(buf), "%ld 0 R", pdev->IdentityCIDSystemInfo_id); code = cos_dict_put_string_copy(pcd, "/CIDSystemInfo", buf); if (code < 0) return code; diff --git a/devices/vector/gdevpsf1.c b/devices/vector/gdevpsf1.c index 672ce241..c045c714 100644 --- a/devices/vector/gdevpsf1.c +++ b/devices/vector/gdevpsf1.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 @@ -663,12 +663,12 @@ write_Private(stream *s, gs_font_type1 *pfont, gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record"); return code; } - gs_sprintf(buf, "dup %d %u -| ", i, code); + gs_snprintf(buf, sizeof(buf), "dup %d %u -| ", i, code); stream_puts(s, buf); write_CharString(s, stripped, code); gs_free_object(pfont->memory, stripped, "free Subrs copy for OtherSubrs"); } else { - gs_sprintf(buf, "dup %d %u -| ", i, gdata.bits.size); + gs_snprintf(buf, sizeof(buf), "dup %d %u -| ", i, gdata.bits.size); stream_puts(s, buf); write_CharString(s, gdata.bits.data, gdata.bits.size); } diff --git a/devices/vector/gdevpsf2.c b/devices/vector/gdevpsf2.c index 4c56c450..a6db8b5b 100644 --- a/devices/vector/gdevpsf2.c +++ b/devices/vector/gdevpsf2.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 @@ -274,7 +274,7 @@ cff_put_real(cff_writer_t *pcw, double f) byte b = 0xff; const char *p; - gs_sprintf(str, "%g", f); + gs_snprintf(str, sizeof(str), "%g", f); sputc(pcw->strm, CD_REAL); for (p = str; ; ++p) { int digit; @@ -1213,17 +1213,21 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, std_string_items = (cff_string_item_t *)gs_alloc_bytes(pfont->memory, (MAX_CFF_STD_STRINGS + number_of_strings) * sizeof(cff_string_item_t), "psf_write_type2_font"); - if (std_string_items == NULL || subset.glyphs.subset_data == NULL) - return_error(gs_error_VMerror); + if (std_string_items == NULL || subset.glyphs.subset_data == NULL) { + code = gs_note_error(gs_error_VMerror); + goto error; + } string_items = std_string_items + MAX_CFF_STD_STRINGS; /* Get subset glyphs. */ code = psf_get_type1_glyphs(&subset.glyphs, pfont, subset_glyphs, subset_size); if (code < 0) - return code; - if (subset.glyphs.notdef == GS_NO_GLYPH) - return_error(gs_error_rangecheck); /* notdef is required */ + goto error; + if (subset.glyphs.notdef == GS_NO_GLYPH) { + code = gs_note_error(gs_error_rangecheck); /* notdef is required */ + goto error; + } /* If we're writing Type 2 CharStrings, don't encrypt them. */ if (options & WRITE_TYPE2_CHARSTRINGS) { @@ -1274,8 +1278,10 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, psf_enumerate_glyphs_reset(&genum); while ((code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1) if (code == 0) { - if (num_glyphs == number_of_glyphs) - return_error(gs_error_limitcheck); + if (num_glyphs == number_of_glyphs){ + code = gs_note_error(gs_error_limitcheck); + goto error; + } subset.glyphs.subset_data[num_glyphs++] = glyph; } subset.glyphs.subset_size = @@ -1347,7 +1353,7 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, if (code == gs_error_undefined) continue; if (code < 0) - return code; + goto error; charset_size += 2; } @@ -1380,7 +1386,7 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, /* Compute the size of the CharStrings Index. */ code = cff_write_CharStrings_offsets(&writer, &genum, &charstrings_count); if (code < 0) - return code; + goto error; charstrings_size = (uint)code; /* Compute the size of the (local) Subrs Index. */ @@ -1424,8 +1430,10 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, Subrs_offset = Private_size; /* relative to Private Dict */ write: - if(check_ioerror(writer.strm)) - return_error(gs_error_ioerror); + if(check_ioerror(writer.strm)) { + code = gs_note_error(gs_error_ioerror); + goto error; + } start_pos = stell(writer.strm); /* Write the header, setting offset_size. */ cff_write_header(&writer, End_offset); @@ -1446,14 +1454,18 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, /* Write the strings Index. */ cff_put_Index(&writer, &writer.strings); - if(check_ioerror(writer.strm)) - return_error(gs_error_ioerror); + if(check_ioerror(writer.strm)){ + code = gs_note_error(gs_error_ioerror); + goto error; + } /* Write the GSubrs Index, if any, checking the offset. */ offset = stell(writer.strm) - start_pos; if_debug2m('l', s->memory, "[l]GSubrs = %u => %u\n", GSubrs_offset, offset); - if (offset > GSubrs_offset) - return_error(gs_error_rangecheck); + if (offset > GSubrs_offset) { + code = gs_note_error(gs_error_rangecheck); + goto error; + } GSubrs_offset = offset; if (gsubrs_count == 0 || cff_convert_charstrings(&writer, pbfont)) cff_put_Index_header(&writer, 0, 0); @@ -1468,26 +1480,34 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, /* Write the CharStrings Index, checking the offset. */ offset = stell(writer.strm) - start_pos; - if (offset > CharStrings_offset) - return_error(gs_error_rangecheck); + if (offset > CharStrings_offset) { + code = gs_note_error(gs_error_rangecheck); + goto error; + } CharStrings_offset = offset; cff_write_CharStrings(&writer, &genum, charstrings_count, charstrings_size); - if(check_ioerror(writer.strm)) - return_error(gs_error_ioerror); + if(check_ioerror(writer.strm)) { + code = gs_note_error(gs_error_ioerror); + goto error; + } /* Write the Private Dict, checking the offset. */ offset = stell(writer.strm) - start_pos; - if (offset > Private_offset) - return_error(gs_error_rangecheck); + if (offset > Private_offset) { + code = gs_note_error(gs_error_rangecheck); + goto error; + } Private_offset = offset; cff_write_Private(&writer, (subrs_size == 0 ? 0 : Subrs_offset), pfont); Private_size = stell(writer.strm) - start_pos - offset; /* Write the Subrs Index, checking the offset. */ offset = stell(writer.strm) - (start_pos + Private_offset); - if (offset > Subrs_offset) - return_error(gs_error_rangecheck); + if (offset > Subrs_offset) { + code = gs_note_error(gs_error_rangecheck); + goto error; + } Subrs_offset = offset; if (cff_convert_charstrings(&writer, pbfont)) cff_put_Index_header(&writer, 0, 0); @@ -1495,11 +1515,15 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, cff_write_Subrs(&writer, subrs_count, subrs_size, pfont, false); /* Check the final offset. */ - if(check_ioerror(writer.strm)) - return_error(gs_error_ioerror); + if(check_ioerror(writer.strm)) { + code = gs_note_error(gs_error_ioerror); + goto error; + } offset = stell(writer.strm) - start_pos; - if (offset > End_offset) - return_error(gs_error_rangecheck); + if (offset > End_offset) { + code = gs_note_error(gs_error_rangecheck); + goto error; + } if (offset == End_offset) { /* The iteration has converged. Write the result. */ if (writer.strm == &poss) { @@ -1516,6 +1540,12 @@ psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options, gs_free_object(pfont->memory, std_string_items, "psf_write_type2_font"); gs_free_object(pfont->memory, subset.glyphs.subset_data, "psf_write_type2_font"); return 0; + +error: + gs_free_object(pfont->memory, std_string_items, "psf_write_type2_font"); + gs_free_object(pfont->memory, subset.glyphs.subset_data, "psf_write_type2_font"); + subset.glyphs.subset_data = NULL; + return code; } /* Write the CFF definition of a CIDFontType 0 font (CIDFont). */ diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c index cbe2b19e..5c885f5f 100644 --- a/devices/vector/gdevtxtw.c +++ b/devices/vector/gdevtxtw.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 @@ -647,20 +647,20 @@ static int simple_text_output(gx_device_txtwrite_t *tdev) return 0; } -static int escaped_Unicode (unsigned short Unicode, char *Buf) +static int escaped_Unicode (unsigned short Unicode, char Buf[32]) { switch (Unicode) { - case 0x3C: gs_sprintf(Buf, "<"); break; - case 0x3E: gs_sprintf(Buf, ">"); break; - case 0x26: gs_sprintf(Buf, "&"); break; - case 0x22: gs_sprintf(Buf, """); break; - case 0x27: gs_sprintf(Buf, "'"); break; + case 0x3C: gs_snprintf(Buf, 32, "<"); break; + case 0x3E: gs_snprintf(Buf, 32, ">"); break; + case 0x26: gs_snprintf(Buf, 32, "&"); break; + case 0x22: gs_snprintf(Buf, 32, """); break; + case 0x27: gs_snprintf(Buf, 32, "'"); break; default: if (Unicode >= 32 && Unicode <= 127) - gs_sprintf(Buf, "%c", Unicode); + gs_snprintf(Buf, 32, "%c", Unicode); else - gs_sprintf(Buf, "&#x%x;", Unicode); + gs_snprintf(Buf, 32, "&#x%x;", Unicode); break; } @@ -683,13 +683,13 @@ static int decorated_text_output(gx_device_txtwrite_t *tdev) x_entry = tdev->PageData.unsorted_text_list; while (x_entry) { next_x = x_entry->next; - gs_sprintf(TextBuffer, "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y, + gs_snprintf(TextBuffer, sizeof(TextBuffer), "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y, x_entry->end.x, x_entry->end.y, x_entry->FontName,x_entry->size); gp_fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file); xpos = x_entry->start.x; for (i=0;i<x_entry->Unicode_Text_Size;i++) { - escaped_Unicode(x_entry->Unicode_Text[i], (char *)&Escaped); - gs_sprintf(TextBuffer, "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\"/>\n", xpos, + escaped_Unicode(x_entry->Unicode_Text[i], Escaped); + gs_snprintf(TextBuffer, sizeof(TextBuffer), "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\"/>\n", xpos, x_entry->start.y, xpos + x_entry->Widths[i], x_entry->end.y, Escaped); gp_fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file); xpos += x_entry->Widths[i]; @@ -806,13 +806,13 @@ static int decorated_text_output(gx_device_txtwrite_t *tdev) gp_fwrite("<line>\n", sizeof(unsigned char), 7, tdev->file); x_entry = block_line->x_ordered_list; while(x_entry) { - gs_sprintf(TextBuffer, "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y, + gs_snprintf(TextBuffer, sizeof(TextBuffer), "<span bbox=\"%0.0f %0.0f %0.0f %0.0f\" font=\"%s\" size=\"%0.4f\">\n", x_entry->start.x, x_entry->start.y, x_entry->end.x, x_entry->end.y, x_entry->FontName,x_entry->size); gp_fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file); xpos = x_entry->start.x; for (i=0;i<x_entry->Unicode_Text_Size;i++) { - escaped_Unicode(x_entry->Unicode_Text[i], (char *)&Escaped); - gs_sprintf(TextBuffer, "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\"/>\n", xpos, + escaped_Unicode(x_entry->Unicode_Text[i], Escaped); + gs_snprintf(TextBuffer, sizeof(TextBuffer), "<char bbox=\"%0.0f %0.0f %0.0f %0.0f\" c=\"%s\"/>\n", xpos, x_entry->start.y, xpos + x_entry->Widths[i], x_entry->end.y, Escaped); gp_fwrite(TextBuffer, 1, strlen(TextBuffer), tdev->file); xpos += x_entry->Widths[i]; @@ -1483,6 +1483,7 @@ txtwrite_process_plain_text(gs_text_enum_t *pte) uint operation = pte->text.operation; txt_glyph_widths_t widths; gs_point wanted; /* user space */ + float glyph_width; for (i=pte->index;i<pte->text.size;i++) { gs_point dpt = {0,0}; @@ -1516,7 +1517,29 @@ txtwrite_process_plain_text(gs_text_enum_t *pte) if (code < 0) return code; + /* Calculate glyph_width from the **original** glyph metrics, not the overriding + * advance width (if TEXT_REPLACE_WIDTHS is set below) + */ txt_char_widths_to_uts(pte->orig_font, &widths); /* convert design->text space */ + glyph_width = widths.real_width.xy.x * penum->text_state->size; + + if (pte->text.operation & TEXT_REPLACE_WIDTHS) + { + gs_point tpt; + + /* We are applying a width override, from x/y/xyshow. This could be from + * a PostScript file, or it could be from a PDF file where we have a font + * with a FontMatrix which is neither horizontal nor vertical. + */ + code = gs_text_replaced_width(&pte->text, pte->xy_index++, &tpt); + if (code < 0) + return_error(gs_error_unregistered); + + widths.Width.w = widths.real_width.w = tpt.x; + widths.Width.xy.x = widths.real_width.xy.x = tpt.x; + widths.Width.xy.y = widths.real_width.xy.y = tpt.y; + } + gs_distance_transform(widths.real_width.xy.x * penum->text_state->size, widths.real_width.xy.y * penum->text_state->size, &penum->text_state->matrix, &wanted); @@ -1524,7 +1547,7 @@ txtwrite_process_plain_text(gs_text_enum_t *pte) pte->returned.total_width.y += wanted.y; penum->Widths[penum->TextBufferIndex] = wanted.x; penum->Advs[penum->TextBufferIndex] = wanted.x; - penum->GlyphWidths[penum->TextBufferIndex] = widths.real_width.xy.x * penum->text_state->size; + penum->GlyphWidths[penum->TextBufferIndex] = glyph_width; penum->SpanDeltaX[penum->TextBufferIndex] = widths.real_width.xy.x * penum->text_state->size; if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) { diff --git a/devices/vector/gdevxps.c b/devices/vector/gdevxps.c index c946f322..1ab854be 100644 --- a/devices/vector/gdevxps.c +++ b/devices/vector/gdevxps.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 @@ -960,7 +960,7 @@ write_str_to_current_page(gx_device_xps *xps, const char *str) char buf[128]; /* easily enough to accommodate the string and a page number */ /* we're one ahead of the page count */ - int code = gs_sprintf(buf, page_template, xps->page_count+1); + int code = gs_snprintf(buf, sizeof(buf), page_template, xps->page_count+1); if (code < 0) return gs_rethrow_code(code); @@ -1011,7 +1011,7 @@ close_page_relationship(gx_device_xps *xps) const char *rels_template = "Documents/1/Pages/_rels/%d.fpage.rels"; char buf[128]; /* easily enough to accommodate the string and a page number */ - int code = gs_sprintf(buf, rels_template, xps->page_count + 1); + int code = gs_snprintf(buf, sizeof(buf), rels_template, xps->page_count + 1); if (code < 0) return gs_rethrow_code(code); @@ -1029,7 +1029,7 @@ write_page_relationship(gx_device_xps* xps) int count = 0; xps_relations_t *rel = xps->relations_head; - int code = gs_sprintf(buf, rels_template, xps->page_count + 1); + int code = gs_snprintf(buf, sizeof(buf), rels_template, xps->page_count + 1); if (code < 0) return gs_rethrow_code(code); @@ -1037,7 +1037,7 @@ write_page_relationship(gx_device_xps* xps) fmt = "<Relationship Target = \"/%s\" Id = \"R%d\" Type = %s/>\n"; while (rel) { - gs_sprintf(line, fmt, rel->relation, count, rels_req_type); + gs_snprintf(line, sizeof(line), fmt, rel->relation, count, rels_req_type); write_str_to_zip_file(xps, buf, line); rel = rel->next; count++; @@ -1350,7 +1350,7 @@ xps_beginpage(gx_device_vector *vdev) { const char *template = "<PageContent Source=\"Pages/%d.fpage\" />"; /* Note page count is 1 less than the current page */ - code = gs_sprintf(buf, template, xps->page_count + 1); + code = gs_snprintf(buf, sizeof(buf), template, xps->page_count + 1); if (code < 0) return gs_rethrow_code(code); @@ -1364,7 +1364,7 @@ xps_beginpage(gx_device_vector *vdev) { const char *page_size_template = "<FixedPage Width=\"%d\" Height=\"%d\" " "xmlns=\"http://schemas.microsoft.com/xps/2005/06\" xml:lang=\"en-US\">\n"; - code = gs_sprintf(buf, page_size_template, + code = gs_snprintf(buf, sizeof(buf), page_size_template, (int)(xps->MediaSize[0] * 4.0/3.0), /* pts -> 1/96 inch */ (int)(xps->MediaSize[1] * 4.0/3.0)); if (code < 0) @@ -1375,7 +1375,7 @@ xps_beginpage(gx_device_vector *vdev) } { const char *canvas_template = "<Canvas RenderTransform=\"%g,%g,%g,%g,%g,%g\">\n"; - code = gs_sprintf(buf, canvas_template, + code = gs_snprintf(buf, sizeof(buf), canvas_template, 96.0/xps->HWResolution[0], 0.0, 0.0, 96.0/xps->HWResolution[1], 0.0, 0.0); if (code < 0) @@ -1507,7 +1507,7 @@ xps_finish_image_path(gx_device_vector *vdev) write_str_to_current_page(xps, "\t<Path.Fill>\n"); write_str_to_current_page(xps, "\t\t<ImageBrush "); fmt = "ImageSource = \"{ColorConvertedBitmap /%s /%s}\" Viewbox=\"%d, %d, %d, %d\" ViewboxUnits = \"Absolute\" Viewport = \"%d, %d, %d, %d\" ViewportUnits = \"Absolute\" TileMode = \"None\" >\n"; - gs_sprintf(line, fmt, xps->xps_pie->file_name, xps->xps_pie->icc_name, + gs_snprintf(line, sizeof(line), fmt, xps->xps_pie->file_name, xps->xps_pie->icc_name, 0, 0, xps->xps_pie->width, xps->xps_pie->height, 0, 0, xps->xps_pie->width, xps->xps_pie->height); write_str_to_current_page(xps, line); @@ -1517,7 +1517,7 @@ xps_finish_image_path(gx_device_vector *vdev) write_str_to_current_page(xps, "\t\t\t<ImageBrush.Transform>\n"); fmt = "\t\t\t\t<MatrixTransform Matrix = \"%g,%g,%g,%g,%g,%g\" />\n"; matrix = xps->xps_pie->mat; - gs_sprintf(line, fmt, + gs_snprintf(line, sizeof(line), fmt, matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.tx, matrix.ty); write_str_to_current_page(xps, line); write_str_to_current_page(xps, "\t\t\t</ImageBrush.Transform>\n"); @@ -1559,7 +1559,7 @@ xps_dorect(gx_device_vector *vdev, fixed x0, fixed y0, if (image_brush_fill(type, xps->filltype)) { /* Do the path data */ fmt = "<Path Data=\"M %g, %g L %g, %g %g, %g %g, %g Z\" >\n"; - gs_sprintf(line, fmt, + gs_snprintf(line, sizeof(line), fmt, fixed2float(x0), fixed2float(y0), fixed2float(x0), fixed2float(y1), fixed2float(x1), fixed2float(y1), @@ -1573,7 +1573,7 @@ xps_dorect(gx_device_vector *vdev, fixed x0, fixed y0, /* NB - F0 should be changed for a different winding type */ fmt = "Fill=\"#%06X\" Data=\"M %g,%g V %g H %g V %g Z\" "; c = xps->fillcolor & 0xffffffL; - gs_sprintf(line, fmt, c, + gs_snprintf(line, sizeof(line), fmt, c, fixed2float(x0), fixed2float(y0), fixed2float(y1), fixed2float(x1), fixed2float(y0)); @@ -1584,7 +1584,7 @@ xps_dorect(gx_device_vector *vdev, fixed x0, fixed y0, write_str_to_current_page(xps, "<Path "); fmt = "Stroke=\"#%06X\" Data=\"M %g,%g V %g H %g V %g Z\" "; c = xps->strokecolor & 0xffffffL; - gs_sprintf(line, fmt, c, + gs_snprintf(line, sizeof(line), fmt, c, fixed2float(x0), fixed2float(y0), fixed2float(y1), fixed2float(x1), fixed2float(y0)); @@ -1593,7 +1593,7 @@ xps_dorect(gx_device_vector *vdev, fixed x0, fixed y0, if (type & gx_path_type_stroke) { /* NB format width. */ fmt = "StrokeThickness=\"%g\" "; - gs_sprintf(line, fmt, xps->linewidth); + gs_snprintf(line, sizeof(line), fmt, xps->linewidth); write_str_to_current_page(xps, line); } write_str_to_current_page(xps, "/>\n"); @@ -1653,7 +1653,7 @@ xps_beginpath(gx_device_vector *vdev, gx_path_type_t type) fmt = "Fill=\"#%06X\" Data=\""; else fmt = "Stroke=\"#%06X\" Data=\""; - gs_sprintf(line, fmt, c); + gs_snprintf(line, sizeof(line), fmt, c); write_str_to_current_page(xps, line); } else { @@ -1680,7 +1680,7 @@ xps_moveto(gx_device_vector *vdev, double x0, double y0, return 0; } - gs_sprintf(line, " M %g,%g", x, y); + gs_snprintf(line, sizeof(line), " M %g,%g", x, y); write_str_to_current_page(xps, line); if_debug1m('_', xps->memory, "xps_moveto %s", line); return 0; @@ -1700,7 +1700,7 @@ xps_lineto(gx_device_vector *vdev, double x0, double y0, if_debug1m('_', xps->memory, "xps_lineto: type not supported %x\n", type); return 0; } - gs_sprintf(line, " L %g,%g", x, y); + gs_snprintf(line, sizeof(line), " L %g,%g", x, y); write_str_to_current_page(xps, line); if_debug1m('_', xps->memory, "xps_lineto %s\n", line); return 0; @@ -1720,7 +1720,7 @@ xps_curveto(gx_device_vector *vdev, double x0, double y0, return 0; } - gs_sprintf(line, " C %g,%g %g,%g %g,%g", x1, y1, + gs_snprintf(line, sizeof(line), " C %g,%g %g,%g %g,%g", x1, y1, x2,y2,x3,y3); write_str_to_current_page(xps,line); if_debug1m('_', xps->memory, "xps_curveto %s\n", line); @@ -1766,7 +1766,7 @@ xps_endpath(gx_device_vector *vdev, gx_path_type_t type) } else if (type & gx_path_type_stroke) { /* NB format width. */ fmt = "\" StrokeThickness=\"%g\" />\n"; - gs_sprintf(line, fmt, xps->linewidth); + gs_snprintf(line, sizeof(line), fmt, xps->linewidth); write_str_to_current_page(xps, line); } else { /* fill */ /* close the path data attribute */ |