[cairo-commit] 11 commits - src/cairo-cff-subset.c src/cairoint.h src/cairo-pdf-operators.c src/cairo-pdf-operators-private.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-scaled-font-subsets-private.h src/cairo-truetype-subset.c src/cairo-type1-fallback.c src/cairo-type1-subset.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Fri Oct 1 04:22:40 PDT 2010


 src/cairo-cff-subset.c                  |   20 +
 src/cairo-pdf-operators-private.h       |    2 
 src/cairo-pdf-operators.c               |   64 ++++--
 src/cairo-pdf-surface.c                 |  191 ++++++++++++-----
 src/cairo-ps-surface.c                  |   32 ++-
 src/cairo-scaled-font-subsets-private.h |   26 ++
 src/cairo-scaled-font-subsets.c         |  341 +++++++++++++++++++++++---------
 src/cairo-truetype-subset.c             |  123 ++++++++---
 src/cairo-type1-fallback.c              |   27 +-
 src/cairo-type1-subset.c                |  136 +++++++++++-
 src/cairoint.h                          |    2 
 11 files changed, 733 insertions(+), 231 deletions(-)

New commits:
commit 165a14b5646d582781d119874f549ec9a02d7f53
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 19:18:28 2010 +0930

    pdf-operators: fix bug that was causing unnecessary repositioning of text
    
    This optimizes the output to increase the maximum amount of text that
    is emitted with a single Tj operator.

diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index 1f5ee17..14d60b6 100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -83,6 +83,7 @@ typedef struct _cairo_pdf_operators {
     int hex_width;
     cairo_bool_t is_latin;
     int num_glyphs;
+    double glyph_buf_x_pos;
     cairo_pdf_glyph_t glyphs[PDF_GLYPH_BUFFER_SIZE];
 
     /* PDF line style */
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 2d718ed..21592b5 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -1016,6 +1016,7 @@ _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
     }
 
     pdf_operators->num_glyphs = 0;
+    pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x;
     status2 = _cairo_output_stream_destroy (word_wrap_stream);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = status2;
@@ -1038,6 +1039,7 @@ _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators
     pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
     pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
     pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
+    pdf_operators->glyph_buf_x_pos += x;
     pdf_operators->num_glyphs++;
     if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
 	return _cairo_pdf_operators_flush_glyphs (pdf_operators);
@@ -1062,6 +1064,7 @@ _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t  *pdf_operators,
     pdf_operators->text_matrix = *matrix;
     pdf_operators->cur_x = 0;
     pdf_operators->cur_y = 0;
+    pdf_operators->glyph_buf_x_pos = 0;
     _cairo_output_stream_printf (pdf_operators->stream,
 				 "%f %f %f %f %f %f Tm\n",
 				 pdf_operators->text_matrix.xx,
@@ -1117,6 +1120,7 @@ _cairo_pdf_operators_set_text_position (cairo_pdf_operators_t  *pdf_operators,
 				 translate.y0);
     pdf_operators->cur_x = 0;
     pdf_operators->cur_y = 0;
+    pdf_operators->glyph_buf_x_pos = 0;
 
     pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix;
     status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
@@ -1167,6 +1171,7 @@ _cairo_pdf_operators_begin_text (cairo_pdf_operators_t    *pdf_operators)
 
     pdf_operators->in_text_object = TRUE;
     pdf_operators->num_glyphs = 0;
+    pdf_operators->glyph_buf_x_pos = 0;
 
     return _cairo_output_stream_get_status (pdf_operators->stream);
 }
@@ -1271,7 +1276,7 @@ _cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t             *pdf_operator
      * PDF consumers that do not handle very large position
      * adjustments in TJ.
      */
-    if (fabs(x - pdf_operators->cur_x) > 10 ||
+    if (fabs(x - pdf_operators->glyph_buf_x_pos) > 10 ||
 	fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
     {
 	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
commit af3b550bc186361a0b6a779df0fc57799c3f163d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 18:07:01 2010 +0930

    PDF: Add support for latin subsets
    
    Add support for Type 1 and TrueType latin subsets.
    
    CFF latin subsets are not yet implemented.

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index a4a434f..48cab14 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -2011,6 +2011,26 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
     free (subset->data);
 }
 
+cairo_bool_t
+_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font)
+{
+    const cairo_scaled_font_backend_t *backend;
+    cairo_status_t status;
+    unsigned long data_length;
+
+    backend = scaled_font->backend;
+    if (!backend->load_truetype_table)
+	return FALSE;
+
+    data_length = 0;
+    status = backend->load_truetype_table(scaled_font,
+					  TT_TAG_CFF, 0, NULL, &data_length);
+    if (status)
+        return FALSE;;
+
+    return TRUE;
+}
+
 static cairo_int_status_t
 _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t  *scaled_font_subset,
                                  cairo_cff_font_t           **font_return,
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index c60e636..3265312 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -357,6 +357,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 	goto BAIL1;
     }
 
+    _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
+
     surface->next_available_resource.id = 1;
     surface->pages_resource = _cairo_pdf_surface_new_object (surface);
     if (surface->pages_resource.id == 0) {
@@ -4069,7 +4071,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
     cairo_pdf_font_t font;
     cairo_status_t status;
     unsigned long length;
-    unsigned int i;
+    unsigned int i, last_glyph;
     char tag[10];
 
     _create_font_subset_tag (font_subset, subset->base_font, tag);
@@ -4105,6 +4107,15 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
     if (_cairo_status_is_error (status))
 	return status;
 
+    if (font_subset->is_latin) {
+	/* find last glyph used */
+	for (i = 255; i >= 32; i--)
+	    if (font_subset->latin_to_subset_glyph_index[i] > 0)
+		break;
+
+	last_glyph = i;
+    }
+
     descriptor = _cairo_pdf_surface_new_object (surface);
     if (descriptor.id == 0)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -4113,7 +4124,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
 				 "%d 0 obj\n"
 				 "<< /Type /FontDescriptor\n"
 				 "   /FontName /%s+%s\n"
-				 "   /Flags 4\n"
+				 "   /Flags %d\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\n"
 				 "   /ItalicAngle 0\n"
 				 "   /Ascent %ld\n"
@@ -4127,6 +4138,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
 				 descriptor.id,
 				 tag,
 				 subset->base_font,
+				 font_subset->is_latin ? 32 : 4,
 				 (long)(subset->x_min*PDF_UNITS_PER_EM),
 				 (long)(subset->y_min*PDF_UNITS_PER_EM),
 				 (long)(subset->x_max*PDF_UNITS_PER_EM),
@@ -4142,20 +4154,34 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
 				 "<< /Type /Font\n"
 				 "   /Subtype /Type1\n"
 				 "   /BaseFont /%s+%s\n"
-				 "   /FirstChar 0\n"
+				 "   /FirstChar %d\n"
 				 "   /LastChar %d\n"
 				 "   /FontDescriptor %d 0 R\n"
 				 "   /Widths [",
 				 subset_resource.id,
 				 tag,
 				 subset->base_font,
-				 font_subset->num_glyphs - 1,
+				 font_subset->is_latin ? 32 : 0,
+				 font_subset->is_latin ? last_glyph : font_subset->num_glyphs - 1,
 				 descriptor.id);
 
-    for (i = 0; i < font_subset->num_glyphs; i++)
-	_cairo_output_stream_printf (surface->output,
-				     " %ld",
-                                     (long)(subset->widths[i]*PDF_UNITS_PER_EM));
+    if (font_subset->is_latin) {
+	for (i = 32; i < last_glyph + 1; i++) {
+	    int glyph = font_subset->latin_to_subset_glyph_index[i];
+	    if (glyph > 0) {
+		_cairo_output_stream_printf (surface->output,
+					     " %ld",
+					     (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
+	    } else {
+		_cairo_output_stream_printf (surface->output, " 0");
+	    }
+	}
+    } else {
+	for (i = 0; i < font_subset->num_glyphs; i++)
+	    _cairo_output_stream_printf (surface->output,
+					 " %ld",
+					 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
+    }
 
     _cairo_output_stream_printf (surface->output,
 				 " ]\n");
@@ -4226,7 +4252,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
     cairo_status_t status;
     cairo_pdf_font_t font;
     cairo_truetype_subset_t subset;
-    unsigned int i;
+    unsigned int i, last_glyph;
     char tag[10];
 
     subset_resource = _cairo_pdf_surface_get_font_resource (surface,
@@ -4289,7 +4315,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
     }
 
     _cairo_output_stream_printf (surface->output,
-				 "   /Flags 4\n"
+				 "   /Flags %d\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\n"
 				 "   /ItalicAngle 0\n"
 				 "   /Ascent %ld\n"
@@ -4300,6 +4326,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 				 "   /FontFile2 %u 0 R\n"
 				 ">>\n"
 				 "endobj\n",
+				 font_subset->is_latin ? 32 : 4,
 				 (long)(subset.x_min*PDF_UNITS_PER_EM),
 				 (long)(subset.y_min*PDF_UNITS_PER_EM),
                                  (long)(subset.x_max*PDF_UNITS_PER_EM),
@@ -4309,60 +4336,108 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 				 (long)(subset.y_max*PDF_UNITS_PER_EM),
 				 stream.id);
 
-    cidfont_dict = _cairo_pdf_surface_new_object (surface);
-    if (cidfont_dict.id == 0) {
-	_cairo_truetype_subset_fini (&subset);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
+    if (font_subset->is_latin) {
+	/* find last glyph used */
+	for (i = 255; i >= 32; i--)
+	    if (font_subset->latin_to_subset_glyph_index[i] > 0)
+		break;
 
-    _cairo_output_stream_printf (surface->output,
-                                 "%d 0 obj\n"
-                                 "<< /Type /Font\n"
-                                 "   /Subtype /CIDFontType2\n"
-                                 "   /BaseFont /%s+%s\n"
-                                 "   /CIDSystemInfo\n"
-                                 "   << /Registry (Adobe)\n"
-                                 "      /Ordering (Identity)\n"
-                                 "      /Supplement 0\n"
-                                 "   >>\n"
-                                 "   /FontDescriptor %d 0 R\n"
-                                 "   /W [0 [",
-                                 cidfont_dict.id,
-				 tag,
-                                 subset.ps_name,
-                                 descriptor.id);
+	last_glyph = i;
+	_cairo_pdf_surface_update_object (surface, subset_resource);
+	_cairo_output_stream_printf (surface->output,
+				     "%d 0 obj\r\n"
+				     "<< /Type /Font\n"
+				     "   /Subtype /TrueType\n"
+				     "   /BaseFont /%s+%s\n"
+				     "   /FirstChar 32\n"
+				     "   /LastChar %d\n"
+				     "   /FontDescriptor %d 0 R\n"
+				     "   /Encoding /WinAnsiEncoding\n"
+				     "   /Widths [",
+				     subset_resource.id,
+				     tag,
+				     subset.ps_name,
+				     last_glyph,
+				     descriptor.id);
+
+	for (i = 32; i < last_glyph + 1; i++) {
+	    int glyph = font_subset->latin_to_subset_glyph_index[i];
+	    if (glyph > 0) {
+		_cairo_output_stream_printf (surface->output,
+					     " %ld",
+					     (long)(subset.widths[glyph]*PDF_UNITS_PER_EM));
+	    } else {
+		_cairo_output_stream_printf (surface->output, " 0");
+	    }
+	}
 
-    for (i = 0; i < font_subset->num_glyphs; i++)
-        _cairo_output_stream_printf (surface->output,
-                                     " %ld",
-                                     (long)(subset.widths[i]*PDF_UNITS_PER_EM));
+	_cairo_output_stream_printf (surface->output,
+				     " ]\n");
 
-    _cairo_output_stream_printf (surface->output,
-                                 " ]]\n"
-				 ">>\n"
-				 "endobj\n");
+	if (to_unicode_stream.id != 0)
+	    _cairo_output_stream_printf (surface->output,
+					 "    /ToUnicode %d 0 R\n",
+					 to_unicode_stream.id);
 
-    _cairo_pdf_surface_update_object (surface, subset_resource);
-    _cairo_output_stream_printf (surface->output,
-				 "%d 0 obj\n"
-				 "<< /Type /Font\n"
-				 "   /Subtype /Type0\n"
-				 "   /BaseFont /%s+%s\n"
-                                 "   /Encoding /Identity-H\n"
-				 "   /DescendantFonts [ %d 0 R]\n",
-				 subset_resource.id,
-				 tag,
-				 subset.ps_name,
-				 cidfont_dict.id);
+	_cairo_output_stream_printf (surface->output,
+				     ">>\n"
+				     "endobj\n");
+    } else {
+	cidfont_dict = _cairo_pdf_surface_new_object (surface);
+	if (cidfont_dict.id == 0) {
+	    _cairo_truetype_subset_fini (&subset);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
 
-    if (to_unicode_stream.id != 0)
-        _cairo_output_stream_printf (surface->output,
-                                     "   /ToUnicode %d 0 R\n",
-                                     to_unicode_stream.id);
+	_cairo_output_stream_printf (surface->output,
+				     "%d 0 obj\n"
+				     "<< /Type /Font\n"
+				     "   /Subtype /CIDFontType2\n"
+				     "   /BaseFont /%s+%s\n"
+				     "   /CIDSystemInfo\n"
+				     "   << /Registry (Adobe)\n"
+				     "      /Ordering (Identity)\n"
+				     "      /Supplement 0\n"
+				     "   >>\n"
+				     "   /FontDescriptor %d 0 R\n"
+				     "   /W [0 [",
+				     cidfont_dict.id,
+				     tag,
+				     subset.ps_name,
+				     descriptor.id);
+
+	for (i = 0; i < font_subset->num_glyphs; i++)
+	    _cairo_output_stream_printf (surface->output,
+					 " %ld",
+					 (long)(subset.widths[i]*PDF_UNITS_PER_EM));
 
-    _cairo_output_stream_printf (surface->output,
-				 ">>\n"
-				 "endobj\n");
+	_cairo_output_stream_printf (surface->output,
+				     " ]]\n"
+				     ">>\n"
+				     "endobj\n");
+
+	_cairo_pdf_surface_update_object (surface, subset_resource);
+	_cairo_output_stream_printf (surface->output,
+				     "%d 0 obj\n"
+				     "<< /Type /Font\n"
+				     "   /Subtype /Type0\n"
+				     "   /BaseFont /%s+%s\n"
+				     "   /Encoding /Identity-H\n"
+				     "   /DescendantFonts [ %d 0 R]\n",
+				     subset_resource.id,
+				     tag,
+				     subset.ps_name,
+				     cidfont_dict.id);
+
+	if (to_unicode_stream.id != 0)
+	    _cairo_output_stream_printf (surface->output,
+					 "   /ToUnicode %d 0 R\n",
+					 to_unicode_stream.id);
+
+	_cairo_output_stream_printf (surface->output,
+				     ">>\n"
+				     "endobj\n");
+    }
 
     font.font_id = font_subset->font_id;
     font.subset_id = font_subset->subset_id;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 7c5756f..44b037a 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -387,6 +387,15 @@ cairo_private void
 _cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
 
 /**
+ * _cairo_cff_scaled_font_is_cff:
+ * @scaled_font: a #cairo_scaled_font_t
+ *
+ * Return %TRUE if @scaled_font is a CFF font, otherwise return %FALSE.
+ **/
+cairo_bool_t
+_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font);
+
+/**
  * _cairo_cff_fallback_init:
  * @cff_subset: a #cairo_cff_subset_t to initialize
  * @font_subset: the #cairo_scaled_font_subset_t to initialize from
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 677bd5a..79a778f 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -70,6 +70,7 @@ typedef struct _cairo_sub_font {
     cairo_bool_t is_scaled;
     cairo_bool_t is_composite;
     cairo_bool_t is_user;
+    cairo_bool_t use_latin_subset;
     cairo_scaled_font_subsets_t *parent;
     cairo_scaled_font_t *scaled_font;
     unsigned int font_id;
@@ -294,7 +295,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
     sub_font->scaled_font = scaled_font;
     sub_font->font_id = font_id;
 
-    if (parent->use_latin_subset)
+    sub_font->use_latin_subset = parent->use_latin_subset;
+    if (_cairo_cff_scaled_font_is_cff (scaled_font))
+	sub_font->use_latin_subset = FALSE; /* CFF latin subsets are NYI */
+
+    if (sub_font->use_latin_subset)
 	sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */
     else
 	sub_font->current_subset = 0;
@@ -616,7 +621,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 	 * create a separate subset just for the .notdef glyph.
 	 */
 	is_latin = FALSE;
-	if (sub_font->parent->use_latin_subset &&
+	if (sub_font->use_latin_subset &&
 	    (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
 	{
 	    latin_character = _cairo_unicode_to_winansi (font_unicode);
@@ -702,7 +707,7 @@ _cairo_sub_font_collect (void *entry, void *closure)
         subset.glyph_names = NULL;
 
 	subset.is_latin = FALSE;
-	if (sub_font->parent->use_latin_subset && i == 0) {
+	if (sub_font->use_latin_subset && i == 0) {
 	    subset.is_latin = TRUE;
 	    subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index;
 	} else {
commit 85c25d79f7e77ae35a68b9444609aef8d5397011
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 18:05:34 2010 +0930

    TrueType subsetting: embed a cmap for latin subsets
    
    To support latin subsets in PDF, TrueType fonts require a cmap to map
    unicode to glyph indices for all characters in the winansi encoding.

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 2a8cd77..7c5756f 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -460,6 +460,9 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
 cairo_private void
 _cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset);
 
+cairo_private int
+_cairo_unicode_to_winansi (unsigned long unicode);
+
 cairo_private const char *
 _cairo_winansi_to_glyphname (int glyph);
 
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 24a700a..677bd5a 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -343,7 +343,8 @@ static unsigned int _winansi_0x80_to_0x9f[] = {
     0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178
 };
 
-static int _unicode_to_winansi (unsigned long unicode)
+int
+_cairo_unicode_to_winansi (unsigned long unicode)
 {
     int i;
 
@@ -618,7 +619,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 	if (sub_font->parent->use_latin_subset &&
 	    (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
 	{
-	    latin_character = _unicode_to_winansi (font_unicode);
+	    latin_character = _cairo_unicode_to_winansi (font_unicode);
 	    if (latin_character > 0 ||
 		(latin_character == 0 && sub_font->num_glyphs_in_latin_subset > 0))
 	    {
@@ -1184,7 +1185,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
 	}
 
 	if (utf16_len == 1) {
-	    int ch = _unicode_to_winansi (utf16[0]);
+	    int ch = _cairo_unicode_to_winansi (utf16[0]);
 	    if (ch > 0)
 		strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf));
 	    else
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 9bf2f8f..b774bd2 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -393,51 +393,98 @@ cairo_truetype_font_check_boundary (cairo_truetype_font_t *font,
     return CAIRO_STATUS_SUCCESS;
 }
 
+typedef struct _cmap_unicode_range {
+    unsigned int start;
+    unsigned int end;
+} cmap_unicode_range_t;
+
+static cmap_unicode_range_t winansi_unicode_ranges[] = {
+    { 0x0020, 0x007f },
+    { 0x00a0, 0x00ff },
+    { 0x0152, 0x0153 },
+    { 0x0178, 0x0178 },
+    { 0x017d, 0x017e },
+    { 0x0192, 0x0192 },
+    { 0x02c6, 0x02c6 },
+    { 0x02dc, 0x02dc },
+    { 0x2013, 0x2026 },
+    { 0x2030, 0x2030 },
+    { 0x2039, 0x203a },
+    { 0x2122, 0x2122 },
+};
+
 static cairo_status_t
 cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
 				      unsigned long          tag)
 {
-    unsigned int i;
+    int i;
+    unsigned int j;
+    int range_offset;
+    int num_ranges;
+    int entry_selector;
+    int length;
+
+    num_ranges = ARRAY_LENGTH (winansi_unicode_ranges);
+
+    length = 16 + (num_ranges + 1)*8;
+    for (i = 0; i < num_ranges; i++)
+	length += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2;
+
+    entry_selector = 0;
+    while ((1 << entry_selector) <= (num_ranges + 1))
+	entry_selector++;
+
+    entry_selector--;
 
     cairo_truetype_font_write_be16 (font, 0);  /* Table version */
-    cairo_truetype_font_write_be16 (font, 2);  /* Num tables */
+    cairo_truetype_font_write_be16 (font, 1);  /* Num tables */
 
     cairo_truetype_font_write_be16 (font, 3);  /* Platform */
-    cairo_truetype_font_write_be16 (font, 0);  /* Encoding */
-    cairo_truetype_font_write_be32 (font, 20); /* Offset to start of table */
+    cairo_truetype_font_write_be16 (font, 1);  /* Encoding */
+    cairo_truetype_font_write_be32 (font, 12); /* Offset to start of table */
 
-    cairo_truetype_font_write_be16 (font, 1);  /* Platform */
-    cairo_truetype_font_write_be16 (font, 0);  /* Encoding */
-    cairo_truetype_font_write_be32 (font, 52); /* Offset to start of table */
-
-    /* Output a format 4 encoding table. */
+    /* Output a format 4 encoding table for the winansi encoding */
 
     cairo_truetype_font_write_be16 (font, 4);  /* Format */
-    cairo_truetype_font_write_be16 (font, 32); /* Length */
+    cairo_truetype_font_write_be16 (font, length); /* Length */
     cairo_truetype_font_write_be16 (font, 0);  /* Version */
-    cairo_truetype_font_write_be16 (font, 4);  /* 2*segcount */
-    cairo_truetype_font_write_be16 (font, 4);  /* searchrange */
-    cairo_truetype_font_write_be16 (font, 1);  /* entry selector */
-    cairo_truetype_font_write_be16 (font, 0);  /* rangeshift */
-    cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */
-    cairo_truetype_font_write_be16 (font, 0xffff);  /* end count[1] */
+    cairo_truetype_font_write_be16 (font, num_ranges*2 + 2);  /* 2*segcount */
+    cairo_truetype_font_write_be16 (font, (1 << (entry_selector + 1)));  /* searchrange */
+    cairo_truetype_font_write_be16 (font, entry_selector);  /* entry selector */
+    cairo_truetype_font_write_be16 (font, num_ranges*2 + 2 - (1 << (entry_selector + 1)));  /* rangeshift */
+    for (i = 0; i < num_ranges; i++)
+	cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].end); /* end count[] */
+    cairo_truetype_font_write_be16 (font, 0xffff);  /* end count[] */
+
     cairo_truetype_font_write_be16 (font, 0);       /* reserved */
-    cairo_truetype_font_write_be16 (font, 0xf000);  /* startCode[0] */
-    cairo_truetype_font_write_be16 (font, 0xffff);  /* startCode[1] */
-    cairo_truetype_font_write_be16 (font, 0x1000);  /* delta[0] */
-    cairo_truetype_font_write_be16 (font, 1);       /* delta[1] */
-    cairo_truetype_font_write_be16 (font, 0);       /* rangeOffset[0] */
-    cairo_truetype_font_write_be16 (font, 0);       /* rangeOffset[1] */
-
-    /* Output a format 6 encoding table. */
-
-    cairo_truetype_font_write_be16 (font, 6);
-    cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs);
-    cairo_truetype_font_write_be16 (font, 0);
-    cairo_truetype_font_write_be16 (font, 0); /* First character */
-    cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
-    for (i = 0; i < font->base.num_glyphs; i++)
-	cairo_truetype_font_write_be16 (font, i);
+
+    for (i = 0; i < num_ranges; i++)
+	cairo_truetype_font_write_be16 (font, winansi_unicode_ranges[i].start);  /* startCode[] */
+    cairo_truetype_font_write_be16 (font, 0xffff);  /* startCode[] */
+
+    for (i = 0; i < num_ranges; i++)
+	cairo_truetype_font_write_be16 (font, 0x0000);  /* delta[] */
+    cairo_truetype_font_write_be16 (font, 1);       /* delta[] */
+
+    range_offset = num_ranges*2 + 2;
+    for (i = 0; i < num_ranges; i++) {
+	cairo_truetype_font_write_be16 (font, range_offset);       /* rangeOffset[] */
+	range_offset += (winansi_unicode_ranges[i].end - winansi_unicode_ranges[i].start + 1)*2 - 2;
+    }
+    cairo_truetype_font_write_be16 (font, 0);       /* rangeOffset[] */
+
+    for (i = 0; i < num_ranges; i++) {
+	for (j = winansi_unicode_ranges[i].start; j < winansi_unicode_ranges[i].end + 1; j++) {
+	    int ch = _cairo_unicode_to_winansi (j);
+	    int glyph;
+
+	    if (ch > 0)
+		glyph = font->scaled_font_subset->latin_to_subset_glyph_index[ch];
+	    else
+		glyph = 0;
+	    cairo_truetype_font_write_be16 (font, glyph);
+	}
+    }
 
     return font->status;
 }
@@ -985,8 +1032,9 @@ cairo_truetype_font_add_truetype_table (cairo_truetype_font_t *font,
  * The tables in the table directory must be listed in alphabetical
  * order.  The "cvt", "fpgm", and "prep" are optional tables. They
  * will only be embedded in the subset if they exist in the source
- * font. The pos parameter of cairo_truetype_font_add_truetype_table()
- * specifies the position of the table in the table directory.
+ * font. "cmap" is only embedded for latin fonts. The pos parameter of
+ * cairo_truetype_font_add_truetype_table() specifies the position of
+ * the table in the table directory.
  */
 static void
 cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
@@ -1016,7 +1064,9 @@ cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
         has_prep = TRUE;
 
     font->num_tables = 0;
-    pos = 1;
+    pos = 0;
+    if (font->scaled_font_subset->is_latin)
+	pos++;
     if (has_cvt)
         pos++;
     if (has_fpgm)
@@ -1024,7 +1074,8 @@ cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
     cairo_truetype_font_add_truetype_table (font, TT_TAG_glyf, cairo_truetype_font_write_glyf_table, pos);
 
     pos = 0;
-    cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap, cairo_truetype_font_write_cmap_table, pos++);
+    if (font->scaled_font_subset->is_latin)
+	cairo_truetype_font_add_truetype_table (font, TT_TAG_cmap, cairo_truetype_font_write_cmap_table, pos++);
     if (has_cvt)
         cairo_truetype_font_add_truetype_table (font, TT_TAG_cvt, cairo_truetype_font_write_generic_table, pos++);
     if (has_fpgm)
commit 7c268bc8382350ab803eecb898d4650999a3a6bb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 18:01:07 2010 +0930

    PS: Enable support for latin subsets
    
    Make PS TrueType embedding use the winansi glyph mapping for latin subsets.
    
    Enable use of latin subsets in PS.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index c73214e..1c5d7a9 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -426,14 +426,29 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,
 
     /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
 
-    for (i = 1; i < font_subset->num_glyphs; i++) {
-	if (font_subset->glyph_names != NULL) {
-	    _cairo_output_stream_printf (surface->final_stream,
-					 "Encoding %d /%s put\n",
-					 i, font_subset->glyph_names[i]);
-	} else {
-	    _cairo_output_stream_printf (surface->final_stream,
-					 "Encoding %d /g%d put\n", i, i);
+    if (font_subset->is_latin) {
+	for (i = 1; i < 256; i++) {
+	    if (font_subset->latin_to_subset_glyph_index[i] > 0) {
+		if (font_subset->glyph_names != NULL) {
+		    _cairo_output_stream_printf (surface->final_stream,
+						 "Encoding %d /%s put\n",
+						 i, font_subset->glyph_names[font_subset->latin_to_subset_glyph_index[i]]);
+		} else {
+		    _cairo_output_stream_printf (surface->final_stream,
+						 "Encoding %d /g%ld put\n", i, font_subset->latin_to_subset_glyph_index[i]);
+		}
+	    }
+	}
+    } else {
+	for (i = 1; i < font_subset->num_glyphs; i++) {
+	    if (font_subset->glyph_names != NULL) {
+		_cairo_output_stream_printf (surface->final_stream,
+					     "Encoding %d /%s put\n",
+					     i, font_subset->glyph_names[i]);
+	    } else {
+		_cairo_output_stream_printf (surface->final_stream,
+					     "Encoding %d /g%d put\n", i, i);
+	    }
 	}
     }
 
@@ -956,6 +971,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
 	goto CLEANUP_OUTPUT_STREAM;
     }
 
+    _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);
     surface->has_creation_date = FALSE;
     surface->eps = FALSE;
     surface->ps_level = CAIRO_PS_LEVEL_3;
commit 52f3db92a747eb694b94f28d6862abd573f3b378
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:58:40 2010 +0930

    Type 1 fallback: add support for latin subsets
    
    For latin subsets the /Encoding array maps the latin encoding to the
    font glyphs.

diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index b93c423..c2d0fa6 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -514,12 +514,27 @@ cairo_type1_font_write_header (cairo_type1_font_t *font,
                                  "} readonly def\n"
                                  "/Encoding 256 array\n"
 				 "0 1 255 {1 index exch /.notdef put} for\n");
-    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
-	if (font->scaled_font_subset->glyph_names != NULL) {
-	    _cairo_output_stream_printf (font->output, "dup %d /%s put\n",
-					 i, font->scaled_font_subset->glyph_names[i]);
-	} else {
-	    _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i);
+    if (font->scaled_font_subset->is_latin) {
+	for (i = 1; i < 256; i++) {
+	    int subset_glyph = font->scaled_font_subset->latin_to_subset_glyph_index[i];
+
+	    if (subset_glyph > 0) {
+		if (font->scaled_font_subset->glyph_names != NULL) {
+		    _cairo_output_stream_printf (font->output, "dup %d /%s put\n",
+						 i, font->scaled_font_subset->glyph_names[subset_glyph]);
+		} else {
+		    _cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, subset_glyph);
+		}
+	    }
+	}
+    } else {
+	for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
+	    if (font->scaled_font_subset->glyph_names != NULL) {
+		_cairo_output_stream_printf (font->output, "dup %d /%s put\n",
+					     i, font->scaled_font_subset->glyph_names[i]);
+	    } else {
+		_cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i);
+	    }
 	}
     }
     _cairo_output_stream_printf (font->output,
commit 4a0e5b7ced989b2c1a17757ba17142eb55e3924d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:58:20 2010 +0930

    Type 1 subsetting: add support for latin subsets
    
    For latin subsets the /Encoding array maps the latin encoding to the
    font glyphs.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 636cc8b..9346951 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -116,6 +116,7 @@ typedef struct _cairo_type1_font_subset {
 static cairo_status_t
 _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 			       cairo_unscaled_font_t      *unscaled_font,
+			       cairo_scaled_font_subset_t *scaled_font_subset,
 			       cairo_bool_t                hex_encode)
 {
     cairo_ft_unscaled_font_t *ft_unscaled_font;
@@ -144,6 +145,7 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 #endif
 
     memset (font, 0, sizeof (*font));
+    font->scaled_font_subset = scaled_font_subset;
     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
     font->base.num_glyphs = face->num_glyphs;
     font->base.x_min = face->bbox.xMin;
@@ -391,13 +393,27 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
     _cairo_output_stream_printf (font->output,
 				 "/Encoding 256 array\n"
 				 "0 1 255 {1 index exch /.notdef put} for\n");
-    for (i = 1; i < font->base.num_glyphs; i++) {
-	if (font->glyphs[i].subset_index < 0)
-	    continue;
-	_cairo_output_stream_printf (font->output,
-				     "dup %d /%s put\n",
-				     font->glyphs[i].subset_index,
-				     font->glyphs[i].name);
+    if (font->scaled_font_subset->is_latin) {
+	for (i = 1; i < 256; i++) {
+	    int subset_glyph = font->scaled_font_subset->latin_to_subset_glyph_index[i];
+	    int parent_glyph = font->scaled_font_subset->glyphs[subset_glyph];
+
+	    if (subset_glyph > 0) {
+		_cairo_output_stream_printf (font->output,
+					     "dup %d /%s put\n",
+					     i,
+					     font->glyphs[parent_glyph].name);
+	    }
+	}
+    } else {
+	for (i = 1; i < font->base.num_glyphs; i++) {
+	    if (font->glyphs[i].subset_index < 0)
+		continue;
+	    _cairo_output_stream_printf (font->output,
+					 "dup %d /%s put\n",
+					 font->glyphs[i].subset_index,
+					 font->glyphs[i].name);
+	}
     }
     _cairo_output_stream_printf (font->output, "readonly def");
 
@@ -1415,7 +1431,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
 
     unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
 
-    status = _cairo_type1_font_subset_init (&font, unscaled_font, hex_encode);
+    status = _cairo_type1_font_subset_init (&font, unscaled_font, scaled_font_subset, hex_encode);
     if (unlikely (status))
 	return status;
 
commit 01ee091ee98bc0544d9a3d5665cdecddd8f368cc
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:57:43 2010 +0930

    Add winansi glyph names
    
    for the PS backend and Type 1 subsetters to use with latin fonts.

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index d119597..2a8cd77 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -460,7 +460,8 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
 cairo_private void
 _cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset);
 
-
+cairo_private const char *
+_cairo_winansi_to_glyphname (int glyph);
 
 typedef struct _cairo_type1_subset {
     char *base_font;
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 3478351..24a700a 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -1184,7 +1184,12 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
 	}
 
 	if (utf16_len == 1) {
-	    snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]);
+	    int ch = _unicode_to_winansi (utf16[0]);
+	    if (ch > 0)
+		strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf));
+	    else
+		snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]);
+
 	    _cairo_string_init_key (&key, buf);
 	    entry = _cairo_hash_table_lookup (names, &key.base);
 	    if (entry != NULL)
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 9c0a2cf..636cc8b 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -804,6 +804,98 @@ static const int16_t ps_standard_encoding_offset[256] = {
 
 #define ps_standard_encoding(index) ((index) ? ps_standard_encoding_symbol+ps_standard_encoding_offset[(index)] : NULL)
 
+/* TODO: Merge these names into ps_standard_encoding_symbol (with a
+ * separate winansi_encoding_offset table) as most of the names are
+ * the same. */
+static const char *winansi_encoding[256] = {
+	/*   0 */
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	/*  16 */
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	NULL,		NULL,		NULL,		NULL,
+	/*  32 */
+	"space",	"exclam",	"quotedbl",	"numbersign",
+	"dollar",	"percent",	"ampersand",	"quoteright",
+	"parenleft",	"parenright",	"asterisk",	"plus",
+	"comma",	"hyphen",	"period",	"slash",
+	/*  48 */
+	"zero",		"one",		"two",		"three",
+	"four",		"five",		"six",		"seven",
+	"eight",	"nine",		"colon",	"semicolon",
+	"less",		"equal",	"greater",	"question",
+	/*  64 */
+	"at",		"A",		"B",		"C",
+	"D",		"E",		"F",		"G",
+	"H",		"I",		"J",		"K",
+	"L",		"M",		"N",		"O",
+	/*  80 */
+	"P",		"Q",		"R",		"S",
+	"T",		"U",		"V",		"W",
+	"X",		"Y",		"Z",		"bracketleft",
+	"backslash",	"bracketright",	"asciicircum",	"underscore",
+	/*  96 */
+	"quoteleft",	"a",		"b",		"c",
+	"d",		"e",		"f",		"g",
+	"h",		"i",		"j",		"k",
+	"l",		"m",		"n",		"o",
+	/* 112 */
+	"p",		"q",		"r",		"s",
+	"t",		"u",		"v",		"w",
+	"x",		"y",		"z",		"braceleft",
+	"bar",		"braceright",	"asciitilde",	NULL,
+	/* 128 */
+	"Euro",		NULL,		"quotesinglbase","florin",
+	"quotedblbase", "ellipsis",	"dagger",	"daggerdbl",
+	"circumflex",	"perthousand",	"Scaron",	"guilsinglleft",
+	"OE",		"bullet",	"Zcaron",	NULL,
+	/* 144 */
+	NULL,		"quoteleft",	"quoteright",	"quotedblleft",
+	"quotedblright","bullet",	"endash",	"emdash",
+	"tilde",	"trademark",	"scaron",	"guilsinglright",
+	"oe",		"bullet",	"zcaron",	"Ydieresis",
+	/* 160 */
+	"space",	"exclamdown",	"cent",		"sterling",
+	"currency",	"yen",		"brokenbar",	"section",
+	"dieresis",	"copyright",	"ordfeminine",	"guillemotleft",
+	"logicalnot",	"hyphen",	"registered",	"macron",
+	/* 176 */
+	"degree",	"plusminus",	"twosuperior",	"threesuperior",
+	"acute",	"mu",		"paragraph",	"periodcentered",
+	"cedilla",	"onesuperior",	"ordmasculine",	"guillemotright",
+	"onequarter",	"onehalf",	"threequarters","questiondown",
+	/* 192 */
+	"Agrave",	"Aacute",	"Acircumflex",	"Atilde",
+	"Adieresis",	"Aring",	"AE",		"Ccedilla",
+	"Egrave",	"Eacute",	"Ecircumflex",	"Edieresis",
+	"Igrave",	"Iacute",	"Icircumflex",	"Idieresis",
+	/* 208 */
+	"Eth",		"Ntilde",	"Ograve",	"Oacute",
+	"Ocircumflex",	"Otilde",	"Odieresis",	"multiply",
+	"Oslash",	"Ugrave",	"Uacute",	"Ucircumflex",
+	"Udieresis",	"Yacute",	"Thorn",	"germandbls",
+	/* 224 */
+	"agrave",	"aacute",	"acircumflex",	"atilde",
+	"adieresis",	"aring",	"ae",		"ccedilla",
+	"egrave",	"eacute",	"ecircumflex",	"edieresis",
+	"igrave",	"iacute",	"icircumflex",	"idieresis",
+	/* 240 */
+	"eth",		"ntilde",	"ograve",	"oacute",
+	"ocircumflex",	"otilde",	"odieresis",	"divide",
+	"oslash",	"ugrave",	"uacute",	"ucircumflex",
+	"udieresis",	"yacute",	"thorn",	"ydieresis"
+};
+
+const char *
+_cairo_winansi_to_glyphname (int glyph)
+{
+    return winansi_encoding[glyph];
+}
+
 static cairo_status_t
 use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
 {
commit e62891cd8f27b62c3ee04d822524c9cee69a2e62
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:55:53 2010 +0930

    Return latin to glyph mapping in cairo_scaled_font_subset_t
    
    so that font subsetters can include the latin to glyph encoding in the
    subsetted font.

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 9d8d6c1..3478351 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -120,6 +120,7 @@ typedef struct _cairo_sub_font_collection {
     unsigned long *glyphs; /* scaled_font_glyph_index */
     char       **utf8;
     unsigned int glyphs_size;
+    unsigned long *latin_to_subset_glyph_index;
     unsigned int max_glyph;
     unsigned int num_glyphs;
 
@@ -230,6 +231,9 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure)
 
     collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
     collection->utf8[subset_glyph_index] = sub_font_glyph->utf8;
+    if (sub_font_glyph->is_latin)
+	collection->latin_to_subset_glyph_index[sub_font_glyph->latin_character] = subset_glyph_index;
+
     if (subset_glyph_index > collection->max_glyph)
 	collection->max_glyph = subset_glyph_index;
 
@@ -674,6 +678,7 @@ _cairo_sub_font_collect (void *entry, void *closure)
 	collection->subset_id = i;
 	collection->num_glyphs = 0;
 	collection->max_glyph = 0;
+	memset (collection->latin_to_subset_glyph_index, 0, 256*sizeof(unsigned long));
 
 	_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
 				   _cairo_sub_font_glyph_collect, collection);
@@ -694,6 +699,15 @@ _cairo_sub_font_collect (void *entry, void *closure)
 	subset.utf8 = collection->utf8;
 	subset.num_glyphs = collection->num_glyphs;
         subset.glyph_names = NULL;
+
+	subset.is_latin = FALSE;
+	if (sub_font->parent->use_latin_subset && i == 0) {
+	    subset.is_latin = TRUE;
+	    subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index;
+	} else {
+	    subset.latin_to_subset_glyph_index = NULL;
+	}
+
         /* No need to check for out of memory here. If to_unicode is NULL, the PDF
          * surface does not emit an ToUnicode stream */
         subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long));
@@ -1005,11 +1019,16 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
 
     collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
     collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *));
-    if (unlikely (collection.glyphs == NULL || collection.utf8 == NULL)) {
+    collection.latin_to_subset_glyph_index = _cairo_malloc_ab (256, sizeof(unsigned long));
+    if (unlikely (collection.glyphs == NULL ||
+		  collection.utf8 == NULL ||
+		  collection.latin_to_subset_glyph_index == NULL)) {
 	if (collection.glyphs != NULL)
 	    free (collection.glyphs);
 	if (collection.utf8 != NULL)
 	    free (collection.utf8);
+	if (collection.latin_to_subset_glyph_index != NULL)
+	    free (collection.latin_to_subset_glyph_index);
 
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
@@ -1031,6 +1050,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
     }
     free (collection.utf8);
     free (collection.glyphs);
+    free (collection.latin_to_subset_glyph_index);
 
     return collection.status;
 }
diff --git a/src/cairoint.h b/src/cairoint.h
index 500b2d9..d0ae66a 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -436,9 +436,11 @@ typedef struct _cairo_scaled_font_subset {
     unsigned long *to_unicode;
     char          **utf8;
     char          **glyph_names;
+    unsigned long *latin_to_subset_glyph_index;
     unsigned int num_glyphs;
     cairo_bool_t is_composite;
     cairo_bool_t is_scaled;
+    cairo_bool_t is_latin;
 } cairo_scaled_font_subset_t;
 
 struct _cairo_scaled_font_backend {
commit 807e690de4fda63a42a49a4342b563a6d54377ce
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:55:02 2010 +0930

    pdf-operators: output (abc) style strings when font is latin

diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index 95d4d53..1f5ee17 100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -81,6 +81,7 @@ typedef struct _cairo_pdf_operators {
     double cur_x; /* Current position in PDF text space (Tm in the PDF reference) */
     double cur_y;
     int hex_width;
+    cairo_bool_t is_latin;
     int num_glyphs;
     cairo_pdf_glyph_t glyphs[PDF_GLYPH_BUFFER_SIZE];
 
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 601011a..2d718ed 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -880,6 +880,26 @@ _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t		*pdf_operators,
 					     operator);
 }
 
+static void
+_cairo_pdf_operators_emit_glyph_index (cairo_pdf_operators_t *pdf_operators,
+				       cairo_output_stream_t *stream,
+				       unsigned int 	      glyph)
+{
+    if (pdf_operators->is_latin) {
+	if (glyph == '(' || glyph == ')' || glyph == '\\')
+	    _cairo_output_stream_printf (stream, "\\%c", glyph);
+	else if (glyph >= 0x20 && glyph <= 0x7e)
+	    _cairo_output_stream_printf (stream, "%c", glyph);
+	else
+	    _cairo_output_stream_printf (stream, "\\%03o", glyph);
+    } else {
+	_cairo_output_stream_printf (stream,
+				     "%0*x",
+				     pdf_operators->hex_width,
+				     glyph);
+    }
+}
+
 #define GLYPH_POSITION_TOLERANCE 0.001
 
 /* Emit the string of glyphs using the 'Tj' operator. This requires
@@ -890,15 +910,14 @@ _cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t   *pdf_operators,
 {
     int i;
 
-    _cairo_output_stream_printf (stream, "<");
+    _cairo_output_stream_printf (stream, "%s", pdf_operators->is_latin ? "(" : "<");
     for (i = 0; i < pdf_operators->num_glyphs; i++) {
-	_cairo_output_stream_printf (stream,
-				     "%0*x",
-				     pdf_operators->hex_width,
-				     pdf_operators->glyphs[i].glyph_index);
+	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
+					       stream,
+					       pdf_operators->glyphs[i].glyph_index);
 	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
     }
-    _cairo_output_stream_printf (stream, ">Tj\n");
+    _cairo_output_stream_printf (stream, "%sTj\n", pdf_operators->is_latin ? ")" : ">");
 
     return _cairo_output_stream_get_status (stream);
 }
@@ -918,7 +937,7 @@ _cairo_pdf_operators_emit_glyph_string_with_positioning (
 {
     int i;
 
-    _cairo_output_stream_printf (stream, "[<");
+    _cairo_output_stream_printf (stream, "[%s", pdf_operators->is_latin ? "(" : "<");
     for (i = 0; i < pdf_operators->num_glyphs; i++) {
 	if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
 	{
@@ -934,10 +953,18 @@ _cairo_pdf_operators_emit_glyph_string_with_positioning (
 	     * calculating subsequent deltas.
 	     */
 	    rounded_delta = _cairo_lround (delta);
+	    if (abs(rounded_delta) < 3)
+		rounded_delta = 0;
 	    if (rounded_delta != 0) {
-		_cairo_output_stream_printf (stream,
-					     ">%d<",
-					     rounded_delta);
+		if (pdf_operators->is_latin) {
+		    _cairo_output_stream_printf (stream,
+						 ")%d(",
+						 rounded_delta);
+		} else {
+		    _cairo_output_stream_printf (stream,
+						 ">%d<",
+						 rounded_delta);
+		}
 	    }
 
 	    /* Convert the rounded delta back to text
@@ -947,13 +974,12 @@ _cairo_pdf_operators_emit_glyph_string_with_positioning (
 	    pdf_operators->cur_x += delta;
 	}
 
-	_cairo_output_stream_printf (stream,
-				     "%0*x",
-				     pdf_operators->hex_width,
-				     pdf_operators->glyphs[i].glyph_index);
+	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
+					       stream,
+					       pdf_operators->glyphs[i].glyph_index);
 	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
     }
-    _cairo_output_stream_printf (stream, ">]TJ\n");
+    _cairo_output_stream_printf (stream, "%s]TJ\n", pdf_operators->is_latin ? ")" : ">");
 
     return _cairo_output_stream_get_status (stream);
 }
@@ -1124,6 +1150,7 @@ _cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t             *pdf_ope
     }
     pdf_operators->font_id = subset_glyph->font_id;
     pdf_operators->subset_id = subset_glyph->subset_id;
+    pdf_operators->is_latin = subset_glyph->is_latin;
 
     if (subset_glyph->is_composite)
 	pdf_operators->hex_width = 4;
commit f1ca978032e973c4dc5cfa385074dea675a6c76d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:53:11 2010 +0930

    Add capability for font subsets to put latin glyphs in a separate subset
    
    This is required to allow PDF/PS output to use "(this is ascii)" style
    strings that can be post processed by applications like psfrag. It
    will also reduce the file size when a large amount of latin text is
    used due to the 8-bit encoding instead of the 16-bit used for CID
    fonts.
    
    The winansi encoding (CP1252) is used for the latin subset as this is
    a standard PDF encoding. Some PDF readers have buggy support for non
    standard PDF 8-bit encodings.

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index b165d9a..d119597 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -47,6 +47,7 @@ typedef struct _cairo_scaled_font_subsets_glyph {
     unsigned int subset_glyph_index;
     cairo_bool_t is_scaled;
     cairo_bool_t is_composite;
+    cairo_bool_t is_latin;
     double       x_advance;
     double       y_advance;
     cairo_bool_t utf8_is_mapped;
@@ -125,6 +126,18 @@ cairo_private void
 _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
 
 /**
+ * _cairo_scaled_font_subsets_enable_latin_subset:
+ * @font_subsets: a #cairo_scaled_font_subsets_t object to be destroyed
+ * @use_latin: a #cairo_bool_t indicating if a latin subset is to be used
+ *
+ * If enabled, all CP1252 characters will be placed in a separate
+ * 8-bit latin subset.
+ **/
+cairo_private void
+_cairo_scaled_font_subsets_enable_latin_subset (cairo_scaled_font_subsets_t *font_subsets,
+						cairo_bool_t                 use_latin);
+
+/**
  * _cairo_scaled_font_subsets_map_glyph:
  * @font_subsets: a #cairo_scaled_font_subsets_t
  * @scaled_font: the font of the glyph to be mapped
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 01bc05b..9d8d6c1 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -76,6 +76,7 @@ typedef struct _cairo_sub_font {
 
     int current_subset;
     int num_glyphs_in_current_subset;
+    int num_glyphs_in_latin_subset;
     int max_glyphs_per_subset;
 
     cairo_hash_table_t *sub_font_glyphs;
@@ -84,6 +85,7 @@ typedef struct _cairo_sub_font {
 
 struct _cairo_scaled_font_subsets {
     cairo_subsets_type_t type;
+    cairo_bool_t use_latin_subset;
 
     int max_glyphs_per_unscaled_subset_used;
     cairo_hash_table_t *unscaled_sub_fonts;
@@ -106,6 +108,8 @@ typedef struct _cairo_sub_font_glyph {
     double       x_advance;
     double       y_advance;
 
+    cairo_bool_t is_latin;
+    int		 latin_character;
     cairo_bool_t is_mapped;
     uint32_t     unicode;
     char  	*utf8;
@@ -159,7 +163,11 @@ _cairo_sub_font_glyph_create (unsigned long	scaled_font_glyph_index,
 			      unsigned int	subset_id,
 			      unsigned int	subset_glyph_index,
                               double            x_advance,
-                              double            y_advance)
+                              double            y_advance,
+			      int	        latin_character,
+			      uint32_t          unicode,
+			      char             *utf8,
+			      int          	utf8_len)
 {
     cairo_sub_font_glyph_t *sub_font_glyph;
 
@@ -174,10 +182,12 @@ _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_latin = (latin_character >= 0);
+    sub_font_glyph->latin_character = latin_character;
     sub_font_glyph->is_mapped = FALSE;
-    sub_font_glyph->unicode = -1;
-    sub_font_glyph->utf8 = NULL;
-    sub_font_glyph->utf8_len = 0;
+    sub_font_glyph->unicode = unicode;
+    sub_font_glyph->utf8 = utf8;
+    sub_font_glyph->utf8_len = utf8_len;
 
     return sub_font_glyph;
 }
@@ -266,8 +276,6 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
 			cairo_sub_font_t               **sub_font_out)
 {
     cairo_sub_font_t *sub_font;
-    cairo_status_t status;
-    cairo_scaled_font_subsets_glyph_t subset_glyph;
 
     sub_font = malloc (sizeof (cairo_sub_font_t));
     if (unlikely (sub_font == NULL))
@@ -282,8 +290,13 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
     sub_font->scaled_font = scaled_font;
     sub_font->font_id = font_id;
 
-    sub_font->current_subset = 0;
+    if (parent->use_latin_subset)
+	sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */
+    else
+	sub_font->current_subset = 0;
+
     sub_font->num_glyphs_in_current_subset = 0;
+    sub_font->num_glyphs_in_latin_subset = 0;
     sub_font->max_glyphs_per_subset = max_glyphs_per_subset;
 
     sub_font->sub_font_glyphs = _cairo_hash_table_create (_cairo_sub_font_glyphs_equal);
@@ -292,18 +305,6 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
     sub_font->next = NULL;
-
-    /* Reserve first glyph in subset for the .notdef glyph except for
-     * Type 3 fonts */
-    if (! is_scaled) {
-	status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &subset_glyph);
-	if (unlikely (status)) {
-	    _cairo_hash_table_destroy (sub_font->sub_font_glyphs);
-	    free (sub_font);
-	    return status;
-	}
-    }
-
     *sub_font_out = sub_font;
     return CAIRO_STATUS_SUCCESS;
 }
@@ -329,10 +330,36 @@ _cairo_sub_font_pluck (void *entry, void *closure)
     _cairo_sub_font_destroy (sub_font);
 }
 
+/* Characters 0x80 to 0x9f in the winansi encoding.
+ * All other characters in the range 0x00 to 0xff map 1:1 to unicode */
+static unsigned int _winansi_0x80_to_0x9f[] = {
+    0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
+    0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000,
+    0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+    0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178
+};
+
+static int _unicode_to_winansi (unsigned long unicode)
+{
+    int i;
+
+    if (unicode < 0x80 || (unicode >= 0xa0 && unicode <= 0xff))
+        return unicode;
+
+    for (i = 0; i < 32; i++) {
+       if (_winansi_0x80_to_0x9f[i] == unicode)
+           return i + 0x80;
+    }
+
+    return -1;
+}
+
 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)
+_cairo_sub_font_glyph_lookup_unicode (cairo_scaled_font_t    *scaled_font,
+				      unsigned long	      scaled_font_glyph_index,
+				      uint32_t     	     *unicode_out,
+				      char  		    **utf8_out,
+				      int          	     *utf8_len_out)
 {
     uint32_t unicode;
     char buf[8];
@@ -356,19 +383,19 @@ _cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
 	    return status;
     }
 
-    sub_font_glyph->unicode = unicode;
-    sub_font_glyph->utf8 = NULL;
-    sub_font_glyph->utf8_len = 0;
+    *unicode_out = unicode;
+    *utf8_out = NULL;
+    *utf8_len_out = 0;
     if (unicode != (uint32_t) -1) {
 	len = _cairo_ucs4_to_utf8 (unicode, buf);
 	if (len > 0) {
-	    sub_font_glyph->utf8 = malloc (len + 1);
-	    if (unlikely (sub_font_glyph->utf8 == NULL))
+	    *utf8_out = malloc (len + 1);
+	    if (unlikely (*utf8_out == NULL))
 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	    memcpy (sub_font_glyph->utf8, buf, len);
-	    sub_font_glyph->utf8[len] = 0;
-	    sub_font_glyph->utf8_len = len;
+	    memcpy (*utf8_out, buf, len);
+	    (*utf8_out)[len] = 0;
+	    *utf8_len_out = len;
 	}
     }
 
@@ -429,9 +456,14 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
     if (sub_font_glyph != NULL) {
         subset_glyph->font_id = sub_font->font_id;
         subset_glyph->subset_id = sub_font_glyph->subset_id;
-        subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
+	if (sub_font_glyph->is_latin)
+	    subset_glyph->subset_glyph_index = sub_font_glyph->latin_character;
+	else
+	    subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
+
         subset_glyph->is_scaled = sub_font->is_scaled;
         subset_glyph->is_composite = sub_font->is_composite;
+	subset_glyph->is_latin = sub_font_glyph->is_latin;
         subset_glyph->x_advance = sub_font_glyph->x_advance;
         subset_glyph->y_advance = sub_font_glyph->y_advance;
 	status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
@@ -446,10 +478,109 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t	                *sub_font,
 }
 
 static cairo_status_t
+_cairo_sub_font_add_glyph (cairo_sub_font_t	   *sub_font,
+			   unsigned long	    scaled_font_glyph_index,
+			   cairo_bool_t		    is_latin,
+			   int			    latin_character,
+			   uint32_t 		    unicode,
+			   char 		   *utf8,
+			   int 			    utf8_len,
+			   cairo_sub_font_glyph_t **sub_font_glyph_out)
+{
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_sub_font_glyph_t *sub_font_glyph;
+    int *num_glyphs_in_subset_ptr;
+    double x_advance;
+    double y_advance;
+    cairo_status_t status;
+
+    _cairo_scaled_font_freeze_cache (sub_font->scaled_font);
+    status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
+					 scaled_font_glyph_index,
+					 CAIRO_SCALED_GLYPH_INFO_METRICS,
+					 &scaled_glyph);
+    assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
+    if (unlikely (status)) {
+	_cairo_scaled_font_thaw_cache (sub_font->scaled_font);
+	return status;
+    }
+
+    x_advance = scaled_glyph->metrics.x_advance;
+    y_advance = scaled_glyph->metrics.y_advance;
+    _cairo_scaled_font_thaw_cache (sub_font->scaled_font);
+
+    if (unlikely (status)) {
+	_cairo_sub_font_glyph_destroy (sub_font_glyph);
+	return status;
+    }
+
+    if (!is_latin && sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
+    {
+	sub_font->current_subset++;
+	sub_font->num_glyphs_in_current_subset = 0;
+    }
+
+    if (is_latin)
+	num_glyphs_in_subset_ptr = &sub_font->num_glyphs_in_latin_subset;
+    else
+	num_glyphs_in_subset_ptr = &sub_font->num_glyphs_in_current_subset;
+
+    /* Reserve first glyph in subset for the .notdef glyph except for
+     * Type 3 fonts */
+    if (*num_glyphs_in_subset_ptr == 0 &&
+	scaled_font_glyph_index != 0 &&
+	! _cairo_font_face_is_user (sub_font->scaled_font->font_face))
+    {
+	status = _cairo_sub_font_add_glyph (sub_font,
+					    0,
+					    is_latin,
+					    0,
+					    0,
+					    NULL,
+					    -1,
+					    &sub_font_glyph);
+	if (unlikely (status))
+	    return status;
+    }
+
+    sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
+						   is_latin ? 0 : sub_font->current_subset,
+						   *num_glyphs_in_subset_ptr,
+						   x_advance,
+						   y_advance,
+						   is_latin ? latin_character : -1,
+						   unicode,
+						   utf8,
+						   utf8_len);
+
+    if (unlikely (sub_font_glyph == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
+    if (unlikely (status)) {
+	_cairo_sub_font_glyph_destroy (sub_font_glyph);
+	return status;
+    }
+
+    (*num_glyphs_in_subset_ptr)++;
+    if (sub_font->is_scaled) {
+	if (*num_glyphs_in_subset_ptr > sub_font->parent->max_glyphs_per_scaled_subset_used)
+	    sub_font->parent->max_glyphs_per_scaled_subset_used = *num_glyphs_in_subset_ptr;
+    } else {
+	if (*num_glyphs_in_subset_ptr > sub_font->parent->max_glyphs_per_unscaled_subset_used)
+	    sub_font->parent->max_glyphs_per_unscaled_subset_used = *num_glyphs_in_subset_ptr;
+    }
+
+    *sub_font_glyph_out = sub_font_glyph;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+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,
+			   const char		*text_utf8,
+			   int			 text_utf8_len,
                            cairo_scaled_font_subsets_glyph_t *subset_glyph)
 {
     cairo_sub_font_glyph_t key, *sub_font_glyph;
@@ -459,79 +590,64 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
     sub_font_glyph = _cairo_hash_table_lookup (sub_font->sub_font_glyphs,
 					       &key.base);
     if (sub_font_glyph == NULL) {
-	cairo_scaled_glyph_t *scaled_glyph;
+	uint32_t font_unicode;
+	char *font_utf8;
+	int font_utf8_len;
+	cairo_bool_t is_latin;
+	int latin_character;
+
+	status = _cairo_sub_font_glyph_lookup_unicode (sub_font->scaled_font,
+						       scaled_font_glyph_index,
+						       &font_unicode,
+						       &font_utf8,
+						       &font_utf8_len);
+	if (unlikely(status))
+	    return status;
 
-	if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
+	/* If glyph is in the winansi encoding and font is not a user
+	 * font, put glyph in the latin subset. If glyph is .notdef
+	 * the latin subset is preferred but only if the latin subset
+	 * already contains at least one glyph. We don't want to
+	 * create a separate subset just for the .notdef glyph.
+	 */
+	is_latin = FALSE;
+	if (sub_font->parent->use_latin_subset &&
+	    (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
 	{
-	    cairo_scaled_font_subsets_glyph_t tmp_subset_glyph;
-
-	    sub_font->current_subset++;
-	    sub_font->num_glyphs_in_current_subset = 0;
-
-	    /* Reserve first glyph in subset for the .notdef glyph
-	     * except for Type 3 fonts */
-	    if (! _cairo_font_face_is_user (sub_font->scaled_font->font_face)) {
-		status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, -1, &tmp_subset_glyph);
-		if (unlikely (status))
-		    return status;
+	    latin_character = _unicode_to_winansi (font_unicode);
+	    if (latin_character > 0 ||
+		(latin_character == 0 && sub_font->num_glyphs_in_latin_subset > 0))
+	    {
+		is_latin = TRUE;
 	    }
 	}
 
-	_cairo_scaled_font_freeze_cache (sub_font->scaled_font);
-        status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
-                                             scaled_font_glyph_index,
-                                             CAIRO_SCALED_GLYPH_INFO_METRICS,
-                                             &scaled_glyph);
-	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
-	if (unlikely (status)) {
-	    _cairo_scaled_font_thaw_cache (sub_font->scaled_font);
-	    return status;
-	}
-
-        sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
-						       sub_font->current_subset,
-						       sub_font->num_glyphs_in_current_subset,
-                                                       scaled_glyph->metrics.x_advance,
-                                                       scaled_glyph->metrics.y_advance);
-	_cairo_scaled_font_thaw_cache (sub_font->scaled_font);
-
-	if (unlikely (sub_font_glyph == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	status = _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
-						       sub_font->scaled_font,
-						       scaled_font_glyph_index);
-	if (unlikely (status)) {
-	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
-	    return status;
-	}
-
-	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
-	if (unlikely (status)) {
-	    _cairo_sub_font_glyph_destroy (sub_font_glyph);
+	status = _cairo_sub_font_add_glyph (sub_font,
+					    scaled_font_glyph_index,
+					    is_latin,
+					    latin_character,
+					    font_unicode,
+					    font_utf8,
+					    font_utf8_len,
+					    &sub_font_glyph);
+	if (unlikely(status))
 	    return status;
-	}
-
-	sub_font->num_glyphs_in_current_subset++;
-
-        if (sub_font->is_scaled) {
-            if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used)
-                sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset;
-        } else {
-            if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used)
-                sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset;
-        }
     }
 
     subset_glyph->font_id = sub_font->font_id;
     subset_glyph->subset_id = sub_font_glyph->subset_id;
-    subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
+    if (sub_font_glyph->is_latin)
+	subset_glyph->subset_glyph_index = sub_font_glyph->latin_character;
+    else
+	subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
+
     subset_glyph->is_scaled = sub_font->is_scaled;
     subset_glyph->is_composite = sub_font->is_composite;
+    subset_glyph->is_latin = sub_font_glyph->is_latin;
     subset_glyph->x_advance = sub_font_glyph->x_advance;
     subset_glyph->y_advance = sub_font_glyph->y_advance;
     status = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph,
-						   utf8, utf8_len,
+						   text_utf8, text_utf8_len,
 						   &subset_glyph->utf8_is_mapped);
     subset_glyph->unicode = sub_font_glyph->unicode;
 
@@ -616,6 +732,7 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
     }
 
     subsets->type = type;
+    subsets->use_latin_subset = FALSE;
     subsets->max_glyphs_per_unscaled_subset_used = 0;
     subsets->max_glyphs_per_scaled_subset_used = 0;
     subsets->num_sub_fonts = 0;
@@ -670,6 +787,13 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
     free (subsets);
 }
 
+void
+_cairo_scaled_font_subsets_enable_latin_subset (cairo_scaled_font_subsets_t *font_subsets,
+						cairo_bool_t                 use_latin)
+{
+    font_subsets->use_latin_subset = use_latin;
+}
+
 cairo_status_t
 _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
 				      cairo_scaled_font_t		*scaled_font,
commit 3f817dcfd39ffdb73ac694fd90a47d9d3a42af74
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Oct 1 17:41:28 2010 +0930

    Fix font metrics in PDF Type 1 fonts
    
    edcefa87 introduced a bug in the Type 1 font metrics in PDF files.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index d92c860..9c0a2cf 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1356,12 +1356,12 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
 	    font.glyphs[i].width;
     }
 
-    type1_subset->x_min = font.base.x_min;
-    type1_subset->y_min = font.base.y_min;
-    type1_subset->x_max = font.base.x_max;
-    type1_subset->y_max = font.base.y_max;
-    type1_subset->ascent = font.base.ascent;
-    type1_subset->descent = font.base.descent;
+    type1_subset->x_min = font.base.x_min/1000.0;
+    type1_subset->y_min = font.base.y_min/1000.0;
+    type1_subset->x_max = font.base.x_max/1000.0;
+    type1_subset->y_max = font.base.y_max/1000.0;
+    type1_subset->ascent = font.base.ascent/1000.0;
+    type1_subset->descent = font.base.descent/1000.0;
 
     length = font.base.header_size +
 	     font.base.data_size +


More information about the cairo-commit mailing list