[gs-cvs] rev 6892 - in trunk/gs: doc lib src
leonardo at ghostscript.com
leonardo at ghostscript.com
Wed Jul 5 07:03:52 PDT 2006
Author: leonardo
Date: 2006-07-05 07:03:49 -0700 (Wed, 05 Jul 2006)
New Revision: 6892
Modified:
trunk/gs/doc/Ps2pdf.htm
trunk/gs/lib/PDFA_def.ps
trunk/gs/src/devs.mak
trunk/gs/src/gdevpdf.c
trunk/gs/src/gdevpdfe.c
trunk/gs/src/gdevpdtf.c
Log:
Fix (pdfwrite) : More PDF/A-1b complience.
DETAILS :
Bug 688742 "PDF/A label missing error in Acrobat preflight", part 2.
1. Always embed all fonts when writing a PDF/A document.
2. Provide a precize time and time zone (see the documentation change included).
3. Wrtte an OutputConditionIdentifier.
See the documentation change for details.
DIFFERENCES :
None.
Modified: trunk/gs/doc/Ps2pdf.htm
===================================================================
--- trunk/gs/doc/Ps2pdf.htm 2006-07-05 10:26:03 UTC (rev 6891)
+++ trunk/gs/doc/Ps2pdf.htm 2006-07-05 14:03:49 UTC (rev 6892)
@@ -135,6 +135,43 @@
different name, you must set <b><tt>GSC</tt></b> to the name of the
executable.
+<p>
+The <b><tt>pdfwrite</tt></b> device uses the value of the environment variable <b><tt>TZ</tt></b>
+for generating values of <b><tt>CreationDate</tt></b> and <b><tt>ModDate</tt></b>
+keys of the <b><tt>Info</tt></b> dictionary, and for
+<b><tt>CreateDate</tt></b> and <b><tt>ModifyDate</tt></b> keys of the document <b><tt>Metadata</tt></b>.
+If the environment variable is not set, the <b><tt>Info</tt></b> dictionary keys do not
+include a time zone specification, and <b><tt>Metadata</tt></b> (if presents)
+specifies the 0th time zone.
+
+Use the commonly known syntax to set the <b><tt>TZ</tt></b> environment variable:
+
+
+<blockquote><b><tt>
+tzn[+ | -]hh[:mm[:ss] ][dzn]
+</b></tt></blockquote>
+
+<ul>
+<li><b><tt>tzn</tt></b>
+- Three-letter time-zone name, such as PST. You must specify the correct offset from local time to UTC
+(not unused by <b><tt>pdfwrite</tt></b>).
+
+<li><b><tt>hh</tt></b>
+- Difference in hours between UTC and local time. Optionally signed.
+
+<li><b><tt>mm</tt></b>
+- Minutes. Separated from hh by a colon (:).
+
+<li><b><tt>ss</tt></b>
+- Seconds. Separated from mm by a colon (:)
+(not unused by <b><tt>pdfwrite</tt></b>).
+
+<li><b><tt>dzn</tt></b>
+- Three-letter daylight-saving-time zone such as PDT. If daylight saving time is never in effect in the locality, set TZ without a value for dzn. The C run-time library assumes the United States' rules for implementing the calculation of Daylight Saving Time (DST)
+(not unused by <b><tt>pdfwrite</tt></b>).
+</ul>
+
+
<hr>
<h2><a name="Orientation"></a>Setting page orientation</h2>
@@ -833,6 +870,9 @@
gs -dPDFX -dBATCH -dNOPAUSE -dNOOUTERSAVE -dUseCIEColor -sDEVICE=pdfwrite -sOutputFile=out-x3.pdf PDFX_def.ps input.ps
</tt></b></blockquote>
+<p>
+Note that the <b><tt>TZ</tt></b> environment variable is necessary for a proper generation
+of the document the <b><tt>Metadata</tt></b>. See the <a href="#Usage">Usage</a> for details.
<p>
<hr>
@@ -855,7 +895,11 @@
gs -dPDFA -dBATCH -dNOPAUSE -dNOOUTERSAVE -dUseCIEColor -sDEVICE=pdfwrite -sOutputFile=out-a.pdf PDFA_def.ps input.ps
</tt></b></blockquote>
+<p>
+Note that the <b><tt>TZ</tt></b> environment variable is necessary for a proper generation
+of the document the <b><tt>Metadata</tt></b>. See the <a href="#Usage">Usage</a> for details.
+
<p>
<hr>
Modified: trunk/gs/lib/PDFA_def.ps
===================================================================
--- trunk/gs/lib/PDFA_def.ps 2006-07-05 10:26:03 UTC (rev 6891)
+++ trunk/gs/lib/PDFA_def.ps 2006-07-05 14:03:49 UTC (rev 6892)
@@ -38,5 +38,6 @@
/Type /OutputIntent % Must be so (the standard requires).
/S /GTS_PDFA1 % Must be so (the standard requires).
/DestOutputProfile {icc_PDFA} % Must be so (see above).
+ /OutputConditionIdentifier (CGATS TR001) % Customize
>> /PUT pdfmark
[{Catalog} <</OutputIntents [ {OutputIntent_PDFA} ]>> /PUT pdfmark
Modified: trunk/gs/src/devs.mak
===================================================================
--- trunk/gs/src/devs.mak 2006-07-05 10:26:03 UTC (rev 6891)
+++ trunk/gs/src/devs.mak 2006-07-05 14:03:49 UTC (rev 6892)
@@ -840,7 +840,7 @@
$(GLOBJ)gdevpdf.$(OBJ) : $(GLSRC)gdevpdf.c $(GDEVH)\
$(fcntl__h) $(memory__h) $(string__h) $(time__h) $(unistd__h) $(gp_h)\
$(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdfx_h) $(gdevpdt_h) $(smd5_h) $(sarc4_h)\
- $(gdevpdfb_h)
+ $(gdevpdfb_h) $(gpgetenv_h)
$(GLCC) $(GLO_)gdevpdf.$(OBJ) $(C_) $(GLSRC)gdevpdf.c
$(GLOBJ)gdevpdfb.$(OBJ) : $(GLSRC)gdevpdfb.c\
Modified: trunk/gs/src/gdevpdf.c
===================================================================
--- trunk/gs/src/gdevpdf.c 2006-07-05 10:26:03 UTC (rev 6891)
+++ trunk/gs/src/gdevpdf.c 2006-07-05 14:03:49 UTC (rev 6892)
@@ -28,6 +28,7 @@
#include "gdevpdt.h"
#include "smd5.h"
#include "sarc4.h"
+#include "gpgetenv.h"
/* Define the default language level and PDF compatibility level. */
/* Acrobat 4 (PDF 1.3) is the default. */
@@ -243,6 +244,39 @@
return 0;
}
+private void
+write_time_zone(char *buf, int offset)
+{
+ char tz[20];
+ char *p = tz + 3;
+ int zl;
+ int code = gp_getenv("TZ", tz, &zl);
+
+ if (code != 0) {
+ buf[offset] = ')';
+ buf[offset + 1] = 0;
+ return;
+ }
+ p = tz + 3;
+ zl -= 3;
+ if (*p != '+' && *p != '-') {
+ buf[offset] = '+';
+ offset++;
+ } else {
+ buf[offset] = *p;
+ offset++;
+ p++;
+ }
+ memcpy(buf + offset, p, 2);
+ offset += 2;
+ p += 2;
+ if (*p != ':') {
+ memcpy(buf + offset, "'00'", 4); /* Set the default time zone 0. */
+ return;
+ }
+ memcpy(buf + offset, p, 3);
+}
+
/* Initialize the IDs allocated at startup. */
void
pdf_initialize_ids(gx_device_pdf * pdev)
@@ -275,14 +309,15 @@
{
struct tm tms;
time_t t;
- char buf[1+2+4+2+2+2+2+2+2+1+1]; /* (D:yyyymmddhhmmss)\0 */
+ char buf[1+2+4+2+2+2+2+2+2+1+1+7]; /* (D:yyyymmddhhmmssZhh'mm')\0 */
time(&t);
tms = *localtime(&t);
sprintf(buf,
- "(D:%04d%02d%02d%02d%02d%02d)",
+ "(D:%04d%02d%02d%02d%02d%02dZhh'mm')",
tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
tms.tm_hour, tms.tm_min, tms.tm_sec);
+ write_time_zone(buf, 17);
cos_dict_put_c_key_string(pdev->Info, "/CreationDate", (byte *)buf,
strlen(buf));
cos_dict_put_c_key_string(pdev->Info, "/ModDate", (byte *)buf,
Modified: trunk/gs/src/gdevpdfe.c
===================================================================
--- trunk/gs/src/gdevpdfe.c 2006-07-05 10:26:03 UTC (rev 6891)
+++ trunk/gs/src/gdevpdfe.c 2006-07-05 14:03:49 UTC (rev 6892)
@@ -153,7 +153,7 @@
/* -------------------------------------------- */
-private void
+private int
pdf_xmp_time(char *buf, int buf_length)
{
/* We don't write a day time because we don't have a time zone. */
@@ -167,8 +167,92 @@
"%04d-%02d-%02d",
tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday);
strncpy(buf, buf1, buf_length);
+ return strlen(buf);
}
+private int
+pdf_xmp_convert_time(char *dt, int dtl, char *buf, int bufl)
+{ /* The 'dt' buffer is of same size as 'buf'. */
+ /* Input sample : D:199812231952?08'00' */
+ /* Output sample : 1997-07-16T19:20:30+01:00 */
+ int l = dtl;
+
+ if (l > bufl)
+ l = bufl;
+ if (dt[0] == 'D' && dt[1] == ':') {
+ l -= 2;
+ memcpy(buf, dt + 2, l);
+ } else
+ memcpy(buf, dt, l);
+ memcpy(dt, buf, 4); /* year */
+ if (l <= 4)
+ return 4;
+
+ dt[4] = '-';
+ memcpy(dt + 5, buf + 4, 2); /* month */
+ if (l <= 6)
+ return 7;
+
+ dt[7] = '-';
+ memcpy(dt + 8, buf + 6, 2); /* day */
+ if (l <= 8)
+ return 10;
+
+ dt[10] = 'T';
+ memcpy(dt + 11, buf + 8, 2); /* hour */
+ dt[13] = ':';
+ memcpy(dt + 14, buf + 10, 2); /* minute */
+ if (l <= 12) {
+ dt[16] = 'Z'; /* Default time zone 0. */
+ return 17;
+ }
+
+ dt[16] = ':';
+ memcpy(dt + 17, buf + 12, 2); /* second */
+ if (l <= 14) {
+ dt[18] = 'Z'; /* Default time zone 0. */
+ return 19;
+ }
+
+ dt[19] = buf[14]; /* designator */
+ if (l <= 15)
+ return 20;
+ memcpy(dt + 20, buf + 15, 2); /* Time zone hour difference. */
+ if (l <= 17)
+ return 22;
+
+ dt[22] = ':';
+ /* Skipping '\'' in 'buf'. */
+ memcpy(dt + 23, buf + 18, 2); /* Time zone hour difference. */
+ return 25;
+}
+
+private int
+pdf_get_docinfo_item(gx_device_pdf *pdev, const char *key, char *buf, int buf_length)
+{
+ const cos_value_t *v = cos_dict_find(pdev->Info, (const byte *)key, strlen(key));
+ int l;
+ const byte *s;
+
+ 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] == '(') {
+ s = v->contents.chars.data + 1;
+ l = v->contents.chars.size - 2;
+ } else {
+ s = v->contents.chars.data;
+ l = v->contents.chars.size;
+ }
+ } else
+ return 0;
+ if (l < 0)
+ l = 0;
+ if (l > buf_length)
+ l = buf_length;
+ memcpy(buf, s, l);
+ return l;
+}
+
private void
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))
@@ -269,7 +353,8 @@
private int
pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6])
{
- char instance_uuid[40], document_uuid[40], date_time[40];
+ char instance_uuid[40], document_uuid[40], cre_date_time[40], mod_date_time[40], date_time_buf[40];
+ int cre_date_time_len, mod_date_time_len;
int code;
stream *s = pdev->strm;
@@ -279,7 +364,18 @@
code = pdf_make_document_uuid(pdev, digest, document_uuid, sizeof(document_uuid));
if (code < 0)
return code;
- pdf_xmp_time(date_time, sizeof(date_time));
+
+
+ cre_date_time_len = pdf_get_docinfo_item(pdev, "/CreationDate", cre_date_time, sizeof(cre_date_time));
+ if (!cre_date_time_len)
+ cre_date_time_len = pdf_xmp_time(cre_date_time, sizeof(cre_date_time));
+ else
+ cre_date_time_len = pdf_xmp_convert_time(cre_date_time, cre_date_time_len, date_time_buf, sizeof(date_time_buf));
+ mod_date_time_len = pdf_get_docinfo_item(pdev, "/CreationDate", mod_date_time, sizeof(mod_date_time));
+ if (!mod_date_time_len)
+ mod_date_time_len = pdf_xmp_time(mod_date_time, sizeof(mod_date_time));
+ else
+ mod_date_time_len = pdf_xmp_convert_time(mod_date_time, mod_date_time_len, date_time_buf, sizeof(date_time_buf));
pdf_xml_ins_beg(s, "xpacket");
pdf_xml_attribute_name(s, "begin");
pdf_xml_copy(s, dd);
@@ -313,22 +409,15 @@
pdf_xml_attribute_name(s, "xmlns:xap");
pdf_xml_attribute_value(s, "http://ns.adobe.com/xap/1.0/");
pdf_xml_attribute_name(s, "xap:ModifyDate");
- pdf_xml_attribute_value(s, date_time);
+ pdf_xml_attribute_value_data(s, (const byte *)mod_date_time, mod_date_time_len);
pdf_xml_attribute_name(s, "xap:CreateDate");
- pdf_xml_attribute_value(s, date_time);
+ pdf_xml_attribute_value_data(s, (const byte *)cre_date_time, cre_date_time_len);
pdf_xml_tag_end(s);
{
pdf_xml_tag_open_beg(s, "xap:CreatorTool");
pdf_xml_tag_end(s);
- {
- char buf[10];
-
- sprintf(buf, "%d.%02d", (int)(gs_revision / 100), (int)(gs_revision % 100));
- pdf_xml_string_write(s, gs_product);
- pdf_xml_string_write(s, " ");
- pdf_xml_string_write(s, buf);
- pdf_xml_string_write(s, " PDF Writer");
- }
+ pdf_xmp_write_docinfo_item(pdev, s, "/Creator", "UnknownApplication",
+ pdf_xml_data_write);
pdf_xml_tag_close(s, "xap:CreatorTool");
}
pdf_xml_tag_close(s, "rdf:Description");
@@ -403,8 +492,7 @@
pdf_xml_attribute_value(s,"1");
pdf_xml_attribute_name(s, "pdfaid:conformance");
pdf_xml_attribute_value(s,"B");
- pdf_xml_tag_end(s);
- pdf_xml_tag_close(s, "rdf:Description");
+ pdf_xml_tag_end_empty(s);
}
}
pdf_xml_copy(s, "</rdf:RDF>\n");
Modified: trunk/gs/src/gdevpdtf.c
===================================================================
--- trunk/gs/src/gdevpdtf.c 2006-07-05 10:26:03 UTC (rev 6891)
+++ trunk/gs/src/gdevpdtf.c 2006-07-05 14:03:49 UTC (rev 6892)
@@ -676,7 +676,7 @@
*/
if (pindex)
*pindex = index;
- if (pdev->PDFX)
+ if (pdev->PDFX || pdev->PDFA)
return FONT_EMBED_YES;
if (pdev->CompatibilityLevel < 1.3) {
if (index >= 0 &&
More information about the gs-cvs
mailing list