[gs-cvs] gs/src

L. Peter Deutsch lpd at casper.ghostscript.com
Tue Jul 9 07:26:48 PDT 2002


Update of /cvs/ghostscript/gs/src
In directory casper:/tmp/cvs-serv21359/src

Modified Files:
	gxfcopy.c gxfcopy.h 
Log Message:

Fixes bugs in font copying (currently used only by the new pdfwrite text
code): TrueType glyphs with multiple names in CharStrings only stored a
single name; copied Encodings were initialized incorrectly to .notdef rather
than GS_NO_GLYPH; some of the procedures of copied TrueType fonts weren't
initialized correctly; 'seac' didn't copy the Encoding entries for the
components.  Also shares the known glyph names when possible, to reduce the
load on the garbage collector.


Index: gxfcopy.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxfcopy.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- gxfcopy.c	28 Jun 2002 22:35:26 -0000	1.13
+++ gxfcopy.c	9 Jul 2002 14:26:45 -0000	1.14
@@ -18,6 +18,7 @@
 /* Font copying for high-level output */
 #include "memory_.h"
 #include "gx.h"
+#include "gscencs.h"
 #include "gserrors.h"
 #include "gsline.h"		/* for BuildChar */
 #include "gspaint.h"		/* for BuildChar */
@@ -109,15 +110,16 @@
  * For Type 1 fonts, this is a hash table; glyph numbers are assigned
  * arbitrarily, according to the hashed placement of the names.
  * For TrueType fonts, this is indexed by GID.
- * The strings in this table are those returned by the font's glyph_name
- * procedure: we assume they are garbage-collected.
+ * The strings in this table are either those returned by the font's
+ * glyph_name procedure, which we assume are garbage-collected, or those
+ * associated with the known encodings, which we assume are immutable.
  */
 typedef struct gs_copied_glyph_name_s {
     gs_glyph glyph;		/* key (for comparison and glyph_name only) */
     gs_const_string str;	/* glyph name */
 } gs_copied_glyph_name_t;
 /*
- * We use the same special GC descriptor as above.
+ * We use the same special GC descriptor as above for 'names'.
  */
 gs_private_st_composite(st_gs_copied_glyph_name_element,
 			gs_copied_glyph_name_t,
@@ -125,8 +127,14 @@
 			copied_glyph_name_enum_ptrs,
 			copied_glyph_name_reloc_ptrs);
 private ENUM_PTRS_WITH(copied_glyph_name_enum_ptrs, gs_copied_glyph_name_t *pcgn)
-     if (index < size / (uint)sizeof(gs_copied_glyph_name_t))
-	 return ENUM_CONST_STRING(&pcgn[index].str);
+     if (index < size / (uint)sizeof(gs_copied_glyph_name_t)) {
+	 const gs_copied_glyph_name_t *const p = &pcgn[index];
+
+	 return (p->str.size == 0 ||
+		 gs_is_c_glyph_name(p->str.data, p->str.size) ?
+		 ENUM_CONST_STRING2(0, 0) :
+		 ENUM_CONST_STRING(&p->str));
+     }
      return 0;
 ENUM_PTRS_END
 private RELOC_PTRS_WITH(copied_glyph_name_reloc_ptrs, gs_copied_glyph_name_t *pcgn)
@@ -135,12 +143,32 @@
     gs_copied_glyph_name_t *p = pcgn;
 
     for (; count > 0; --count, ++p)
-	if (p->str.size > 0)
+	if (p->str.size > 0 && !gs_is_c_glyph_name(p->str.data, p->str.size))
 	    RELOC_CONST_STRING_VAR(p->str);
 }
 RELOC_PTRS_END
 
 /*
+ * To accommodate glyphs with multiple names, there is an additional
+ * 'extra_names' table.  Since this is rare, this table uses linear search.
+ */
+typedef struct gs_copied_glyph_extra_name_s gs_copied_glyph_extra_name_t;
+struct gs_copied_glyph_extra_name_s {
+    gs_copied_glyph_name_t name;
+    uint gid;			/* index in glyphs table */
+    gs_copied_glyph_extra_name_t *next;
+};
+BASIC_PTRS(gs_copied_glyph_extra_name_ptrs) {
+    GC_STRING_ELT(gs_copied_glyph_extra_name_t, name.str),
+    GC_OBJ_ELT(gs_copied_glyph_extra_name_t, next)
+};
+gs_private_st_basic(st_gs_copied_glyph_extra_name,
+		    gs_copied_glyph_extra_name_t,
+		    "gs_copied_glyph_extra_name_t",
+		    gs_copied_glyph_extra_name_ptrs,
+		    gs_copied_glyph_extra_name_data);
+
+/*
  * The client_data of copied fonts points to an instance of
  * gs_copied_font_data_t.
  */
@@ -154,7 +182,8 @@
      * We don't use a union for the rest of the data, because some of the
      * cases overlap and it's just not worth the trouble.
      */
-    gs_copied_glyph_name_t *names; /* (Type 1/2) [glyphs_size] */
+    gs_copied_glyph_name_t *names; /* (Type 1/2, TrueType) [glyphs_size] */
+    gs_copied_glyph_extra_name_t *extra_names; /* (TrueType) */
     byte *data;			/* (TrueType and CID fonts) copied data */
     uint data_size;		/* (TrueType and CID fonts) */
     gs_glyph *Encoding;		/* (Type 1/2 and Type 42) [256] */
@@ -221,7 +250,7 @@
     if (Encoding == 0)
 	return_error(gs_error_VMerror);
     for (i = 0; i < 256; ++i)
-	Encoding[i] = cfdata->notdef;
+	Encoding[i] = GS_NO_GLYPH;
     cfdata->Encoding = Encoding;
     return 0;
 }
@@ -364,14 +393,26 @@
 named_glyph_slot_linear(gs_copied_font_data_t *cfdata, gs_glyph glyph,
 			gs_copied_glyph_t **pslot)
 {
-    gs_copied_glyph_name_t *names = cfdata->names;
-    int i;
+    {
+	gs_copied_glyph_name_t *names = cfdata->names;
+	int i;
 
-    for (i = 0; i < cfdata->glyphs_size; ++i)
-	if (names[i].glyph == glyph) {
-	    *pslot = &cfdata->glyphs[i];
-	    return 0;
-	}
+	for (i = 0; i < cfdata->glyphs_size; ++i)
+	    if (names[i].glyph == glyph) {
+		*pslot = &cfdata->glyphs[i];
+		return 0;
+	    }
+    }
+    /* This might be a glyph with multiple names.  Search extra_names. */
+    {
+	gs_copied_glyph_extra_name_t *extra_name = cfdata->extra_names;
+
+	for (; extra_name != 0; extra_name = extra_name->next)
+	    if (extra_name->name.glyph == glyph) {
+		*pslot = &cfdata->glyphs[extra_name->gid];
+		return 0;
+	    }
+    }
     return_error(gs_error_rangecheck);
 }
 
@@ -437,6 +478,7 @@
 copy_glyph_name(gs_font *font, gs_glyph glyph, gs_font *copied,
 		gs_glyph copied_glyph)
 {
+    gs_glyph known_glyph;
     gs_copied_font_data_t *const cfdata = cf_data(copied);
     gs_copied_glyph_t *pcg;
     int code = copied_glyph_slot(cfdata, copied_glyph, &pcg);
@@ -444,11 +486,32 @@
     gs_const_string str;
 
     if (code < 0 ||
-	(code = font->procs.glyph_name(font, glyph, &str)) < 0 ||
-	(code = copy_string(copied->memory, &str, "copy_glyph_name")) < 0
+	(code = font->procs.glyph_name(font, glyph, &str)) < 0
 	)
 	return code;
+    /* Try to share a permanently allocated known glyph name. */
+    if ((known_glyph = gs_c_name_glyph(str.data, str.size)) != GS_NO_GLYPH)
+	gs_c_glyph_name(known_glyph, &str);
+    else if ((code = copy_string(copied->memory, &str, "copy_glyph_name")) < 0)
+	return code;
     pcgn = cfdata->names + (pcg - cfdata->glyphs);
+    if (pcgn->glyph != GS_NO_GLYPH &&
+	(pcgn->str.size != str.size ||
+	 memcmp(pcgn->str.data, str.data, str.size))
+	) {
+	/* This is a glyph with multiple names.  Add an extra_name entry. */
+	gs_copied_glyph_extra_name_t *extra_name =
+	    gs_alloc_struct(copied->memory, gs_copied_glyph_extra_name_t,
+			    &st_gs_copied_glyph_extra_name,
+			    "copy_glyph_name(extra_name)");
+
+	if (extra_name == 0)
+	    return_error(gs_error_VMerror);
+	extra_name->next = cfdata->extra_names;
+	extra_name->gid = pcg - cfdata->glyphs;
+	cfdata->extra_names = extra_name;
+	pcgn = &extra_name->name;
+    }
     pcgn->glyph = glyph;
     pcgn->str = str;
     return 0;
@@ -489,7 +552,7 @@
     code = copied_glyph_slot(cfdata, glyph, &pslot);
     if (code < 0)
 	return code;
-    if (Encoding[chr] != glyph && Encoding[chr] != cfdata->notdef)
+    if (Encoding[chr] != glyph && Encoding[chr] != GS_NO_GLYPH)
 	return_error(gs_error_invalidaccess);
     Encoding[chr] = glyph;
     return 0;
@@ -873,7 +936,11 @@
     code = gs_type42_font_init(copied42);
     if (code < 0)
 	goto fail2;
+    /* gs_type42_font_init overwrites enumerate_glyph. */
+    copied42->procs.enumerate_glyph = copied_enumerate_glyph;
+    copied42->data.get_glyph_index = copied_type42_get_glyph_index;
     copied42->data.get_outline = copied_type42_get_outline;
+    copied42->data.get_metrics = copied_type42_get_metrics;
     copied42->data.metrics[0].numMetrics =
 	copied42->data.metrics[1].numMetrics =
 	extra / 8;
@@ -883,8 +950,6 @@
 	copied42->data.metrics[1].length =
 	extra / 2;
     memset(cfdata->data + cfdata->data_size - extra, 0, extra);
-    copied42->data.get_metrics = copied_type42_get_metrics;
-    copied42->data.get_glyph_index = copied_type42_get_glyph_index;
     copied42->data.numGlyphs = font42->data.numGlyphs;
     copied42->data.trueNumGlyphs = font42->data.trueNumGlyphs;
     return 0;
@@ -920,7 +985,7 @@
 	return code;
     rcode = code;
     if (glyph < GS_MIN_CID_GLYPH)
-	code = copy_glyph_name((gs_font *)font, glyph, copied,
+	code = copy_glyph_name(font, glyph, copied,
 			       gid + GS_MIN_CID_GLYPH);
     DISCARD(copied_glyph_slot(cfdata, glyph, &pcg)); /* can't fail */
     for (i = 0; i < 2; ++i) {
@@ -1370,6 +1435,7 @@
 
 	bfont->FAPI = 0;
 	bfont->FAPI_font_data = 0;
+	bfont->encoding_index = ENCODING_INDEX_UNKNOWN;
 	code = uid_copy(&bfont->UID, mem, "gs_copy_font(UID)");
 	if (code < 0)
 	    goto fail;
@@ -1382,6 +1448,12 @@
     if (names)
 	memset(names, 0, glyphs_size * sizeof(*names));
     cfdata->names = names;
+    if (names != 0) {
+	uint i;
+
+	for (i = 0; i < glyphs_size; ++i)
+	    names[i].glyph = GS_NO_GLYPH;
+    }
 
     /* Do FontType-specific initialization. */
 
@@ -1445,6 +1517,35 @@
 	code = gs_copy_glyph_options(font, glyphs[i], copied,
 				     options & ~COPY_GLYPH_NO_OLD);
 	if (code < 0)
+	    return code;
+    }
+    /*
+     * Because 'seac' accesses the Encoding of the font as well as the
+     * glyphs, we have to copy the Encoding entries as well.
+     */
+    if (count == 1)
+	return 0;
+    switch (font->FontType) {
+    case ft_encrypted:
+    case ft_encrypted2:
+	break;
+    default:
+	return 0;
+    }
+    {
+	gs_copied_glyph_t *pcg;
+	gs_glyph_data_t gdata;
+	gs_char chars[2];
+
+	/* Since we just copied the glyph, copied_glyph_slot can't fail. */
+	DISCARD(copied_glyph_slot(cf_data(copied), glyph, &pcg));
+	gs_glyph_data_from_string(&gdata, pcg->gdata.data, pcg->gdata.size,
+				  NULL);
+	code = gs_type1_piece_codes((gs_font_type1 *)font, &gdata, chars);
+	if (code <= 0 ||	/* 0 is not possible here */
+	    (code = gs_copied_font_add_encoding(copied, chars[0], glyphs[1])) < 0 ||
+	    (code = gs_copied_font_add_encoding(copied, chars[1], glyphs[2])) < 0
+	    )
 	    return code;
     }
     return 0;

Index: gxfcopy.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxfcopy.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- gxfcopy.h	27 Jun 2002 17:51:57 -0000	1.5
+++ gxfcopy.h	9 Jul 2002 14:26:45 -0000	1.6
@@ -78,7 +78,8 @@
  *
  *	Type 1, Type 2 - the destination and source must have the same
  *	Subrs.  glyph must be a name (not an integer).  Copies the
- *	CharString entry.
+ *	CharString entry.  Note that the Type 1/2 'seac' operator requires
+ *	copying not only the sub-glyphs but their Encoding entries as well.
  *
  *	Type 42 - the destination and source must have compatible tables
  *	other than glyf and loca.  In practice this means that the source




More information about the gs-cvs mailing list