[gs-cvs] rev 8296 - in trunk/gs: lib src
ken at ghostscript.com
ken at ghostscript.com
Tue Oct 16 00:54:08 PDT 2007
Author: ken
Date: 2007-10-16 00:54:08 -0700 (Tue, 16 Oct 2007)
New Revision: 8296
Modified:
trunk/gs/lib/opdfread.ps
trunk/gs/src/gdevpsf1.c
Log:
ps2write: When encountering font names which contain unfortunate characters
such as white space, or delimiters, emit the name as an escaped string and
'cvn' instead of a literal name.
DETAILS:
Bug #689420 "Errors with ps2write and special chars in FontName"
Patch from SaGS with some minor improvements.
Fonts whose name contains white space, or delimiter characters (eg /,(,[ etc)
were being written into the type 1 font stream using the name unchanged. This
causes the resulting PostScript to fail on any PostScript interpreter. The
exact error varies depending on the placement of the invalid character and
the following data.
This is now handled by emitting the font name as a string, and using the cvn
operator to convert the string to a name, escaping characters if required.
Note that both the C portion of the code needs to change, in order to write
escaped names, and the PostScript prolog in order to undo any name escapement.
1. (gdevpsf1.c) write_font_name, check to see if the font name contains any
characters which we need to escape. If so, then use the existing routine
's_PSSE_template.process' to convert the name to an escaped character
sequence.
Update the write_font_name routine so that it optionally writes a name
to the output. If the name does not need escaping, then simply prepend a
'/' to make a literal name, otherwise append a 'cvn' to convert the
escaped string to a name. When writing out the font header we just need
the font name as a human readable string. When writing the /FontName
entry in the font dictionary we need a PostScript name, either a literal
or a PostScript escaped string converted to a name. (see below)
2. (gdevpsf1.c) psf_write_type1_font, alter the use of write_font_name in two
places. Firstly to emit the name as part of the font comment, secondly to
put the name as the value for the /FontName key in the fotn dictionary. In
the first case we write it as a simple string, in the second as a name.
3. (opdfread.ps) The TypeDameons procedure extracts the FontName from the Font
dictionary in the body of the job. Since the FontName can now be escaped,
we need to undo the escapement before defining the font. Firstly we define
a new procedure 'UnPDFEscape', secondly we call this when dealing with the
FontName and the BaseFont keys, in order to convert the escaped name back
to a normal name, so that the font can be found with findfont.
EXPECTED DIFFERENCES:
None
Modified: trunk/gs/lib/opdfread.ps
===================================================================
--- trunk/gs/lib/opdfread.ps 2007-10-16 00:36:28 UTC (rev 8295)
+++ trunk/gs/lib/opdfread.ps 2007-10-16 07:54:08 UTC (rev 8296)
@@ -925,6 +925,35 @@
/Subtype get 1 index exch /FontFileType exch put
} bind def
+/UnPDFEscape { % <namepdf> UnPDFEscape <nameps>
+ dup dup length string cvs % /namepdf (name)
+ dup (#) search {
+ % name contains PDF-style escapes ("#hh") that need to be removed
+ { % ... (po..st) (#) (pre)
+ pop % ... (po..st) (#)
+ (16#--) 2 index 0 2 getinterval % ... (po..st) (#) (16#--) (po)
+ 1 index 3 2 getinterval copy pop % ... (po..st) (#) (16#po)
+ cvi % ... (po..st) (#) 16#po
+ 0 exch put % ... (po..st); 16#po patched into (#)
+ 0 % ... (po..st) 0
+ 1 index 2 1 index length 2 sub getinterval % ... (po..st) 0 (..st)
+ 3 copy putinterval % ... (..stst) 0 (XXst)
+ length % ... (..stst) 0 LEN_OF_(po..st)-2
+ 3 copy exch put % ... (..st\0t) 0 LEN_OF_(po..st)-2
+ getinterval % ... (..st), stored at begining of old (po..st)
+ (#) search not {
+ pop exit % /namepdf (nameps\0..)
+ } if
+ } loop
+ % we have a '\0' marker (not allowed in PDF names) after all usefull characters
+ (\0) search pop exch pop exch pop
+ cvn
+ exch pop
+ } {
+ pop pop
+ } ifelse
+} bind def
+
/TypeDaemons << % <id> <obj> proc <id> <obj>
/Page
{ //PDFR_DEBUG {
@@ -944,6 +973,9 @@
{ //PDFR_DEBUG {
(Recognized a font descriptor.) =
} if
+ dup /FontName //knownget exec {
+ 1 index /FontName 3 -1 roll //UnPDFEscape exec put
+ } if
{
dup dup /FontFile known {/FontFile} {/FontFile2} ifelse
//knownget exec { % id obj ff
@@ -963,6 +995,7 @@
(Recognized a font resource.) =
} if
dup /BaseFont //knownget exec {
+ //UnPDFEscape exec 2 copy /BaseFont exch put
% cache the installed font (if any) before replacing it.
//PDFReader /RemoveFontNamePrefix get exec
currentglobal exch % A hack against HP LaserJet 1320 bug :
Modified: trunk/gs/src/gdevpsf1.c
===================================================================
--- trunk/gs/src/gdevpsf1.c 2007-10-16 00:36:28 UTC (rev 8295)
+++ trunk/gs/src/gdevpsf1.c 2007-10-16 07:54:08 UTC (rev 8296)
@@ -88,12 +88,39 @@
/* Write the font name. */
static void
write_font_name(stream *s, const gs_font_type1 *pfont,
- const gs_const_string *alt_font_name)
+ const gs_const_string *alt_font_name, bool as_name)
{
- if (alt_font_name)
- stream_write(s, alt_font_name->data, alt_font_name->size);
- else
- stream_write(s, pfont->font_name.chars, pfont->font_name.size);
+ const byte *c;
+ const byte *name = (alt_font_name ? alt_font_name->data : pfont->font_name.chars);
+ int n = (alt_font_name ? alt_font_name->size : pfont->font_name.size);
+
+ if (n == 0)
+ /* empty name, may need to write it as empty string */
+ stream_puts(s, (as_name ? "/" : "()"));
+ else {
+ for (c = (byte *)"()<>[]{}/% \n\r\t\b\f\004\033"; *c; c++)
+ if (memchr(name, *c, n))
+ break;
+ if (*c || memchr(name, 0, n)) {
+ /* name contains whitespace (NUL included) or a PostScript separator */
+ byte pssebuf[1 + 4 * gs_font_name_max + 1]; /* "(" + "\ooo" * gs_font_name_max + ")" */
+ stream_cursor_read r;
+ stream_cursor_write w;
+
+ pssebuf[0] = '(';
+ r.limit = (r.ptr = name - 1) + n;
+ w.limit = (w.ptr = pssebuf) + sizeof pssebuf - 1;
+ s_PSSE_template.process(NULL, &r, &w, true);
+ stream_write(s, pssebuf, w.ptr - pssebuf + 1);
+ if (as_name)
+ stream_puts(s, " cvn");
+ } else {
+ /* name without any special characters */
+ if (as_name)
+ stream_putc(s, '/');
+ stream_write(s, name, n);
+ }
+ }
}
/*
* Write the Encoding array. This is a separate procedure only for
@@ -390,7 +417,7 @@
/* Write the font header. */
stream_puts(s, "%!FontType1-1.0: ");
- write_font_name(s, pfont, alt_font_name);
+ write_font_name(s, pfont, alt_font_name, false);
stream_puts(s, "\n11 dict begin\n");
/* Write FontInfo. */
@@ -418,8 +445,8 @@
/* Write the main font dictionary. */
- stream_puts(s, "/FontName /");
- write_font_name(s, pfont, alt_font_name);
+ stream_puts(s, "/FontName ");
+ write_font_name(s, pfont, alt_font_name, true);
stream_puts(s, " def\n");
code = write_Encoding(s, pfont, options, glyphs.subset_glyphs,
glyphs.subset_size, glyphs.notdef);
More information about the gs-cvs
mailing list