[cairo-commit] 9 commits - src/cairo-cff-subset.c src/cairo-ft-font.c src/cairoint.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-type1-subset.c src/cairo-win32-font.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Mon Jul 18 06:09:36 PDT 2011


 src/cairo-cff-subset.c          |    2 
 src/cairo-ft-font.c             |  121 +++++++
 src/cairo-pdf-surface.c         |   14 
 src/cairo-ps-surface.c          |    4 
 src/cairo-scaled-font-subsets.c |    3 
 src/cairo-type1-subset.c        |  668 ++++++++++++++++++++++------------------
 src/cairo-win32-font.c          |   66 +++
 src/cairoint.h                  |   39 ++
 8 files changed, 610 insertions(+), 307 deletions(-)

New commits:
commit bf5892e2a6ff85e550f82c6b1fe8c0d4a0fb01f0
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 22:31:34 2011 +0930

    Add win32 font backend functions for Type 1 subsetting
    
    Native Type 1 font subsetting now works on Windows.

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 5bd5999..0aad373 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -132,6 +132,8 @@ typedef struct {
     cairo_bool_t is_bitmap;
     cairo_bool_t is_type1;
     cairo_bool_t delete_scaled_hfont;
+    cairo_bool_t has_type1_notdef_index;
+    unsigned long type1_notdef_index;
 } cairo_win32_scaled_font_t;
 
 static cairo_status_t
@@ -355,6 +357,7 @@ _win32_scaled_font_create (LOGFONTW                   *logfont,
     f->em_square = 0;
     f->scaled_hfont = NULL;
     f->unscaled_hfont = NULL;
+    f->has_type1_notdef_index = FALSE;
 
     if (f->quality == logfont->lfQuality ||
         (logfont->lfQuality == DEFAULT_QUALITY &&
@@ -1656,6 +1659,65 @@ _cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
     return FALSE;
 }
 
+static cairo_int_status_t
+_cairo_win32_scaled_font_index_to_glyph_name (void	      	*abstract_font,
+					      char             **glyph_names,
+					      int              	 num_glyph_names,
+					      unsigned long      glyph_index,
+					      unsigned long     *glyph_array_index)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    int i;
+
+    /* Windows puts .notdef at index 0 then numbers the remaining
+     * glyphs starting from 1 in the order they appear in the font. */
+
+    /* Find the position of .notdef in the list of glyph names. We
+     * only need to do this once per scaled font. */
+    if (! scaled_font->has_type1_notdef_index) {
+	for (i = 0; i < num_glyph_names; i++) {
+	    if (strcmp (glyph_names[i], ".notdef") == 0) {
+		scaled_font->type1_notdef_index = i;
+		scaled_font->has_type1_notdef_index = TRUE;
+		break;
+	    }
+	}
+	if (! scaled_font->has_type1_notdef_index)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* Once we know the position of .notdef the position of any glyph
+     * in the font can easily be obtained. */
+    if (glyph_index == 0)
+	*glyph_array_index = scaled_font->type1_notdef_index;
+    else if (glyph_index <= scaled_font->type1_notdef_index)
+	*glyph_array_index = glyph_index - 1;
+    else
+	*glyph_array_index = glyph_index;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_scaled_font_load_type1_data (void	            *abstract_font,
+					  long               offset,
+					  unsigned char     *buffer,
+					  unsigned long     *length)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+
+    if (! scaled_font->is_type1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Using the tag 0 retrieves the entire font file. This works with
+     * Type 1 fonts as well as TTF/OTF fonts. */
+    return _cairo_win32_scaled_font_load_truetype_table (scaled_font,
+							 0,
+							 offset,
+							 buffer,
+							 length);
+}
+
 static cairo_status_t
 _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
                                              cairo_scaled_glyph_t      *scaled_glyph)
@@ -1904,7 +1966,9 @@ 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_index_to_ucs4,
-    _cairo_win32_scaled_font_is_synthetic
+    _cairo_win32_scaled_font_is_synthetic,
+    _cairo_win32_scaled_font_index_to_glyph_name,
+    _cairo_win32_scaled_font_load_type1_data
 };
 
 /* #cairo_win32_font_face_t */
commit 068df654daa74cdf516657af432002471a03c161
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 22:26:43 2011 +0930

    type1-subset: Remove FT dependency part 6
    
    Remove all remaining FT dependencies from the Type1 subsetting.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 8ae1358..dbb7228 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4447,7 +4447,6 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
     return _cairo_array_append (&surface->fonts, &font);
 }
 
-#if CAIRO_HAS_FT_FONT
 static cairo_status_t
 _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
@@ -4471,7 +4470,6 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t		*surface,
     _cairo_type1_subset_fini (&subset);
     return status;
 }
-#endif
 
 static cairo_status_t
 _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t	*surface,
@@ -4983,11 +4981,9 @@ _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_s
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-#if CAIRO_HAS_FT_FONT
     status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
-#endif
 
     status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index cf6908f..72a82f3 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -339,7 +339,6 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
     }
 }
 
-#if CAIRO_HAS_FT_FONT
 static cairo_status_t
 _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t		*surface,
 					  cairo_scaled_font_subset_t	*font_subset)
@@ -371,7 +370,6 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t		*surface,
 
     return CAIRO_STATUS_SUCCESS;
 }
-#endif
 
 static cairo_status_t
 _cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t		*surface,
@@ -698,11 +696,9 @@ _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t	*font_su
     if (_cairo_status_is_error (status))
 	return status;
 
-#if CAIRO_HAS_FT_FONT
     status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
-#endif
 
     status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index ec228ca..433ca3f 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -907,10 +907,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
 		return unscaled_font->status;
 
             subset_glyph->is_scaled = FALSE;
-            type1_font = FALSE;
-#if CAIRO_HAS_FT_FONT
             type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
-#endif
             if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) {
                 max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
                 subset_glyph->is_composite = TRUE;
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 8ad3d6b..3e02656 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -49,16 +49,6 @@
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-output-stream-private.h"
 
-/* XXX: Eventually, we need to handle other font backends */
-#if CAIRO_HAS_FT_FONT
-
-#include "cairo-ft-private.h"
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_OUTLINE_H
-#include FT_TYPE1_TABLES_H
-
 #include <ctype.h>
 
 typedef struct {
@@ -72,7 +62,6 @@ typedef struct _cairo_type1_font_subset {
     cairo_scaled_font_subset_t *scaled_font_subset;
 
     struct {
-	cairo_unscaled_font_t *unscaled_font;
 	unsigned int font_id;
 	char *base_font;
 	unsigned int num_glyphs;
@@ -86,7 +75,6 @@ typedef struct _cairo_type1_font_subset {
 	unsigned long  trailer_size;
     } base;
 
-    FT_Face face;
     int num_glyphs;
 
     /* The glyphs and glyph_names arrays are indexed by the order of
@@ -133,37 +121,11 @@ 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;
-    cairo_status_t status;
-    FT_Face face;
-    PS_FontInfoRec font_info;
-
-    ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
-
-    face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
-    if (unlikely (face == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    if (FT_Get_PS_Font_Info(face, &font_info) != 0) {
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
-        goto fail1;
-    }
-
-    /* OpenType/CFF fonts also have a PS_FontInfoRec */
-#if HAVE_FT_LOAD_SFNT_TABLE
-    if (FT_IS_SFNT (face)) {
-	status = CAIRO_INT_STATUS_UNSUPPORTED;
-        goto fail1;
-    }
-#endif
-
     memset (font, 0, sizeof (*font));
     font->scaled_font_subset = scaled_font_subset;
-    font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
 
     _cairo_array_init (&font->glyphs_array, sizeof (glyph_data_t));
     _cairo_array_init (&font->glyph_names_array, sizeof (char *));
@@ -175,15 +137,7 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 
     _cairo_array_init (&font->contents, sizeof (char));
 
-    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
-
     return CAIRO_STATUS_SUCCESS;
-
-    _cairo_unscaled_font_destroy (unscaled_font);
- fail1:
-    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
-
-    return status;
 }
 
 static void
@@ -1196,13 +1150,26 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_bool_t
+check_fontdata_is_type1 (const unsigned char *data, long length)
+{
+    /* Test for  Type 1 Binary (PFB) */
+    if (length > 2 && data[0] == 0x80 && data[1] == 0x01)
+	return TRUE;
+
+    /* Test for Type 1 1 ASCII (PFA) */
+    if (length > 2 && data[0] == '%' && data[1] == '!')
+	return TRUE;
+
+    return FALSE;
+}
+
 static cairo_status_t
 cairo_type1_font_subset_generate (void       *abstract_font,
 				  const char *name)
 
 {
     cairo_type1_font_subset_t *font = abstract_font;
-    cairo_ft_unscaled_font_t *ft_unscaled_font;
     cairo_scaled_font_t *scaled_font;
     cairo_status_t status;
     unsigned long data_length;
@@ -1226,6 +1193,9 @@ cairo_type1_font_subset_generate (void       *abstract_font,
     if (unlikely (status))
         return status;
 
+    if (!check_fontdata_is_type1 ((unsigned char *)font->type1_data, data_length))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     status = _cairo_array_grow_by (&font->contents, 4096);
     if (unlikely (status))
 	return status;
@@ -1264,8 +1234,6 @@ _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
     _cairo_array_fini (&font->glyph_names_array);
     _cairo_array_fini (&font->glyphs_array);
 
-    _cairo_unscaled_font_destroy (font->base.unscaled_font);
-
     if (font->output != NULL)
 	status = _cairo_output_stream_destroy (font->output);
 
@@ -1288,24 +1256,14 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
     cairo_status_t status, status_ignored;
     unsigned long length;
     unsigned int i;
-    cairo_unscaled_font_t *unscaled_font;
     char buf[30];
 
-    /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
-    if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
     /* We need to use a fallback font generated from the synthesized outlines. */
     if (scaled_font_subset->scaled_font->backend->is_synthetic &&
 	scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
-
-    status = _cairo_type1_font_subset_init (&font, unscaled_font, scaled_font_subset, hex_encode);
+    status = _cairo_type1_font_subset_init (&font, scaled_font_subset, hex_encode);
     if (unlikely (status))
 	return status;
 
@@ -1377,32 +1335,26 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
 cairo_bool_t
 _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
 {
-    cairo_ft_unscaled_font_t *unscaled;
-    FT_Face face;
-    PS_FontInfoRec font_info;
-    cairo_bool_t is_type1 = FALSE;
-
-    if (!_cairo_scaled_font_is_ft (scaled_font))
-       return FALSE;
-    unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
-    face = _cairo_ft_unscaled_font_lock_face (unscaled);
-    if (!face)
-        return FALSE;
-
-    if (FT_Get_PS_Font_Info(face, &font_info) == 0)
-        is_type1 = TRUE;
-
-    /* OpenType/CFF fonts also have a PS_FontInfoRec */
-#if HAVE_FT_LOAD_SFNT_TABLE
-    if (FT_IS_SFNT (face))
-        is_type1 = FALSE;
-#endif
-
-    _cairo_ft_unscaled_font_unlock_face (unscaled);
-
-    return is_type1;
-}
+    cairo_status_t status;
+    unsigned long length;
+    unsigned char buf[64];
+
+    if (!scaled_font->backend->load_type1_data)
+	return FALSE;
+
+    status = scaled_font->backend->load_type1_data (scaled_font, 0, NULL, &length);
+    if (status)
+	return FALSE;
+
+    /* We only need a few bytes to test for Type 1 */
+    if (length > sizeof (buf))
+	length = sizeof (buf);
 
-#endif /* CAIRO_HAS_FT_FONT */
+    status = scaled_font->backend->load_type1_data (scaled_font, 0, buf, &length);
+    if (status)
+	return FALSE;
+
+    return check_fontdata_is_type1 (buf, length);
+}
 
 #endif /* CAIRO_HAS_FONT_SUBSET */
commit 895dfc628a3c77ecfc0d81b9cc7bc261ed1e9031
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 22:23:21 2011 +0930

    type1-subset: Remove FT dependency part 5
    
    Add a font backend function, load_type1_data, for loading Type 1 font
    data. Replace the FT code for loading the font with a call
    load_type1_data.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 4c924de..6389200 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -54,6 +54,7 @@
 #include FT_OUTLINE_H
 #include FT_IMAGE_H
 #include FT_TRUETYPE_TABLES_H
+#include FT_XFREE86_H
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
 #include FT_SYNTHESIS_H
 #endif
@@ -2497,6 +2498,64 @@ _cairo_index_to_glyph_name (void	         *abstract_font,
     return CAIRO_INT_STATUS_UNSUPPORTED;
 }
 
+static cairo_int_status_t
+_cairo_ft_load_type1_data (void	            *abstract_font,
+			   long              offset,
+			   unsigned char    *buffer,
+			   unsigned long    *length)
+{
+    cairo_ft_scaled_font_t *scaled_font = abstract_font;
+    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+    FT_Face face;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    unsigned long available_length;
+    unsigned long ret;
+    const char *font_format;
+
+    assert (length != NULL);
+
+    if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    face = _cairo_ft_unscaled_font_lock_face (unscaled);
+    if (!face)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    font_format = FT_Get_X11_Font_Format (face);
+    if (!(font_format && strcmp (font_format, "Type 1") == 0)) {
+        status = CAIRO_INT_STATUS_UNSUPPORTED;
+	goto unlock;
+    }
+
+    available_length = MAX (face->stream->size - offset, 0);
+    if (!buffer) {
+	*length = available_length;
+    } else {
+	if (*length > available_length) {
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
+	} else if (face->stream->read != NULL) {
+	    /* Note that read() may be implemented as a macro, thanks POSIX!, so we
+	     * need to wrap the following usage in parentheses in order to
+	     * disambiguate it for the pre-processor - using the verbose function
+	     * pointer dereference for clarity.
+	     */
+	    ret = (* face->stream->read) (face->stream,
+					  offset,
+					  buffer,
+					  *length);
+	    if (ret != *length)
+		status = _cairo_error (CAIRO_STATUS_READ_ERROR);
+	} else {
+	    memcpy (buffer, face->stream->base + offset, *length);
+	}
+    }
+
+  unlock:
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+    return status;
+}
+
 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_fini,
@@ -2507,7 +2566,8 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     _cairo_ft_load_truetype_table,
     _cairo_ft_index_to_ucs4,
     _cairo_ft_is_synthetic,
-    _cairo_index_to_glyph_name
+    _cairo_index_to_glyph_name,
+    _cairo_ft_load_type1_data
 };
 
 /* #cairo_ft_font_face_t */
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 9812970..8ad3d6b 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1203,40 +1203,28 @@ cairo_type1_font_subset_generate (void       *abstract_font,
 {
     cairo_type1_font_subset_t *font = abstract_font;
     cairo_ft_unscaled_font_t *ft_unscaled_font;
-    unsigned long ret;
+    cairo_scaled_font_t *scaled_font;
     cairo_status_t status;
+    unsigned long data_length;
 
-    ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
-    font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
-    if (unlikely (font->face == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    scaled_font = font->scaled_font_subset->scaled_font;
+    if (!scaled_font->backend->load_type1_data)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    font->type1_length = font->face->stream->size;
-    font->type1_data = malloc (font->type1_length);
-    if (unlikely (font->type1_data == NULL)) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail;
-    }
+    status = scaled_font->backend->load_type1_data (scaled_font, 0, NULL, &data_length);
+    if (status)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (font->face->stream->read != NULL) {
-	/* Note that read() may be implemented as a macro, thanks POSIX!, so we
-	 * need to wrap the following usage in parentheses in order to
-	 * disambiguate it for the pre-processor - using the verbose function
-	 * pointer dereference for clarity.
-	 */
-	ret = (* font->face->stream->read) (font->face->stream, 0,
-					    (unsigned char *) font->type1_data,
-					    font->type1_length);
-	if (ret != font->type1_length) {
-	    status = _cairo_error (CAIRO_STATUS_READ_ERROR);
-	    goto fail;
-	}
-    } else {
-	memcpy (font->type1_data,
-		font->face->stream->base, font->type1_length);
-    }
+    font->type1_length = data_length;
+    font->type1_data = malloc (font->type1_length);
+    if (unlikely (font->type1_data == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
+    status = scaled_font->backend->load_type1_data (scaled_font, 0,
+						    (unsigned char *) font->type1_data,
+						    &data_length);
+    if (unlikely (status))
+        return status;
 
     status = _cairo_array_grow_by (&font->contents, 4096);
     if (unlikely (status))
@@ -1253,11 +1241,6 @@ cairo_type1_font_subset_generate (void       *abstract_font,
     font->base.data = _cairo_array_index (&font->contents, 0);
 
     return status;
-
- fail:
-    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
-
-    return status;
 }
 
 static cairo_status_t
diff --git a/src/cairoint.h b/src/cairoint.h
index dc16a7c..0ae2051 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -565,6 +565,26 @@ struct _cairo_scaled_font_backend {
 			   int                   num_glyph_names,
 			   unsigned long         glyph_index,
 			   unsigned long        *glyph_array_index);
+
+    /* Read data from a PostScript font.
+     * @scaled_font: font
+     * @offset: offset into the table
+     * @buffer: buffer to write data into. Caller must ensure there is sufficient space.
+     *          If NULL, return the size of the table in @length.
+     * @length: If @buffer is NULL, the size of the table will be returned in @length.
+     *          If @buffer is not null, @length specifies the number of bytes to read.
+     *
+     * If less than @length bytes are available to read this function
+     * returns CAIRO_INT_STATUS_UNSUPPORTED. If an error occurs the
+     * output value of @length is undefined.
+     *
+     * Returns CAIRO_INT_STATUS_UNSUPPORTED if not a Type 1 font.
+     */
+    cairo_warn cairo_int_status_t
+    (*load_type1_data)    (void		        *scaled_font,
+                           long                  offset,
+                           unsigned char        *buffer,
+                           unsigned long        *length);
 };
 
 struct _cairo_font_face_backend {
commit a94644f1774a67741686b6ff50cd4b4607d423f2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 22:18:22 2011 +0930

    type1-subset: Remove FT dependency part 4
    
    Remove the dependency on FT for getting the font name.
    
    The font name is obtained directly from the font.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index e8d6d46..9812970 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -141,7 +141,6 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
     cairo_status_t status;
     FT_Face face;
     PS_FontInfoRec font_info;
-    int i, j;
 
     ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
 
@@ -166,20 +165,6 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
     font->scaled_font_subset = scaled_font_subset;
     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
 
-    if (face->family_name) {
-	font->base.base_font = strdup (face->family_name);
-	if (unlikely (font->base.base_font == NULL)) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto fail2;
-	}
-	for (i = 0, j = 0; font->base.base_font[j]; j++) {
-	    if (font->base.base_font[j] == ' ')
-		continue;
-	    font->base.base_font[i++] = font->base.base_font[j];
-	}
-	font->base.base_font[i] = '\0';
-    }
-
     _cairo_array_init (&font->glyphs_array, sizeof (glyph_data_t));
     _cairo_array_init (&font->glyph_names_array, sizeof (char *));
     font->subset_index_to_glyphs = NULL;
@@ -194,7 +179,6 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 
     return CAIRO_STATUS_SUCCESS;
 
- fail2:
     _cairo_unscaled_font_destroy (unscaled_font);
  fail1:
     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
@@ -410,6 +394,50 @@ cairo_type1_font_subset_get_bbox (cairo_type1_font_subset_t *font)
 }
 
 static cairo_status_t
+cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
+{
+    const char *start, *end, *segment_end;
+    char *s;
+
+    segment_end = font->header_segment + font->header_segment_size;
+    start = find_token (font->header_segment, segment_end, "/FontName");
+    if (start == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    start += strlen ("/FontName");
+
+    end = find_token (start, segment_end, "def");
+    if (end == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    s = malloc (end - start + 1);
+    if (unlikely (s == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    strncpy (s, start, end - start);
+    s[end - start] = 0;
+
+    start = strchr (s, '/');
+    if (!start++ || !start) {
+	free (s);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    font->base.base_font = strdup (start);
+    free (s);
+    if (unlikely (font->base.base_font == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    s = font->base.base_font;
+    while (*s && !is_ps_delimiter(*s))
+	s++;
+
+    *s = 0;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
 					 const char *name)
 {
@@ -1146,6 +1174,10 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
     if (unlikely (status))
 	return status;
 
+    status = cairo_type1_font_subset_get_fontname (font);
+    if (unlikely (status))
+	return status;
+
     status = cairo_type1_font_subset_write_private_dict (font, name);
     if (unlikely (status))
 	return status;
commit 549acc4beb59be9ad05a1d61d6a2ec3a42e2f879
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 22:16:07 2011 +0930

    type1-subset: Remove FT dependency part 3
    
    Remove the dependency on FT for getting the bbox and EM size.
    
    The FontBBox and FontMatrix in the font file are parsed to obtain this data.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 9eb9209..e8d6d46 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -165,13 +165,6 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
     memset (font, 0, sizeof (*font));
     font->scaled_font_subset = scaled_font_subset;
     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
-    font->base.x_min = face->bbox.xMin / (double)face->units_per_EM;
-    font->base.y_min = face->bbox.yMin / (double)face->units_per_EM;
-    font->base.x_max = face->bbox.xMax / (double)face->units_per_EM;
-    font->base.y_max = face->bbox.yMax / (double)face->units_per_EM;
-    font->base.ascent = face->ascender / (double)face->units_per_EM;
-    font->base.descent = face->descender / (double)face->units_per_EM;
-    font->base.units_per_em = face->units_per_EM;
 
     if (face->family_name) {
 	font->base.base_font = strdup (face->family_name);
@@ -334,6 +327,89 @@ cairo_type1_font_erase_dict_key (cairo_type1_font_subset_t *font,
 }
 
 static cairo_status_t
+cairo_type1_font_subset_get_matrix (cairo_type1_font_subset_t *font,
+				    const char                *name,
+				    double                    *a,
+				    double                    *b,
+				    double                    *c,
+				    double                    *d)
+{
+    const char *start, *end, *segment_end;
+    int ret;
+    char *s;
+
+    segment_end = font->header_segment + font->header_segment_size;
+    start = find_token (font->header_segment, segment_end, name);
+    if (start == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    end = find_token (start, segment_end, "def");
+    if (end == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    s = malloc (end - start + 1);
+    if (unlikely (s == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    strncpy (s, start, end - start);
+    s[end - start] = 0;
+
+    start = strpbrk (s, "{[");
+    if (!start) {
+	free (s);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    start++;
+    ret = 0;
+    if (*start)
+	ret = sscanf(start, "%lf %lf %lf %lf", a, b, c, d);
+
+    free (s);
+
+    if (ret != 4)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+cairo_type1_font_subset_get_bbox (cairo_type1_font_subset_t *font)
+{
+    cairo_status_t status;
+    double x_min, y_min, x_max, y_max;
+    double xx, yx, xy, yy;
+
+    status = cairo_type1_font_subset_get_matrix (font, "/FontBBox",
+						 &x_min,
+						 &y_min,
+						 &x_max,
+						 &y_max);
+    if (unlikely (status))
+	return status;
+
+    status = cairo_type1_font_subset_get_matrix (font, "/FontMatrix",
+						 &xx, &yx, &xy, &yy);
+    if (unlikely (status))
+	return status;
+
+    if (yy == 0.0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Freetype uses 1/yy to get units per EM */
+    font->base.units_per_em = 1.0/yy;
+
+    font->base.x_min = x_min / font->base.units_per_em;
+    font->base.y_min = y_min / font->base.units_per_em;
+    font->base.x_max = x_max / font->base.units_per_em;
+    font->base.y_max = y_max / font->base.units_per_em;
+    font->base.ascent = font->base.y_max;
+    font->base.descent = font->base.y_min;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
 					 const char *name)
 {
@@ -1066,6 +1142,10 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
     font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
     font->hex_column = 0;
 
+    status = cairo_type1_font_subset_get_bbox (font);
+    if (unlikely (status))
+	return status;
+
     status = cairo_type1_font_subset_write_private_dict (font, name);
     if (unlikely (status))
 	return status;
commit b83fcf7d52720105a143b057aa56c4a04f827d17
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 22:12:06 2011 +0930

    type1-subset: Remove FT dependency part 2
    
    Remove the dependency on getting the number of glyphs in the font from
    FT. The number of glyphs is instead obtained by counting the
    charstrings.
    
    Some fixed size malloced data is replaced with cairo_array_t so they
    can be populated before we know the number of glyphs.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 88ea823..9eb9209 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -61,6 +61,13 @@
 
 #include <ctype.h>
 
+typedef struct {
+    int subset_index;
+    double width;
+    const char *encrypted_charstring;
+    int encrypted_charstring_length;
+} glyph_data_t;
+
 typedef struct _cairo_type1_font_subset {
     cairo_scaled_font_subset_t *scaled_font_subset;
 
@@ -88,13 +95,10 @@ typedef struct _cairo_type1_font_subset {
      * function is used to map the glyph index to the glyph order in
      * the Charstrings. */
 
-    struct {
-	int subset_index;
-	double width;
-	const char *encrypted_charstring;
-	int encrypted_charstring_length;
-    } *glyphs;
+    glyph_data_t *glyphs;
     char **glyph_names;
+    cairo_array_t glyphs_array;
+    cairo_array_t glyph_names_array;
 
     /* Indexed by subset_index this maps to the glyph order in the
      * glyph_names and glyphs arrays. Has font->num_golyphs
@@ -161,7 +165,6 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
     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 / (double)face->units_per_EM;
     font->base.y_min = face->bbox.yMin / (double)face->units_per_EM;
     font->base.x_max = face->bbox.xMax / (double)face->units_per_EM;
@@ -184,28 +187,13 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 	font->base.base_font[i] = '\0';
     }
 
-    font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
-    if (unlikely (font->glyphs == NULL)) {
-        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail3;
-    }
-
-    font->glyph_names = calloc (face->num_glyphs, sizeof font->glyph_names[0]);
-    if (unlikely (font->glyph_names == NULL)) {
-        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail4;
-    }
-
-    font->subset_index_to_glyphs = calloc (face->num_glyphs, sizeof font->subset_index_to_glyphs[0]);
-    if (unlikely (font->subset_index_to_glyphs == NULL)) {
-        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto fail5;
-    }
+    _cairo_array_init (&font->glyphs_array, sizeof (glyph_data_t));
+    _cairo_array_init (&font->glyph_names_array, sizeof (char *));
+    font->subset_index_to_glyphs = NULL;
+    font->base.num_glyphs = 0;
 
     font->hex_encode = hex_encode;
     font->num_glyphs = 0;
-    for (i = 0; i < face->num_glyphs; i++)
-	font->glyphs[i].subset_index = -1;
 
     _cairo_array_init (&font->contents, sizeof (char));
 
@@ -213,15 +201,6 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 
     return CAIRO_STATUS_SUCCESS;
 
- fail5:
-    if (font->glyph_names)
-	free (font->glyph_names);
- fail4:
-    if (font->glyphs)
-	free (font->glyphs);
- fail3:
-    if (font->base.base_font)
-	free (font->base.base_font);
  fail2:
     _cairo_unscaled_font_destroy (unscaled_font);
  fail1:
@@ -651,17 +630,28 @@ cairo_type1_font_subset_build_glyph_list (cairo_type1_font_subset_t *font,
 					  const char *name, int name_length,
 					  const char *encrypted_charstring, int encrypted_charstring_length)
 {
-    font->glyph_names[glyph_number] = malloc (name_length + 1);
-    if (unlikely (font->glyph_names[glyph_number] == NULL))
+    char *s;
+    glyph_data_t glyph;
+    cairo_status_t status;
+
+    s = malloc (name_length + 1);
+    if (unlikely (s == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    strncpy (font->glyph_names[glyph_number], name, name_length);
-    font->glyph_names[glyph_number][name_length] = 0;
+    strncpy (s, name, name_length);
+    s[name_length] = 0;
 
-    font->glyphs[glyph_number].encrypted_charstring = encrypted_charstring;
-    font->glyphs[glyph_number].encrypted_charstring_length = encrypted_charstring_length;
+    status = _cairo_array_append (&font->glyph_names_array, &s);
+    if (unlikely (status))
+	return status;
 
-    return CAIRO_STATUS_SUCCESS;
+    glyph.subset_index = -1;
+    glyph.width = 0;
+    glyph.encrypted_charstring = encrypted_charstring;
+    glyph.encrypted_charstring_length = encrypted_charstring_length;
+    status = _cairo_array_append (&font->glyphs_array, &glyph);
+
+    return status;
 }
 
 
@@ -906,6 +896,15 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
 						     font->cleartext_end,
 						     cairo_type1_font_subset_build_glyph_list,
 						     &p);
+    if (unlikely(status))
+	return status;
+
+    font->glyphs = _cairo_array_index (&font->glyphs_array, 0);
+    font->glyph_names = _cairo_array_index (&font->glyph_names_array, 0);
+    font->base.num_glyphs = _cairo_array_num_elements (&font->glyphs_array);
+    font->subset_index_to_glyphs = calloc (font->base.num_glyphs, sizeof font->subset_index_to_glyphs[0]);
+    if (unlikely (font->subset_index_to_glyphs == NULL))
+        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     backend = font->scaled_font_subset->scaled_font->backend;
     if (!backend->index_to_glyph_name)
@@ -1161,12 +1160,14 @@ _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
     _cairo_array_fini (&font->contents);
 
     free (font->type1_data);
-    if (font->glyph_names != NULL) {
-	for (i = 0; i < font->base.num_glyphs; i++)
-	    free (font->glyph_names[i]);
+    for (i = 0; i < _cairo_array_num_elements (&font->glyph_names_array); i++) {
+	char **s;
 
-	free (font->glyph_names);
+	s = _cairo_array_index (&font->glyph_names_array, i);
+	free (*s);
     }
+    _cairo_array_fini (&font->glyph_names_array);
+    _cairo_array_fini (&font->glyphs_array);
 
     _cairo_unscaled_font_destroy (font->base.unscaled_font);
 
@@ -1176,8 +1177,8 @@ _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
     if (font->base.base_font)
 	free (font->base.base_font);
 
-    free (font->glyphs);
-    free (font->subset_index_to_glyphs);
+    if (font->subset_index_to_glyphs)
+	free (font->subset_index_to_glyphs);
 
     return status;
 }
commit d46df1dffbb151bee6d2709664c7888e5fc5dd3c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 21:55:37 2011 +0930

    type1-subset: Remove FT dependency part 1
    
    Remove cairo_type1_font_subset_get_glyph_names_and_widths().
    
    The glyph names are read from the font file instead of via FT. The
    charstrings are parsed to extract the glyph widths.
    
    A new font backend function, index_to_glyph_name, has been added for
    obtaining the glyph name for a given glyph index. This function is
    supplied with the array of glyph names and a glyph index and is
    required to return the array index of the glyph name corresponding to
    the glyph index.
    
    The reason for passing in the array of glyph names is that:
    
    1) On windows there is no API for accessing glyph names so we will
    use knowledge of how the glyphs in a Type 1 font are numbered to
    perform name lookup.
    
    2) We can also use knowledge of how FT assigns the glyph numbers in a
    Type 1 font to optimize the name lookup.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index d007fd2..4c924de 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2439,6 +2439,64 @@ _cairo_ft_is_synthetic (void	        *abstract_font)
 	return FALSE;
 }
 
+static cairo_int_status_t
+_cairo_index_to_glyph_name (void	         *abstract_font,
+			    char                **glyph_names,
+			    int                   num_glyph_names,
+			    unsigned long         glyph_index,
+			    unsigned long        *glyph_array_index)
+{
+    cairo_ft_scaled_font_t *scaled_font = abstract_font;
+    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+    FT_Face face;
+    char buffer[256]; /* PLRM spcifies max name length of 127 */
+    FT_Error error;
+    int i;
+
+    face = _cairo_ft_unscaled_font_lock_face (unscaled);
+    if (!face)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    error = FT_Get_Glyph_Name (face, glyph_index, buffer, sizeof buffer);
+
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+    if (error != FT_Err_Ok) {
+	/* propagate fatal errors from FreeType */
+	if (error == FT_Err_Out_Of_Memory)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* FT first numbers the glyphs in the order they are read from the
+     * Type 1 font. Then if .notdef is not the first glyph, the first
+     * glyph is swapped with .notdef to ensure that .notdef is at
+     * glyph index 0.
+     *
+     * As all but two glyphs in glyph_names already have the same
+     * index as the FT glyph index, we first check if
+     * glyph_names[glyph_index] is the name we are looking for. If not
+     * we fall back to searching the entire array.
+     */
+
+    if (strcmp (glyph_names[glyph_index], buffer) == 0) {
+	*glyph_array_index = glyph_index;
+
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    for (i = 0; i < num_glyph_names; i++) {
+	if (strcmp (glyph_names[i], buffer) == 0) {
+	    *glyph_array_index = i;
+
+	    return CAIRO_STATUS_SUCCESS;
+	}
+    }
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_fini,
@@ -2448,7 +2506,8 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     NULL,			/* show_glyphs */
     _cairo_ft_load_truetype_table,
     _cairo_ft_index_to_ucs4,
-    _cairo_ft_is_synthetic
+    _cairo_ft_is_synthetic,
+    _cairo_index_to_glyph_name
 };
 
 /* #cairo_ft_font_face_t */
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 082526d..88ea823 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -71,6 +71,7 @@ typedef struct _cairo_type1_font_subset {
 	unsigned int num_glyphs;
 	double x_min, y_min, x_max, y_max;
 	double ascent, descent;
+	double units_per_em;
 
 	const char    *data;
 	unsigned long  header_size;
@@ -81,11 +82,24 @@ typedef struct _cairo_type1_font_subset {
     FT_Face face;
     int num_glyphs;
 
+    /* The glyphs and glyph_names arrays are indexed by the order of
+     * the Charstrings in the font. This is not necessarily the same
+     * order as the glyph index. The index_to_glyph_name() font backend
+     * function is used to map the glyph index to the glyph order in
+     * the Charstrings. */
+
     struct {
 	int subset_index;
 	double width;
-	char *name;
+	const char *encrypted_charstring;
+	int encrypted_charstring_length;
     } *glyphs;
+    char **glyph_names;
+
+    /* Indexed by subset_index this maps to the glyph order in the
+     * glyph_names and glyphs arrays. Has font->num_golyphs
+     * elements. */
+    int *subset_index_to_glyphs;
 
     cairo_output_stream_t *output;
     cairo_array_t contents;
@@ -154,6 +168,7 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
     font->base.y_max = face->bbox.yMax / (double)face->units_per_EM;
     font->base.ascent = face->ascender / (double)face->units_per_EM;
     font->base.descent = face->descender / (double)face->units_per_EM;
+    font->base.units_per_em = face->units_per_EM;
 
     if (face->family_name) {
 	font->base.base_font = strdup (face->family_name);
@@ -175,6 +190,18 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 	goto fail3;
     }
 
+    font->glyph_names = calloc (face->num_glyphs, sizeof font->glyph_names[0]);
+    if (unlikely (font->glyph_names == NULL)) {
+        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto fail4;
+    }
+
+    font->subset_index_to_glyphs = calloc (face->num_glyphs, sizeof font->subset_index_to_glyphs[0]);
+    if (unlikely (font->subset_index_to_glyphs == NULL)) {
+        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto fail5;
+    }
+
     font->hex_encode = hex_encode;
     font->num_glyphs = 0;
     for (i = 0; i < face->num_glyphs; i++)
@@ -186,6 +213,12 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t  *font,
 
     return CAIRO_STATUS_SUCCESS;
 
+ fail5:
+    if (font->glyph_names)
+	free (font->glyph_names);
+ fail4:
+    if (font->glyphs)
+	free (font->glyphs);
  fail3:
     if (font->base.base_font)
 	free (font->base.base_font);
@@ -203,7 +236,9 @@ cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
     if (font->glyphs[glyph].subset_index >= 0)
 	return;
 
-    font->glyphs[glyph].subset_index = font->num_glyphs++;
+    font->glyphs[glyph].subset_index = font->num_glyphs;
+    font->subset_index_to_glyphs[font->num_glyphs] = glyph;
+    font->num_glyphs++;
 }
 
 static cairo_bool_t
@@ -396,13 +431,13 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
     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];
+	    int glyph_num = font->subset_index_to_glyphs[subset_glyph];
 
 	    if (subset_glyph > 0) {
 		_cairo_output_stream_printf (font->output,
 					     "dup %d /%s put\n",
 					     i,
-					     font->glyphs[parent_glyph].name);
+					     font->glyph_names[glyph_num]);
 	    }
 	}
     } else {
@@ -412,7 +447,7 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
 	    _cairo_output_stream_printf (font->output,
 					 "dup %d /%s put\n",
 					 font->glyphs[i].subset_index,
-					 font->glyphs[i].name);
+					 font->glyph_names[i]);
 	}
     }
     _cairo_output_stream_printf (font->output, "readonly def");
@@ -547,64 +582,6 @@ skip_token (const char *p, const char *end)
     return p;
 }
 
-static int
-cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font,
-				      const char *glyph_name, int length)
-{
-    unsigned int i;
-
-    for (i = 0; i < font->base.num_glyphs; i++) {
-	if (font->glyphs[i].name &&
-	    strncmp (font->glyphs[i].name, glyph_name, length) == 0 &&
-	    font->glyphs[i].name[length] == '\0')
-	    return i;
-    }
-
-    return -1;
-}
-
-static cairo_status_t
-cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font)
-{
-    unsigned int i;
-    char buffer[256];
-    FT_Error error;
-
-    /* Get glyph names and width using the freetype API */
-    for (i = 0; i < font->base.num_glyphs; i++) {
-	if (font->glyphs[i].name != NULL)
-	    continue;
-
-	error = FT_Load_Glyph (font->face, i,
-			       FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING |
-			       FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
-	if (error != FT_Err_Ok) {
-	    /* propagate fatal errors from FreeType */
-	    if (error == FT_Err_Out_Of_Memory)
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-
-	font->glyphs[i].width = font->face->glyph->metrics.horiAdvance / (double)font->face->units_per_EM;
-
-	error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);
-	if (error != FT_Err_Ok) {
-	    /* propagate fatal errors from FreeType */
-	    if (error == FT_Err_Out_Of_Memory)
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-
-	font->glyphs[i].name = strdup (buffer);
-	if (unlikely (font->glyphs[i].name == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static void
 cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out)
 {
@@ -642,6 +619,7 @@ static cairo_status_t
 use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
 {
     const char *glyph_name;
+    unsigned int i;
 
     if (index < 0 || index > 255)
 	return CAIRO_STATUS_SUCCESS;
@@ -650,24 +628,46 @@ use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
     if (glyph_name == NULL)
 	return CAIRO_STATUS_SUCCESS;
 
-    index = cairo_type1_font_subset_lookup_glyph (font,
-						  glyph_name,
-						  strlen(glyph_name));
-    if (index < 0)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    for (i = 0; i < font->base.num_glyphs; i++) {
+	if (font->glyph_names[i] &&  strcmp (font->glyph_names[i], glyph_name) == 0) {
+	    cairo_type1_font_subset_use_glyph (font, i);
+
+	    return CAIRO_STATUS_SUCCESS;
+	}
+    }
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+#define TYPE1_CHARSTRING_COMMAND_ESCAPE		0x0c
+#define TYPE1_CHARSTRING_COMMAND_SEAC		0x0c06
+#define TYPE1_CHARSTRING_COMMAND_SBW		0x0c07
+#define TYPE1_CHARSTRING_COMMAND_HSBW		0x0d
 
-    cairo_type1_font_subset_use_glyph (font, index);
+
+static cairo_status_t
+cairo_type1_font_subset_build_glyph_list (cairo_type1_font_subset_t *font,
+					  int glyph_number,
+					  const char *name, int name_length,
+					  const char *encrypted_charstring, int encrypted_charstring_length)
+{
+    font->glyph_names[glyph_number] = malloc (name_length + 1);
+    if (unlikely (font->glyph_names[glyph_number] == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    strncpy (font->glyph_names[glyph_number], name, name_length);
+    font->glyph_names[glyph_number][name_length] = 0;
+
+    font->glyphs[glyph_number].encrypted_charstring = encrypted_charstring;
+    font->glyphs[glyph_number].encrypted_charstring_length = encrypted_charstring_length;
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-#define TYPE1_CHARSTRING_COMMAND_ESCAPE		(12)
-#define TYPE1_CHARSTRING_COMMAND_SEAC		(32 + 6)
 
+/* Get glyph width and look for seac operatorParse charstring */
 static cairo_status_t
-cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
-				      const char *name, int name_length,
-				      const char *encrypted_charstring, int encrypted_charstring_length)
+cairo_type1_font_subset_parse_charstring(cairo_type1_font_subset_t *font, int glyph)
 {
     cairo_status_t status;
     unsigned char *charstring;
@@ -675,6 +675,11 @@ cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
     const unsigned char *p;
     int stack[5], sp, value;
     int command;
+    const char *encrypted_charstring;
+    int encrypted_charstring_length;
+
+    encrypted_charstring = font->glyphs[glyph].encrypted_charstring;
+    encrypted_charstring_length = font->glyphs[glyph].encrypted_charstring_length;
 
     charstring = malloc (encrypted_charstring_length);
     if (unlikely (charstring == NULL))
@@ -692,32 +697,42 @@ cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
     while (p < end) {
         if (*p < 32) {
 	    command = *p++;
-
-	    if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE)
-		command = 32 + *p++;
-
 	    switch (command) {
-	    case TYPE1_CHARSTRING_COMMAND_SEAC:
-		/* The seac command takes five integer arguments.  The
-		 * last two are glyph indices into the PS standard
-		 * encoding give the names of the glyphs that this
-		 * glyph is composed from.  All we need to do is to
-		 * make sure those glyphs are present in the subset
-		 * under their standard names. */
-		status = use_standard_encoding_glyph (font, stack[3]);
-		if (unlikely (status))
-		    return status;
-
-		status = use_standard_encoding_glyph (font, stack[4]);
-		if (unlikely (status))
-		    return status;
-
-		sp = 0;
-		break;
-
-	    default:
-		sp = 0;
-		break;
+		case TYPE1_CHARSTRING_COMMAND_HSBW:
+		    font->glyphs[glyph].width = stack[1]/font->base.units_per_em;
+		    sp = 0;
+		    break;
+
+		case TYPE1_CHARSTRING_COMMAND_ESCAPE:
+		    command = command << 8 | *p++;
+		    switch (command) {
+			case TYPE1_CHARSTRING_COMMAND_SEAC:
+			    /* The seac command takes five integer arguments.  The
+			     * last two are glyph indices into the PS standard
+			     * encoding give the names of the glyphs that this
+			     * glyph is composed from.  All we need to do is to
+			     * make sure those glyphs are present in the subset
+			     * under their standard names. */
+			    status = use_standard_encoding_glyph (font, stack[3]);
+			    if (unlikely (status))
+				return status;
+
+			    status = use_standard_encoding_glyph (font, stack[4]);
+			    if (unlikely (status))
+				return status;
+
+			    sp = 0;
+			    break;
+
+			case TYPE1_CHARSTRING_COMMAND_SBW:
+			    font->glyphs[glyph].width = stack[2]/font->base.units_per_em;
+			    sp = 0;
+			    break;
+
+			default:
+			    sp = 0;
+			    break;
+		    }
 	    }
         } else {
             /* integer argument */
@@ -734,6 +749,7 @@ cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
 
 static cairo_status_t
 write_used_glyphs (cairo_type1_font_subset_t *font,
+		   int glyph_number,
 		   const char *name, int name_length,
 		   const char *charstring, int charstring_length)
 {
@@ -741,6 +757,9 @@ write_used_glyphs (cairo_type1_font_subset_t *font,
     char buffer[256];
     int length;
 
+    if (font->glyphs[glyph_number].subset_index < 0)
+	return CAIRO_STATUS_SUCCESS;
+
     length = snprintf (buffer, sizeof buffer,
 		       "/%.*s %d %s ",
 		       name_length, name, charstring_length, font->rd);
@@ -763,6 +782,7 @@ write_used_glyphs (cairo_type1_font_subset_t *font,
 }
 
 typedef cairo_status_t (*glyph_func_t) (cairo_type1_font_subset_t *font,
+					int glyph_number,
 			                const char *name, int name_length,
 			                const char *charstring, int charstring_length);
 
@@ -773,9 +793,11 @@ cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
 					glyph_func_t func,
 					const char **dict_out)
 {
-    int charstring_length, name_length, glyph_index;
+    int charstring_length, name_length;
     const char *p, *charstring, *name;
     char *end;
+    cairo_status_t status;
+    int glyph_count;
 
     /* We're looking at '/' in the name of the first glyph.  The glyph
      * definitions are on the form:
@@ -792,7 +814,7 @@ cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
      */
 
     p = dict_start;
-
+    glyph_count = 0;
     while (*p == '/') {
 	name = p + 1;
 	p = skip_token (p, dict_end);
@@ -816,15 +838,11 @@ cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,
 	if (p == dict_end)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
-	glyph_index = cairo_type1_font_subset_lookup_glyph (font,
-							    name, name_length);
-	if (font->glyphs[glyph_index].subset_index >= 0) {
-	    cairo_status_t status = func (font,
-		                          name, name_length,
-					  charstring, charstring_length);
-	    if (unlikely (status))
-		return status;
-	}
+	status = func (font, glyph_count++,
+		       name, name_length,
+		       charstring, charstring_length);
+	if (unlikely (status))
+	    return status;
     }
 
     *dict_out = p;
@@ -842,6 +860,8 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
     const char *closefile_token;
     char buffer[32], *glyph_count_end;
     int num_charstrings, length;
+    const cairo_scaled_font_backend_t *backend;
+    unsigned int i;
 
     /* The private dict holds hint information, common subroutines and
      * the actual glyph definitions (charstrings).
@@ -878,30 +898,49 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     dict_start = p;
 
-    status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
-    if (unlikely (status))
-	return status;
-
     /* Now that we have the private dictionary broken down in
      * sections, do the first pass through the glyph definitions to
-     * figure out which subrs and othersubrs are use and which extra
-     * glyphs may be required by the seac operator. */
+     * build a list of glyph names and charstrings. */
     status = cairo_type1_font_subset_for_each_glyph (font,
 						     dict_start,
 						     font->cleartext_end,
-						     cairo_type1_font_subset_look_for_seac,
+						     cairo_type1_font_subset_build_glyph_list,
 						     &p);
-    if (unlikely (status))
-	return status;
+
+    backend = font->scaled_font_subset->scaled_font->backend;
+    if (!backend->index_to_glyph_name)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Find the glyph number corresponding to each glyph in the subset
+     * and mark it as in use */
+
+    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+	unsigned long index;
+
+	status = backend->index_to_glyph_name (font->scaled_font_subset->scaled_font,
+					       font->glyph_names,
+					       font->base.num_glyphs,
+					       font->scaled_font_subset->glyphs[i],
+					       &index);
+	if (unlikely(status))
+	    return status;
+
+	cairo_type1_font_subset_use_glyph (font, index);
+    }
+
+    /* Go through the charstring of each glyph in use, get the glyph
+     * width and figure out which extra glyphs may be required by the
+     * seac operator. */
+    for (i = 0; i < font->base.num_glyphs; i++) {
+	status = cairo_type1_font_subset_parse_charstring (font, i);
+	if (unlikely (status))
+	    return status;
+    }
 
     closefile_token = find_token (p, font->cleartext_end, "closefile");
     if (closefile_token == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = cairo_type1_font_subset_get_glyph_names_and_widths (font);
-    if (unlikely (status))
-	return status;
-
     /* We're ready to start outputting. First write the header,
      * i.e. the public part of the font dict.*/
     status = cairo_type1_font_subset_write_header (font, name);
@@ -1086,20 +1125,24 @@ cairo_type1_font_subset_generate (void       *abstract_font,
 		font->face->stream->base, font->type1_length);
     }
 
+    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
+
     status = _cairo_array_grow_by (&font->contents, 4096);
     if (unlikely (status))
-	goto fail;
+	return status;
 
     font->output = _cairo_output_stream_create (type1_font_write, NULL, font);
     if (unlikely ((status = font->output->status)))
-	goto fail;
+	return status;
 
     status = cairo_type1_font_subset_write (font, name);
     if (unlikely (status))
-	goto fail;
+	return status;
 
     font->base.data = _cairo_array_index (&font->contents, 0);
 
+    return status;
+
  fail:
     _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
 
@@ -1118,9 +1161,11 @@ _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
     _cairo_array_fini (&font->contents);
 
     free (font->type1_data);
-    if (font->glyphs != NULL) {
+    if (font->glyph_names != NULL) {
 	for (i = 0; i < font->base.num_glyphs; i++)
-	    free (font->glyphs[i].name);
+	    free (font->glyph_names[i]);
+
+	free (font->glyph_names);
     }
 
     _cairo_unscaled_font_destroy (font->base.unscaled_font);
@@ -1130,7 +1175,9 @@ _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font)
 
     if (font->base.base_font)
 	free (font->base.base_font);
+
     free (font->glyphs);
+    free (font->subset_index_to_glyphs);
 
     return status;
 }
@@ -1143,7 +1190,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
 {
     cairo_type1_font_subset_t font;
     cairo_status_t status, status_ignored;
-    unsigned long parent_glyph, length;
+    unsigned long length;
     unsigned int i;
     cairo_unscaled_font_t *unscaled_font;
     char buf[30];
@@ -1166,11 +1213,6 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
     if (unlikely (status))
 	return status;
 
-    for (i = 0; i < scaled_font_subset->num_glyphs; i++) {
-	parent_glyph = scaled_font_subset->glyphs[i];
-	cairo_type1_font_subset_use_glyph (&font, parent_glyph);
-    }
-
     status = cairo_type1_font_subset_generate (&font, name);
     if (unlikely (status))
 	goto fail1;
diff --git a/src/cairoint.h b/src/cairoint.h
index 5a21616..dc16a7c 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -546,6 +546,25 @@ struct _cairo_scaled_font_backend {
 
     cairo_warn cairo_bool_t
     (*is_synthetic)(void                       *scaled_font);
+
+    /* For type 1 fonts, return the glyph name for a given glyph index.
+     * A glyph index and list of glyph names in the Type 1 fonts is provided.
+     * The function returns the index of the glyph in the list of glyph names.
+     * @scaled_font: font
+     * @glyph_names: the names of each glyph in the Type 1 font in the
+     *   order they appear in the CharStrings array
+     * @num_glyph_names: the number of names in the glyph_names array
+     * @glyph_index: the given glyph index
+     * @glyph_array_index: (index into glyph_names) the glyph name corresponding
+     *  to the glyph_index
+     */
+
+    cairo_warn cairo_int_status_t
+    (*index_to_glyph_name)(void                 *scaled_font,
+			   char                **glyph_names,
+			   int                   num_glyph_names,
+			   unsigned long         glyph_index,
+			   unsigned long        *glyph_array_index);
 };
 
 struct _cairo_font_face_backend {
commit 9fc3f1086c30d28eb1a2c5795f17e9d4ff4353b9
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 21:47:16 2011 +0930

    cff-subset: Fix /guillemotright SID encoding

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 1f4fbbb..1a52ca2 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -1793,7 +1793,7 @@ static const int winansi_to_cff_std_string[] = {
     131, 170, 139, 106, 151,   0, 165, 128,
 	/* 176 */
     161, 156, 164, 169, 125, 152, 115, 114,
-    133, 150, 143, 187, 158, 155, 163, 123,
+    133, 150, 143, 120, 158, 155, 163, 123,
 	/* 192 */
     174, 171, 172, 176, 173, 175, 138, 177,
     181, 178, 179, 180, 185, 182, 183, 184,
commit 722e976044a30b237c9011e7e19ba022cb488f69
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Jul 18 21:44:18 2011 +0930

    png: fix type1 encoding bugs
    
    glyphs outside of the StandardEncoding were not being displayed by acroread

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 9447c36..8ae1358 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4368,7 +4368,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
 				 "%d 0 obj\n"
 				 "<< /Type /FontDescriptor\n"
 				 "   /FontName /%s+%s\n"
-				 "   /Flags %d\n"
+				 "   /Flags 4\n"
 				 "   /FontBBox [ %ld %ld %ld %ld ]\n"
 				 "   /ItalicAngle 0\n"
 				 "   /Ascent %ld\n"
@@ -4382,7 +4382,6 @@ _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),
@@ -4400,8 +4399,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
 				 "   /BaseFont /%s+%s\n"
 				 "   /FirstChar %d\n"
 				 "   /LastChar %d\n"
-				 "   /FontDescriptor %d 0 R\n"
-				 "   /Widths [",
+				 "   /FontDescriptor %d 0 R\n",
 				 subset_resource.id,
 				 tag,
 				 subset->base_font,
@@ -4409,6 +4407,10 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t		*surface,
 				 font_subset->is_latin ? last_glyph : font_subset->num_glyphs - 1,
 				 descriptor.id);
 
+    if (font_subset->is_latin)
+	_cairo_output_stream_printf (surface->output, "   /Encoding /WinAnsiEncoding\n");
+
+    _cairo_output_stream_printf (surface->output, "   /Widths [");
     if (font_subset->is_latin) {
 	for (i = 32; i < last_glyph + 1; i++) {
 	    int glyph = font_subset->latin_to_subset_glyph_index[i];


More information about the cairo-commit mailing list