[cairo] Strange problem with PDF generation

Adrian Johnson ajohnson at redneon.com
Thu Feb 1 06:01:34 PST 2007


Umberto Allievi wrote:

> The generated pdf looks good when viewed in both evince and acrobat
> reader, but when printed (even with cups-PDF) it ...
>  - looks weird if printed with acrobat reader
>  - evince outputs a blank sheet
> If I generate a PS file everything is OK.

The attached patch seems to correct this problem. I am interested
in getting feedback on how well the it works. Note that the patch in its
present form breaks non TrueType fonts. I will fix this once I am
certain this patch fixes the PDF TrueType printing problem.

This patch contains two changes:
- Include glyph 0 (.notdef) in the subset and map character 0 to notdef.
- Include an Encoding dictionary in the PDF TrueType subset.

-------------- next part --------------
>From 305ef4d85fd1e673b4574ce2345debd6afc7fd19 Mon Sep 17 00:00:00 2001
From: asj <asj at tux.lan>
Date: Thu, 1 Feb 2007 23:46:20 +1030
Subject: [PATCH] Truetype Subsetting: Include .notdef and add Encoding to PDF

---
 src/cairo-pdf-surface.c     |   29 +++++++++++++++++++++++------
 src/cairo-ps-surface.c      |   10 +++++-----
 src/cairo-truetype-subset.c |    3 ++-
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index bdfef00..7db4a6c 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -138,7 +138,7 @@ typedef struct _cairo_pdf_surface {
     cairo_paginated_mode_t paginated_mode;
 } cairo_pdf_surface_t;
 
-#define PDF_SURFACE_MAX_GLYPHS_PER_FONT	256
+#define PDF_SURFACE_MAX_GLYPHS_PER_FONT	255
 
 static cairo_pdf_resource_t
 _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
@@ -1876,7 +1876,7 @@ static cairo_status_t
 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 					      cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_pdf_resource_t stream, descriptor, subset_resource;
+    cairo_pdf_resource_t stream, encoding, descriptor, subset_resource;
     cairo_status_t status;
     cairo_pdf_font_t font;
     cairo_truetype_subset_t subset;
@@ -1913,11 +1913,26 @@ _cairo_pdf_surface_emit_truetype_font_su
 				 "endobj\r\n");
     free (compressed);
 
+    encoding = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /Encoding\r\n"
+				 "   /Differences [0 /.notdef ",
+                                 encoding.id);
+
+    for (i = 0; i < font_subset->num_glyphs; i++)
+        _cairo_output_stream_printf (surface->output, "/g%d ", i + 1);
+
+    _cairo_output_stream_printf (surface->output,
+                                 " ]\r\n"
+				 ">>\r\n"
+				 "endobj\r\n");
+
     descriptor = _cairo_pdf_surface_new_object (surface);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /FontDescriptor\r\n"
-				 "   /FontName /7%s\r\n"
+				 "   /FontName /%s\r\n"
 				 "   /Flags 4\r\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
 				 "   /ItalicAngle 0\r\n"
@@ -1948,11 +1963,13 @@ _cairo_pdf_surface_emit_truetype_font_su
 				 "   /FirstChar 0\r\n"
 				 "   /LastChar %d\r\n"
 				 "   /FontDescriptor %d 0 R\r\n"
+				 "   /Encoding %d 0 R\r\n"
 				 "   /Widths [",
 				 subset_resource.id,
 				 subset.base_font,
 				 font_subset->num_glyphs - 1,
-				 descriptor.id);
+				 descriptor.id,
+                                 encoding.id);
 
     for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->output,
@@ -2819,14 +2836,14 @@ _cairo_pdf_surface_show_glyphs (void			*
                                          -scaled_font->scale.yy,
                                          glyphs[i].x,
                                          glyphs[i].y,
-                                         subset_glyph_index);
+                                         subset_glyph_index + 1);
 	    current_subset_id = subset_id;
         } else {
             _cairo_output_stream_printf (surface->output,
                                          "%f %f Td <%02x> Tj\r\n",
                                          (glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx,
                                          (glyphs[i].y - glyphs[i-1].y)/scaled_font->scale.yy,
-                                         subset_glyph_index);
+                                         subset_glyph_index + 1);
         }
     }
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 45d9fe7..238e2a5 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -84,7 +84,7 @@ typedef struct cairo_ps_surface {
 
 } cairo_ps_surface_t;
 
-#define PS_SURFACE_MAX_GLYPHS_PER_FONT	256
+#define PS_SURFACE_MAX_GLYPHS_PER_FONT	255
 
 /* A word wrap stream can be used as a filter to do word wrapping on
  * top of an existing output stream. The word wrapping is quite
@@ -484,7 +484,7 @@ _cairo_ps_surface_emit_truetype_font_sub
 
     /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
 
-    for (i = 1; i < font_subset->num_glyphs; i++)
+    for (i = 1; i <= font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->final_stream,
 				     "Encoding %d /g%d put\n", i, i);
 
@@ -493,7 +493,7 @@ _cairo_ps_surface_emit_truetype_font_sub
 				 "/.notdef 0 def\n",
 				 font_subset->num_glyphs);
 
-    for (i = 1; i < font_subset->num_glyphs; i++)
+    for (i = 1; i <= font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->final_stream,
 				     "/g%d %d def\n", i, i);
 
@@ -2217,12 +2217,12 @@ _cairo_ps_surface_show_glyphs (void
         }
 
         if (i == last) {
-            _cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id);
+            _cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id + 1);
         } else {
             word_wrap = _word_wrap_stream_create (surface->stream, 79);
             _cairo_output_stream_printf (word_wrap, "<");
             for (j = i; j < last+1; j++)
-                _cairo_output_stream_printf (word_wrap, "%02x", glyph_ids[j].glyph_id);
+                _cairo_output_stream_printf (word_wrap, "%02x", glyph_ids[j].glyph_id + 1);
             _cairo_output_stream_printf (word_wrap, ">\n[");
 
             if (horizontal) {
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 86509df..0c48168 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -243,7 +243,7 @@ _cairo_truetype_font_create (cairo_scale
     }
     font->base.base_font[i] = '\0';
 
-    font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
+    font->base.widths = calloc (font->num_glyphs_in_face + 1, sizeof (int));
     if (font->base.widths == NULL)
 	goto fail5;
 
@@ -813,6 +813,7 @@ _cairo_truetype_subset_init (cairo_truet
     if (status)
 	return status;
 
+    cairo_truetype_font_use_glyph (font, 0);
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
 	parent_glyph = font->scaled_font_subset->glyphs[i];
 	cairo_truetype_font_use_glyph (font, parent_glyph);
-- 
1.4.3.4



More information about the cairo mailing list