[cairo-commit] 12 commits - src/cairo-ft-font.c src/cairoint.h src/cairo-pdf-operators.c src/cairo-pdf-operators-private.h src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-scaled-font-subsets-private.h src/cairo-svg-surface.c src/cairo-truetype-subset.c src/cairo-unicode.c src/cairo-win32-font.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Sun Jun 29 04:55:55 PDT 2008


 src/cairo-ft-font.c                     |   34 +--
 src/cairo-pdf-operators-private.h       |   16 +
 src/cairo-pdf-operators.c               |  298 +++++++++++++++++++++++++-------
 src/cairo-pdf-surface-private.h         |    5 
 src/cairo-pdf-surface.c                 |  174 ++++++++++++++----
 src/cairo-ps-surface.c                  |   15 +
 src/cairo-scaled-font-subsets-private.h |   36 +++
 src/cairo-scaled-font-subsets.c         |  148 +++++++++++++--
 src/cairo-svg-surface.c                 |    1 
 src/cairo-truetype-subset.c             |  102 +++++-----
 src/cairo-unicode.c                     |   39 ++++
 src/cairo-win32-font.c                  |   47 ++---
 src/cairoint.h                          |   14 +
 13 files changed, 694 insertions(+), 235 deletions(-)

New commits:
commit 22facbe66e5fd72c6c5ce780d3699fe7a63dc7fb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:55:41 2008 +0930

    Add show_text_glyphs to PDF surface

diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 711afb5..a2962f8 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -90,8 +90,13 @@ typedef struct _cairo_pdf_smask_group
     cairo_stroke_style_t *style;
     cairo_matrix_t	  ctm;
     cairo_matrix_t	  ctm_inverse;
+    char           	 *utf8;
+    int                   utf8_len;
     cairo_glyph_t	 *glyphs;
     int			  num_glyphs;
+    cairo_text_cluster_t *clusters;
+    int                   num_clusters;
+    cairo_bool_t          backward;
     cairo_scaled_font_t	 *scaled_font;
 } cairo_pdf_smask_group_t;
 
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 87edbb1..f2f8453 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -747,8 +747,12 @@ _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
 	cairo_pattern_destroy (group->source);
     if (group->mask)
 	cairo_pattern_destroy (group->mask);
+    if (group->utf8)
+	free (group->utf8);
     if (group->glyphs)
 	free (group->glyphs);
+    if (group->clusters)
+	free (group->clusters);
     if (group->scaled_font)
 	cairo_scaled_font_destroy (group->scaled_font);
     free (group);
@@ -3960,10 +3964,10 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
 	break;
     case PDF_SHOW_GLYPHS:
 	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
-							NULL, 0,
+							group->utf8, group->utf8_len,
 							group->glyphs, group->num_glyphs,
-							NULL, 0,
-							FALSE,
+							group->clusters, group->num_clusters,
+							group->backward,
 							group->scaled_font);
 	break;
     }
@@ -4719,14 +4723,24 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
     return _cairo_output_stream_get_status (surface->output);
 }
 
+static cairo_bool_t
+_cairo_pdf_surface_has_show_text_glyphs	(void			*abstract_surface)
+{
+    return TRUE;
+}
+
 static cairo_int_status_t
-_cairo_pdf_surface_show_glyphs (void			*abstract_surface,
-				cairo_operator_t	 op,
-				cairo_pattern_t		*source,
-				cairo_glyph_t		*glyphs,
-				int			 num_glyphs,
-				cairo_scaled_font_t	*scaled_font,
-				int		        *remaining_glyphs)
+_cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
+				     cairo_operator_t	 	 op,
+				     cairo_pattern_t	       	*source,
+				     const char                 *utf8,
+				     int                         utf8_len,
+				     cairo_glyph_t		*glyphs,
+				     int			 num_glyphs,
+				     const cairo_text_cluster_t *clusters,
+				     int                         num_clusters,
+				     cairo_bool_t                backward,
+				     cairo_scaled_font_t	*scaled_font)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
@@ -4754,13 +4768,37 @@ _cairo_pdf_surface_show_glyphs (void			*abstract_surface,
 	group->operation = PDF_SHOW_GLYPHS;
 	group->source = cairo_pattern_reference (source);
 	group->source_res = pattern_res;
-	group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
-	if (group->glyphs == NULL) {
-	    _cairo_pdf_smask_group_destroy (group);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	if (utf8_len) {
+	    group->utf8 = malloc(utf8_len);
+	    if (group->utf8) {
+		_cairo_pdf_smask_group_destroy (group);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    memcpy (group->utf8, utf8, utf8_len);
+	}
+	group->utf8_len = utf8_len;
+
+	if (num_glyphs) {
+	    group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+	    if (group->glyphs == NULL) {
+		_cairo_pdf_smask_group_destroy (group);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 	}
-	memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
 	group->num_glyphs = num_glyphs;
+
+	if (num_clusters) {
+	    group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
+	    if (group->clusters) {
+		_cairo_pdf_smask_group_destroy (group);
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    }
+	    memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
+	}
+	group->num_clusters = num_clusters;
+
 	group->scaled_font = cairo_scaled_font_reference (scaled_font);
 	status = _cairo_pdf_surface_add_smask_group (surface, group);
 	if (status) {
@@ -4800,10 +4838,10 @@ _cairo_pdf_surface_show_glyphs (void			*abstract_surface,
 	}
 
 	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
-							NULL, 0,
+							utf8, utf8_len,
 							glyphs, num_glyphs,
-							NULL, 0,
-							FALSE,
+							clusters, num_clusters,
+							backward,
 							scaled_font);
 	if (status)
 	    return status;
@@ -4816,6 +4854,26 @@ _cairo_pdf_surface_show_glyphs (void			*abstract_surface,
     return _cairo_output_stream_get_status (surface->output);
 }
 
+static cairo_int_status_t
+_cairo_pdf_surface_show_glyphs (void			*abstract_surface,
+				cairo_operator_t	 op,
+				cairo_pattern_t	       	*source,
+				cairo_glyph_t		*glyphs,
+				int			 num_glyphs,
+				cairo_scaled_font_t	*scaled_font,
+				int		        *remaining_glyphs)
+{
+    return _cairo_pdf_surface_show_text_glyphs (abstract_surface,
+						op,
+						source,
+						NULL, 0,
+						glyphs, num_glyphs,
+						NULL, 0,
+						FALSE,
+						scaled_font);
+}
+
+
 static void
 _cairo_pdf_surface_set_paginated_mode (void			*abstract_surface,
 				       cairo_paginated_mode_t	 paginated_mode)
@@ -4861,6 +4919,9 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
     NULL, /* is_compatible */
     NULL, /* reset */
     _cairo_pdf_surface_fill_stroke,
+    NULL, /* create_solid_pattern_surface */
+    _cairo_pdf_surface_has_show_text_glyphs,
+    _cairo_pdf_surface_show_text_glyphs,
 };
 
 static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
commit 770b7c9a74e3497692020255686c5c5b4e38001e
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:38:13 2008 +0930

    Add show_text_glyphs to PDF operators

diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index e29834b..b482335 100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -71,10 +71,12 @@ typedef struct _cairo_pdf_operators {
     cairo_bool_t in_text_object; /* inside BT/ET pair */
 
     /* PDF text state */
+    cairo_bool_t is_new_text_object; /* text object started but matrix and font not yet selected */
     unsigned int font_id;
     unsigned int subset_id;
     cairo_matrix_t text_matrix; /* PDF text matrix (Tlm in the PDF reference) */
     cairo_matrix_t cairo_to_pdftext; /* translate cairo coords to PDF text space */
+    cairo_matrix_t font_matrix_inverse;
     double cur_x; /* Current position in PDF text space (Tm in the PDF reference) */
     double cur_y;
     int hex_width;
@@ -134,9 +136,15 @@ _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t 	*pdf_operators,
 				  cairo_matrix_t		*ctm_inverse);
 
 cairo_private cairo_int_status_t
-_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
-				  cairo_glyph_t		*glyphs,
-				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font);
+_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t	  *pdf_operators,
+				       const char                 *utf8,
+				       int                         utf8_len,
+				       cairo_glyph_t              *glyphs,
+				       int                         num_glyphs,
+				       const cairo_text_cluster_t *clusters,
+				       int                         num_clusters,
+				       cairo_bool_t                backward,
+				       cairo_scaled_font_t	  *scaled_font);
+
 
 #endif /* CAIRO_PDF_OPERATORS_H */
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index af8eafe..ad62cfa 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -931,7 +931,6 @@ _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
 static cairo_status_t
 _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators,
 				cairo_scaled_font_subsets_glyph_t *glyph,
-				cairo_matrix_t                    *font_matrix_inverse,
 				double 			           x_position)
 {
     double x, y;
@@ -939,7 +938,7 @@ _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators
     x = glyph->x_advance;
     y = glyph->y_advance;
     if (glyph->is_scaled)
-	cairo_matrix_transform_distance (font_matrix_inverse, &x, &y);
+	cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
 
     pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
     pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
@@ -1073,7 +1072,12 @@ _cairo_pdf_operators_begin_text (cairo_pdf_operators_t    *pdf_operators)
 static cairo_status_t
 _cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators)
 {
-    _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    cairo_status_t status;
+
+    status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    if (status)
+	return status;
+
     _cairo_output_stream_printf (pdf_operators->stream, "ET\n");
 
     pdf_operators->in_text_object = FALSE;
@@ -1092,35 +1096,215 @@ _cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
 	    a->yy == b->yy);
 }
 
-cairo_int_status_t
-_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t	*pdf_operators,
-				  cairo_glyph_t		*glyphs,
-				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font)
+static cairo_status_t
+_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
+				       const char 	     *utf8,
+				       int		      utf8_len)
 {
-    cairo_scaled_font_subsets_glyph_t subset_glyph;
+    uint16_t *utf16;
+    int utf16_len;
     cairo_status_t status;
     int i;
-    cairo_matrix_t text_matrix, invert_y_axis, font_matrix_inverse;
+
+    _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
+    if (utf8_len) {
+	status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
+	if (status)
+	    return status;
+
+	for (i = 0; i < utf16_len; i++) {
+	    _cairo_output_stream_printf (pdf_operators->stream,
+					 "%04x", (int) (utf16[i]));
+	}
+	free (utf16);
+    }
+    _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t    *pdf_operators)
+{
+    _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
+
+    return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t             *pdf_operators,
+				 cairo_glyph_t              	   *glyph,
+				 cairo_scaled_font_subsets_glyph_t *subset_glyph)
+{
     double x, y;
-    cairo_bool_t new_text_object = FALSE;
+    cairo_status_t status;
 
-    if (num_glyphs <= 0)
-	return CAIRO_STATUS_SUCCESS;
+    if (pdf_operators->is_new_text_object ||
+	pdf_operators->font_id != subset_glyph->font_id ||
+	pdf_operators->subset_id != subset_glyph->subset_id)
+    {
+	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
+	if (status)
+	    return status;
+
+	pdf_operators->is_new_text_object = FALSE;
+    }
+
+    x = glyph->x;
+    y = glyph->y;
+    cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
+
+    /* The TJ operator for displaying text strings can only set
+     * the horizontal position of the glyphs. If the y position
+     * (in text space) changes, use the Td operator to change the
+     * current position to the next glyph. We also use the Td
+     * operator to move the current position if the horizontal
+     * position changes by more than 10 (in text space
+     * units). This is becauses the horizontal glyph positioning
+     * in the TJ operator is intended for kerning and there may be
+     * PDF consumers that do not handle very large position
+     * adjustments in TJ.
+     */
+    if (fabs(x - pdf_operators->cur_x) > 10 ||
+	fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
+    {
+	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+	if (status)
+	    return status;
+
+	x = glyph->x;
+	y = glyph->y;
+	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
+	status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
+	if (status)
+	    return status;
 
-    font_matrix_inverse = scaled_font->font_matrix;
-    status = cairo_matrix_invert (&font_matrix_inverse);
+	x = 0.0;
+	y = 0.0;
+    }
+
+    status = _cairo_pdf_operators_add_glyph (pdf_operators,
+					     subset_glyph,
+					     x);
+    return status;
+}
+
+/* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
+ * empty string.
+ */
+static cairo_int_status_t
+_cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t      *pdf_operators,
+				   const char                 *utf8,
+				   int                         utf8_len,
+				   cairo_glyph_t              *glyphs,
+				   int                         num_glyphs,
+				   cairo_bool_t                backward,
+				   cairo_scaled_font_t	      *scaled_font)
+{
+    cairo_scaled_font_subsets_glyph_t subset_glyph;
+    cairo_glyph_t *cur_glyph;
+    cairo_status_t status;
+    int i;
+
+    /* If the cluster maps 1 glyph to 1 or more unicode characters, we
+     * first try _map_glyph() with the unicode string to see if it can
+     * use toUnicode to map our glyph to the unicode. This will fail
+     * if the glyph is already mapped to a different unicode string.
+     *
+     * We also go through this path if no unicode mapping was
+     * supplied (utf8_len < 0).
+     *
+     * Mapping a glyph to a zero length unicode string requires the
+     * use of ActualText.
+     */
+    if (num_glyphs == 1 && utf8_len != 0) {
+	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+						       scaled_font,
+						       glyphs->index,
+						       utf8,
+						       utf8_len < 0 ? 0 : utf8_len,
+						       &subset_glyph);
+	if (status)
+	    return status;
+
+	if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
+	    status = _cairo_pdf_operators_emit_glyph (pdf_operators,
+						      glyphs,
+						      &subset_glyph);
+	    return 0;
+	}
+    }
+
+    /* Fallback to using ActualText to map zero or more glyphs to a
+     * unicode string. */
+    _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
+    cur_glyph = glyphs;
+    for (i = 0; i < num_glyphs; i++) {
+	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+						       scaled_font,
+						       cur_glyph->index,
+						       NULL, 0,
+						       &subset_glyph);
+	if (status)
+	    return status;
+
+	status = _cairo_pdf_operators_emit_glyph (pdf_operators,
+						  cur_glyph,
+						  &subset_glyph);
+	if (status)
+	    return status;
+
+	if (backward)
+	    cur_glyph--;
+	else
+	    cur_glyph++;
+    }
+    status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+    if (status)
+	return status;
+
+    status = _cairo_pdf_operators_end_actualtext (pdf_operators);
+
+    return status;
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t	  *pdf_operators,
+				       const char                 *utf8,
+				       int                         utf8_len,
+				       cairo_glyph_t              *glyphs,
+				       int                         num_glyphs,
+				       const cairo_text_cluster_t *clusters,
+				       int                         num_clusters,
+				       cairo_bool_t                backward,
+				       cairo_scaled_font_t	  *scaled_font)
+{
+    cairo_status_t status;
+    int i;
+    cairo_matrix_t text_matrix, invert_y_axis;
+    double x, y;
+    const char *cur_text;
+    cairo_glyph_t *cur_glyph;
+
+    pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
+    status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
     if (status == CAIRO_STATUS_INVALID_MATRIX)
 	return CAIRO_STATUS_SUCCESS;
     if (status)
 	return status;
 
+    pdf_operators->is_new_text_object = FALSE;
     if (pdf_operators->in_text_object == FALSE) {
 	_cairo_pdf_operators_begin_text (pdf_operators);
 
 	/* Force Tm and Tf to be emitted when starting a new text
 	 * object.*/
-	new_text_object = TRUE;
+	pdf_operators->is_new_text_object = TRUE;
     }
 
     cairo_matrix_init_scale (&invert_y_axis, 1, -1);
@@ -1132,7 +1316,7 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t	*pdf_operators,
     /* Invert y axis in device space  */
     cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
 
-    if (new_text_object ||
+    if (pdf_operators->is_new_text_object ||
 	! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
     {
 	_cairo_pdf_operators_flush_glyphs (pdf_operators);
@@ -1148,55 +1332,36 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t	*pdf_operators,
 	    return status;
     }
 
-    for (i = 0; i < num_glyphs; i++) {
-        status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
-                                                       scaled_font, glyphs[i].index,
-						       NULL, 0,
-                                                       &subset_glyph);
-	if (status)
-            return status;
-
-	if (new_text_object ||
-	    pdf_operators->font_id != subset_glyph.font_id ||
-	    pdf_operators->subset_id != subset_glyph.subset_id)
-	{
-	    _cairo_pdf_operators_flush_glyphs (pdf_operators);
-	    _cairo_pdf_operators_set_font_subset (pdf_operators, &subset_glyph);
-	    new_text_object = FALSE;
+    if (num_clusters > 0) {
+	cur_text = utf8;
+	if (backward)
+	    cur_glyph = glyphs + num_glyphs - 1;
+	else
+	    cur_glyph = glyphs;
+	for (i = 0; i < num_clusters; i++) {
+	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
+							cur_text,
+							clusters[i].num_bytes,
+							cur_glyph,
+							clusters[i].num_glyphs,
+							backward,
+							scaled_font);
+	    cur_text += clusters[i].num_bytes;
+	    if (backward)
+		cur_glyph -= clusters[i].num_glyphs;
+	    else
+		cur_glyph += clusters[i].num_glyphs;
 	}
-
-	x = glyphs[i].x;
-	y = glyphs[i].y;
-	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
-
-	/* The TJ operator for displaying text strings can only set
-	 * the horizontal position of the glyphs. If the y position
-	 * (in text space) changes, use the Td operator to change the
-	 * current position to the next glyph. We also use the Td
-	 * operator to move the current position if the horizontal
-	 * position changes by more than 10 (in text space
-	 * units). This is becauses the horizontal glyph positioning
-	 * in the TJ operator is intended for kerning and there may be
-	 * PDF consumers that do not handle very large position
-	 * adjustments in TJ.
-	 */
-	if (fabs(x - pdf_operators->cur_x) > 10 ||
-	    fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
-	{
-	    _cairo_pdf_operators_flush_glyphs (pdf_operators);
-
-	    x = glyphs[i].x;
-	    y = glyphs[i].y;
-	    cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
-	    _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
-	    x = 0.0;
-	    y = 0.0;
+    } else {
+	for (i = 0; i < num_glyphs; i++) {
+	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
+							NULL,
+							-1, /* no unicode string available */
+							&glyphs[i],
+							1,
+							FALSE,
+							scaled_font);
 	}
-
-	_cairo_pdf_operators_add_glyph (pdf_operators,
-					&subset_glyph,
-					&font_matrix_inverse,
-					x);
     }
 
     return _cairo_output_stream_get_status (pdf_operators->stream);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index faef964..87edbb1 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3959,10 +3959,12 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t     *surface,
 					      &group->ctm_inverse);
 	break;
     case PDF_SHOW_GLYPHS:
-	status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
-						   group->glyphs,
-						   group->num_glyphs,
-						   group->scaled_font);
+	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+							NULL, 0,
+							group->glyphs, group->num_glyphs,
+							NULL, 0,
+							FALSE,
+							group->scaled_font);
 	break;
     }
     if (status)
@@ -4797,10 +4799,12 @@ _cairo_pdf_surface_show_glyphs (void			*abstract_surface,
 		return status;
 	}
 
-	status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
-						   glyphs,
-						   num_glyphs,
-						   scaled_font);
+	status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+							NULL, 0,
+							glyphs, num_glyphs,
+							NULL, 0,
+							FALSE,
+							scaled_font);
 	if (status)
 	    return status;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a4266d2..3261247 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -175,6 +175,11 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 				 "/W* { eoclip } bind def\n"
 				 "/BT { } bind def\n"
 				 "/ET { } bind def\n"
+				 "/pdfmark where { pop globaldict /?pdfmark /exec load put }\n"
+				 "    { globaldict begin /?pdfmark /pop load def /pdfmark\n"
+				 "    /cleartomark load def end } ifelse\n"
+				 "/BDC { mark 3 1 roll /BDC pdfmark } bind def\n"
+				 "/EMC { mark /EMC pdfmark } bind def\n"
 				 "/Tj { show } bind def\n"
 				 "/TJ {\n"
 				 "  {\n"
@@ -3091,10 +3096,12 @@ _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
     if (status)
 	return status;
 
-    return _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
-					     glyphs,
-					     num_glyphs,
-					     scaled_font);
+    return _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+						  NULL, 0,
+						  glyphs, num_glyphs,
+						  NULL, 0,
+						  FALSE,
+						  scaled_font);
 }
 
 static void
commit 55dda8c64fc38cda75878f1a34eb1f86b1a445cb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:36:29 2008 +0930

    Remove unused map_glyphs_to_unicode functions

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 9c18949..4620653 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2176,40 +2176,6 @@ _cairo_ft_load_truetype_table (void	       *abstract_font,
 }
 
 static cairo_int_status_t
-_cairo_ft_map_glyphs_to_unicode (void	                    *abstract_font,
-                                 cairo_scaled_font_subset_t *font_subset)
-{
-    cairo_ft_scaled_font_t *scaled_font = abstract_font;
-    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
-    FT_Face face;
-    FT_UInt glyph;
-    unsigned long charcode;
-    unsigned int i;
-    int count;
-
-    face = _cairo_ft_unscaled_font_lock_face (unscaled);
-    if (!face)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    count = font_subset->num_glyphs;
-    charcode = FT_Get_First_Char( face, &glyph);
-    while (glyph != 0 && count > 0)
-    {
-        for (i = 0; i < font_subset->num_glyphs; i++) {
-            if (font_subset->glyphs[i] == glyph) {
-                font_subset->to_unicode[i] = charcode;
-                count--;
-                break;
-            }
-        }
-        charcode = FT_Get_Next_Char (face, charcode, &glyph);
-    }
-    _cairo_ft_unscaled_font_unlock_face (unscaled);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
 _cairo_ft_index_to_ucs4(void	        *abstract_font,
 			unsigned long    index,
 			uint32_t	*ucs4)
@@ -2248,7 +2214,6 @@ const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     _cairo_ft_ucs4_to_index,
     NULL, 			/* show_glyphs */
     _cairo_ft_load_truetype_table,
-    _cairo_ft_map_glyphs_to_unicode,
     _cairo_ft_index_to_ucs4
 };
 
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 7b84334..5c68f07 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1457,101 +1457,6 @@ _cairo_win32_scaled_font_load_truetype_table (void	       *abstract_font,
     return status;
 }
 
-static cairo_int_status_t
-_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font,
-						cairo_scaled_font_subset_t *font_subset)
-{
-    cairo_win32_scaled_font_t *scaled_font = abstract_font;
-    GLYPHSET *glyph_set;
-    uint16_t *utf16 = NULL;
-    WORD *glyph_indices = NULL;
-    HDC hdc = NULL;
-    int res;
-    unsigned int i, j, k, count, num_glyphs;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
-    hdc = _get_global_font_dc ();
-    if (!hdc)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
-    if (status)
-	return status;
-
-    res = GetFontUnicodeRanges(hdc, NULL);
-    if (res == 0) {
-	status = _cairo_win32_print_gdi_error (
-	    "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
-	goto fail1;
-    }
-
-    glyph_set = malloc (res);
-    if (glyph_set == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail1;
-    }
-
-    res = GetFontUnicodeRanges(hdc, glyph_set);
-    if (res == 0) {
-	status = _cairo_win32_print_gdi_error (
-	    "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
-	goto fail2;
-    }
-
-    count = font_subset->num_glyphs;
-    for (i = 0; i < glyph_set->cRanges && count > 0; i++) {
-	num_glyphs = glyph_set->ranges[i].cGlyphs;
-
-	utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
-	if (utf16 == NULL) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto fail2;
-	}
-
-	glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
-	if (glyph_indices == NULL) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto fail2;
-	}
-
-	for (j = 0; j < num_glyphs; j++)
-	    utf16[j] = glyph_set->ranges[i].wcLow + j;
-	utf16[j] = 0;
-
-	if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
-	    status = _cairo_win32_print_gdi_error (
-		"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetGlyphIndicesW");
-	    goto fail2;
-	}
-
-	for (j = 0; j < num_glyphs; j++) {
-	    for (k = 0; k < font_subset->num_glyphs; k++) {
-		if (font_subset->glyphs[k] == glyph_indices[j]) {
-		    font_subset->to_unicode[k] = utf16[j];
-		    count--;
-		    break;
-		}
-	    }
-	}
-
-	free (glyph_indices);
-	glyph_indices = NULL;
-	free (utf16);
-	utf16= NULL;
-    }
-
-fail2:
-    if (glyph_indices)
-	free (glyph_indices);
-    if (utf16)
-	free (utf16);
-    free (glyph_set);
-fail1:
-    cairo_win32_scaled_font_done_font (&scaled_font->base);
-
-    return status;
-}
-
 static cairo_status_t
 _cairo_win32_scaled_font_index_to_ucs4 (void 		*abstract_font,
 					unsigned long    index,
@@ -1879,7 +1784,6 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
     NULL,			/* ucs4_to_index */
     _cairo_win32_scaled_font_show_glyphs,
     _cairo_win32_scaled_font_load_truetype_table,
-    _cairo_win32_scaled_font_map_glyphs_to_unicode,
     _cairo_win32_scaled_font_index_to_ucs4,
 };
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 12ccd7f..bd33c44 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -440,10 +440,6 @@ struct _cairo_scaled_font_backend {
                            unsigned char        *buffer,
                            unsigned long        *length);
 
-    cairo_warn cairo_int_status_t
-    (*map_glyphs_to_unicode)(void                       *scaled_font,
-                             cairo_scaled_font_subset_t *font_subset);
-
     /* returns -1 if the unicode character could not be found for the glyph */
     cairo_warn cairo_int_status_t
     (*index_to_ucs4)(void                       *scaled_font,
commit 2012d4f7364f9efa0789996e7906f269d5d59d41
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:36:10 2008 +0930

    Removed unused cairo_truetype_create_glyph_to_unicode_map()

diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 5e4210e..53d7232 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1173,153 +1173,6 @@ _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
 }
 
 static cairo_int_status_t
-_cairo_truetype_map_glyphs_to_unicode (cairo_scaled_font_subset_t *font_subset,
-                                       unsigned long               table_offset)
-{
-    cairo_status_t status;
-    const cairo_scaled_font_backend_t *backend;
-    tt_segment_map_t *map;
-    char buf[4];
-    unsigned int num_segments, i, j;
-    unsigned long size;
-    uint16_t *start_code;
-    uint16_t *end_code;
-    uint16_t *delta;
-    uint16_t *range_offset;
-    uint16_t *glyph_array;
-    uint16_t  g_id, c;
-
-    backend = font_subset->scaled_font->backend;
-    size = 4;
-    status = backend->load_truetype_table (font_subset->scaled_font,
-                                           TT_TAG_cmap, table_offset,
-					   (unsigned char *) &buf,
-					   &size);
-    if (status)
-	return status;
-
-    /* All table formats have the same first two words */
-    map = (tt_segment_map_t *) buf;
-    if (be16_to_cpu (map->format) != 4)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    size = be16_to_cpu (map->length);
-    map = malloc (size);
-    if (map == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = backend->load_truetype_table (font_subset->scaled_font,
-                                           TT_TAG_cmap, table_offset,
-                                           (unsigned char *) map,
-                                           &size);
-    if (status)
-	goto fail;
-
-    num_segments = be16_to_cpu (map->segCountX2)/2;
-    end_code = map->endCount;
-    start_code = &(end_code[num_segments + 1]);
-    delta = &(start_code[num_segments]);
-    range_offset = &(delta[num_segments]);
-    glyph_array = &(range_offset[num_segments]);
-
-    i = 0;
-    while (i < font_subset->num_glyphs) {
-        g_id = (uint16_t) font_subset->glyphs[i];
-
-        /* search for glyph in segments
-         * with rangeOffset=0 */
-        for (j = 0; j < num_segments; j++) {
-            c = g_id - be16_to_cpu (delta[j]);
-            if (range_offset[j] == 0 &&
-                c >= be16_to_cpu (start_code[j]) &&
-                c <= be16_to_cpu (end_code[j]))
-            {
-                font_subset->to_unicode[i] = c;
-                goto next_glyph;
-            }
-        }
-
-        /* search for glyph in segments with rangeOffset=1 */
-        for (j = 0; j < num_segments; j++) {
-            if (range_offset[j] != 0) {
-                uint16_t *glyph_ids = &range_offset[j] + be16_to_cpu (range_offset[j])/2;
-                int range_size = be16_to_cpu (end_code[j]) - be16_to_cpu (start_code[j]) + 1;
-                uint16_t g_id_be = cpu_to_be16 (g_id);
-                int k;
-
-                for (k = 0; k < range_size; k++) {
-                    if (glyph_ids[k] == g_id_be) {
-                        font_subset->to_unicode[i] = be16_to_cpu (start_code[j]) + k;
-                        goto next_glyph;
-                    }
-                }
-            }
-        }
-
-    next_glyph:
-        i++;
-    }
-    status = CAIRO_STATUS_SUCCESS;
-fail:
-    free (map);
-
-    return status;
-}
-
-cairo_int_status_t
-_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t	*font_subset)
-{
-    cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-    const cairo_scaled_font_backend_t *backend;
-    tt_cmap_t *cmap;
-    char buf[4];
-    int num_tables, i;
-    unsigned long size;
-
-    backend = font_subset->scaled_font->backend;
-    if (!backend->load_truetype_table)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    size = 4;
-    status = backend->load_truetype_table (font_subset->scaled_font,
-                                           TT_TAG_cmap, 0,
-					   (unsigned char *) &buf,
-					   &size);
-    if (status)
-	return status;
-
-    cmap = (tt_cmap_t *) buf;
-    num_tables = be16_to_cpu (cmap->num_tables);
-    size = 4 + num_tables*sizeof(tt_cmap_index_t);
-    cmap = malloc (size);
-    if (cmap == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    status = backend->load_truetype_table (font_subset->scaled_font,
-	                                   TT_TAG_cmap, 0,
-					   (unsigned char *) cmap,
-					   &size);
-    if (status)
-        goto cleanup;
-
-    /* Find a table with Unicode mapping */
-    for (i = 0; i < num_tables; i++) {
-        if (be16_to_cpu (cmap->index[i].platform) == 3 &&
-            be16_to_cpu (cmap->index[i].encoding) == 1) {
-            status = _cairo_truetype_map_glyphs_to_unicode (font_subset,
-                                                            be32_to_cpu (cmap->index[i].offset));
-            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-                goto cleanup;
-        }
-    }
-
-cleanup:
-    free (cmap);
-
-    return status;
-}
-
-static cairo_int_status_t
 _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
 			      unsigned long        table_offset,
 			      unsigned long        index,
commit 154324f121e7aad8af474ac26e0e320cddd37579
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:35:43 2008 +0930

    Use subset utf8 mapping to create the glyph names for PS fonts

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index e04e944..7be7181 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -893,29 +893,14 @@ create_string_entry (char *s, cairo_string_entry_t **entry)
 cairo_int_status_t
 _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset)
 {
-    const cairo_scaled_font_backend_t *backend;
     unsigned int i;
     cairo_status_t status;
     cairo_hash_table_t *names;
     cairo_string_entry_t key, *entry;
     char buf[30];
-
-    if (subset->to_unicode == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _cairo_truetype_create_glyph_to_unicode_map (subset);
-    if (status) {
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
-
-        backend = subset->scaled_font->backend;
-        if (backend->map_glyphs_to_unicode == NULL)
-            return CAIRO_INT_STATUS_UNSUPPORTED;
-
-        status = backend->map_glyphs_to_unicode (subset->scaled_font, subset);
-	if (status)
-	    return status;
-    }
+    char *utf8;
+    uint16_t *utf16;
+    int utf16_len;
 
     names = _cairo_hash_table_create (_cairo_string_equal);
     if (names == NULL)
@@ -944,8 +929,17 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
     }
 
     for (i = 1; i < subset->num_glyphs; i++) {
-	if (subset->to_unicode[i] <= 0xffff) {
-	    snprintf (buf, sizeof(buf), "uni%04X", (unsigned int)(subset->to_unicode[i]));
+	utf8 = subset->utf8[i];
+	utf16 = NULL;
+	utf16_len = 0;
+	if (utf8 && *utf8) {
+	    status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
+	    if (status && status != CAIRO_STATUS_INVALID_STRING)
+		return status; // FIXME
+	}
+
+	if (utf16_len == 1) {
+	    snprintf (buf, sizeof(buf), "uni%04X", (int)(utf16[0]));
 	    _cairo_string_init_key (&key, buf);
 	    if (_cairo_hash_table_lookup (names, &key.base,
 					  (cairo_hash_entry_t **) &entry)) {
@@ -954,6 +948,8 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
 	} else {
 	    snprintf (buf, sizeof(buf), "g%d", i);
 	}
+	if (utf16)
+	    free (utf16);
 
 	subset->glyph_names[i] = strdup (buf);
 	if (subset->glyph_names[i] == NULL) {
commit 2a21fafa078a2519dea7881b4553d74667c928f2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:35:12 2008 +0930

    Use subset utf8 mapping in PDF ToUnicode stream

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 1c74376..faef964 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2839,34 +2839,54 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
 				 "endobj\n");
 }
 
+static cairo_status_t
+_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t	*surface,
+					   const char 		*utf8)
+{
+    uint16_t *utf16 = NULL;
+    int utf16_len = 0;
+    cairo_status_t status;
+    int i;
+
+    if (utf8 && *utf8) {
+	status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
+	if (status && status != CAIRO_STATUS_INVALID_STRING)
+	    return status;
+    }
+
+    _cairo_output_stream_printf (surface->output, "<");
+    if (utf16 == NULL || utf16_len == 0) {
+	/* According to the "ToUnicode Mapping File Tutorial"
+	 * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
+	 *
+	 * Glyphs that do not map to a Unicode code point must be
+	 * mapped to 0xfffd "REPLACEMENT CHARACTER".
+	 */
+	_cairo_output_stream_printf (surface->output,
+				     "fffd");
+    } else {
+	for (i = 0; i < utf16_len; i++)
+	    _cairo_output_stream_printf (surface->output,
+					 "%04x", (int) (utf16[i]));
+    }
+    _cairo_output_stream_printf (surface->output, ">");
+
+    if (utf16)
+	free (utf16);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_int_status_t
 _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset,
                                            cairo_bool_t                  is_composite,
 					   cairo_pdf_resource_t         *stream)
 {
-    const cairo_scaled_font_backend_t *backend;
     unsigned int i, num_bfchar;
     cairo_int_status_t status;
 
     stream->id = 0;
-    if (font_subset->to_unicode == NULL)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _cairo_truetype_create_glyph_to_unicode_map (font_subset);
-    if (status) {
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    return status;
-
-        backend = font_subset->scaled_font->backend;
-        if (backend->map_glyphs_to_unicode == NULL)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-        status = backend->map_glyphs_to_unicode (font_subset->scaled_font,
-		                                 font_subset);
-	if (status)
-	    return status;
-    }
 
     status = _cairo_pdf_surface_open_stream (surface,
 					      NULL,
@@ -2900,10 +2920,12 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
                                   "endcodespacerange\n");
 
     num_bfchar = font_subset->num_glyphs - 1;
+
     /* The CMap specification has a limit of 100 characters per beginbfchar operator */
     _cairo_output_stream_printf (surface->output,
                                  "%d beginbfchar\n",
                                  num_bfchar > 100 ? 100 : num_bfchar);
+
     for (i = 0; i < num_bfchar; i++) {
         if (i != 0 && i % 100 == 0) {
             _cairo_output_stream_printf (surface->output,
@@ -2913,13 +2935,16 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t		*surface,
         }
         if (is_composite) {
             _cairo_output_stream_printf (surface->output,
-                                         "<%04x> <%04lx>\n",
-                                         i + 1, font_subset->to_unicode[i + 1]);
+                                         "<%04x> ",
+                                         i + 1);
         } else {
             _cairo_output_stream_printf (surface->output,
-                                         "<%02x> <%04lx>\n",
-                                         i + 1, font_subset->to_unicode[i + 1]);
+                                         "<%02x> ",
+                                         i + 1);
         }
+	_cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
+	_cairo_output_stream_printf (surface->output,
+				     "\n");
     }
     _cairo_output_stream_printf (surface->output,
                                  "endbfchar\n");
diff --git a/src/cairoint.h b/src/cairoint.h
index 1aa943e..12ccd7f 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2343,7 +2343,7 @@ cairo_private int
 _cairo_ucs4_to_utf8 (uint32_t    unicode,
 		     char       *utf8);
 
-#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0
+#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0 || CAIRO_HAS_PDF_SURFACE+0
 # define CAIRO_HAS_UTF8_TO_UTF16 1
 #endif
 #if CAIRO_HAS_UTF8_TO_UTF16
commit d77b04fd0635c1648bb024b5308b715c220e1e74
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:33:58 2008 +0930

    Allow _cairo_scaled_font_subsets_map_glyph() to specify utf8 mapping

diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 81c99e9..af8eafe 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -1151,6 +1151,7 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t	*pdf_operators,
     for (i = 0; i < num_glyphs; i++) {
         status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
                                                        scaled_font, glyphs[i].index,
+						       NULL, 0,
                                                        &subset_glyph);
 	if (status)
             return status;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index c621235..1de3f86 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -47,6 +47,8 @@ typedef struct _cairo_scaled_font_subsets_glyph {
     cairo_bool_t is_composite;
     double       x_advance;
     double       y_advance;
+    cairo_bool_t utf8_is_mapped;
+    uint32_t 	 unicode;
 } cairo_scaled_font_subsets_glyph_t;
 
 /**
@@ -176,8 +178,14 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
  * @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font
  * subset is created for each font scale used. If false, the outline of the mapped glyph
  * is available. One font subset for each font face is created.
- * @x_advance: When @is_scaled is true, @x_advance contains the x_advance for the mapped glyph in device space.
- * When @is_scaled is false, @x_advance contains the x_advance for the the mapped glyph from an unhinted 1 point font.
+ * @x_advance, @y_advance: When @is_scaled is true, @x_advance and @y_advance contain
+ * the x and y advance for the mapped glyph in device space.
+ * When @is_scaled is false, @x_advance and @y_advance contain the x and y advance for
+ * the the mapped glyph from an unhinted 1 point font.
+ * @utf8_is_mapped: If true the utf8 string provided to _cairo_scaled_font_subsets_map_glyph()
+ * is (or already was) the utf8 string mapped to this glyph. If false the glyph is already
+ * mapped to a different utf8 string.
+ * @unicode: the unicode character mapped to this glyph by the font backend.
  *
  * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
  * value indicating an error. Possible errors include
@@ -187,6 +195,8 @@ cairo_private cairo_status_t
 _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*font_subsets,
 				      cairo_scaled_font_t		*scaled_font,
 				      unsigned long			 scaled_font_glyph_index,
+				      const char * 			 utf8,
+				      int				 utf8_len,
                                       cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
 
 typedef cairo_status_t
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index f70d978..e04e944 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -94,10 +94,16 @@ typedef struct _cairo_sub_font_glyph {
     unsigned int subset_glyph_index;
     double       x_advance;
     double       y_advance;
+
+    cairo_bool_t is_mapped;
+    uint32_t     unicode;
+    char  	*utf8;
+    int          utf8_len;
 } cairo_sub_font_glyph_t;
 
 typedef struct _cairo_sub_font_collection {
     unsigned long *glyphs; /* scaled_font_glyph_index */
+    char       **utf8;
     unsigned int glyphs_size;
     unsigned int max_glyph;
     unsigned int num_glyphs;
@@ -117,6 +123,8 @@ typedef struct _cairo_string_entry {
 static cairo_status_t
 _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 			   unsigned long	 scaled_font_glyph_index,
+			   const char * 	 utf8,
+			   int			 utf8_len,
                            cairo_scaled_font_subsets_glyph_t *subset_glyph);
 
 static void
@@ -155,6 +163,10 @@ _cairo_sub_font_glyph_create (unsigned long	scaled_font_glyph_index,
     sub_font_glyph->subset_glyph_index = subset_glyph_index;
     sub_font_glyph->x_advance = x_advance;
     sub_font_glyph->y_advance = y_advance;
+    sub_font_glyph->is_mapped = FALSE;
+    sub_font_glyph->unicode = -1;
+    sub_font_glyph->utf8 = NULL;
+    sub_font_glyph->utf8_len = 0;
 
     return sub_font_glyph;
 }
@@ -193,6 +205,7 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure)
     assert (subset_glyph_index < collection->glyphs_size);
 
     collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
+    collection->utf8[subset_glyph_index] = sub_font_glyph->utf8;
     if (subset_glyph_index > collection->max_glyph)
 	collection->max_glyph = subset_glyph_index;
 
@@ -264,7 +277,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
     sub_font->next = NULL;
 
     /* Reserve first glyph in subset for the .notdef glyph */
-    status = _cairo_sub_font_map_glyph (sub_font, 0, &subset_glyph);
+    status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &subset_glyph);
     if (status) {
 	_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
 	free (sub_font);
@@ -296,9 +309,86 @@ _cairo_sub_font_pluck (void *entry, void *closure)
     _cairo_sub_font_destroy (sub_font);
 }
 
+static cairo_status_t
+_cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
+				      cairo_scaled_font_t    *scaled_font,
+				      unsigned long	      scaled_font_glyph_index)
+{
+    uint32_t unicode;
+    char buf[8];
+    int len;
+    cairo_status_t status;
+
+    /* Do a reverse lookup on the glyph index. unicode is -1 if the
+     * index could not be mapped to a unicode character. */
+    status = _cairo_truetype_index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	unicode = -1;
+
+    if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4)
+	status = scaled_font->backend->index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
+
+    sub_font_glyph->unicode = unicode;
+    sub_font_glyph->utf8 = NULL;
+    sub_font_glyph->utf8_len = 0;
+    if (unicode != (uint32_t)-1) {
+	len = _cairo_ucs4_to_utf8 (unicode, buf);
+	if (len > 0) {
+	    sub_font_glyph->utf8 = malloc(len + 1);
+	    memcpy (sub_font_glyph->utf8, buf, len);
+	    sub_font_glyph->utf8[len] = 0;
+	    sub_font_glyph->utf8_len = len;
+	}
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_bool_t
+_cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
+				      const char 	     *utf8,
+				      int 		      utf8_len)
+{
+    int add_zero_byte = 0;
+
+    if (utf8 != NULL && utf8_len != 0) {
+	if (sub_font_glyph->utf8 != NULL) {
+	    if (utf8_len == sub_font_glyph->utf8_len &&
+		memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
+	    {
+		/* Requested utf8 mapping matches the existing mapping */
+		return TRUE;
+	    }
+	    else
+	    {
+		/* Requested utf8 mapping does not match the existing mapping */
+		return FALSE;
+	    }
+	} else {
+	    /* No existing mapping. Use the requested mapping */
+	    if (sub_font_glyph->utf8[utf8_len - 1] != 0)
+		add_zero_byte = 1;
+	    sub_font_glyph->utf8 = malloc (utf8_len + add_zero_byte);
+	    memcpy (sub_font_glyph->utf8, utf8, utf8_len);
+	    if (add_zero_byte)
+		sub_font_glyph->utf8[utf8_len] = 0;
+	    sub_font_glyph->utf8_len = utf8_len;
+	    return TRUE;
+	}
+    }
+
+    /* No mapping was requested. */
+    return FALSE;
+}
+
 static cairo_bool_t
 _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
                               unsigned long	                 scaled_font_glyph_index,
+			      const char * 			 utf8,
+			      int				 utf8_len,
                               cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_glyph_t key, *sub_font_glyph;
@@ -314,8 +404,10 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
         subset_glyph->is_composite = sub_font->is_composite;
         subset_glyph->x_advance = sub_font_glyph->x_advance;
         subset_glyph->y_advance = sub_font_glyph->y_advance;
+	subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+	subset_glyph->unicode = sub_font_glyph->unicode;
 
-        return TRUE;
+	return TRUE;
     }
 
     return FALSE;
@@ -324,6 +416,8 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
 static cairo_status_t
 _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 			   unsigned long	 scaled_font_glyph_index,
+			   const char * 	 utf8,
+			   int			 utf8_len,
                            cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_glyph_t key, *sub_font_glyph;
@@ -341,7 +435,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 	    sub_font->num_glyphs_in_current_subset = 0;
 
 	    /* Reserve first glyph in subset for the .notdef glyph */
-	    status = _cairo_sub_font_map_glyph (sub_font, 0, &tmp_subset_glyph);
+	    status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &tmp_subset_glyph);
 	    if (status)
 		return status;
 	}
@@ -362,6 +456,10 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 	if (sub_font_glyph == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
+	_cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
+					      sub_font->scaled_font,
+					      scaled_font_glyph_index);
+
 	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
 	if (status) {
 	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
@@ -425,6 +523,7 @@ _cairo_sub_font_collect (void *entry, void *closure)
 	subset.font_id = sub_font->font_id;
 	subset.subset_id = i;
 	subset.glyphs = collection->glyphs;
+	subset.utf8 = collection->utf8;
 	subset.num_glyphs = collection->num_glyphs;
         subset.glyph_names = NULL;
         /* No need to check for out of memory here. If to_unicode is NULL, the PDF
@@ -523,6 +622,8 @@ cairo_status_t
 _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
 				      cairo_scaled_font_t		*scaled_font,
 				      unsigned long			 scaled_font_glyph_index,
+				      const char * 			 utf8,
+				      int				 utf8_len,
                                       cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_t key, *sub_font;
@@ -544,6 +645,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
         {
             if (_cairo_sub_font_lookup_glyph (sub_font,
                                               scaled_font_glyph_index,
+					      utf8, utf8_len,
                                               subset_glyph))
                 return CAIRO_STATUS_SUCCESS;
         }
@@ -557,6 +659,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
     {
         if (_cairo_sub_font_lookup_glyph (sub_font,
                                           scaled_font_glyph_index,
+					  utf8, utf8_len,
                                           subset_glyph))
             return CAIRO_STATUS_SUCCESS;
     }
@@ -684,6 +787,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
 
     return _cairo_sub_font_map_glyph (sub_font,
                                       scaled_font_glyph_index,
+				      utf8, utf8_len,
                                       subset_glyph);
 }
 
@@ -705,6 +809,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
 	return CAIRO_STATUS_SUCCESS;
 
     collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
+    collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *));
     if (collection.glyphs == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
@@ -721,6 +826,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
 	_cairo_sub_font_collect (sub_font, &collection);
 	sub_font = sub_font->next;
     }
+    free (collection.utf8);
     free (collection.glyphs);
 
     return collection.status;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 93e82bc..0b0165e 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2177,6 +2177,7 @@ _cairo_svg_surface_show_glyphs (void			*abstract_surface,
     for (i = 0; i < num_glyphs; i++) {
 	status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
 						       scaled_font, glyphs[i].index,
+						       NULL, 0,
                                                        &subset_glyph);
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 	    _cairo_output_stream_printf (surface->xml_node, "</g>\n");
diff --git a/src/cairoint.h b/src/cairoint.h
index a99c26c..1aa943e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -379,6 +379,7 @@ typedef struct _cairo_scaled_font_subset {
      */
     unsigned long *glyphs;
     unsigned long *to_unicode;
+    char          **utf8;
     char          **glyph_names;
     unsigned int num_glyphs;
     cairo_bool_t is_composite;
commit f4d6e714a63ab44e388a06fba8d849f2ad7f0000
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:32:19 2008 +0930

    Add _cairo_ucs4_to_utf8

diff --git a/src/cairo-unicode.c b/src/cairo-unicode.c
index c4873d5..973ef57 100644
--- a/src/cairo-unicode.c
+++ b/src/cairo-unicode.c
@@ -262,6 +262,45 @@ _cairo_utf8_to_ucs4 (const char *str,
     return CAIRO_STATUS_SUCCESS;
 }
 
+/**
+ * _cairo_ucs4_to_utf8:
+ * @unicode: a UCS-4 character
+ * @utf8: buffer to write utf8 string into. Must have at least 4 bytes
+ * space available.
+ *
+ * Return value: Number of bytes in the utf8 string or 0 if an invalid
+ * unicode character
+ **/
+int
+_cairo_ucs4_to_utf8 (uint32_t  unicode,
+		     char     *utf8)
+{
+    int bytes;
+    char *p;
+
+    if (unicode < 0x80) {
+	*utf8 = unicode;
+	return 1;
+    } else if (unicode < 0x800) {
+	bytes = 2;
+    } else if (unicode < 0x10000) {
+	bytes = 3;
+    } else if (unicode < 0x200000) {
+	bytes = 4;
+    } else {
+	return 0;
+    }
+
+    p = utf8 + bytes;
+    while (p > utf8) {
+	*--p = 0x80 | (unicode & 0x3f);
+	unicode >>= 6;
+    }
+    *p |= 0xf0 << (4 - bytes);
+
+    return bytes;
+}
+
 #if CAIRO_HAS_UTF8_TO_UTF16
 /**
  * _cairo_utf8_to_utf16:
diff --git a/src/cairoint.h b/src/cairoint.h
index d5404f9..a99c26c 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2338,6 +2338,10 @@ _cairo_utf8_to_ucs4 (const char *str,
 		     uint32_t  **result,
 		     int	*items_written);
 
+cairo_private int
+_cairo_ucs4_to_utf8 (uint32_t    unicode,
+		     char       *utf8);
+
 #if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0
 # define CAIRO_HAS_UTF8_TO_UTF16 1
 #endif
commit 2f99a294cd2367c4649428534b3429522448260c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:31:47 2008 +0930

    Add _cairo_truetype_index_to_ucs4()
    
    for doing reverse cmap lookups on truetype/opentype fonts one glyph at
    a time.

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index da64f7f..c621235 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -554,4 +554,26 @@ _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
 cairo_private cairo_int_status_t
 _cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t	*font_subset);
 
+/**
+ * _cairo_truetype_index_to_ucs4:
+ * @scaled_font: the #cairo_scaled_font_t
+ * @index: the glyph index
+ * @ucs4: return value for the unicode value of the glyph
+ *
+ * If possible (depending on the format of the underlying
+ * #cairo_scaled_font_t and the font backend in use) assign
+ * the unicode character of the glyph to @ucs4.
+ *
+ * If mapping glyph indices to unicode is supported but the unicode
+ * value of the specified glyph is not available, @ucs4 is set to -1.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if successful,
+ * %CAIRO_INT_STATUS_UNSUPPORTED if mapping glyph indices to unicode
+ * is not supported.  Possible errors include %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_int_status_t
+_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
+                               unsigned long        index,
+                               uint32_t            *ucs4);
+
 #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index c3f0b05..5e4210e 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1318,3 +1318,154 @@ cleanup:
 
     return status;
 }
+
+static cairo_int_status_t
+_cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
+			      unsigned long        table_offset,
+			      unsigned long        index,
+			      uint32_t            *ucs4)
+{
+    cairo_status_t status;
+    const cairo_scaled_font_backend_t *backend;
+    tt_segment_map_t *map;
+    char buf[4];
+    unsigned int num_segments, i;
+    unsigned long size;
+    uint16_t *start_code;
+    uint16_t *end_code;
+    uint16_t *delta;
+    uint16_t *range_offset;
+    uint16_t *glyph_array;
+    uint16_t  c;
+
+    backend = scaled_font->backend;
+    size = 4;
+    status = backend->load_truetype_table (scaled_font,
+                                           TT_TAG_cmap, table_offset,
+					   (unsigned char *) &buf,
+					   &size);
+    if (status)
+	return status;
+
+    /* All table formats have the same first two words */
+    map = (tt_segment_map_t *) buf;
+    if (be16_to_cpu (map->format) != 4)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    size = be16_to_cpu (map->length);
+    map = malloc (size);
+    if (map == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = backend->load_truetype_table (scaled_font,
+                                           TT_TAG_cmap, table_offset,
+                                           (unsigned char *) map,
+                                           &size);
+    if (status)
+	goto fail;
+
+    num_segments = be16_to_cpu (map->segCountX2)/2;
+    end_code = map->endCount;
+    start_code = &(end_code[num_segments + 1]);
+    delta = &(start_code[num_segments]);
+    range_offset = &(delta[num_segments]);
+    glyph_array = &(range_offset[num_segments]);
+
+    /* search for glyph in segments
+     * with rangeOffset=0 */
+    for (i = 0; i < num_segments; i++) {
+	c = index - be16_to_cpu (delta[i]);
+	if (range_offset[i] == 0 &&
+	    c >= be16_to_cpu (start_code[i]) &&
+	    c <= be16_to_cpu (end_code[i]))
+	{
+	    *ucs4 = c;
+	    goto found;
+	}
+    }
+
+    /* search for glyph in segments with rangeOffset=1 */
+    for (i = 0; i < num_segments; i++) {
+	if (range_offset[i] != 0) {
+	    uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
+	    int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
+	    uint16_t g_id_be = cpu_to_be16 (index);
+	    int j;
+
+	    for (j = 0; j < range_size; j++) {
+		if (glyph_ids[j] == g_id_be) {
+		    *ucs4 = be16_to_cpu (start_code[i]) + j;
+		    goto found;
+		}
+	    }
+	}
+    }
+
+    /* glyph not found */
+    *ucs4 = -1;
+
+found:
+    status = CAIRO_STATUS_SUCCESS;
+
+fail:
+    free (map);
+
+    return status;
+}
+
+cairo_int_status_t
+_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
+                               unsigned long        index,
+                               uint32_t            *ucs4)
+{
+    cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+    const cairo_scaled_font_backend_t *backend;
+    tt_cmap_t *cmap;
+    char buf[4];
+    int num_tables, i;
+    unsigned long size;
+
+    backend = scaled_font->backend;
+    if (!backend->load_truetype_table)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    size = 4;
+    status = backend->load_truetype_table (scaled_font,
+                                           TT_TAG_cmap, 0,
+					   (unsigned char *) &buf,
+					   &size);
+    if (status)
+	return status;
+
+    cmap = (tt_cmap_t *) buf;
+    num_tables = be16_to_cpu (cmap->num_tables);
+    size = 4 + num_tables*sizeof(tt_cmap_index_t);
+    cmap = malloc (size);
+    if (cmap == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = backend->load_truetype_table (scaled_font,
+	                                   TT_TAG_cmap, 0,
+					   (unsigned char *) cmap,
+					   &size);
+    if (status)
+        goto cleanup;
+
+    /* Find a table with Unicode mapping */
+    for (i = 0; i < num_tables; i++) {
+        if (be16_to_cpu (cmap->index[i].platform) == 3 &&
+            be16_to_cpu (cmap->index[i].encoding) == 1) {
+            status = _cairo_truetype_reverse_cmap (scaled_font,
+						   be32_to_cpu (cmap->index[i].offset),
+						   index,
+						   ucs4);
+            if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+                break;
+        }
+    }
+
+cleanup:
+    free (cmap);
+
+    return status;
+}
commit 95771d62c57c081fe350e0d33326aaa6a27139da
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:31:23 2008 +0930

    Implement win32 index_to_ucs4 font backend function

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 140093b..7b84334 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1553,6 +1553,98 @@ fail1:
 }
 
 static cairo_status_t
+_cairo_win32_scaled_font_index_to_ucs4 (void 		*abstract_font,
+					unsigned long    index,
+					uint32_t	*ucs4)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    GLYPHSET *glyph_set;
+    uint16_t *utf16 = NULL;
+    WORD *glyph_indices = NULL;
+    HDC hdc = NULL;
+    int res;
+    unsigned int i, j, num_glyphs;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    hdc = _get_global_font_dc ();
+    if (!hdc)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	return status;
+
+    res = GetFontUnicodeRanges(hdc, NULL);
+    if (res == 0) {
+	status = _cairo_win32_print_gdi_error (
+	    "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
+	goto exit1;
+    }
+
+    glyph_set = malloc (res);
+    if (glyph_set == NULL) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto exit1;
+    }
+
+    res = GetFontUnicodeRanges(hdc, glyph_set);
+    if (res == 0) {
+	status = _cairo_win32_print_gdi_error (
+	    "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
+	goto exit1;
+    }
+
+    for (i = 0; i < glyph_set->cRanges; i++) {
+	num_glyphs = glyph_set->ranges[i].cGlyphs;
+
+	utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
+	if (utf16 == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto exit1;
+	}
+
+	glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
+	if (glyph_indices == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto exit2;
+	}
+
+	for (j = 0; j < num_glyphs; j++)
+	    utf16[j] = glyph_set->ranges[i].wcLow + j;
+	utf16[j] = 0;
+
+	if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
+	    status = _cairo_win32_print_gdi_error (
+		"_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW");
+	    goto exit2;
+	}
+
+	for (j = 0; j < num_glyphs; j++) {
+	    if (glyph_indices[j] == index) {
+		*ucs4 = utf16[j];
+		goto exit2;
+	    }
+	}
+
+	free (glyph_indices);
+	glyph_indices = NULL;
+	free (utf16);
+	utf16 = NULL;
+    }
+
+exit2:
+    if (glyph_indices)
+	free (glyph_indices);
+    if (utf16)
+	free (utf16);
+    free (glyph_set);
+exit1:
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return status;
+}
+
+static cairo_status_t
 _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
                                              cairo_scaled_glyph_t      *scaled_glyph)
 {
@@ -1788,6 +1880,7 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
     _cairo_win32_scaled_font_show_glyphs,
     _cairo_win32_scaled_font_load_truetype_table,
     _cairo_win32_scaled_font_map_glyphs_to_unicode,
+    _cairo_win32_scaled_font_index_to_ucs4,
 };
 
 /* #cairo_win32_font_face_t */
commit 4619b0b309861daa64b9c3ced9fdea20c461edf2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:30:14 2008 +0930

    Add index_to_ucs4 font backend function and FT implementation

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 7313984..9c18949 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2209,6 +2209,36 @@ _cairo_ft_map_glyphs_to_unicode (void	                    *abstract_font,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_int_status_t
+_cairo_ft_index_to_ucs4(void	        *abstract_font,
+			unsigned long    index,
+			uint32_t	*ucs4)
+{
+    cairo_ft_scaled_font_t *scaled_font = abstract_font;
+    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+    FT_Face face;
+    FT_ULong  charcode;
+    FT_UInt   gindex;
+
+    face = _cairo_ft_unscaled_font_lock_face (unscaled);
+    if (!face)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    *ucs4 = (uint32_t) -1;
+    charcode = FT_Get_First_Char(face, &gindex);
+    while (gindex != 0) {
+	charcode = FT_Get_Next_Char (face, charcode, &gindex);
+	if (gindex == index) {
+	    *ucs4 = charcode;
+	    break;
+	}
+    }
+
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_create_toy,
@@ -2219,6 +2249,7 @@ const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     NULL, 			/* show_glyphs */
     _cairo_ft_load_truetype_table,
     _cairo_ft_map_glyphs_to_unicode,
+    _cairo_ft_index_to_ucs4
 };
 
 /* #cairo_ft_font_face_t */
diff --git a/src/cairoint.h b/src/cairoint.h
index 50f5681..d5404f9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -441,8 +441,13 @@ struct _cairo_scaled_font_backend {
 
     cairo_warn cairo_int_status_t
     (*map_glyphs_to_unicode)(void                       *scaled_font,
-                                   cairo_scaled_font_subset_t *font_subset);
+                             cairo_scaled_font_subset_t *font_subset);
 
+    /* returns -1 if the unicode character could not be found for the glyph */
+    cairo_warn cairo_int_status_t
+    (*index_to_ucs4)(void                       *scaled_font,
+		     unsigned long               index,
+                     uint32_t                   *ucs4);
 };
 
 struct _cairo_font_face_backend {
commit 54f63e7859baeff18f7345cf22630d6a9b709e1c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 29 19:28:39 2008 +0930

    PDF: Ensure text object is closed before emitting fill or stroke

diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 463af87..81c99e9 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -655,6 +655,9 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t	*pdf_operators,
     cairo_bool_t has_ctm = TRUE;
     double scale = 1.0;
 
+    if (pdf_operators->in_text_object)
+	status = _cairo_pdf_operators_end_text (pdf_operators);
+
     /* Optimize away the stroke ctm when it does not affect the
      * stroke. There are other ctm cases that could be optimized
      * however this is the most common.
@@ -750,6 +753,9 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t	*pdf_operators,
     const char *pdf_operator;
     cairo_status_t status;
 
+    if (pdf_operators->in_text_object)
+	status = _cairo_pdf_operators_end_text (pdf_operators);
+
     status = _cairo_pdf_operators_emit_path (pdf_operators,
 					     path,
 					     &pdf_operators->cairo_to_pdf,


More information about the cairo-commit mailing list