[cairo] PDF show glyphs

Adrian Johnson ajohnson at redneon.com
Mon Feb 5 06:22:29 PST 2007


I've been putting together a patch to get the PDF backend to write out
strings using the TJ operator similar to what is described in bug 2713.

The current issues with the patch are:

- It currently does a _cairo_scaled_glyph_lookup() for every glyph.
  I'm thinking of moving this into _cairo_sub_font_glyph_create()
  and returning the x_advance it via
  cairo_scaled_font_subsets_map_glyph().

- The gnome-print-pdf.c patch referenced in bug 2713 allows
  a 0.001*font_scale error when comparing glyph positions. I haven't
  done this although it seems to work.

- If the x coordinate of the next glyph in a sequence is > 10*font_scale
  I terminate the string and reposition before starting a new string.
  I'm not sure if this is necessary.

- Should I limit the maximum string length to prevent the accumulation
  of rounding errors?

- It needs more testing.

-------------- next part --------------
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 18f79ca..b31403d 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2796,8 +2796,12 @@ _cairo_pdf_surface_show_glyphs (void			*
     cairo_pdf_surface_t *surface = abstract_surface;
     unsigned int current_subset_id = (unsigned int)-1;
     unsigned int font_id, subset_id, subset_glyph_index;
-    cairo_bool_t diagonal;
+    cairo_bool_t diagonal, in_TJ;
     cairo_status_t status;
+    cairo_scaled_glyph_t *scaled_glyph;
+    double x_advance;
+    double Tlm_x, Tlm_y;
+    double Tm_x;
     int i;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -2818,38 +2822,110 @@ _cairo_pdf_surface_show_glyphs (void			*
     else
         diagonal = FALSE;
 
+    in_TJ = FALSE;
     for (i = 0; i < num_glyphs; i++) {
+        status = _cairo_scaled_glyph_lookup (scaled_font,
+                                             glyphs[i].index,
+                                             CAIRO_SCALED_GLYPH_INFO_METRICS,
+                                             &scaled_glyph);
+	if (status)
+	    return status;
+        x_advance = scaled_glyph->metrics.x_advance;
+        
 	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
 						       scaled_font, glyphs[i].index,
 						       &font_id, &subset_id, &subset_glyph_index);
-	if (status)
+        if (status)
 	    return status;
 
-	if (subset_id != current_subset_id)
+	if (subset_id != current_subset_id) {
+            if (in_TJ) {
+                _cairo_output_stream_printf (surface->output, "] TJ\r\n");
+                in_TJ = FALSE;
+            }
 	    _cairo_output_stream_printf (surface->output,
 					 "/CairoFont-%d-%d 1 Tf\r\n",
 					 font_id, subset_id);
+        }
 
         if (subset_id != current_subset_id || !diagonal) {
             _cairo_output_stream_printf (surface->output,
-                                         "%f %f %f %f %f %f Tm <%02x> Tj\r\n",
+                                         "%f %f %f %f %f %f Tm\r\n",
                                          scaled_font->scale.xx,
                                          scaled_font->scale.yx,
                                          -scaled_font->scale.xy,
                                          -scaled_font->scale.yy,
                                          glyphs[i].x,
-                                         glyphs[i].y,
-                                         subset_glyph_index);
+                                         glyphs[i].y);
 	    current_subset_id = subset_id;
+            Tlm_x = glyphs[i].x;
+            Tlm_y = glyphs[i].y;
+            Tm_x = Tlm_x;
+        }
+
+        if (diagonal) { 
+            if (i < num_glyphs - 1 &&
+                glyphs[i].y == glyphs[i+1].y &&
+                fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10) {
+                if (!in_TJ) {
+                    if (i != 0) {
+                        _cairo_output_stream_printf (surface->output,
+                                                     "%f %f Td\r\n",
+                                                     (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+                                                     (glyphs[i].y - Tlm_x)/-scaled_font->scale.yy);
+                        Tlm_x = glyphs[i].x;
+                        Tlm_y = glyphs[i].y;
+                        Tm_x = Tlm_x;
+                    }
+                    _cairo_output_stream_printf (surface->output,
+                                                 "[<%02x",
+                                                 subset_glyph_index);
+                    Tm_x += x_advance;
+                    in_TJ = TRUE;
+                } else {
+                    if (glyphs[i].x != Tm_x) {
+                        double delta = (long)(1000.0*(glyphs[i].x - Tm_x));
+                        
+                        _cairo_output_stream_printf (surface->output,
+                                                     "> %f <",
+                                                     -delta/scaled_font->scale.xx);
+                        Tm_x += delta;
+                    }
+                    _cairo_output_stream_printf (surface->output,
+                                                 "%02x",
+                                                 subset_glyph_index);
+                    Tm_x += x_advance;
+                }
+            }
+            else {
+                if (in_TJ) {
+                    _cairo_output_stream_printf (surface->output,
+                                                 "%02x>] TJ\r\n",
+                                                 subset_glyph_index);
+                    Tm_x += x_advance;
+                    in_TJ = FALSE;
+                } else {
+                    if (i != 0) {
+                        _cairo_output_stream_printf (surface->output,
+                                                     "%f %f Td ",
+                                                     (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+                                                     (glyphs[i].y - Tlm_x)/-scaled_font->scale.yy);
+                        Tlm_x = glyphs[i].x;
+                        Tlm_y = glyphs[i].y;
+                        Tm_x = Tlm_x;
+                    }
+                    _cairo_output_stream_printf (surface->output,
+                                                 "<%02x> Tj",
+                                                 subset_glyph_index);
+                    Tm_x += x_advance;
+                }
+            }
         } 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,
+                                         "<%02x> Tj\r\n",
                                          subset_glyph_index);
         }
     }
-
     _cairo_output_stream_printf (surface->output,
 				 "ET\r\n");
 


More information about the cairo mailing list