summaryrefslogtreecommitdiff
path: root/devices
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2023-02-24 09:38:08 +0000
committerKen Sharp <ken.sharp@artifex.com>2023-02-24 11:56:49 +0000
commitad3f17ad44d94268e20d8fea23e563557850fc56 (patch)
treec0f7686fd07d90acb0efe4957ec1267aae09e323 /devices
parentec203362d93fd7d61ca2775aaac17b23c1cca6c8 (diff)
downloadghostpdl-ad3f17ad44d94268e20d8fea23e563557850fc56.tar.gz
Graphics library - drop all copied components of a glyph on error
Bug #705476 "Some Russian letters disappear in PDF" The problem here is quite subtle. We have multiple embedded TrueType fonts which all have the same /FontName and so pdfwrite attempts to 'merge' the fonts into one, because it thinks they are the same font. When the glyph cannot be embedded into the type 42 font we punt and drop back to creating a type 3 font. However.... Some of the glyphs in this file are compound glyphs, and the first component can be added to the Type 42 font, but the second one cannot. So we throw an error and don't add the second glyph, but we leave the initial glyph in place. The error causes us to fall back to type 3 for this glyph. Then we encounter the same compound glyph again. Checking the font we see that it is already embedded, and we don't check the components because we assume that if we embedded the glyph we also embedded any component glyphs. So we go ahead and use the embedded glyph and that then fails to produce the correct outline. When adding a component glyph to a font fails we need to 'unadd' the initial glyph and any other components, so that we don't end up trying to use any of them inappropriately. For almost all fonts this is relatively straight-forward, but for TrueType (type 42) fonts it is more complicated, so I've added another member to the copied fonts procs so that we can have a specific method for each font type. So far the only case I've found is the TrueType font in this bug report and since this has been present in the code forever it is clearly an extremely rare case. Although I've added the code for the other font types I'm not really able to test these terribly well.
Diffstat (limited to 'devices')
-rw-r--r--devices/gxfcopy.c99
1 files changed, 92 insertions, 7 deletions
diff --git a/devices/gxfcopy.c b/devices/gxfcopy.c
index 571ff6463..1f4d7028c 100644
--- a/devices/gxfcopy.c
+++ b/devices/gxfcopy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2022 Artifex Software, Inc.
+/* Copyright (C) 2001-2023 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -59,6 +59,8 @@ typedef struct gs_copied_font_procs_s {
font_proc_encode_char((*encode_char));
font_proc_glyph_info((*glyph_info));
font_proc_glyph_outline((*glyph_outline));
+ int (*uncopy_glyph)(gs_font *font, gs_glyph glyph, gs_font *copied,
+ int options);
} gs_copied_font_procs_t;
/*
@@ -1038,6 +1040,22 @@ copy_font_type1(gs_font *font, gs_font *copied)
}
static int
+uncopy_glyph_type1(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
+{
+ gs_copied_glyph_t *pcg = NULL;
+
+ (void)copied_glyph_slot(cf_data(copied), glyph, &pcg);
+ if (pcg != NULL) {
+ if (pcg->gdata.data != NULL) {
+ gs_free_string(copied->memory, (byte *)pcg->gdata.data, pcg->gdata.size, "Free copied glyph name");
+ pcg->gdata.size = 0;
+ }
+ pcg->used = 0;
+ }
+ return 0;
+}
+
+static int
copy_glyph_type1(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
{
gs_glyph_data_t gdata;
@@ -1123,7 +1141,8 @@ copied_type1_glyph_outline(gs_font *font, int WMode, gs_glyph glyph,
static const gs_copied_font_procs_t copied_procs_type1 = {
copy_font_type1, copy_glyph_type1, copied_char_add_encoding,
named_glyph_slot_hashed,
- copied_encode_char, gs_type1_glyph_info, copied_type1_glyph_outline
+ copied_encode_char, gs_type1_glyph_info, copied_type1_glyph_outline,
+ uncopy_glyph_type1
};
static void hash_subrs(gs_font_type1 *pfont)
@@ -1367,6 +1386,28 @@ copy_font_type42(gs_font *font, gs_font *copied)
return code;
}
+static int uncopy_glyph_type42(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
+{
+ gs_copied_glyph_t *pcg = NULL;
+ gs_font_type42 *font42 = (gs_font_type42 *)font;
+ gs_font_cid2 *fontCID2 = (gs_font_cid2 *)font;
+ uint gid = (options & COPY_GLYPH_BY_INDEX ? glyph - GS_MIN_GLYPH_INDEX :
+ font->FontType == ft_CID_TrueType
+ ? fontCID2->cidata.CIDMap_proc(fontCID2, glyph)
+ : font42->data.get_glyph_index(font42, glyph));
+
+ (void)copied_glyph_slot(cf_data(copied), gid + GS_MIN_GLYPH_INDEX, &pcg);
+ if (pcg != NULL) {
+ if (pcg->gdata.data != NULL) {
+ gs_free_string(copied->memory, (byte *)pcg->gdata.data, pcg->gdata.size, "Free copied glyph name");
+ pcg->gdata.size = 0;
+ }
+ pcg->used = 0;
+ }
+
+ return 0;
+}
+
static int
copy_glyph_type42(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
{
@@ -1467,7 +1508,8 @@ copied_type42_encode_char(gs_font *copied, gs_char chr,
static const gs_copied_font_procs_t copied_procs_type42 = {
copy_font_type42, copy_glyph_type42, copied_char_add_encoding,
named_glyph_slot_linear,
- copied_type42_encode_char, gs_type42_glyph_info, gs_type42_glyph_outline
+ copied_type42_encode_char, gs_type42_glyph_info, gs_type42_glyph_outline,
+ uncopy_glyph_type42
};
static inline int
@@ -1757,6 +1799,22 @@ copy_font_cid0(gs_font *font, gs_font *copied)
}
static int
+uncopy_glyph_cid0(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
+{
+ gs_copied_glyph_t *pcg = NULL;
+
+ (void)copied_glyph_slot(cf_data(copied), glyph, &pcg);
+ if (pcg != NULL) {
+ if (pcg->gdata.data != NULL) {
+ gs_free_string(copied->memory, (byte *)pcg->gdata.data, pcg->gdata.size, "Free copied glyph name");
+ pcg->gdata.size = 0;
+ }
+ pcg->used = 0;
+ }
+ return 0;
+}
+
+static int
copy_glyph_cid0(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
{
gs_glyph_data_t gdata;
@@ -1783,7 +1841,8 @@ copy_glyph_cid0(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
static const gs_copied_font_procs_t copied_procs_cid0 = {
copy_font_cid0, copy_glyph_cid0, copied_no_add_encoding,
named_glyph_slot_none,
- gs_no_encode_char, copied_cid0_glyph_info, copied_cid0_glyph_outline
+ gs_no_encode_char, copied_cid0_glyph_info, copied_cid0_glyph_outline,
+ uncopy_glyph_cid0
};
static int
@@ -1895,6 +1954,22 @@ static int expand_CIDMap(gs_font_cid2 *copied2, uint CIDCount)
}
static int
+uncopy_glyph_cid2(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
+{
+ gs_copied_glyph_t *pcg = NULL;
+
+ (void)copied_glyph_slot(cf_data(copied), glyph, &pcg);
+ if (pcg != NULL) {
+ if (pcg->gdata.data != NULL) {
+ gs_free_string(copied->memory, (byte *)pcg->gdata.data, pcg->gdata.size, "Free copied glyph name");
+ pcg->gdata.size = 0;
+ }
+ pcg->used = 0;
+ }
+ return 0;
+}
+
+static int
copy_glyph_cid2(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
{
gs_font_cid2 *fcid2 = (gs_font_cid2 *)font;
@@ -1945,7 +2020,8 @@ copy_glyph_cid2(gs_font *font, gs_glyph glyph, gs_font *copied, int options)
static const gs_copied_font_procs_t copied_procs_cid2 = {
copy_font_cid2, copy_glyph_cid2, copied_no_add_encoding,
named_glyph_slot_none,
- gs_no_encode_char, gs_type42_glyph_info, gs_type42_glyph_outline
+ gs_no_encode_char, gs_type42_glyph_info, gs_type42_glyph_outline,
+ uncopy_glyph_cid2
};
static int
@@ -2386,10 +2462,12 @@ gs_copy_glyph_options(gs_font *font, gs_glyph glyph, gs_font *copied,
#define MAX_GLYPH_PIECES 64 /* arbitrary, but 32 is too small - bug 687698. */
gs_glyph glyphs[MAX_GLYPH_PIECES];
uint count = 1, i;
+ gs_copied_font_data_t *cfdata = NULL;
if (copied->procs.font_info != copied_font_info)
return_error(gs_error_rangecheck);
- code = cf_data(copied)->procs->copy_glyph(font, glyph, copied, options);
+ cfdata = cf_data(copied);
+ code = cfdata->procs->copy_glyph(font, glyph, copied, options);
if (code != 0)
return code;
/* Copy any sub-glyphs. */
@@ -2403,8 +2481,15 @@ gs_copy_glyph_options(gs_font *font, gs_glyph glyph, gs_font *copied,
for (i = 1; i < count; ++i) {
code = gs_copy_glyph_options(font, glyphs[i], copied,
(options & ~COPY_GLYPH_NO_OLD) | COPY_GLYPH_BY_INDEX);
- if (code < 0)
+ if (code < 0) {
+ int j = 0;
+
+ for (j = 0; j < i; j++) {
+ if (cfdata->procs->uncopy_glyph != NULL)
+ (void)cfdata->procs->uncopy_glyph(font, glyph, copied, options);
+ }
return code;
+ }
/* if code > 0 then we already have the glyph, so no need to process further.
* If the original glyph was not a CID then we are copying by name, not by index.
* But the copy above copies by index which means we don't have an entry for