diff options
Diffstat (limited to 'devices/vector')
65 files changed, 646 insertions, 421 deletions
diff --git a/devices/vector/gdevagl.c b/devices/vector/gdevagl.c index f9428a6e..a551bb38 100644 --- a/devices/vector/gdevagl.c +++ b/devices/vector/gdevagl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevagl.h b/devices/vector/gdevagl.h index e3569226..066eae76 100644 --- a/devices/vector/gdevagl.h +++ b/devices/vector/gdevagl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -16,6 +16,9 @@ * Unicode code points. */ +#ifndef gdevagl_h_INCLUDED +#define gdevagl_h_INCLUDED + typedef struct single_glyph_list_s { const char *Glyph; unsigned short Unicode; @@ -35,3 +38,5 @@ typedef struct quad_glyph_list_s { const char *Glyph; unsigned short Unicode[4]; } quad_glyph_list_t; + +#endif diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c index b25a4a6a..6752fabb 100644 --- a/devices/vector/gdevpdf.c +++ b/devices/vector/gdevpdf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -467,6 +467,12 @@ pdf_compute_fileID(gx_device_pdf * pdev) pdev->KeyLength = KeyLength; if (code < 0) return code; + /* Generally we would call s_close_filters() here in order to free the data buffer + * associated with the MD5 filter, but the data buffer we passed in to s_MD5E_make_stream() + * is part of the device structure, so we must *NOT* free that buffer. Therefore we must + * instead call sclose(). This confusion over ownership of the stream buffers causes + * a lot of problems...... + */ sclose(s); gs_free_object(mem, s, "pdf_compute_fileID"); return 0; @@ -1410,6 +1416,11 @@ pdf_output_page(gx_device * dev, int num_copies, int flush) gx_device_pdf *const pdev = (gx_device_pdf *) dev; int code; + if (pdev->Eps2Write && pdev->next_page != 0 && !gx_outputfile_is_separate_pages(pdev->fname, dev->memory)) { + emprintf(pdev->memory, "\n *** EPS files may not contain multiple pages.\n *** Use of the %%d filename format is required to output pages to multiple EPS files.\n"); + return_error(gs_error_ioerror); + } + if (pdev->ForOPDFRead) { code = pdf_close_page(pdev, num_copies); if (code < 0) @@ -2555,6 +2566,7 @@ pdf_close(gx_device * dev) int64_t start_section, end_section; char str[256]; pdf_linearisation_t linear_params; + bool file_per_page = false; if (!dev->is_open) return_error(gs_error_undefined); @@ -2577,26 +2589,14 @@ pdf_close(gx_device * dev) * marks. */ if (pdev->next_page == 0) { - /* If we didn't get called from pdf_output_page, and we are doign file-per-page - * output, then the call from close_device will leave an empty file which we don't - * want. So here we delete teh file. - */ - if (!pdev->InOutputPage && gx_outputfile_is_separate_pages(pdev->fname, pdev->memory)) { - code = gdev_vector_close_file((gx_device_vector *) pdev); - if (code != 0) - return code; - code = pdf_close_files(pdev, 0); + file_per_page = !pdev->InOutputPage && + gx_outputfile_is_separate_pages(pdev->fname, pdev->memory); + if (!file_per_page) { + code = pdf_open_page(pdev, PDF_IN_STREAM); + if (code < 0) return code; - code = gx_device_delete_output_file((const gx_device *)pdev, pdev->fname); - if (code != 0) - return gs_note_error(gs_error_ioerror); - return code; } - code = pdf_open_page(pdev, PDF_IN_STREAM); - - if (code < 0) - return code; } if (pdev->contents_id != 0) pdf_close_page(pdev, 1); @@ -2945,6 +2945,14 @@ pdf_close(gx_device * dev) stream_puts(pdev->strm, "%%EOF\n"); } + if (pdev->params.PSPageOptions.size) { + int ix; + + for (ix = 0; ix < pdev->params.PSPageOptions.size;ix++) + gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data[ix].data, "freeing old string array copy"); + gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data, "freeing old string array"); + } + if (pdev->Linearise) { linear_params.LastResource = pdev->next_id - 1; linear_params.Offsets = (gs_offset_t *)gs_alloc_bytes(pdev->pdf_memory, pdev->next_id * sizeof(gs_offset_t), "temp xref storage"); @@ -3450,6 +3458,18 @@ pdf_close(gx_device * dev) if (code < 0) return code; + /* If we didn't get called from pdf_output_page, and we are doign file-per-page + * output, then the call from close_device will leave an empty file which we don't + * want. So here we delete the file. + * NOTE: We needed to let it process the whole page in order to make sure everything + * got properly freed. + */ + if (file_per_page) { + code = gx_device_delete_output_file((const gx_device *)pdev, pdev->fname); + if (code != 0) + code = gs_note_error(gs_error_ioerror); + } + pdf_free_pdf_font_cache(pdev); return code; } diff --git a/devices/vector/gdevpdfb.c b/devices/vector/gdevpdfb.c index e35531d7..20339038 100644 --- a/devices/vector/gdevpdfb.c +++ b/devices/vector/gdevpdfb.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfb.h b/devices/vector/gdevpdfb.h index 5ea7a355..16521e0d 100644 --- a/devices/vector/gdevpdfb.h +++ b/devices/vector/gdevpdfb.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfc.c b/devices/vector/gdevpdfc.c index 259d143c..3a3096c4 100644 --- a/devices/vector/gdevpdfc.c +++ b/devices/vector/gdevpdfc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -643,6 +643,10 @@ pdf_indexed_color_space(gx_device_pdf *pdev, const gs_gstate * pgs, cos_value_t } stream_write(&es, palette, table_size); gs_free_string(mem, palette, table_size, "pdf_color_space(palette)"); + /* Another case where we use sclose() and not sclose_filters(), because the + * buffer we supplied to s_init_filter is a heap based C object, so we + * must not free it. + */ sclose(&es); sflush(&s); string_used = (uint)stell(&s); @@ -874,6 +878,11 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs, if (code < 0) return_error(gs_error_unregistered); /* Must not happen. */ serialized_size = stell(&s); + /* I think this is another case where we use sclose() and not sclose_filters(). + * It seems like we don't actually write anything, but it allows us to find the + * length of the serialised data. No buffer hre, so we must no call + * s_close_filters() as that will try to free it. + */ sclose(&s); if (serialized_size <= sizeof(serialized0)) serialized = serialized0; diff --git a/devices/vector/gdevpdfc.h b/devices/vector/gdevpdfc.h index 69770933..e9056be3 100644 --- a/devices/vector/gdevpdfc.h +++ b/devices/vector/gdevpdfc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c index 1e62bad1..32a6c41b 100644 --- a/devices/vector/gdevpdfd.c +++ b/devices/vector/gdevpdfd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -181,20 +181,6 @@ pdf_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, ymin -= d; ymax += d; } - if (pdev->CompatibilityLevel < 1.5) { - /* - * Clamp coordinates to avoid tripping over Acrobat Reader's limit - * of 32K on user coordinate values. - */ - if (x0 < xmin) - x0 = xmin; - if (x1 > xmax) - x1 = xmax; - if (y0 < ymin) - y0 = ymin; - if (y1 > ymax) - y1 = ymax; - } return psdf_dorect(vdev, x0, y0, x1, y1, type); } @@ -236,6 +222,7 @@ const gx_device_vector_procs pdf_vector_procs = { int pdf_remember_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath) { + int code = 0; /* Used for skipping redundant clip paths. SF bug #624168. */ if (pdev->clip_path != 0) { gx_path_free(pdev->clip_path, "pdf clip path"); @@ -247,7 +234,22 @@ pdf_remember_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath) pdev->clip_path = gx_path_alloc(pdev->pdf_memory, "pdf clip path"); if (pdev->clip_path == 0) return_error(gs_error_VMerror); - return gx_cpath_to_path((gx_clip_path *)pcpath, pdev->clip_path); + + code = gx_cpath_to_path((gx_clip_path *)pcpath, pdev->clip_path); + if (code < 0) + return code; + + /* gx_cpath_to_path above ends up going through gx_path_assign_preserve + * which specifically states that the segments of the paths (in this case pcpath + * and pdev->clip_path) must have been allocated with the same allocator. + * If that's not true (eg pdfi running inside GS) then we need to 'unshare' + * the path. Otherwise we mauy end up with pcpath being freed and discarded + * while the pdfwrite devcie still thinks it has a pointer to it. + */ + if (pcpath->path.memory != pdev->pdf_memory) + code = gx_path_unshare(pdev->clip_path); + + return code; } /* Check if same clipping path. */ @@ -778,38 +780,6 @@ pdf_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath) } /* - * Compute the scaling to ensure that user coordinates for a path are within - * Acrobat's range. Return true if scaling was needed. In this case, the - * CTM will be multiplied by *pscale, and all coordinates will be divided by - * *pscale. - */ -static bool -make_rect_scaling(const gx_device_pdf *pdev, const gs_fixed_rect *bbox, - double prescale, double *pscale) -{ - double bmin, bmax; - - if (pdev->CompatibilityLevel > 1.4) { - *pscale = 1; - return false; - } - - bmin = min(bbox->p.x / pdev->scale.x, bbox->p.y / pdev->scale.y) * prescale; - bmax = max(bbox->q.x / pdev->scale.x, bbox->q.y / pdev->scale.y) * prescale; - if (bmin <= int2fixed(-MAX_USER_COORD) || - bmax > int2fixed(MAX_USER_COORD) - ) { - /* Rescale the path. */ - *pscale = max(bmin / int2fixed(-MAX_USER_COORD), - bmax / int2fixed(MAX_USER_COORD)); - return true; - } else { - *pscale = 1; - return false; - } -} - -/* * Prepare a fill with a color anc a clipping path. * Return 1 if there is nothing to paint. * Changes *box to the clipping box. @@ -1652,9 +1622,6 @@ gdev_pdf_fill_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath, return code; { stream *s = pdev->strm; - double scale; - gs_matrix smat; - gs_matrix *psmat = NULL; gs_path_enum cenum; gdev_vector_dopath_state_t state; @@ -1667,19 +1634,11 @@ gdev_pdf_fill_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath, pprintg1(s, "%g i\n", params->flatness); pdev->state.flatness = params->flatness; } - if (make_rect_scaling(pdev, &box1, 1.0, &scale)) { - gs_make_scaling(pdev->scale.x * scale, pdev->scale.y * scale, - &smat); - pdf_put_matrix(pdev, "q ", &smat, "cm\n"); - psmat = &smat; - } - code = pdf_write_path(pdev, (gs_path_enum *)&cenum, &state, (gx_path *)ppath, 0, gx_path_type_fill | gx_path_type_optimize, psmat); + code = pdf_write_path(pdev, (gs_path_enum *)&cenum, &state, (gx_path *)ppath, 0, gx_path_type_fill | gx_path_type_optimize, NULL); if (code < 0) return code; stream_puts(s, (params->rule < 0 ? "f\n" : "f*\n")); - if (psmat) - stream_puts(s, "Q\n"); } return 0; } @@ -1693,10 +1652,9 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_device_pdf *pdev = (gx_device_pdf *) dev; stream *s; int code; - double scale, path_scale; + double scale; bool set_ctm; gs_matrix mat; - double prescale = 1; gs_fixed_rect bbox; gs_path_enum cenum; gdev_vector_dopath_state_t state; @@ -1782,20 +1740,6 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_gstate * pgs, scale = fabs(pgs->ctm.xx + pgs->ctm.xy + pgs->ctm.yx + pgs->ctm.yy) /* Using the non-zero coeff. */ / sqrt(2); /* Empirically from Adobe. */ } - if (set_ctm) { - /* - * We want a scaling factor that will bring the largest reasonable - * user coordinate within bounds. We choose a factor based on the - * minor axis of the transformation. Thanks to Raph Levien for - * the following formula. - */ - double a = mat.xx, b = mat.xy, c = mat.yx, d = mat.yy; - double u = fabs(a * d - b * c); - double v = a * a + b * b + c * c + d * d; - double minor = (sqrt(v + 2 * u) - sqrt(v - 2 * u)) * 0.5; - - prescale = (minor == 0 || minor > 1 ? 1 : 1 / minor); - } gx_path_bbox(ppath, &bbox); { /* Check whether a painting appears inside the clipping box. @@ -1828,15 +1772,6 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_gstate * pgs, if (stroke_bbox.q.x < stroke_bbox.p.x || stroke_bbox.q.y < stroke_bbox.p.y) return 0; } - if (make_rect_scaling(pdev, &bbox, prescale, &path_scale)) { - scale /= path_scale; - if (set_ctm) - gs_matrix_scale(&mat, path_scale, path_scale, &mat); - else { - gs_make_scaling(path_scale, path_scale, &mat); - set_ctm = true; - } - } code = gdev_vector_prepare_stroke((gx_device_vector *)pdev, pgs, params, pdcolor, scale); if (code < 0) @@ -1903,8 +1838,7 @@ gdev_pdf_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath, } else { bool set_ctm; gs_matrix mat; - double scale, path_scale; - double prescale = 1; + double scale; gs_fixed_rect bbox; gs_path_enum cenum; gdev_vector_dopath_state_t state; @@ -1918,7 +1852,6 @@ gdev_pdf_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath, gx_cpath_outer_box(pcpath, &cbox); if (cbox.p.x >= cbox.q.x || cbox.p.y >= cbox.q.y) return 1; /* empty clipping path */ -// *box = cbox; } code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs); if (code < 0) @@ -1968,20 +1901,6 @@ gdev_pdf_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath, scale = fabs(pgs->ctm.xx + pgs->ctm.xy + pgs->ctm.yx + pgs->ctm.yy) /* Using the non-zero coeff. */ / sqrt(2); /* Empirically from Adobe. */ } - if (set_ctm) { - /* - * We want a scaling factor that will bring the largest reasonable - * user coordinate within bounds. We choose a factor based on the - * minor axis of the transformation. Thanks to Raph Levien for - * the following formula. - */ - double a = mat.xx, b = mat.xy, c = mat.yx, d = mat.yy; - double u = fabs(a * d - b * c); - double v = a * a + b * b + c * c + d * d; - double minor = (sqrt(v + 2 * u) - sqrt(v - 2 * u)) * 0.5; - - prescale = (minor == 0 || minor > 1 ? 1 : 1 / minor); - } gx_path_bbox(ppath, &bbox); { /* Check whether a painting appears inside the clipping box. @@ -2014,15 +1933,6 @@ gdev_pdf_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath, if (stroke_bbox.q.x < stroke_bbox.p.x || stroke_bbox.q.y < stroke_bbox.p.y) return 0; } - if (make_rect_scaling(pdev, &bbox, prescale, &path_scale)) { - scale /= path_scale; - if (set_ctm) - gs_matrix_scale(&mat, path_scale, path_scale, &mat); - else { - gs_make_scaling(path_scale, path_scale, &mat); - set_ctm = true; - } - } code = pdf_setfillcolor((gx_device_vector *)pdev, pgs, pdcolor_fill); if (code == gs_error_rangecheck) { @@ -2077,9 +1987,6 @@ gdev_pdf_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, int code; gs_fixed_rect box1 = *rect, box = box1; gx_device_pdf *pdev = (gx_device_pdf *) dev; - double scale; - gs_matrix smat; - gs_matrix *psmat = NULL; const bool convert_to_image = (pdev->CompatibilityLevel <= 1.2 && gx_dc_is_pattern2_color(pdcolor)); @@ -2098,16 +2005,9 @@ gdev_pdf_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, rect_intersect(box1, box); if (box1.p.x > box1.q.x || box1.p.y > box1.q.y) return 0; /* outside the clipping path */ - if (make_rect_scaling(pdev, &box1, 1.0, &scale)) { - gs_make_scaling(pdev->scale.x * scale, pdev->scale.y * scale, &smat); - pdf_put_matrix(pdev, "q ", &smat, "cm\n"); - psmat = &smat; - } pprintg4(pdev->strm, "%g %g %g %g re f\n", - fixed2float(box1.p.x) / scale, fixed2float(box1.p.y) / scale, - fixed2float(box1.q.x - box1.p.x) / scale, fixed2float(box1.q.y - box1.p.y) / scale); - if (psmat) - stream_puts(pdev->strm, "Q\n"); + fixed2float(box1.p.x), fixed2float(box1.p.y), + fixed2float(box1.q.x - box1.p.x) , fixed2float(box1.q.y - box1.p.y)); if (pdev->Eps2Write) { gs_rect *Box; diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c index 1c540709..f9544c5d 100644 --- a/devices/vector/gdevpdfe.c +++ b/devices/vector/gdevpdfe.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfg.c b/devices/vector/gdevpdfg.c index 0aa93e53..39da7ea4 100644 --- a/devices/vector/gdevpdfg.c +++ b/devices/vector/gdevpdfg.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -1467,7 +1467,7 @@ int pdf_reset_color(gx_device_pdf * pdev, const gs_gstate * pgs, * unlike shading patterns we have no fallback. */ if (pdev->CompatibilityLevel < 1.2) { - return_error(gs_error_undefined); + return_error(gs_error_undefined); } code = pdf_put_colored_pattern(pdev, pdc, pcs, ppscc, pgs, &pres); @@ -2426,7 +2426,8 @@ pdf_write_spot_halftone(gx_device_pdf *pdev, const gs_spot_halftone *psht, if (compare_gx_ht_order_levels(&order,porder)) continue; if (memcmp(order.bit_data, porder->bit_data, - order.num_bits * porder->procs->bit_data_elt_size)) + (size_t)order.num_bits * + porder->procs->bit_data_elt_size)) continue; /* We have a match. */ break; @@ -2609,7 +2610,7 @@ pdf_get_halftone_component_index(const gs_multiple_halftone *pmht, return j; } static int -pdf_write_multiple_halftone(gx_device_pdf *pdev, +pdf_write_multiple_halftone(gx_device_pdf *pdev, gs_gstate *pgs, const gs_multiple_halftone *pmht, const gx_device_halftone *pdht, long *pid) { @@ -2679,7 +2680,7 @@ pdf_write_multiple_halftone(gx_device_pdf *pdev, done_Default = true; } phtc = &pmht->components[code]; - if ((code = pmht->get_colorname_string(pdev->memory, phtc->cname, &str, &len)) < 0 || + if ((code = pmht->get_colorname_string(pgs, phtc->cname, &str, &len)) < 0 || (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0) return code; cos_value_write(&value, pdev); @@ -2739,7 +2740,7 @@ pdf_update_halftone(gx_device_pdf *pdev, const gs_gstate *pgs, break; case ht_type_multiple: case ht_type_multiple_colorscreen: - code = pdf_write_multiple_halftone(pdev, &pht->params.multiple, + code = pdf_write_multiple_halftone(pdev, (gs_gstate *)pgs, &pht->params.multiple, pdht, &id); break; default: diff --git a/devices/vector/gdevpdfg.h b/devices/vector/gdevpdfg.h index e846b1a8..e9faa670 100644 --- a/devices/vector/gdevpdfg.h +++ b/devices/vector/gdevpdfg.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -347,10 +347,10 @@ int pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex, gs_image_t *pim, pdf_image_writer *piw, int for_pattern); -#endif /* gdevpdfg_INCLUDED */ - /* ---------------- Exported by gdevpdfe.c ---------------- */ /* Write metadata */ int pdf_document_metadata(gx_device_pdf *pdev); int pdf_get_docinfo_item(gx_device_pdf *pdev, const char *key, char *buf, int buf_length); + +#endif /* gdevpdfg_INCLUDED */ diff --git a/devices/vector/gdevpdfi.c b/devices/vector/gdevpdfi.c index b73ed3d6..c6bdee9d 100644 --- a/devices/vector/gdevpdfi.c +++ b/devices/vector/gdevpdfi.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -976,7 +976,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, const gs_pixel_image_t *pim; gs_int_rect rect; gs_image_format_t format; - const gs_color_space *pcs; + gs_color_space *pcs; int num_components; pdf_image_enum *pie; const pdf_color_space_names_t *names; @@ -1213,6 +1213,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, } pcs = pim->ColorSpace; + rc_increment_cs(pcs); num_components = (is_mask ? 1 : gs_color_space_num_components(pcs)); code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs); @@ -1238,6 +1239,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, * to DeviceGray here. */ /* {csrc} make sure this gets freed */ + rc_decrement(pcs, "pdf_begin_typed_image(pcs)"); pcs = gs_cspace_new_DeviceGray(pdev->memory); if (pcs == NULL) code = gs_note_error(gs_error_VMerror); @@ -1401,9 +1403,6 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, if (pdev->params.TransferFunctionInfo == tfi_Apply && pdev->transfer_not_identity && !is_mask) pdev->JPEG_PassThrough = 0; -/* if (pdev->JPEG_PassThrough) - uncompressed = pie->writer.binary[0].strm;*/ - /* Code below here deals with setting up the multiple data stream writing. * We can have up to 4 stream writers, which we keep in an array. We must * always have at least one which writes the uncompressed stream. If we @@ -1612,9 +1611,11 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs, gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), "pdf_begin_typed_image(image)"); + rc_decrement(pcs, "pdf_begin_typed_image(pcs)"); return 0; fail_and_fallback: + rc_decrement(pcs, "pdf_begin_typed_image(pcs)"); pdev->JPEG_PassThrough = 0; gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t), "pdf_begin_typed_image(image)"); @@ -1928,7 +1929,14 @@ pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last, /* Clean up any outstanding streams before freeing the enumerator */ while (pie->writer.alt_writer_count-- > 0) { ecode = psdf_end_binary(&(pie->writer.binary[pie->writer.alt_writer_count])); - if (ecode < 0 && code >= 0) code = ecode; + /* If we are skipping an image (because its clipped out or similar) then we + * won't have written any data to it. Some filters (notably the DCTEncode filter) + * throw an error (premature EOD) if we close the filter without writing any data to it. + * So if we are skipping the image, ignore errors when closing the stream. + * Unfortunately we don't set pie->skipping until after begin_typed_image() + * or we could avoid a lot of setup.... + */ + if (ecode < 0 && code >= 0 && !pie->skipping) code = ecode; } gx_image_free_enum(&info); diff --git a/devices/vector/gdevpdfj.c b/devices/vector/gdevpdfj.c index 0af81fc2..4c73e171 100644 --- a/devices/vector/gdevpdfj.c +++ b/devices/vector/gdevpdfj.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfk.c b/devices/vector/gdevpdfk.c index 7914c0ee..e48718d1 100644 --- a/devices/vector/gdevpdfk.c +++ b/devices/vector/gdevpdfk.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -778,9 +778,10 @@ pdf_iccbased_color_space(gx_device_pdf *pdev, const gs_gstate * pgs, cos_value_t const gs_color_space *pcs, cos_array_t *pca) { cos_stream_t * pcstrm; - int code = 0; + int code = 0, code1 = 0; unsigned char major = 0, minor = 0; bool downgrade_icc = false; + pdf_resource_t *pres = NULL; /* * This would arise only in a pdf ==> pdf translation, but we @@ -864,13 +865,22 @@ pdf_iccbased_color_space(gx_device_pdf *pdev, const gs_gstate * pgs, cos_value_t pcs->cmm_icc_profile_data->buffer_size); } - if (code >= 0) - code = pdf_finish_iccbased(pdev, pcstrm); /* - * The stream has been added to the array: in case of failure, the - * caller will free the array, so there is no need to free the stream - * explicitly here. + * The stream has been added to the array: However because the stream cos object + * has an id (it has to be an indirect object), freeing the colour space won't + * free the ICC profile stream. In order to have the stream freed we must add it to + * a resource chain; we don't have a resource chain for ICC profiles, so add it to + * resourceOther instead. This means it will be among the last objects released. */ + code1 = pdf_alloc_resource(pdev, resourceOther, pcstrm->id, &pres, -1); + if (code1 >= 0) { + COS_FREE(pres->object, "pdf_iccbased_color_space"); + pres->object = (cos_object_t *)pcstrm; + } + + if (code >= 0) + code = pdf_finish_iccbased(pdev, pcstrm); + return code; } diff --git a/devices/vector/gdevpdfm.c b/devices/vector/gdevpdfm.c index 6e018aa4..18ea50c5 100644 --- a/devices/vector/gdevpdfm.c +++ b/devices/vector/gdevpdfm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfo.c b/devices/vector/gdevpdfo.c index 402d290c..70b66c6b 100644 --- a/devices/vector/gdevpdfo.c +++ b/devices/vector/gdevpdfo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -1132,6 +1132,10 @@ static int write_key_as_string_encrypted(const gx_device_pdf *pdev, const byte * memcpy(buffer, str, size); s_arcfour_process_buffer(&sarc4, buffer, size); stream_write(&sout, buffer, size); + /* Another case where we use sclose() and not s_close_filters(), because the + * buffer we supplied to s_init_filter is a heap based C object, so we + * must not free it. + */ sclose(&sout); /* Writes ')'. */ gs_free_object(pdev->pdf_memory, buffer, "Free encryption buffer"); return 0; diff --git a/devices/vector/gdevpdfo.h b/devices/vector/gdevpdfo.h index 0b6ef201..b30e9676 100644 --- a/devices/vector/gdevpdfo.h +++ b/devices/vector/gdevpdfo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfp.c b/devices/vector/gdevpdfp.c index 2f29dba5..d06e585c 100644 --- a/devices/vector/gdevpdfp.c +++ b/devices/vector/gdevpdfp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfr.c b/devices/vector/gdevpdfr.c index 6d9f7f6f..b0ee06c4 100644 --- a/devices/vector/gdevpdfr.c +++ b/devices/vector/gdevpdfr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdft.c b/devices/vector/gdevpdft.c index 46f4d312..a963cb51 100644 --- a/devices/vector/gdevpdft.c +++ b/devices/vector/gdevpdft.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -107,7 +107,7 @@ pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams a group color specified. In this case, the parent group is inherited from the previous group or the device color space */ - if (pgs != NULL && pparams->group_color != UNKNOWN) { + if (pgs != NULL && pparams->group_color_type != UNKNOWN) { const gs_color_space *cs = gs_currentcolorspace_inline(pgs); code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, cs, @@ -274,7 +274,7 @@ pdf_begin_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams) { if (pparams->subtype == TRANSPARENCY_MASK_None) { - int code, id = pgs->soft_mask_id; + int code; pdf_resource_t *pres = 0L; /* reset the soft mask ID. Apparently this is only used by pdfwrite, if we don't @@ -284,10 +284,11 @@ pdf_begin_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev, pgs->soft_mask_id = 0; code = pdf_prepare_drawing(pdev, pgs, &pres, false); if (code == gs_error_interrupt) { - /* Not in an appropriate context, ignore it but restore - * the old soft_mask_id. Not sure this is correct, but it works for now. + /* */ + /* Not in an appropriate context. Do not restore the soft_mask_id. + Otherwise any group push that occurs following this will use that + softmask, which clearly should be NONE here. */ - pgs->soft_mask_id = id; /* ignore return code, we don't care about this graphics state as we aren't * emitting it anyway */ diff --git a/devices/vector/gdevpdfu.c b/devices/vector/gdevpdfu.c index 05ea7881..e5a9df01 100644 --- a/devices/vector/gdevpdfu.c +++ b/devices/vector/gdevpdfu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -568,6 +568,7 @@ int ps2write_dsc_header(gx_device_pdf * pdev, int pages) if (code < 0) return code; } + stream_puts(s, "10 dict dup begin\n"); stream_puts(s, "/DSC_OPDFREAD true def\n"); if (pdev->Eps2Write) { stream_puts(s, "/SetPageSize false def\n"); @@ -577,6 +578,7 @@ int ps2write_dsc_header(gx_device_pdf * pdev, int pages) stream_puts(s, "/SetPageSize true def\n"); stream_puts(s, "/EPS2Write false def\n"); } + stream_puts(s, "end\n"); code = copy_procsets(s, pdev->HaveTrueTypes, false); if (code < 0) @@ -626,6 +628,7 @@ pdfwrite_pdf_open_document(gx_device_pdf * pdev) if (code < 0) return code; } + stream_puts(s, "10 dict dup begin\n"); stream_puts(s, "/DSC_OPDFREAD false def\n"); code = copy_procsets(s, pdev->HaveTrueTypes, true); if (code < 0) @@ -646,6 +649,7 @@ pdfwrite_pdf_open_document(gx_device_pdf * pdev) stream_puts(s, "/FitPages true def\n"); if(pdev->CenterPages) stream_puts(s, "/CenterPages true def\n"); + stream_puts(s, "end\n"); pdev->OPDFRead_procset_length = stell(s); } } @@ -1000,21 +1004,6 @@ pdf_begin_encrypt(gx_device_pdf * pdev, stream **s, gs_id object_id) */ } -/* Remove the encryption filter. */ -void -pdf_end_encrypt(gx_device_pdf * pdev) -{ - if (pdev->KeyLength) { - stream *s = pdev->strm; - stream *fs = s->strm; - - sclose(s); - gs_free_object(pdev->pdf_memory, s->cbuf, "encrypt buffer"); - gs_free_object(pdev->pdf_memory, s, "encrypt stream"); - pdev->strm = fs; - } -} - /* Enter stream context. */ static int none_to_stream(gx_device_pdf * pdev) @@ -1168,6 +1157,7 @@ stream_to_none(gx_device_pdf * pdev) stream *s = pdev->strm; gs_offset_t length; int code; + stream *target; if (pdev->ResourcesBeforeUsage) { int code = pdf_exit_substream(pdev); @@ -1180,22 +1170,16 @@ stream_to_none(gx_device_pdf * pdev) if (code < 0) return code; } - if (pdev->compression_at_page_start == pdf_compress_Flate) { /* Terminate the filters. */ - stream *fs = s->strm; - - if (!pdev->binary_ok) { - sclose(s); /* Terminate the ASCII85 filter. */ - gs_free_object(pdev->pdf_memory, s->cbuf, "A85E contents buffer"); - gs_free_object(pdev->pdf_memory, s, "A85E contents stream"); - pdev->strm = s = fs; - fs = s->strm; - } - sclose(s); /* Next terminate the compression filter */ - gs_free_object(pdev->pdf_memory, s->cbuf, "zlib buffer"); - gs_free_object(pdev->pdf_memory, s, "zlib stream"); - pdev->strm = fs; - } - pdf_end_encrypt(pdev); + target = pdev->strm; + + if (pdev->compression_at_page_start == pdf_compress_Flate) + target = target->strm; + if (!pdev->binary_ok) + target = target->strm; + if (pdf_end_encrypt(pdev)) + target = target->strm; + s_close_filters(&pdev->strm, target); + s = pdev->strm; length = pdf_stell(pdev) - pdev->contents_pos; if (pdev->PDFA != 0) @@ -2014,13 +1998,18 @@ pdf_unclip(gx_device_pdf * pdev) /* ------ Miscellaneous output ------ */ /* Generate the default Producer string. */ +/* This calculation is also performed for Ghostscript generally + * The code is in ghostpdl/base/gsmisc.c printf_program_ident(). + * Should we change this calculation both sets of code need to be updated. + */ void pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER]) { - if ((gs_revision % 100) == 0) - gs_sprintf(buf, "(%s %1.1f)", gs_product, gs_revision / 100.0); - else - gs_sprintf(buf, "(%s %1.2f)", gs_product, gs_revision / 100.0); + 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); } /* Write matrix values. */ @@ -2133,6 +2122,10 @@ pdf_encrypt_encoded_string(const gx_device_pdf *pdev, const byte *str, uint size break; } } + /* Another case where we use sclose() and not sclose_filters(), because the + * buffer we supplied to s_init_filter is a heap based C object, so we + * must not free it. + */ sclose(&sout); /* Writes ')'. */ return (int)stell(&sinp) + 1; } @@ -2697,7 +2690,7 @@ pdf_function_aux(gx_device_pdf *pdev, const gs_function_t *pfn, stream_write(writer.strm, ptr, count); } code = psdf_end_binary(&writer); - sclose(s); + s_close_filters(&s, s->strm); } pdev->strm = save; if (code < 0) diff --git a/devices/vector/gdevpdfv.c b/devices/vector/gdevpdfv.c index 2f71d86a..dd7d4c7c 100644 --- a/devices/vector/gdevpdfv.c +++ b/devices/vector/gdevpdfv.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdfx.h b/devices/vector/gdevpdfx.h index 0e43a028..c8b44b46 100644 --- a/devices/vector/gdevpdfx.h +++ b/devices/vector/gdevpdfx.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -41,7 +41,11 @@ * Windows and Linux fail with coordinates outside +/- 16383. Hence, we * limit coordinates to 16k, with a little slop. */ -#define MAX_USER_COORD 16300 +/* 28/05/2020 This was only being applied to text and a subset of paths. Since + * Acrobat 4 is now more than 20 years old, lets just drop support for it. The + * PDF specification never had this limit, just Adobe's software. + */ +/* #define MAX_USER_COORD 16300 */ /* ---------------- Statically allocated sizes ---------------- */ /* These should really be dynamic.... */ @@ -1168,7 +1172,12 @@ int pdf_copy_data_safe(stream *s, gp_file *file, gs_offset_t position, long coun /* Add the encryption filter. */ int pdf_begin_encrypt(gx_device_pdf * pdev, stream **s, gs_id object_id); /* Remove the encryption filter. */ -void pdf_end_encrypt(gx_device_pdf * pdev); +static int inline pdf_end_encrypt(gx_device_pdf *pdev) +{ + if (pdev->KeyLength) + return 1; + return 0; +} /* Initialize encryption. */ int pdf_encrypt_init(const gx_device_pdf * pdev, gs_id object_id, stream_arcfour_state *psarc4); diff --git a/devices/vector/gdevpdt.c b/devices/vector/gdevpdt.c index 6a3b5a7f..970dd76a 100644 --- a/devices/vector/gdevpdt.c +++ b/devices/vector/gdevpdt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdt.h b/devices/vector/gdevpdt.h index a4e736db..ee7a1c1e 100644 --- a/devices/vector/gdevpdt.h +++ b/devices/vector/gdevpdt.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtb.c b/devices/vector/gdevpdtb.c index 9caa640e..61961c4a 100644 --- a/devices/vector/gdevpdtb.c +++ b/devices/vector/gdevpdtb.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -359,7 +359,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%lx", (ulong)copied); + gs_sprintf(fnbuf, ".F" PRI_INTPTR, (intptr_t)copied); font_name.data = (byte *)fnbuf; font_name.size = strlen(fnbuf); } diff --git a/devices/vector/gdevpdtb.h b/devices/vector/gdevpdtb.h index 1e160eb1..8753aa98 100644 --- a/devices/vector/gdevpdtb.h +++ b/devices/vector/gdevpdtb.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtc.c b/devices/vector/gdevpdtc.c index 95af86ff..5c6da535 100644 --- a/devices/vector/gdevpdtc.c +++ b/devices/vector/gdevpdtc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtd.c b/devices/vector/gdevpdtd.c index 45e2888e..ce6efa05 100644 --- a/devices/vector/gdevpdtd.c +++ b/devices/vector/gdevpdtd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtd.h b/devices/vector/gdevpdtd.h index 9c3078e2..92e64758 100644 --- a/devices/vector/gdevpdtd.h +++ b/devices/vector/gdevpdtd.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdte.c b/devices/vector/gdevpdte.c index 3e7e2237..6f0eb158 100644 --- a/devices/vector/gdevpdte.c +++ b/devices/vector/gdevpdte.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -160,6 +160,8 @@ pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfon if (pdfont->cmap_ToUnicode != NULL) gs_cmap_ToUnicode_add_pair(pdfont->cmap_ToUnicode, ch, unicode, length); + if (length > 2 && pdfont->u.simple.Encoding != NULL) + pdfont->TwoByteToUnicode = 0; } if (unicode) gs_free_object(pdev->memory, unicode, "temporary Unicode array"); diff --git a/devices/vector/gdevpdtf.c b/devices/vector/gdevpdtf.c index d14fa346..c823b18c 100644 --- a/devices/vector/gdevpdtf.c +++ b/devices/vector/gdevpdtf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -572,6 +572,7 @@ font_resource_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, pfres->u.simple.BaseEncoding = -1; pfres->u.simple.preferred_encoding_index = -1; pfres->u.simple.last_reserved_char = -1; + pfres->TwoByteToUnicode = 1; *ppfres = pfres; return 0; } diff --git a/devices/vector/gdevpdtf.h b/devices/vector/gdevpdtf.h index 4a9e8961..f0006641 100644 --- a/devices/vector/gdevpdtf.h +++ b/devices/vector/gdevpdtf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -203,6 +203,15 @@ struct pdf_font_resource_s { gs_cmap_t *cmap_ToUnicode; /* CMap (not used for CIDFonts) */ gs_glyph_mark_proc_t mark_glyph; void *mark_glyph_data; /* closure data */ + + /* We use this when determining whether we should use an existing ToUnicode + * CMap or just use the Encoding, for s aimple font. Even if the Encoding + * only uses named glyphs, with names we can understand, the original + * ToUnicode may have mapped these in a non-standard way. + * See Bug #702201 where the ffi ligature is mapped to 3 code points + */ + int TwoByteToUnicode; + union { struct /*type0*/ { @@ -253,7 +262,6 @@ struct pdf_font_resource_s { gs_point *v; /* [256], glyph origin for WMode 1 */ int last_reserved_char; /* Except for synthesised Type 3, which stores such data in LastChar */ - gs_glyph standard_glyph_code_for_notdef; union { diff --git a/devices/vector/gdevpdti.c b/devices/vector/gdevpdti.c index 7ba56fd6..0205604a 100644 --- a/devices/vector/gdevpdti.c +++ b/devices/vector/gdevpdti.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -479,7 +479,9 @@ pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos) stream *s; gs_offset_t start_pos, end_pos, length; - pdf_end_encrypt(pdev); + if (pdf_end_encrypt(pdev)) + s_close_filters(&pdev->strm, pdev->strm->strm); + s = pdev->strm; start_pos = ppos->start_pos; end_pos = stell(s); diff --git a/devices/vector/gdevpdti.h b/devices/vector/gdevpdti.h index 65e1efcb..81409e67 100644 --- a/devices/vector/gdevpdti.h +++ b/devices/vector/gdevpdti.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdts.c b/devices/vector/gdevpdts.c index 055aeb44..aa41f516 100644 --- a/devices/vector/gdevpdts.c +++ b/devices/vector/gdevpdts.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -81,11 +81,6 @@ append_text_move(pdf_text_state_t *pts, double dw) rounded = floor(dw + 0.5); if (fabs(dw - rounded) < 0.001) dw = rounded; - if (dw < -MAX_USER_COORD) { - /* Acrobat reader 4.0c, 5.0 can't handle big offsets. - Adobe Reader 6 can. */ - return -1; - } if (dw != 0) { if (count == MAX_TEXT_BUFFER_MOVES) return -1; @@ -173,47 +168,11 @@ add_text_delta_move(gx_device_pdf *pdev, const gs_matrix *pmat) * for the xhow and once for the Width override. Otherwise, we do * want to use TJ as it makes for smaller files. */ - if (pts->can_use_TJ && dnotw == 0 && pts->buffer.count_chars > 0 && - /* - * Acrobat Reader limits the magnitude of user-space - * coordinates. Also, AR apparently doesn't handle large - * positive movement values (negative X displacements), even - * though the PDF Reference says this bug was fixed in AR3. - * - * Old revisions used the upper threshold 1000 for tdw, - * but it appears too big when a font sets a too big - * character width in setcachedevice. Particularly this happens - * with a Type 3 font generated by Aldus Freehand 4.0 - * to represent a texture - see bug #687051. - * The problem is that when the Widths is multiplied - * to the font size, the viewer represents the result - * with insufficient fraction bits to represent the precise width. - * We work around that problem here restricting tdw - * with a smaller threshold 990. Our intention is to - * disable Tj when the real glyph width appears smaller - * than 1% of the width specified in setcachedevice. - * A Td instruction will be generated instead. - * Note that the value 990 is arbitrary and may need a - * further adjustment. - */ - /* Revised the above. It seems unreasonable to use a fixed - * value which is not based on the point size, when the problem is - * caused by a large point size being multiplied by the width. The - * original fix also caused bitmap fonts (from PCL and other sources) - * to fail to use kerning, as these fonts are scaled to 1 point and - * therefore use large kerning values. Instead we check the kerned value - * multiplied by the point size of the font. - */ - (tdw >= -MAX_USER_COORD && (tdw * pts->in.size) < MAX_USER_COORD) - ) { + if (pts->can_use_TJ && dnotw == 0 && pts->buffer.count_chars > 0) { /* Use TJ. */ int code; - if (tdw < MAX_USER_COORD || pdev->CompatibilityLevel > 1.4) - code = append_text_move(pts, tdw); - else - return -1; - + code = append_text_move(pts, tdw); if (code >= 0) goto finish; } diff --git a/devices/vector/gdevpdts.h b/devices/vector/gdevpdts.h index cde7a3c8..b3699eb2 100644 --- a/devices/vector/gdevpdts.h +++ b/devices/vector/gdevpdts.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtt.c b/devices/vector/gdevpdtt.c index f248e998..5884115e 100644 --- a/devices/vector/gdevpdtt.c +++ b/devices/vector/gdevpdtt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtt.h b/devices/vector/gdevpdtt.h index cf3b7625..9a710151 100644 --- a/devices/vector/gdevpdtt.h +++ b/devices/vector/gdevpdtt.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtv.c b/devices/vector/gdevpdtv.c index eb9a18fe..a16a48d7 100644 --- a/devices/vector/gdevpdtv.c +++ b/devices/vector/gdevpdtv.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtv.h b/devices/vector/gdevpdtv.h index 89502365..5e27ecd1 100644 --- a/devices/vector/gdevpdtv.h +++ b/devices/vector/gdevpdtv.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtw.c b/devices/vector/gdevpdtw.c index be3c874d..6d197bd5 100644 --- a/devices/vector/gdevpdtw.c +++ b/devices/vector/gdevpdtw.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -119,6 +119,9 @@ pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t *pdfont) In this circumstance, write the ToUnicode map to get a searchable PDF. */ return true; + if (!pdfont->TwoByteToUnicode) + return true; + for (ch = 0; ch < 256; ++ch) { pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; gs_glyph glyph = pet->glyph; @@ -136,6 +139,7 @@ pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t *pdfont) if( glyph > GS_C_PDF_MAX_GOOD_GLYPH || !(gs_c_pdf_glyph_type[glyph >> 2] & (mask << (( glyph & 3 )<<1) ))) return true; + } return false; } diff --git a/devices/vector/gdevpdtw.h b/devices/vector/gdevpdtw.h index 4ff32453..34feeed2 100644 --- a/devices/vector/gdevpdtw.h +++ b/devices/vector/gdevpdtw.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpdtx.h b/devices/vector/gdevpdtx.h index 92374aa0..d5fe6177 100644 --- a/devices/vector/gdevpdtx.h +++ b/devices/vector/gdevpdtx.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsdf.h b/devices/vector/gdevpsdf.h index 5047f43a..a20c61b0 100644 --- a/devices/vector/gdevpsdf.h +++ b/devices/vector/gdevpsdf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -194,7 +194,7 @@ extern const stream_template s_zlibE_template; 500000, /* ImageMemory */ \ 0, /* LockDistillerParams (false) */ \ 0, /* LZWEncodePages (false) */ \ - 1, /* Overprintmode (OPM) */ \ + 0, /* Overprintmode (OPM) */ \ 0, /* PreserveOPIComments (false) */ \ 1, /* UseFlateCompression (true) */ \ /* Color processing parameters */\ @@ -332,8 +332,7 @@ extern_st(st_device_psdf); params.MonoImage.Dict),\ GC_OBJ_ELT2(gx_device_psdf, params.AlwaysEmbed.data,\ params.NeverEmbed.data),\ - GC_CONST_STRING_ELT(gx_device_psdf, params.PSDocOptions),\ - GC_OBJ_ELT(gx_device_psdf, params.PSPageOptions.data)\ + GC_CONST_STRING_ELT(gx_device_psdf, params.PSDocOptions)\ };\ gs_public_st_basic_super_final(st_device_psdf, gx_device_psdf,\ "gx_device_psdf", device_psdf_ptrs, device_psdf_data,\ diff --git a/devices/vector/gdevpsdi.c b/devices/vector/gdevpsdi.c index 9c2adb72..f093edf1 100644 --- a/devices/vector/gdevpsdi.c +++ b/devices/vector/gdevpsdi.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -529,7 +529,7 @@ setup_downsampling(psdf_binary_writer * pbw, const psdf_image_params * pdip, ss->params.EntireWidthIn = ss->params.WidthIn = ss->params.PatchWidthIn = pim->Width; ss->params.EntireHeightIn = ss->params.HeightIn = ss->params.PatchHeightIn = pim->Height; ss->params.EntireWidthOut = ss->params.WidthOut = ss->params.PatchWidthOut = s_Downsample_size_out(pim->Width, factor, false); - ss->params.EntireHeightOut = ss->params.HeightOut = s_Downsample_size_out(pim->Height, factor, false); + ss->params.EntireHeightOut = ss->params.HeightOut = ss->params.PatchHeightOut = ss->params.PatchHeightOut2 = s_Downsample_size_out(pim->Height, factor, false); /* Bug #697944 The code below to apply the downsampling filter always * resizes the input data to the filter with 8BPC and then resizes the output back to whatever @@ -539,8 +539,8 @@ setup_downsampling(psdf_binary_writer * pbw, const psdf_image_params * pdip, ss->params.BitsPerComponentIn = ss->params.BitsPerComponentOut = 8; ss->params.spp_interp = ss->params.spp_decode = Colors; - ss->params.TopMarginIn = ss->params.TopMarginOut = ss->params.LeftMarginIn = ss->params.LeftMarginOut = 0; - ss->params.src_y_offset = 0; + ss->params.TopMarginIn = ss->params.TopMarginOut = ss->params.TopMarginOut2 = ss->params.LeftMarginIn = ss->params.LeftMarginOut = 0; + ss->params.src_y_offset = ss->params.pad_y = 0; ss->params.early_cm = true; ss->params.MaxValueIn = ss->params.MaxValueOut = (int)pow(2, pdip->Depth); diff --git a/devices/vector/gdevpsdp.c b/devices/vector/gdevpsdp.c index bda3fe2a..c8a48ee5 100644 --- a/devices/vector/gdevpsdp.c +++ b/devices/vector/gdevpsdp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -232,7 +232,7 @@ static const gs_param_item_t psdf_param_items[] = { /* (DefaultRenderingIntent) */ pi("DetectBlends", gs_param_type_bool, DetectBlends), pi("DoThumbnails", gs_param_type_bool, DoThumbnails), - pi("ImageMemory", gs_param_type_long, ImageMemory), + pi("ImageMemory", gs_param_type_size_t, ImageMemory), /* (LockDistillerParams) */ pi("LZWEncodePages", gs_param_type_bool, LZWEncodePages), pi("OPM", gs_param_type_int, OPM), @@ -625,6 +625,10 @@ gdev_psdf_get_params(gx_device * dev, gs_param_list * plist) if (code < 0) return code; + code = param_write_string_array(plist, "PSPageOptions", &pdev->params.PSPageOptions); + if (code < 0) + return code; + code = psdf_write_name(plist, "CannotEmbedFontPolicy", CannotEmbedFontPolicy_names[(int)pdev->params.CannotEmbedFontPolicy]); @@ -1040,6 +1044,65 @@ psdf_put_image_params(const gx_device_psdf * pdev, gs_param_list * plist, return ecode; } +/* This is a convenience routine. There doesn't seem to be any way to have a param_string_array + * enumerated for garbage collection, and we have (currently) three members of the psdf_distiller_params + * structure which store param_string_array. If the interpreter is using garbage collection then there + * is the potential for the array, or its contents, to be relocated or freed while we are still + * maintaining pointers to them, unless we enumerate the pointers. + * Instead, we'll copy the string data from the interpreter, make our own param_string_array, and + * manage the memory ourselves. This allows us to move the data into non-GC memory which is preferable + * anyway. + */ +static int psdf_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, gs_param_string_array *sa, gs_param_string_array *da) +{ + int code; + + if (sa->size > 0) { + int ix; + byte **dest; + + if (da->data != NULL) { + for (ix = 0; ix < da->size;ix++) + gs_free_object(mem->non_gc_memory, (byte *)da->data[ix].data, "freeing old string array copy"); + gs_free_object(mem->non_gc_memory, (byte *)da->data, "freeing old string array"); + } + da->data = (const gs_param_string *)gs_alloc_bytes(mem->non_gc_memory, sa->size * sizeof(gs_param_string), "allocate new string array"); + if (da->data == NULL) + return_error(gs_note_error(gs_error_VMerror)); + memset((byte *)da->data, 0x00, sa->size * sizeof(gs_param_string)); + da->size = sa->size; + da->persistent = false; + + for(ix=0;ix < sa->size;ix++) { + ((gs_param_string *)&da->data[ix])->data = gs_alloc_bytes(mem->non_gc_memory, sa->data[ix].size, "allocate new strings"); + if (da->data[ix].data == NULL) + return_error(gs_note_error(gs_error_VMerror)); + memcpy((byte *)(da->data[ix].data), sa->data[ix].data, sa->data[ix].size); + ((gs_param_string *)&da->data[ix])->size = sa->data[ix].size; + ((gs_param_string *)&da->data[ix])->persistent = false; + } + gs_free_object(plist->memory, (byte *)sa->data, "freeing temporary param string array"); + sa->data = NULL; + sa->size = 0; + } + return 0; +} + +static int psdf_read_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, char *Key, gs_param_string_array *da) +{ + gs_param_string_array sa; + int code; + + code = param_read_embed_array(plist, Key, &sa); + if (code < 0) + return code; + + if(sa.size) + code = psdf_copy_param_string_array(mem, plist, &sa, da); + + return code; +} + /* Put parameters. */ int gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) @@ -1076,6 +1139,8 @@ gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) params.MonoImage.ACSDict = params.MonoImage.Dict = 0; params.AlwaysEmbed.data = params.NeverEmbed.data = 0; params.AlwaysEmbed.size = params.AlwaysEmbed.persistent = params.NeverEmbed.size = params.NeverEmbed.persistent = 0; + params.PSPageOptions.data = NULL; + params.PSPageOptions.size = 0; } /* General parameters. */ @@ -1184,6 +1249,7 @@ gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) ¶ms.AlwaysEmbed, mem, ecode); ecode = psdf_put_embed_param(plist, "~NeverEmbed", ".NeverEmbed", ¶ms.NeverEmbed, mem, ecode); + params.CannotEmbedFontPolicy = (enum psdf_cannot_embed_font_policy) psdf_put_enum(plist, "CannotEmbedFontPolicy", (int)params.CannotEmbedFontPolicy, @@ -1199,7 +1265,7 @@ gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) if (code < 0) goto exit; - code = param_read_embed_array(plist, "PSPageOptions", ¶ms.PSPageOptions); + code = psdf_read_copy_param_string_array(pdev->memory, plist, "PSPageOptions", ¶ms.PSPageOptions); if (code < 0) goto exit; @@ -1208,6 +1274,14 @@ gdev_psdf_put_params(gx_device * dev, gs_param_list * plist) exit: if (!(pdev->params.LockDistillerParams && params.LockDistillerParams)) { /* Only update the device paramters if there was no error */ + /* If we have any copied param_string_arrays, start by freeing them */ + if (pdev->params.PSPageOptions.size && params.PSPageOptions.size) { + int ix; + + for (ix = 0; ix < pdev->params.PSPageOptions.size;ix++) + gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data[ix].data, "freeing old string array copy"); + gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data, "freeing old string array"); + } pdev->params = params; } else { /* We read a bunch of parameters and are now throwing them away. Either because there @@ -1216,10 +1290,15 @@ exit: */ gs_memory_t *stable_mem = gs_memory_stable(mem); - if (params.NeverEmbed.data != 0) - gs_free_object(stable_mem, (void *)params.NeverEmbed.data, "free dummy param NeverEmbed"); - if (params.AlwaysEmbed.data != 0) - gs_free_object(stable_mem, (void *)params.AlwaysEmbed.data, "free dummy param AlwaysEmbed"); + if (params.PSPageOptions.data != NULL) { + int ix; + + for (ix = 0; ix < pdev->params.PSPageOptions.size;ix++) + gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data[ix].data, "freeing dummy PSPageOptions"); + gs_free_object(mem->non_gc_memory, (byte *)pdev->params.PSPageOptions.data, "freeing dummy PSPageOptions"); + params.PSPageOptions.data = NULL; + params.PSPageOptions.size = 0; + } if (params.CalCMYKProfile.data != 0) gs_free_string(stable_mem, (void *)params.CalCMYKProfile.data, params.CalCMYKProfile.size, "free dummy param CalCMYKProfile"); if (params.CalGrayProfile.data != 0) diff --git a/devices/vector/gdevpsds.c b/devices/vector/gdevpsds.c index 65bbf544..bc932902 100644 --- a/devices/vector/gdevpsds.c +++ b/devices/vector/gdevpsds.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -822,7 +822,8 @@ s_Bicubic_data_at(stream_Bicubic_state *const ss, int x, int y, int c) y = ss->HeightIn - 1; y -= ss->y_in; idx = ss->l_size * (y < 0 ? 0 : y) + - (x < 0 ? 0 : x >= ss->WidthIn ? ss->WidthIn-1 : x) * ss->Colors + c; + (size_t)(x < 0 ? 0 : x >= ss->WidthIn ? ss->WidthIn-1 : x) * + ss->Colors + c; return (idx < ss->d_len) ? ss->data[idx] : 0; } @@ -952,7 +953,8 @@ s_compr_chooser_set_dimensions(stream_compr_chooser_state * ss, int width, ss->height = height; ss->depth = depth; ss->bits_per_sample = bits_per_sample; - ss->sample = gs_alloc_bytes(ss->memory, width * depth, "s_compr_chooser_set_dimensions"); + ss->sample = gs_alloc_bytes(ss->memory, (size_t)width * depth, + "s_compr_chooser_set_dimensions"); if (ss->sample == 0) return_error(gs_error_VMerror); return 0; diff --git a/devices/vector/gdevpsds.h b/devices/vector/gdevpsds.h index 35a756f0..207e54c4 100644 --- a/devices/vector/gdevpsds.h +++ b/devices/vector/gdevpsds.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsdu.c b/devices/vector/gdevpsdu.c index d626358a..c4be6ac0 100644 --- a/devices/vector/gdevpsdu.c +++ b/devices/vector/gdevpsdu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsf.h b/devices/vector/gdevpsf.h index 275e526d..9105eb86 100644 --- a/devices/vector/gdevpsf.h +++ b/devices/vector/gdevpsf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsf1.c b/devices/vector/gdevpsf1.c index 7e167b45..feed79eb 100644 --- a/devices/vector/gdevpsf1.c +++ b/devices/vector/gdevpsf1.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsf2.c b/devices/vector/gdevpsf2.c index 985cd25e..3c38e988 100644 --- a/devices/vector/gdevpsf2.c +++ b/devices/vector/gdevpsf2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -703,7 +703,7 @@ cff_write_Top_fdarray(cff_writer_t *pcw, gs_font_base *pbfont, gs_font_info_t info; cff_get_Top_info_common(pcw, pbfont, false, &info); - cff_write_Top_common(pcw, pbfont, false, &info); + cff_write_Top_common(pcw, pbfont, true, &info); cff_put_int(pcw, Private_size); cff_put_int_value(pcw, Private_offset, TOP_Private); if (pfname->size == 0) diff --git a/devices/vector/gdevpsfm.c b/devices/vector/gdevpsfm.c index fea025ef..b38266c2 100644 --- a/devices/vector/gdevpsfm.c +++ b/devices/vector/gdevpsfm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsft.c b/devices/vector/gdevpsft.c index 970a3149..9bc00312 100644 --- a/devices/vector/gdevpsft.c +++ b/devices/vector/gdevpsft.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsfu.c b/devices/vector/gdevpsfu.c index 157c7bab..e848bdc8 100644 --- a/devices/vector/gdevpsfu.c +++ b/devices/vector/gdevpsfu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsfx.c b/devices/vector/gdevpsfx.c index b839f9e8..43459327 100644 --- a/devices/vector/gdevpsfx.c +++ b/devices/vector/gdevpsfx.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsu.c b/devices/vector/gdevpsu.c index 094ff945..5e3e5a2b 100644 --- a/devices/vector/gdevpsu.c +++ b/devices/vector/gdevpsu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpsu.h b/devices/vector/gdevpsu.h index 70cceeaf..c62ed8c6 100644 --- a/devices/vector/gdevpsu.h +++ b/devices/vector/gdevpsu.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevpx.c b/devices/vector/gdevpx.c index a1fce1b7..5195339f 100644 --- a/devices/vector/gdevpx.c +++ b/devices/vector/gdevpx.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c index 87f9355d..d46a935e 100644 --- a/devices/vector/gdevtxtw.c +++ b/devices/vector/gdevtxtw.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -34,6 +34,7 @@ #include "gxdevsop.h" #include "gzpath.h" #include "gdevkrnlsclass.h" /* 'standard' built in subclasses, currently First/Last Page and obejct filter */ +#include "gxchar.h" /* #define TRACE_TXTWRITE 1 */ @@ -73,6 +74,7 @@ typedef struct text_list_entry_s { gs_point end; gs_point FontBBox_bottomleft, FontBBox_topright; float *Widths; + float *Advs; unsigned short *Unicode_Text; int Unicode_Text_Size; int render_mode; @@ -140,10 +142,14 @@ static dev_proc_dev_spec_op(txtwrite_dev_spec_op); /* Define the text enumerator. */ typedef struct textw_text_enum_s { gs_text_enum_common; + gs_text_enum_t *pte_fallback; + double d1_width; + bool d1_width_set; bool charproc_accum; bool cdevproc_callout; double cdevproc_result[10]; float *Widths; + float *Advs; unsigned short *TextBuffer; int TextBufferIndex; text_list_entry_t *text_state; @@ -289,7 +295,7 @@ txtwrite_close_device(gx_device * dev) } #ifdef TRACE_TXTWRITE - fclose(tdev->DebugFile); + gp_fclose(tdev->DebugFile); #endif return code; } @@ -339,14 +345,14 @@ static int merge_vertically(gx_device_txtwrite_t *tdev) to = y_list->x_ordered_list; from = next->x_ordered_list; #ifdef TRACE_TXTWRITE - fprintf(tdev->DebugFile, "\nConsolidating two horizontal lines, line 1:"); + gp_fprintf(tdev->DebugFile, "\nConsolidating two horizontal lines, line 1:"); debug_x = from; while (debug_x) { gp_fprintf(tdev->DebugFile, "\n\t"); gp_fwrite(debug_x->Unicode_Text, sizeof(unsigned short), debug_x->Unicode_Text_Size, tdev->DebugFile); debug_x = debug_x->next; } - fprintf(tdev->DebugFile, "\nConsolidating two horizontal lines, line 2"); + gp_fprintf(tdev->DebugFile, "\nConsolidating two horizontal lines, line 2"); debug_x = to; while (debug_x) { gp_fprintf(tdev->DebugFile, "\n\t"); @@ -384,14 +390,14 @@ static int merge_vertically(gx_device_txtwrite_t *tdev) } y_list->x_ordered_list = new_order; #ifdef TRACE_TXTWRITE - fprintf(tdev->DebugFile, "\nAfter:"); + gp_fprintf(tdev->DebugFile, "\nAfter:"); debug_x = new_order; while (debug_x) { gp_fprintf(tdev->DebugFile, "\n\t"); gp_fwrite(debug_x->Unicode_Text, sizeof(unsigned short), debug_x->Unicode_Text_Size, tdev->DebugFile); debug_x = debug_x->next; } - fprintf(tdev->DebugFile, "\n"); + gp_fprintf(tdev->DebugFile, "\n"); #endif y_list->next = next->next; if (next->next) @@ -830,6 +836,46 @@ static int decorated_text_output(gx_device_txtwrite_t *tdev) return 0; } +static int extract_text_output(gx_device_txtwrite_t *tdev) +{ + text_list_entry_t* entry; + gp_fprintf(tdev->file, "<page>\n"); + for (entry = tdev->PageData.unsorted_text_list; + entry; + entry = entry->next + ) { + float x = entry->start.x; + int i; + gp_fprintf(tdev->file, + "<span bbox=\"%0.4f %0.4f %0.4f %0.4f\" font=\"%s\" size=\"%0.4f\">\n", + entry->start.x, + entry->start.y, + entry->end.x, + entry->end.y, + entry->FontName, + entry->size + ); + for (i=0; i<entry->Unicode_Text_Size; i++) { + float x_next = x + entry->Widths[i]; + char escaped[32]; + escaped_Unicode(entry->Unicode_Text[i], escaped); + gp_fprintf(tdev->file, + "<char bbox=\"%0.4f %0.4f %0.4f %0.4f\" c=\"%s\" adv=\"%0.4f\"/>\n", + x, + entry->start.y, + x_next, + entry->end.y, + escaped, + entry->Advs[i] + ); + x = x_next; + } + gp_fprintf(tdev->file, "</span>\n"); + } + gp_fprintf(tdev->file, "</page>\n"); + return 0; +} + static int txtwrite_output_page(gx_device * dev, int num_copies, int flush) { @@ -866,6 +912,12 @@ txtwrite_output_page(gx_device * dev, int num_copies, int flush) return code; break; + case 4: + code = extract_text_output(tdev); + if (code < 0) + return code; + break; + default: return gs_note_error(gs_error_rangecheck); break; @@ -882,6 +934,7 @@ txtwrite_output_page(gx_device * dev, int num_copies, int flush) while (x_entry) { gs_free(tdev->memory, x_entry->Unicode_Text, x_entry->Unicode_Text_Size, sizeof (usnigned short), "txtwrite free text fragment text buffer"); gs_free(tdev->memory, x_entry->Widths, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free widths array"); + gs_free(tdev->memory, x_entry->Advs, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free advs array"); gs_free(tdev->memory, x_entry->FontName, 1, strlen(x_entry->FontName) + 1, "txtwrite free Font Name"); if (x_entry->next) { x_entry = x_entry->next; @@ -907,6 +960,7 @@ txtwrite_output_page(gx_device * dev, int num_copies, int flush) next_x = x_entry->next; gs_free(tdev->memory, x_entry->Unicode_Text, x_entry->Unicode_Text_Size, sizeof (usnigned short), "txtwrite free unsorted text fragment text buffer"); gs_free(tdev->memory, x_entry->Widths, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free widths array"); + gs_free(tdev->memory, x_entry->Advs, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free advs array"); gs_free(tdev->memory, x_entry->FontName, 1, strlen(x_entry->FontName) + 1, "txtwrite free Font Name"); gs_free(tdev->memory, x_entry, 1, sizeof(text_list_entry_t), "txtwrite free unsorted text fragment"); x_entry = next_x; @@ -1487,6 +1541,9 @@ get_missing_width(gs_font *font, int wmode, const gs_matrix *scale_c, FONT_INFO_MISSING_WIDTH, &finfo); if (code < 0) return code; + if (!(finfo.members & FONT_INFO_MISSING_WIDTH)) + return_error(gs_error_undefined); + if (wmode) { gs_distance_transform(0.0, -finfo.MissingWidth, scale_c, &pwidths->real_width.xy); pwidths->Width.xy.x = 0; @@ -1561,7 +1618,7 @@ txt_glyph_widths(gs_font *font, int wmode, gs_glyph glyph, && (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))) { code = get_missing_width(font, wmode, &scale_c, pwidths); if (code < 0) - v.y = 0; + return code; else v.y = pwidths->Width.v.y; if (wmode && (ofont->FontType == ft_CID_encrypted || @@ -1812,11 +1869,11 @@ static int get_unicode(textw_text_enum_t *penum, gs_font *font, gs_glyph glyph, #else b = (char *)Buffer; u = (char *)unicode; - while (l >= 0) { - *b++ = *(u + l); - l--; - } + for (l=0;l<length;l+=2, u+=2){ + *b++ = *(u+1); + *b++ = *u; + } #endif gs_free_object(penum->dev->memory, unicode, "free temporary unicode buffer"); return length / sizeof(short); @@ -1930,27 +1987,33 @@ txtwrite_process_plain_text(gs_text_enum_t *pte) uint operation = pte->text.operation; txt_glyph_widths_t widths; gs_point wanted; /* user space */ - gs_point dpt = {0,0}; - for (i=0;i<pte->text.size;i++) { + for (i=pte->index;i<pte->text.size;i++) { + gs_point dpt = {0,0}; if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) { - ch = pte->text.data.bytes[pte->index++]; + ch = pte->text.data.bytes[pte->index]; } else if (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR)) { - ch = pte->text.data.chars[pte->index++]; + 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)); } else { gdata = &pte->text.data.d_glyph; - pte->index++; } } glyph = (gdata == NULL ? pte->orig_font->procs.encode_char(pte->orig_font, ch, GLYPH_SPACE_NAME) : *gdata); code = txt_glyph_widths(font, font->WMode, glyph, (gs_font *)font, &widths, NULL); - if (code < 0) - return code; + if (code < 0) { + if (penum->d1_width_set) { + widths.Width.w = widths.Width.xy.x = widths.real_width.w = widths.real_width.xy.x = penum->d1_width; + penum->d1_width = 0; + penum->d1_width_set = 0; + } + else + return code; + } penum->cdevproc_callout = false; code = txt_update_text_state(penum->text_state, (textw_text_enum_t *)pte, pte->orig_font, &font->FontMatrix); @@ -1963,7 +2026,8 @@ txtwrite_process_plain_text(gs_text_enum_t *pte) &penum->text_state->matrix, &wanted); pte->returned.total_width.x += wanted.x; pte->returned.total_width.y += wanted.y; - penum->Widths[pte->index - 1] = wanted.x; + penum->Widths[penum->TextBufferIndex] = wanted.x; + penum->Advs[penum->TextBufferIndex] = wanted.x; if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) { gs_point tpt; @@ -1984,8 +2048,20 @@ txtwrite_process_plain_text(gs_text_enum_t *pte) pte->returned.total_width.x += dpt.x; pte->returned.total_width.y += dpt.y; - penum->TextBufferIndex += get_unicode(penum, (gs_font *)pte->orig_font, glyph, ch, &penum->TextBuffer[penum->TextBufferIndex]); - penum->Widths[pte->index - 1] += dpt.x; + penum->Widths[penum->TextBufferIndex] += dpt.x; + code = get_unicode(penum, (gs_font *)pte->orig_font, glyph, ch, &penum->TextBuffer[penum->TextBufferIndex]); + /* If a single text code returned multiple Unicode values, then we need to set the + * 'extra' code points' widths to 0. + */ + if (code > 1) { + memset(&penum->Widths[penum->TextBufferIndex + 1], 0x00, (code - 1) * sizeof(float)); + memset(&penum->Advs[penum->TextBufferIndex + 1], 0x00, (code - 1) * sizeof(float)); + } + penum->TextBufferIndex += code; +/* gs_moveto_aux(penum->pgs, gx_current_path(penum->pgs), + fixed2float(penum->origin.x) + wanted.x + dpt.x, + fixed2float(penum->origin.y) + wanted.y + dpt.y);*/ + pte->index++; } return 0; } @@ -2020,7 +2096,7 @@ txt_add_sorted_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum) /* Already have text at this y-position */ text_list_entry_t *X_List = Y_List->x_ordered_list; - while (X_List->next && X_List->start.x < penum->text_state->start.x) + while (X_List->next && X_List->start.x <= penum->text_state->start.x) X_List = X_List->next; if (X_List->start.x > penum->text_state->start.x) { @@ -2095,6 +2171,20 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum) { text_list_entry_t *unsorted_entry, *t; +#ifdef TRACE_TXTWRITE + gp_fprintf(tdev->DebugFile, "txt_add_fragment: "); + gp_fwrite(penum->TextBuffer, sizeof(unsigned short), penum->TextBufferIndex, tdev->DebugFile); + gp_fprintf(tdev->DebugFile, "\n"); + { + int i=0; + gp_fprintf(tdev->DebugFile, "widths:"); + for (i=0; i<penum->TextBufferIndex; ++i) { + gp_fprintf(tdev->DebugFile, " %f", penum->Widths[i]); + } + gp_fprintf(tdev->DebugFile, "\n"); + } +#endif + /* Create a duplicate entry for the unsorted list */ unsorted_entry = (text_list_entry_t *)gs_malloc(tdev->memory->stable_memory, 1, sizeof(text_list_entry_t), "txtwrite alloc sorted text state"); @@ -2122,8 +2212,14 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum) penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array"); if (!penum->text_state->Widths) return gs_note_error(gs_error_VMerror); + penum->text_state->Advs = (float *)gs_malloc(tdev->memory->stable_memory, + penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array"); + if (!penum->text_state->Advs) + return gs_note_error(gs_error_VMerror); memset(penum->text_state->Widths, 0x00, penum->TextBufferIndex * sizeof(float)); - memcpy(penum->text_state->Widths, penum->Widths, penum->text.size * sizeof(float)); + memcpy(penum->text_state->Widths, penum->Widths, penum->TextBufferIndex * sizeof(float)); + memset(penum->text_state->Advs, 0x00, penum->TextBufferIndex * sizeof(float)); + memcpy(penum->text_state->Advs, penum->Advs, penum->TextBufferIndex * sizeof(float)); unsorted_entry->Unicode_Text = (unsigned short *)gs_malloc(tdev->memory->stable_memory, penum->TextBufferIndex, sizeof(unsigned short), "txtwrite alloc sorted text buffer"); @@ -2135,8 +2231,14 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum) penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array"); if (!unsorted_entry->Widths) return gs_note_error(gs_error_VMerror); + unsorted_entry->Advs = (float *)gs_malloc(tdev->memory->stable_memory, + penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array"); + if (!unsorted_entry->Advs) + return gs_note_error(gs_error_VMerror); memset(unsorted_entry->Widths, 0x00, penum->TextBufferIndex * sizeof(float)); - memcpy(unsorted_entry->Widths, penum->Widths, penum->text.size * sizeof(float)); + memcpy(unsorted_entry->Widths, penum->Widths, penum->TextBufferIndex * sizeof(float)); + memset(unsorted_entry->Advs, 0x00, penum->TextBufferIndex * sizeof(float)); + memcpy(unsorted_entry->Advs, penum->Advs, penum->TextBufferIndex * sizeof(float)); unsorted_entry->FontName = (char *)gs_malloc(tdev->memory->stable_memory, (strlen(penum->text_state->FontName) + 1), sizeof(unsigned char), "txtwrite alloc sorted text buffer"); @@ -2175,10 +2277,20 @@ textw_text_process(gs_text_enum_t *pte) gs_font *font = pte->orig_font; gs_font_base *font_base = (gs_font_base *)pte->current_font; int code = 0; + gs_text_enum_t *pte_fallback; if (pte->text.size == 0) return 0; + pte_fallback = penum->pte_fallback; + if (pte_fallback) { + code = gx_default_text_restore_state(pte_fallback); + if (code < 0) + return code; + gs_text_release(pte_fallback, "txtwrite_text_process"); + } + pte_fallback = penum->pte_fallback = NULL; + if (!penum->TextBuffer) { /* We can get up to 4 Unicode points per glyph, and a glyph can be * be represented by as little as one byte. So we make a very large @@ -2192,9 +2304,13 @@ textw_text_process(gs_text_enum_t *pte) if (!penum->TextBuffer) return gs_note_error(gs_error_VMerror); penum->Widths = (float *)gs_malloc(tdev->memory->stable_memory, - pte->text.size, sizeof(float), "txtwrite temporary widths array"); + pte->text.size * 4, sizeof(float), "txtwrite temporary widths array"); if (!penum->Widths) return gs_note_error(gs_error_VMerror); + penum->Advs = (float *)gs_malloc(tdev->memory->stable_memory, + pte->text.size * 4, sizeof(float), "txtwrite temporary advs array"); + if (!penum->Advs) + return gs_note_error(gs_error_VMerror); } { switch (font->FontType) { @@ -2217,6 +2333,8 @@ textw_text_process(gs_text_enum_t *pte) break; } if (code == 0) { + penum->d1_width = 0; + penum->d1_width_set = false; if (font_base->FontBBox.p.x != font_base->FontBBox.q.x || font_base->FontBBox.p.y != font_base->FontBBox.q.y) { gs_point p0, p1, p2, p3; @@ -2239,6 +2357,29 @@ textw_text_process(gs_text_enum_t *pte) return code; code = txt_add_fragment(tdev, penum); + } else { + if (code == gs_error_unregistered) /* Debug purpose only. */ + return code; + if (code == gs_error_VMerror) + return code; + if (code == gs_error_invalidfont) /* Bug 688370. */ + return code; + /* Fall back to the default implementation. */ + code = gx_default_text_begin(pte->dev, pte->pgs, &pte->text, pte->current_font, + pte->path, pte->pdcolor, pte->pcpath, pte->memory, &pte_fallback); + if (code < 0) + return code; + penum->pte_fallback = pte_fallback; + gs_text_enum_copy_dynamic(pte_fallback, pte, false); + + code = gs_text_process(pte_fallback); + if (code != 0) { + penum->returned.current_char = pte_fallback->returned.current_char; + penum->returned.current_glyph = pte_fallback->returned.current_glyph; + return code; + } + gs_text_release(pte_fallback, "txtwrite_text_process"); + penum->pte_fallback = 0; } } return code; @@ -2271,6 +2412,11 @@ textw_text_set_cache(gs_text_enum_t *pte, const double *pw, switch (control) { case TEXT_SET_CHAR_WIDTH: case TEXT_SET_CACHE_DEVICE: + if (penum->pte_fallback != NULL) { + penum->d1_width = *pw; + penum->d1_width_set = true; + return 0; + } return gs_text_set_cache(pte, pw, control); case TEXT_SET_CACHE_DEVICE2: if (penum->cdevproc_callout) { @@ -2355,6 +2501,9 @@ txtwrite_text_begin(gx_device * dev, gs_gstate * pgs, penum->TextBuffer = NULL; penum->TextBufferIndex = 0; penum->Widths = NULL; + penum->pte_fallback = NULL; + penum->d1_width = 0; + penum->d1_width_set = false; /* The enumerator's text_release method frees this memory */ penum->text_state = (text_list_entry_t *)gs_malloc(tdev->memory->stable_memory, 1, sizeof(text_list_entry_t), "txtwrite alloc text state"); diff --git a/devices/vector/gdevxps.c b/devices/vector/gdevxps.c index 5d98c283..8eb26196 100644 --- a/devices/vector/gdevxps.c +++ b/devices/vector/gdevxps.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -1868,7 +1868,7 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs, rc_increment(pcs); code = dev_proc(dev, get_profile)(dev, &(dev_profile)); /* Just use the "default" profile for now */ - icc_profile = dev_profile->device_profile[0]; + icc_profile = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]; force8bit = true; /* Output image is 8 bit regardless of source */ } else { /* An ICC, RGB, CMYK, Gray color space */ diff --git a/devices/vector/opdfread.ps b/devices/vector/opdfread.ps index cff0498e..e0d6f112 100644 --- a/devices/vector/opdfread.ps +++ b/devices/vector/opdfread.ps @@ -1,6 +1,6 @@ %!PS-Adobe-2.0 % -% Copyright (C) 2001-2019 Artifex Software, Inc. +% Copyright (C) 2001-2020 Artifex Software, Inc. % All Rights Reserved. % % This software is provided AS-IS with no warranty, either express or @@ -46,25 +46,44 @@ % ====================== Error handler ======================= % A general error handler prints an error to page. -currentdict /DSC_OPDFREAD known { - % See if our notification from ps2write is present. If it is - % then pick it up. Otherwise define it as false. Used to prevent - % use of setmatrix at start of each page. The DSC-compliant - % output from ps2write wraps pages in a save/restore, so we don't - % need the setmatrix, and it breaks use of psnup with the output. - - currentdict /DSC_OPDFREAD get -}{ - false +% At this point if we have been written by the (e)ps2write device, there will +% be a dictionary on the operand stack which contains some flags controlling the +% later behaviour of this ProcSet. Be aware that this dictionary is present until +% it is processed by the main dictionary handling at line 155 of this file, it is +% important to make sure this dictionary is preserved, and remains top of the stack +% when we reach that point. +% For safety, the code between now and that point which also uses that configuration +% information must check to see that the operand stack has at least one operand and that +% its a dictionary, and must preserve that dictionary if it uses it. + +% Determine whether to create a custom error handler. +% Check to see there's at least one object on the stack, +% and that said object is a dicitonary. If either is not true +% then create a custom error handler. If there is a dictionary, +% assume its the 'global config' dictionary written by ps2write +% (this should always be true!) and look to see if it has a +% EPS2Write key. If it does get it. If EPS2Write is true then +% don't create a custom error handler. If it is false or not present +% then do create a custom error handler. +count 0 ne { + dup type /dicttype eq { + dup /EPS2Write known { + dup /EPS2Write get not + } + { + true + }ifelse + } + { + true + } ifelse +} +{ + true } ifelse 10 dict begin % A dictionary for local binding -% This switch used to control paeg independent values, like -% whether to use InitialMatrix in SetupPageView -% -/DSC_OPDFREAD exch def - /this currentdict def /y 720 def /ebuf 200 string def @@ -79,63 +98,86 @@ currentdict /DSC_OPDFREAD known { //this /y 2 copy get 12 sub put } bind def -errordict /handleerror -{ systemdict begin - $error begin - newerror - { (%%[ Error handled by opdfread.ps : ) print errorname //ebuf cvs print (; OffendingCommand: ) - print /command load //ebuf cvs print ( ]%%) = flush - /newerror false store vmstatus pop pop 0 ne - { grestoreall - } if - errorname (VMerror) ne - { showpage - } if - initgraphics - 0 720 moveto - errorname (VMerror) eq - { //this /ehsave known - { clear //this /ehsave get restore 2 vmreclaim +% We only actually create and push the custom error handler if we are not an EPS. +{ + errordict /handleerror + { systemdict begin + $error begin + newerror + { (%%[ Error handled by opdfread.ps : ) print errorname //ebuf cvs print (; OffendingCommand: ) + print /command load //ebuf cvs print ( ]%%) = flush + /newerror false store vmstatus pop pop 0 ne + { grestoreall } if - vmstatus exch pop exch pop - } - /Courier 12 selectfont - { - (ERROR: ) //prnt exec errorname //prnt exec - (OFFENDING COMMAND: ) //prnt exec - /command load //prnt exec - $error /ostack known { - (%%[STACK:) = - (STACK:) //prnt exec - $error /ostack get aload length { - //newline exec - dup mark eq { - (-mark-) dup = show - } { - dup type /nametype eq { - dup xcheck not { - (/) show - (/) print - } if - } if - dup = //ebuf cvs show - } ifelse - } repeat + errorname (VMerror) ne + { showpage } if - } ifelse - (%%]%) = - //systemdict /showpage get exec - quit - } if - end - end -} bind readonly put + initgraphics + 0 720 moveto + errorname (VMerror) eq + { //this /ehsave known + { clear //this /ehsave get restore 2 vmreclaim + } if + vmstatus exch pop exch pop + } + /Courier 12 selectfont + { + (ERROR: ) //prnt exec errorname //prnt exec + (OFFENDING COMMAND: ) //prnt exec + /command load //prnt exec + $error /ostack known { + (%%[STACK:) = + (STACK:) //prnt exec + $error /ostack get aload length { + //newline exec + dup mark eq { + (-mark-) dup = show + } { + dup type /nametype eq { + dup xcheck not { + (/) show + (/) print + } if + } if + dup = //ebuf cvs show + } ifelse + } repeat + } if + } ifelse + (%%]%) = + //systemdict /showpage get exec + quit + } if + end + end + } bind readonly put +} if end % A dictionary for local binding - 50 dict begin +% Read the definitions of various global parameters from the dictionary +% written at the head of the file by ps2write, and define the parameters +% in this dictionary. Check first to make sure we have a dictionary on the +% stack; if we do, assume its the 'global configuration' dictionary. +count 0 ne { + dup type /dicttype eq { + {def} forall + false + } + { + true + } ifelse +} +{ + true +} ifelse + +{ + ( *** Warning: global definitions dictionary not found, file may be corrupted.\n) print flush +} if + % ===================== Debugging ========================================= /DefaultSwitch % <name> DefaultSwitch - @@ -4176,7 +4218,10 @@ currentdict end readonly def } bind def /ShowText % <string> ShowText - -{ //GraphicState /TextRenderingMode get 0 eq { +{ + //GraphicState /TextRenderingMode get dup 0 eq + exch 3 eq not currentfont /FontType get 3 eq and or + { //GraphicState /WordSpacing get 0 32 //GraphicState /CharacterSpacing get 0 @@ -4236,13 +4281,28 @@ currentdict end readonly def } bind def /ShowTextBeg % - ShowTextBeg - -{ //GraphicState /TextRenderingMode get 0 ne { - currentpoint newpath moveto - } if +{ + //GraphicState /TextRenderingMode get dup 0 ne + { + 3 ne + currentfont /FontType get 3 eq not and { + currentpoint newpath moveto + } if + } + { + pop + } ifelse } bind def /ShowTextEnd % - ShowTextEnd - -{ //GraphicState /TextRenderingMode get +{ + //GraphicState /TextRenderingMode get + currentfont /FontType get 3 eq { + dup 3 ne { + pop 0 + } if + }if + { dup 1 eq { stroke exit } if diff --git a/devices/vector/whitelst.c b/devices/vector/whitelst.c index 652926f4..af4c14fc 100644 --- a/devices/vector/whitelst.c +++ b/devices/vector/whitelst.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or diff --git a/devices/vector/whitelst.h b/devices/vector/whitelst.h index 2e562fd8..a566da54 100644 --- a/devices/vector/whitelst.h +++ b/devices/vector/whitelst.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2019 Artifex Software, Inc. +/* Copyright (C) 2001-2020 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or |