[gs-cvs] rev 8178 - in trunk/gs: doc lib src
leonardo at ghostscript.com
leonardo at ghostscript.com
Sun Aug 5 06:55:36 PDT 2007
Author: leonardo
Date: 2007-08-05 06:55:26 -0700 (Sun, 05 Aug 2007)
New Revision: 8178
Added:
trunk/gs/src/ConvertUTF.c
trunk/gs/src/ConvertUTF.h
Modified:
trunk/gs/doc/Ps2pdf.htm
trunk/gs/lib/gs_agl.ps
trunk/gs/lib/gs_pdfwr.ps
trunk/gs/src/devs.mak
trunk/gs/src/gdevpdfb.h
trunk/gs/src/gdevpdfe.c
trunk/gs/src/gdevpdfp.c
trunk/gs/src/gdevpdfx.h
Log:
Fix (pdfwrite) : A wrong encoding of Metadata.
DETAILS :
Bug 689244 "Wrong encoding of title in metadata for PDF/A".
Thanks to mpsuzuki for preliminary analyzis.
1. See the documentation change.
2. gs_pdfwr.ps converts the specified name into a translation table.
We believe that popolar encodings translate into single Unicode
characters, so we don't implement Unicode compositions now.
This may be a subject of further improvements. In this case
the generated integer array should use a complex format
for representing the translation table.
3. The translation table is passed to pdfwrite
as a new device parameter DSCEncodingToUnicode.
4. When it is specified, gdevpdfe.c performs the translation
first into UTF-8, then into XML.
5. The new modules ConvertUTF.c, ConvertUTF.h are obtained from
Unicode Inc.
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/doc/Ps2pdf.htm
===================================================================
--- trunk/gs/doc/Ps2pdf.htm 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/doc/Ps2pdf.htm 2007-08-05 13:55:26 UTC (rev 8178)
@@ -433,6 +433,21 @@
and <b><tt>InstanceUUID</tt></b> are specified, <b><tt>DocumentTimeSeq</tt></b> is being ignored.
</dl>
+<dl>
+<dt><b><tt>-sDSCEncoding=</tt></b><em>string</em>
+<dd>Defines a name of Postscript encoding in which
+DSC comments are encoded in the source document.
+If specified, the comments are converted
+from that encoding into Unicode UTF-8 when writing <b><tt>Metadata</b></tt>.
+If not specified, the comments are copied to <b><tt>Metadata</b></tt>
+with no conversion. Note that Adobe Distiller for
+Windows uses the default locale's code page
+for this translation, so it's result may differ from Ghostscript.
+Adobe Acrobat appears to use <b><tt>PDFDocEncoding</b></tt> when
+displaying document's properties,
+so we recommend this value.
+</dl>
+
<p>
<b><tt>ps2pdf</tt></b> recognizes all of the Acrobat Distiller 5 parameters
defined in the DistillerParameters document included in the
Modified: trunk/gs/lib/gs_agl.ps
===================================================================
--- trunk/gs/lib/gs_agl.ps 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/lib/gs_agl.ps 2007-08-05 13:55:26 UTC (rev 8178)
@@ -23,7 +23,7 @@
% The AdobeGlyphList dictionary maps glyph names to Unicode values.
% Nearly all names map to a single value; however, a few names map to
% multiple values. See the above file, and also
-% http://partners.adobe.com/asn/developer/typeforum/unicodegn.html
+% http://www.adobe.com/devnet/opentype/archives/glyph.html
% for more details.
/AdobeGlyphList 1500 dict
Modified: trunk/gs/lib/gs_pdfwr.ps
===================================================================
--- trunk/gs/lib/gs_pdfwr.ps 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/lib/gs_pdfwr.ps 2007-08-05 13:55:26 UTC (rev 8178)
@@ -682,6 +682,7 @@
/EmbedAllFonts { }
/MaxSubsetPct { }
/SubsetFonts { }
+ /DSCEncodingToUnicode { }
.dicttomark readonly def
/.distillerdevice
{ currentdevice .devicename dup /pdfwrite eq exch /ps2write eq or
@@ -754,6 +755,37 @@
} ifelse
} .bind odef
+% Create a table for translation DSC comments into Unicode UTF-16
+/.make_DSC_translation_table { % <encoding> .make_DSC_translation_table <array>
+ dup type /stringtype eq {
+ cvn
+ } if
+ dup type /nametype eq {
+ /Encoding findresource
+ } if
+ dup length array exch % [out] [in]
+ 0 1 2 index length 1 sub { % [out] [in] i
+ dup 2 index exch get % [out] [in] i n
+ dup dup null eq exch /.notdef eq or {
+ pop -1
+ } {
+ dup //AdobeGlyphList exch .knownget { % [out] [in] i n c
+ dup type dup /arraytype eq exch /packedarraytype eq or {
+ 0 get % fixme: using the 1st char
+ } if
+ exch pop % [out] [in] i c
+ } { % [out] [in] i n
+ (DSCEncoding defines a character that is not in AdobeGlyphList : )
+ exch .namestring concatstrings =
+ /.make_DSC_translation_table cvx /undefined signalerror
+ } ifelse
+ } ifelse
+ 3 index % [out] [in] i c [out]
+ 3 1 roll put % [out] [in]
+ } for
+ pop % [out]
+} bind def
+
1000 % priority
{
% Note, this may not work if the initial device is not pdfwrite
@@ -792,6 +824,14 @@
systemdict 2 index known { pop pop } { def } ifelse
} forall
} repeat
+ currentdevice .devicename /pdfwrite eq {
+ systemdict /PDFX known systemdict /PDFA known or {
+ /DSCEncoding where {
+ /DSCEncoding get .make_DSC_translation_table
+ /DSCEncodingToUnicode exch def
+ } if
+ } if
+ } if
currentdict end .setdistillerparams
.distillerdevice //null false mark .putdeviceparams
dup type /booleantype eq not { cleartomark pop } if pop pop
Added: trunk/gs/src/ConvertUTF.c
===================================================================
--- trunk/gs/src/ConvertUTF.c 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/ConvertUTF.c 2007-08-05 13:55:26 UTC (rev 8178)
@@ -0,0 +1,542 @@
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* $Id$*/
+
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Source code file.
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Sept 2001: fixed const & error conditions per
+ mods suggested by S. Parent & A. Lillich.
+ June 2002: Tim Dodd added detection and handling of incomplete
+ source sequences, enhanced error detection, added casts
+ to eliminate compiler warnings.
+ July 2003: slight mods to back out aggressive FFFE detection.
+ Jan 2004: updated switches in from-UTF8 conversions.
+ Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
+
+ See the header file "ConvertUTF.h" for complete documentation.
+
+------------------------------------------------------------------------ */
+
+
+#include "ConvertUTF.h"
+#ifdef CVTUTF_DEBUG
+#include <stdio.h>
+#endif
+
+static const int halfShift = 10; /* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+#define false 0
+#define true 1
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF32* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_LEGAL_UTF32) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ --source; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF32 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16* source = *sourceStart;
+ UTF32* target = *targetStart;
+ UTF32 ch, ch2;
+ while (source < sourceEnd) {
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ *target++ = ch;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+#ifdef CVTUTF_DEBUG
+if (result == sourceIllegal) {
+ fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
+ fflush(stderr);
+}
+#endif
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
+ */
+static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "isLegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF8 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns false. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static Boolean isLegalUTF8(const UTF8 *source, int length) {
+ UTF8 a;
+ const UTF8 *srcptr = source+length;
+ switch (length) {
+ default: return false;
+ /* Everything else falls through when "true"... */
+ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 2: if ((a = (*--srcptr)) > 0xBF) return false;
+
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return false; break;
+ case 0xED: if (a > 0x9F) return false; break;
+ case 0xF0: if (a < 0x90) return false; break;
+ case 0xF4: if (a > 0x8F) return false; break;
+ default: if (a < 0x80) return false;
+ }
+
+ case 1: if (*source >= 0x80 && *source < 0xC2) return false;
+ }
+ if (*source > 0xF4) return false;
+ return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
+ int length = trailingBytesForUTF8[*source]+1;
+ if (source+length > sourceEnd) {
+ return false;
+ }
+ return isLegalUTF8(source, length);
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8* source = *sourceStart;
+ UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (! isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead+1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF8 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF32* source = *sourceStart;
+ UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ if (flags == strictConversion ) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF32 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8* source = *sourceStart;
+ UTF32* target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (! isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up the source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = ch;
+ }
+ } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+ Note A.
+ The fall-through switches in UTF-8 reading code save a
+ temp variable, some decrements & conditionals. The switches
+ are equivalent to the following loop:
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
+ In UTF-8 writing code, the switches on "bytesToWrite" are
+ similarly unrolled loops.
+
+ --------------------------------------------------------------------- */
Property changes on: trunk/gs/src/ConvertUTF.c
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: trunk/gs/src/ConvertUTF.h
===================================================================
--- trunk/gs/src/ConvertUTF.h 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/ConvertUTF.h 2007-08-05 13:55:26 UTC (rev 8178)
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* $Id$*/
+
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Header file.
+
+ Several funtions are included here, forming a complete set of
+ conversions between the three formats. UTF-7 is not included
+ here, but is handled in a separate source file.
+
+ Each of these routines takes pointers to input buffers and output
+ buffers. The input buffers are const.
+
+ Each routine converts the text between *sourceStart and sourceEnd,
+ putting the result into the buffer between *targetStart and
+ targetEnd. Note: the end pointers are *after* the last item: e.g.
+ *(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+ and if not, whether the problem was in the source or target buffers.
+ (Only the first encountered problem is indicated.)
+
+ After the conversion, *sourceStart and *targetStart are both
+ updated to point to the end of last text successfully converted in
+ the respective buffers.
+
+ Input parameters:
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
+
+ These conversion functions take a ConversionFlags argument. When this
+ flag is set to strict, both irregular sequences and isolated surrogates
+ will cause an error. When the flag is set to lenient, both irregular
+ sequences and isolated surrogates are converted.
+
+ Whether the flag is strict or lenient, all illegal sequences will cause
+ an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+ or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ must check for illegal sequences.
+
+ When the flag is set to lenient, characters over 0x10FFFF are converted
+ to the replacement character; otherwise (when the flag is set to strict)
+ they constitute an error.
+
+ Output parameters:
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
+
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+/* ---------------------------------------------------------------------
+ The following 4 definitions are compiler-specific.
+ The C standard does not guarantee that wchar_t has at least
+ 16 bits, so wchar_t is no less portable than unsigned short!
+ All should be unsigned values to avoid sign extension during
+ bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned long UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
+
+/* Some fundamental constants */
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+typedef enum {
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+} ConversionResult;
+
+typedef enum {
+ strictConversion = 0,
+ lenientConversion
+} ConversionFlags;
+
+/* This is for C++ and does no harm in C */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ConversionResult ConvertUTF8toUTF16 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF8 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF8toUTF32 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF8 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF32 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF16 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* --------------------------------------------------------------------- */
Property changes on: trunk/gs/src/ConvertUTF.h
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: trunk/gs/src/devs.mak
===================================================================
--- trunk/gs/src/devs.mak 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/devs.mak 2007-08-05 13:55:26 UTC (rev 8178)
@@ -250,6 +250,7 @@
gdevsvga_h=$(GLSRC)gdevsvga.h
# Out of order
gdevdljm_h=$(GLSRC)gdevdljm.h $(gdevpcl_h)
+ConvertUTF_h=$(GLSRC)ConvertUTF.h
GDEVLDFJB2CC=$(CC_) $(I_)$(GLI_) $(II)$(LDF_JB2I_)$(_I) $(JB2CF_) $(GLF_)
GDEVLWFJPXCC=$(CC_) $(I_)$(GLI_) $(II)$(LWF_JPXI_)$(_I) $(JPXCF_) $(GLF_)
@@ -807,7 +808,7 @@
pdfwrite6_=$(GLOBJ)gdevpdfo.$(OBJ) $(GLOBJ)gdevpdfp.$(OBJ) $(GLOBJ)gdevpdft.$(OBJ)
pdfwrite7_=$(GLOBJ)gdevpdfr.$(OBJ)
pdfwrite8_=$(GLOBJ)gdevpdfu.$(OBJ) $(GLOBJ)gdevpdfv.$(OBJ)
-pdfwrite9_=
+pdfwrite9_= $(GLOBJ)ConvertUTF.$(OBJ)
pdfwrite10_=$(GLOBJ)gsflip.$(OBJ)
pdfwrite11_=$(GLOBJ)scantab.$(OBJ) $(GLOBJ)sfilter2.$(OBJ)
pdfwrite_=$(pdfwrite1_) $(pdfwrite2_) $(pdfwrite3_) $(pdfwrite4_)\
@@ -880,8 +881,8 @@
$(GLCC) $(GLO_)gdevpdfd.$(OBJ) $(C_) $(GLSRC)gdevpdfd.c
$(GLOBJ)gdevpdfe.$(OBJ) : $(GLSRC)gdevpdfe.c\
- $(gx_h) $(string__h) $(time__h) $(stream_h) $(gp_h) $(smd5_h) $(gscdefs_h)\
- $(gdevpdfx_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdtf_h)
+ $(gx_h) $(gserrors_h) $(string__h) $(time__h) $(stream_h) $(gp_h) $(smd5_h) $(gscdefs_h)\
+ $(gdevpdfx_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdtf_h) $(ConvertUTF_h)
$(GLCC) $(GLO_)gdevpdfe.$(OBJ) $(C_) $(GLSRC)gdevpdfe.c
$(GLOBJ)gdevpdfg.$(OBJ) : $(GLSRC)gdevpdfg.c $(GXERR) $(math__h) $(string__h)\
@@ -955,6 +956,9 @@
$(szlibx_h)
$(GLCC) $(GLO_)gdevpdfv.$(OBJ) $(C_) $(GLSRC)gdevpdfv.c
+$(GLOBJ)ConvertUTF.$(OBJ) : $(GLSRC)ConvertUTF.c $(ConvertUTF_h)
+ $(GLCC) $(GLO_)ConvertUTF.$(OBJ) $(C_) $(GLSRC)ConvertUTF.c
+
######## pdfwrite text
# The text facilities for the PDF writer are so large and complex that
Modified: trunk/gs/src/gdevpdfb.h
===================================================================
--- trunk/gs/src/gdevpdfb.h 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/gdevpdfb.h 2007-08-05 13:55:26 UTC (rev 8178)
@@ -127,6 +127,7 @@
max_long, /* MaxViewerMemorySize */
256000, /* MaxShadingBitmapSize */
PDF_DEVICE_MaxInlineImageSize, /* MaxInlineImageSize */
+ {0, 0}, /* DSCEncodingToUnicode */
{0, 0, 0}, /* OwnerPassword */
{0, 0, 0}, /* UserPassword */
0, /* KeyLength */
Modified: trunk/gs/src/gdevpdfe.c
===================================================================
--- trunk/gs/src/gdevpdfe.c 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/gdevpdfe.c 2007-08-05 13:55:26 UTC (rev 8178)
@@ -14,6 +14,7 @@
/* $Id$ */
/* Metadata writer. */
#include "gx.h"
+#include "gserrors.h"
#include "string_.h"
#include "time_.h"
#include "stream.h"
@@ -24,7 +25,17 @@
#include "gdevpdfg.h"
#include "gdevpdfo.h"
#include "gdevpdtf.h"
+#include "ConvertUTF.h"
+
+private void
+copy_bytes(stream *s, const byte **data, int *data_length, int n)
+{
+ while (n-- && (*data_length)--) {
+ stream_putc(s, *((*data)++));
+ }
+}
+
/* Write XML data */
private void
pdf_xml_data_write(stream *s, const byte *data, int data_length)
@@ -32,18 +43,34 @@
int l = data_length;
const byte *p = data;
- for (; l--; p++) {
+ while (l > 0) {
switch (*p) {
- case '<' : stream_puts(s, "<"); break;
- case '>' : stream_puts(s, ">"); break;
- case '&' : stream_puts(s, "&"); break;
- case '\'': stream_puts(s, "'"); break;
- case '"' : stream_puts(s, """); break;
+ case '<' : stream_puts(s, "<"); l--; p++; break;
+ case '>' : stream_puts(s, ">"); l--; p++; break;
+ case '&' : stream_puts(s, "&"); l--; p++; break;
+ case '\'': stream_puts(s, "'"); l--; p++; break;
+ case '"' : stream_puts(s, """); l--; p++; break;
default:
- if (*p < 32 || *p > 127)
+ if (*p < 32) {
+ /* Not allowed in XML. */
pprintd1(s, "&#%d;", *p);
- else
+ l--; p++;
+ } else if (*p >= 0x7F && *p <= 0x9f) {
+ /* Control characters are discouraged in XML. */
+ pprintd1(s, "&#%d;", *p);
+ } else if ((*p & 0xE0) == 0xC0) {
+ /* A 2-byte UTF-8 sequence */
+ copy_bytes(s, &p, &l, 2);
+ } else if ((*p & 0xF0) == 0xE0) {
+ /* A 3-byte UTF-8 sequence */
+ copy_bytes(s, &p, &l, 3);
+ } else if ((*p & 0xF0) == 0xF0) {
+ /* A 4-byte UTF-8 sequence */
+ copy_bytes(s, &p, &l, 4);
+ } else {
stream_putc(s, *p);
+ l--; p++;
+ }
}
}
}
@@ -253,7 +280,95 @@
return l;
}
-private void
+private inline byte
+decode_escape(const byte *data, int data_length, int *index)
+{
+ byte c;
+
+ (*index)++; /* skip '\' */
+ if (*index >= data_length)
+ return 0; /* Must_not_happen, because the string is PS encoded. */
+ c = data[*index];
+ switch (c) {
+ case 'n': (*index)++; return '\n';
+ case 'r': (*index)++; return '\r';
+ case 't': (*index)++; return '\t';
+ default:
+ break;
+ }
+ if (c >= '0' && c <= '7') {
+ /* octal */
+ byte v = c - '0';
+
+ for (;;) {
+ (*index)++;
+ if (*index >= data_length)
+ return v;
+ c = data[*index];
+ if (c < '0' || c > '7')
+ break;
+ v = v * 8 + (c - '0');
+ }
+ return v;
+ }
+ return c; /* A wrong escapement sequence. */
+}
+
+private int
+pdf_xmp_write_translated(gx_device_pdf *pdev, stream *s, const byte *data, int data_length,
+ void(*write)(stream *s, const byte *data, int data_length))
+{
+ if (pdev->DSCEncodingToUnicode.data == 0) {
+ write(s, data, data_length);
+ return 0;
+ } else {
+ UTF16 *buf0, *buf0b;
+ UTF8 *buf1, *buf1b;
+ int i, j = 0;
+
+ buf0 = (UTF16 *)gs_alloc_bytes(pdev->memory, data_length * sizeof(UTF16),
+ "pdf_xmp_write_translated");
+ if (buf0 == NULL)
+ return_error(gs_error_VMerror);
+ buf1 = (UTF8 *)gs_alloc_bytes(pdev->memory, data_length * 2,
+ "pdf_xmp_write_translated");
+ if (buf1 == NULL)
+ return_error(gs_error_VMerror);
+ buf0b = buf0;
+ buf1b = buf1;
+ for (i = 0; i < data_length; i++) {
+ byte c = data[i];
+ int v;
+
+ if (c == '\\')
+ c = decode_escape(data, data_length, &i);
+ if (c > pdev->DSCEncodingToUnicode.size)
+ return_error(gs_error_rangecheck);
+
+ v = pdev->DSCEncodingToUnicode.data[c];
+ if (v == -1)
+ v = '?'; /* Arbitrary. */
+ buf0[j] = v;
+ j++;
+ }
+ switch (ConvertUTF16toUTF8(&buf0b, buf0 + j,
+ &buf1b, buf1 + data_length * 2, strictConversion)) {
+ case conversionOK:
+ write(s, buf1, buf1b - buf1);
+ break;
+ case sourceExhausted:
+ case targetExhausted:
+ case sourceIllegal:
+ default:
+ return_error(gs_error_rangecheck);
+ }
+ gs_free_object(pdev->memory, buf0, "pdf_xmp_write_translated");
+ gs_free_object(pdev->memory, buf1, "pdf_xmp_write_translated");
+ return 0;
+ }
+}
+
+private int
pdf_xmp_write_docinfo_item(gx_device_pdf *pdev, stream *s, const char *key, const char *default_value,
void(*write)(stream *s, const byte *data, int data_length))
{
@@ -262,11 +377,15 @@
if (v != NULL && (v->value_type == COS_VALUE_SCALAR ||
v->value_type == COS_VALUE_CONST)) {
if (v->contents.chars.size > 2 && v->contents.chars.data[0] == '(')
- write(s, v->contents.chars.data + 1, v->contents.chars.size - 2);
+ return pdf_xmp_write_translated(pdev, s, v->contents.chars.data + 1,
+ v->contents.chars.size - 2, write);
else
- write(s, v->contents.chars.data, v->contents.chars.size);
- } else
+ return pdf_xmp_write_translated(pdev, s, v->contents.chars.data,
+ v->contents.chars.size, write);
+ } else {
stream_puts(s, default_value);
+ return 0;
+ }
}
private uint64_t
@@ -398,8 +517,10 @@
pdf_xml_attribute_name(s, "xmlns:pdf");
pdf_xml_attribute_value(s, "http://ns.adobe.com/pdf/1.3/");
pdf_xml_attribute_name(s, "pdf:Producer");
- pdf_xmp_write_docinfo_item(pdev, s, "/Producer", "UnknownProduicer",
+ code = pdf_xmp_write_docinfo_item(pdev, s, "/Producer", "UnknownProduicer",
pdf_xml_attribute_value_data);
+ if (code < 0)
+ return code;
pdf_xml_tag_end_empty(s);
pdf_xml_newline(s);
@@ -416,8 +537,10 @@
{
pdf_xml_tag_open_beg(s, "xap:CreatorTool");
pdf_xml_tag_end(s);
- pdf_xmp_write_docinfo_item(pdev, s, "/Creator", "UnknownApplication",
+ code = pdf_xmp_write_docinfo_item(pdev, s, "/Creator", "UnknownApplication",
pdf_xml_data_write);
+ if (code < 0)
+ return code;
pdf_xml_tag_close(s, "xap:CreatorTool");
}
pdf_xml_tag_close(s, "rdf:Description");
@@ -451,8 +574,10 @@
pdf_xml_attribute_value(s, "x-default");
pdf_xml_tag_end(s);
{
- pdf_xmp_write_docinfo_item(pdev, s, "/Title", "Untitled",
+ code = pdf_xmp_write_docinfo_item(pdev, s, "/Title", "Untitled",
pdf_xml_data_write);
+ if (code < 0)
+ return code;
}
pdf_xml_tag_close(s, "rdf:li");
}
@@ -470,8 +595,10 @@
{
pdf_xml_tag_open(s, "rdf:li");
{
- pdf_xmp_write_docinfo_item(pdev, s, "/Author", "Unknown",
+ code = pdf_xmp_write_docinfo_item(pdev, s, "/Author", "Unknown",
pdf_xml_data_write);
+ if (code < 0)
+ return code;
}
pdf_xml_tag_close(s, "rdf:li");
}
Modified: trunk/gs/src/gdevpdfp.c
===================================================================
--- trunk/gs/src/gdevpdfp.c 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/gdevpdfp.c 2007-08-05 13:55:26 UTC (rev 8178)
@@ -73,6 +73,7 @@
pi("CompressFonts", gs_param_type_bool, CompressFonts),
pi("PrintStatistics", gs_param_type_bool, PrintStatistics),
pi("MaxInlineImageSize", gs_param_type_long, MaxInlineImageSize),
+ pi("DSCEncodingToUnicode", gs_param_type_int_array, DSCEncodingToUnicode),
/* PDF Encryption */
pi("OwnerPassword", gs_param_type_string, OwnerPassword),
Modified: trunk/gs/src/gdevpdfx.h
===================================================================
--- trunk/gs/src/gdevpdfx.h 2007-08-05 03:08:49 UTC (rev 8177)
+++ trunk/gs/src/gdevpdfx.h 2007-08-05 13:55:26 UTC (rev 8178)
@@ -450,6 +450,7 @@
a bitmap representation of a shading.
(Bigger shadings to be downsampled). */
long MaxInlineImageSize;
+ gs_param_int_array DSCEncodingToUnicode;
/* Encryption parameters */
gs_param_string OwnerPassword;
gs_param_string UserPassword;
@@ -673,8 +674,8 @@
m(28,sbstack) m(29,substream_Resources) m(30,font3)\
m(31,accumulating_substream_resource) \
m(32,pres_soft_mask_dict) m(33,PDFXTrimBoxToMediaBoxOffset.data)\
- m(34,PDFXBleedBoxToTrimBoxOffset.data)
-#define gx_device_pdf_num_ptrs 35
+ m(34,PDFXBleedBoxToTrimBoxOffset.data) m(35, DSCEncodingToUnicode.data)
+#define gx_device_pdf_num_ptrs 36
#define gx_device_pdf_do_param_strings(m)\
m(0, OPDFReadProcsetPath) m(1, OwnerPassword) m(2, UserPassword) m(3, NoEncrypt)\
m(4, DocumentUUID) m(5, InstanceUUID)
More information about the gs-cvs
mailing list