[gs-cvs] rev 7057 - trunk/gs/src

leonardo at ghostscript.com leonardo at ghostscript.com
Tue Sep 19 11:59:11 PDT 2006


Author: leonardo
Date: 2006-09-19 11:59:10 -0700 (Tue, 19 Sep 2006)
New Revision: 7057

Modified:
   trunk/gs/src/gdevpdfb.h
   trunk/gs/src/gdevpdfx.h
   trunk/gs/src/gdevpdtd.c
   trunk/gs/src/gdevpdtf.c
   trunk/gs/src/gdevpdtf.h
   trunk/gs/src/gdevpdtw.c
Log:
Fix (pdfwrite) : Wrinting a PDF/A, convert True Type fonts into CIDFontType2.

DETAILS :

THis is a partial fix the bug 688790  
"pdfwrite : The PDF/A conversion needs to re-encode texts".

PDF/A doesn't allow True Type fonts with Encoding Differences.
Therefore we convert such fonts into CIDFontType2.
The main work is done with 2 functions :
pdf_convert_truetype_font_descriptor and
pdf_convert_truetype_font.
See comments in code about the conversion algorithm.

Minor change (gdevpdtw.c) : The old code always compressed CIDToGIDMap.
The new code does dependently on the CompressFonts distiller parameter.
Except that, for a non-PDFA run the code change should be equivalent.

Now the font conversion works, but Adobe preflight tool
reports missed glyphs by unknown reason.
Will need a separate patch for that.

EXPECTED DIFFERENCES :

None.


Modified: trunk/gs/src/gdevpdfb.h
===================================================================
--- trunk/gs/src/gdevpdfb.h	2006-09-19 16:08:49 UTC (rev 7056)
+++ trunk/gs/src/gdevpdfb.h	2006-09-19 18:59:10 UTC (rev 7057)
@@ -178,6 +178,8 @@
  {0},				/* cs_Patterns */
  {0},				/* Identity_ToUnicode_CMaps */
  0,				/* last_resource */
+ 0,				/* OneByteIdentityH */
+ gs_no_id,			/* IdentityCIDSystemInfo_id */
  {
      {
 	 {0}}},			/* outline_levels */

Modified: trunk/gs/src/gdevpdfx.h
===================================================================
--- trunk/gs/src/gdevpdfx.h	2006-09-19 16:08:49 UTC (rev 7056)
+++ trunk/gs/src/gdevpdfx.h	2006-09-19 18:59:10 UTC (rev 7057)
@@ -534,6 +534,8 @@
     pdf_resource_t *cs_Patterns[5];
     pdf_resource_t *Identity_ToUnicode_CMaps[2]; /* WMode = 0,1 */
     pdf_resource_t *last_resource;
+    pdf_resource_t *OneByteIdentityH;
+    gs_id IdentityCIDSystemInfo_id;
     pdf_outline_level_t outline_levels[MAX_OUTLINE_DEPTH];
     int outline_depth;
     int closed_outline_depth;

Modified: trunk/gs/src/gdevpdtd.c
===================================================================
--- trunk/gs/src/gdevpdtd.c	2006-09-19 16:08:49 UTC (rev 7056)
+++ trunk/gs/src/gdevpdtd.c	2006-09-19 18:59:10 UTC (rev 7057)
@@ -681,7 +681,38 @@
  * Convert True Type font descriptor into CID font descriptor for PDF/A.
  */
 int 
-pdf_convert_truetype_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
+pdf_convert_truetype_font_descriptor(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
 {
+    pdf_font_descriptor_t *pfd = pdfont->FontDescriptor;
+    int num_CIDs = 256;
+    int length_CIDSet = num_CIDs / 8;
+    int length_CIDToGIDMap = num_CIDs * sizeof(ushort);
+    pdf_base_font_t *pbfont = pfd->base_font;
+    gs_font *pfont = (gs_font *)pbfont->copied;
+    gs_char ch;
+    /* Save the simple font descriptor data because CID font data overlap them. */
+    int FirstChar = pdfont->u.simple.FirstChar, LastChar = pdfont->u.simple.LastChar;
+    pdf_encoding_element_t *Encoding = pdfont->u.simple.Encoding;
+
+    pfd->FontType = ft_CID_TrueType;
+    pdfont->u.simple.Encoding = NULL; /* Drop due to overlapping against a garbager problem. */
+    pbfont->CIDSet = gs_alloc_bytes(pdev->pdf_memory, length_CIDSet, 
+			"pdf_convert_truetype_font_descriptor");
+    if (pbfont->CIDSet == NULL)
+	return_error(gs_error_VMerror);
+    memset(pbfont->CIDSet, 0, length_CIDSet);
+    pdfont->u.cidfont.CIDToGIDMap = (ushort *)gs_alloc_bytes(pdev->pdf_memory, 
+			length_CIDToGIDMap, "pdf_convert_truetype_font_descriptor");
+    if (pdfont->u.cidfont.CIDToGIDMap == NULL)
+	return_error(gs_error_VMerror);
+    memset(pdfont->u.cidfont.CIDToGIDMap, 0, length_CIDToGIDMap);
+    for (ch = FirstChar; ch <= LastChar; ch++) {
+	if (Encoding[ch].glyph != GS_NO_GLYPH) {
+	    gs_glyph glyph = pfont->procs.encode_char(pfont, ch, GLYPH_SPACE_INDEX);
+
+	    pbfont->CIDSet[ch / 8] |= 0x80 >> (ch % 8);
+	    pdfont->u.cidfont.CIDToGIDMap[ch] = glyph - GS_MIN_GLYPH_INDEX;
+	}
+    }
     return 0;
 }

Modified: trunk/gs/src/gdevpdtf.c
===================================================================
--- trunk/gs/src/gdevpdtf.c	2006-09-19 16:08:49 UTC (rev 7056)
+++ trunk/gs/src/gdevpdtf.c	2006-09-19 18:59:10 UTC (rev 7057)
@@ -882,6 +882,19 @@
 
 /* ------ CID-keyed ------ */
 
+/* Write CIDSystemInfo */
+private int
+pdf_write_cid_systemInfo_separate(gx_device_pdf *pdev, const gs_cid_system_info_t *pcidsi, long *id)
+{   
+    int code;
+
+    *id = pdf_begin_separate(pdev);
+    code = pdf_write_cid_system_info(pdev, pcidsi, *id);
+    pdf_end_separate(pdev);
+    return code;
+}
+
+
 /* Allocate a CIDFont resource. */
 int
 pdf_font_cidfont_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
@@ -939,15 +952,9 @@
      * Write the CIDSystemInfo now, so we don't try to access it after
      * the font may no longer be available.
      */
-    {
-	long cidsi_id = pdf_begin_separate(pdev);
-
-	code = pdf_write_cid_system_info(pdev, pcidsi, cidsi_id);
-	if (code < 0)
-	    return code;
-	pdf_end_separate(pdev);
-	pdfont->u.cidfont.CIDSystemInfo_id = cidsi_id;
-    }
+    code = pdf_write_cid_systemInfo_separate(pdev, pcidsi, &pdfont->u.cidfont.CIDSystemInfo_id);
+    if (code < 0)
+	return code;
     *ppfres = pdfont;
     return pdf_compute_BaseFont(pdev, pdfont, false);
 }
@@ -1004,16 +1011,49 @@
 int 
 pdf_convert_truetype_font(gx_device_pdf *pdev, pdf_resource_t *pres)
 {
-    if (!pdev->PDFA )
+    if (!pdev->PDFA)
 	return 0;
     else {
-	pdf_font_resource_t *pdfont = (pdf_font_resource_t *) pres;
+	pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres;
 
 	if (pdfont->FontType != ft_TrueType)
 	    return 0;
+	else if (pdf_resource_id(pres) == -1)
+	    return 0; /* An unused font. */
 	else {
-	    /* Reserved for future implementation. */
-	    return 0;
+	    int code = pdf_different_encoding_index(pdfont, 0);
+
+	    if (code < 0)
+		return code;
+	    if (code == 256)
+		return 0;
+	    {	/* The encoding have a difference - do convert. */
+		pdf_font_resource_t *pdfont0;
+		gs_const_string CMapName = {(const byte *)"OneByteIdentityH", 16};
+
+		code = pdf_convert_truetype_font_descriptor(pdev, pdfont);
+		if (code < 0)
+		    return code;
+		code = pdf_font_type0_alloc(pdev, &pdfont0, pres->rid + 1, pdfont, &CMapName);
+		if (code < 0)
+		    return code;
+		/* Pass the font object ID to the type 0 font resource. */
+		pdf_reserve_object_id(pdev, (pdf_resource_t *)pdfont0, pdf_resource_id(pres));
+		pdf_reserve_object_id(pdev, (pdf_resource_t *)pdfont, gs_no_id);
+		/* Set Encoding_name because we won't call attach_cmap_resource for it : */
+		code = pdf_write_OneByteIdentityH(pdev);
+		if (code < 0)
+		    return 0;
+		pdfont->u.cidfont.CIDSystemInfo_id = pdev->IdentityCIDSystemInfo_id;
+		sprintf(pdfont0->u.type0.Encoding_name, "%ld 0 R", pdf_resource_id(pdev->OneByteIdentityH));
+		/* Move ToUnicode : */
+		pdfont0->res_ToUnicode = pdfont->res_ToUnicode; pdfont->res_ToUnicode = 0;
+		pdfont0->cmap_ToUnicode = pdfont->cmap_ToUnicode; pdfont->cmap_ToUnicode = 0;
+		/* Change the font type to CID font : */
+		pdfont->FontType = ft_CID_TrueType;
+		pdfont->write_contents = pdf_write_contents_cid2;
+		return 0;
+	    }
 	}
     }
 }
@@ -1029,3 +1069,78 @@
 {
     return pdf_write_cmap(pdev, pcmap, ppres, font_index_only);
 }
+
+static const char *OneByteIdentityH[] = {
+    "/CIDInit /ProcSet findresource begin",
+    "12 dict begin",
+    "begincmap",
+    "/CIDSystemInfo 3 dict dup begin",
+      "/Registry (Adobe) def",
+      "/Ordering (Identity) def",
+      "/Supplement 0 def",
+    "end def",
+    "/CMapName /OneByteIdentityH def",
+    "/CMapVersion 1.000 def",
+    "/CMapType 1 def",
+    "/UIDOffset 0 def",
+    "/XUID [1 10 25404 9999] def",
+    "/WMode 0 def",
+    "1 begincodespacerange",
+    "<00> <FF>",
+    "endcodespacerange",
+    "1 begincidrange",
+    "<00> <FF> 0",
+    "endcidrange",
+    "endcmap",
+    "CMapName currentdict /CMap defineresource pop",
+    "end",
+    "end",
+NULL};
+
+/* 
+ * Write OneByteIdentityH CMap. 
+ */
+int
+pdf_write_OneByteIdentityH(gx_device_pdf *pdev)
+{ 
+    int code, i;
+    pdf_data_writer_t writer;
+    cos_dict_t *pcd;
+    char buf[200];
+    static const gs_cid_system_info_t cidsi = {{(const byte *)"Adobe", 5}, {(const byte *)"Identity", 8}, 0};
+    long id;
+
+    if (pdev->IdentityCIDSystemInfo_id == gs_no_id) {
+	code = pdf_write_cid_systemInfo_separate(pdev, &cidsi, &id);
+	if (code < 0)
+	    return code;
+	pdev->IdentityCIDSystemInfo_id = id;
+    }
+    if (pdev->OneByteIdentityH != NULL)
+	return 0;
+    code = pdf_begin_data_stream(pdev, &writer,
+				 DATA_STREAM_NOT_BINARY |
+			    /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
+			       See comment in pdf_begin_encrypt. */
+				 (pdev->CompressFonts ? 
+				  DATA_STREAM_COMPRESS : 0), gs_no_id);
+    if (code < 0)
+	return code;
+    pdev->OneByteIdentityH = writer.pres;
+    pcd = (cos_dict_t *)writer.pres->object;
+    code = cos_dict_put_c_key_string(pcd, "/CMapName", "/OneByteIdentityH", 17);
+    if (code < 0)
+	return code;
+    sprintf(buf, "%ld 0 R", pdev->IdentityCIDSystemInfo_id);
+    code = cos_dict_put_c_key_string(pcd, "/CIDSystemInfo", buf, strlen(buf));
+    if (code < 0)
+	return code;
+    code = cos_dict_put_string_copy(pcd, "/Type", "/CMap");
+    if (code < 0)
+	return code;
+    for (i = 0; OneByteIdentityH[i]; i++) {
+	stream_puts(pdev->strm, OneByteIdentityH[i]);
+	stream_putc(pdev->strm, '\n');
+    }
+    return pdf_end_data(&writer);
+}

Modified: trunk/gs/src/gdevpdtf.h
===================================================================
--- trunk/gs/src/gdevpdtf.h	2006-09-19 16:08:49 UTC (rev 7056)
+++ trunk/gs/src/gdevpdtf.h	2006-09-19 18:59:10 UTC (rev 7057)
@@ -440,7 +440,7 @@
 /*
  * Convert True Type font descriptor into CID font descriptor for PDF/A.
  */
-int pdf_convert_truetype_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd);
+int pdf_convert_truetype_font_descriptor(gx_device_pdf *pdev, pdf_font_resource_t *pdfont);
 
 /* ---------------- CMap resources ---------------- */
 
@@ -450,6 +450,11 @@
 int pdf_cmap_alloc(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
 		   pdf_resource_t **ppres /* CMap */, int font_index_only);
 
+/* 
+ * Write OneByteIdentityH CMap. 
+ */
+int pdf_write_OneByteIdentityH(gx_device_pdf *pdev);
+
 /*
  * Add a CID-to-GID mapping to a CIDFontType 2 font resource.
  */

Modified: trunk/gs/src/gdevpdtw.c
===================================================================
--- trunk/gs/src/gdevpdtw.c	2006-09-19 16:08:49 UTC (rev 7056)
+++ trunk/gs/src/gdevpdtw.c	2006-09-19 18:59:10 UTC (rev 7057)
@@ -507,7 +507,7 @@
 	int i;
 
 	pdf_begin_data_stream(pdev, &writer,
-	    DATA_STREAM_BINARY | DATA_STREAM_COMPRESS,
+	    DATA_STREAM_BINARY | (pdev->CompressFonts ? DATA_STREAM_COMPRESS : 0),
 		    /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
 		       See comment in pdf_begin_encrypt. */
 		    map_id);



More information about the gs-cvs mailing list