[cairo-commit] 8 commits - ROADMAP src/cairo-output-stream.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-scaled-font-subsets-private.h src/cairo-svg-surface.c src/Makefile.am

Carl Worth cworth at kemper.freedesktop.org
Wed May 10 15:18:05 PDT 2006


 ROADMAP                                 |    1 
 src/Makefile.am                         |    2 
 src/cairo-output-stream.c               |    6 
 src/cairo-ps-surface.c                  |  394 +++++++-------------------------
 src/cairo-scaled-font-subsets-private.h |   79 ++++++
 src/cairo-scaled-font-subsets.c         |  383 +++++++++++++++++++++++++++++++
 src/cairo-svg-surface.c                 |  272 +++-------------------
 7 files changed, 608 insertions(+), 529 deletions(-)

New commits:
diff-tree 7c137b7e2ccbe76bb7870756a8fd29458b571a71 (from f459c1f0de1d874da55ab9eff075834c4b8633b8)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed May 10 15:14:10 2006 -0700

    SVG: Discard custom font subsetting in favor of sharing cairo-scaled-font-subsets

diff --git a/ROADMAP b/ROADMAP
index 50dbb68..9120f7a 100644
--- a/ROADMAP
+++ b/ROADMAP
@@ -71,7 +71,7 @@ We don't expect to release without these
 	   cairo_set_line_width should immediately use CTM
 	   _transform_glyph_bitmap http://lists.freedesktop.org/archives/cairo/2005-October/005564.html
      6759  fontconfig option AntiAlias doesn't work in cairo 1.1.2
-	   PS/PDF subsetting code needs bitmapped-glyph support
+	   SVG/PS/PDF emit_glyph functions need to support bitmapped glyphs
 
  Fix memory leaks
      1. Ensure 'make check-valgrind' passes with no leaks
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 931e115..3bd5121 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2,6 +2,7 @@
  *
  * Copyright © 2004 Red Hat, Inc
  * Copyright © 2005-2006 Emmanuel Pacaud <emmanuel.pacaud at free.fr>
+ * Copyright © 2006 Red Hat, Inc
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -34,6 +35,7 @@
  * Contributor(s):
  *	Kristian Høgsberg <krh at redhat.com>
  * 	Emmanuel Pacaud <emmanuel.pacaud at univ-poitiers.fr>
+ *	Carl Worth <cworth at cworth.org>
  */
 
 #include "cairoint.h"
@@ -42,6 +44,7 @@
 #include "cairo-ft-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-paginated-surface-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 #include <libxml/tree.h>
 
@@ -73,19 +76,6 @@ static const char * _cairo_svg_internal_
     "1.2"
 };
 
-typedef struct cairo_svg_glyph {
-    cairo_hash_entry_t	    base;	    /* font glyph index */
-    unsigned int	    output_glyph;   /* font glyph index */
-} cairo_svg_glyph_t;
-
-typedef struct cairo_svg_font {
-    cairo_hash_entry_t	    base;
-    cairo_scaled_font_t	    *scaled_font;
-    unsigned int	    output_font;
-    cairo_hash_table_t	    *glyphs;
-    unsigned int	    max_glyph;
-} cairo_svg_font_t;
-
 struct cairo_svg_document {
     cairo_output_stream_t *output_stream;
     unsigned long refcount;
@@ -116,8 +106,7 @@ struct cairo_svg_document {
 
     cairo_svg_version_t svg_version;
 
-    cairo_hash_table_t *fonts;
-    unsigned int	max_font;
+    cairo_scaled_font_subsets_t *font_subsets;
 };
 
 struct cairo_svg_surface {
@@ -556,167 +545,12 @@ _cairo_svg_path_close_path (void *closur
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_bool_t
-_cairo_svg_glyph_equal (const void *key_a, const void *key_b)
-{
-    const cairo_svg_glyph_t *svg_glyph_a = key_a;
-    const cairo_svg_glyph_t *svg_glyph_b = key_b;
-
-    return svg_glyph_a->base.hash == svg_glyph_b->base.hash;
-}
-
-static void
-_cairo_svg_glyph_key_init (cairo_svg_glyph_t	*svg_glyph,
-			   unsigned long	 index)
-{
-    svg_glyph->base.hash = index;
-}
-
-static cairo_svg_glyph_t *
-_cairo_svg_glyph_create (cairo_svg_font_t   *svg_font,
-			 unsigned long	     index)
-{
-    cairo_svg_glyph_t *svg_glyph = malloc (sizeof (cairo_svg_glyph_t));
-
-    if (!svg_glyph)
-	return NULL;
-    
-    _cairo_svg_glyph_key_init (svg_glyph, index);
-    svg_glyph->output_glyph = svg_font->max_glyph++;
-    
-    return svg_glyph;
-}
-
-static void
-_cairo_svg_glyph_destroy (cairo_svg_glyph_t *svg_glyph)
-{
-    free (svg_glyph);
-}
-
 static cairo_status_t
-_cairo_svg_glyph_find (cairo_svg_font_t	     *font,
-		       cairo_scaled_font_t   *scaled_font,
-		       unsigned long	      index,
-		       cairo_svg_glyph_t    **result)
-{
-    cairo_svg_glyph_t	 key;
-    cairo_svg_glyph_t	*svg_glyph;
-    cairo_status_t	 status;
-
-    _cairo_svg_glyph_key_init (&key, index);
-    if (!_cairo_hash_table_lookup (font->glyphs, 
-				   &key.base, 
-				   (cairo_hash_entry_t **) &svg_glyph)) {
-	svg_glyph = _cairo_svg_glyph_create (font, index);
-	if (!svg_glyph)
-	    return CAIRO_STATUS_NO_MEMORY;
-	
-	status = _cairo_hash_table_insert (font->glyphs, &svg_glyph->base);
-	if (status)
-	    return status;
-    }
-    *result = svg_glyph;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-_cairo_svg_font_equal (const void *key_a, const void *key_b)
-{
-    const cairo_svg_font_t   *svg_font_a = key_a;
-    const cairo_svg_font_t   *svg_font_b = key_b;
-
-    return svg_font_a->scaled_font == svg_font_b->scaled_font;
-}
-
-static void
-_cairo_svg_font_key_init (cairo_svg_font_t	*svg_font,
-			 cairo_scaled_font_t	*scaled_font)
-{
-    /* FIXME cast a pointer to unsigned long, really ? */
-    svg_font->base.hash = (unsigned long) scaled_font;
-    svg_font->scaled_font = scaled_font;
-}
-
-static cairo_svg_font_t *
-_cairo_svg_document_font_create (cairo_svg_document_t *document,
-				 cairo_scaled_font_t  *scaled_font)
-{
-    cairo_svg_font_t *svg_font = malloc (sizeof (cairo_svg_font_t));
-
-    if (!svg_font)
-	return NULL;
-
-    _cairo_svg_font_key_init (svg_font, scaled_font);
-    svg_font->glyphs = _cairo_hash_table_create (_cairo_svg_glyph_equal);
-    if (!svg_font->glyphs) {
-	free (svg_font);
-	return NULL;
-    }
-
-    svg_font->max_glyph = 0;
-    svg_font->output_font = document->max_font++;
-    cairo_scaled_font_reference (svg_font->scaled_font);
-    return svg_font;
-}
-
-static void
-_cairo_svg_font_destroy_glyph (void *entry, void *closure)
-{
-    cairo_svg_glyph_t *svg_glyph = entry;
-    cairo_svg_font_t  *svg_font = closure;
-    
-    _cairo_hash_table_remove (svg_font->glyphs, &svg_glyph->base);
-    _cairo_svg_glyph_destroy (svg_glyph);
-}
-
-static void
-_cairo_svg_font_destroy (cairo_svg_font_t *svg_font)
-{
-    _cairo_hash_table_foreach (svg_font->glyphs,
-			       _cairo_svg_font_destroy_glyph,
-			       svg_font);
-    _cairo_hash_table_destroy (svg_font->glyphs);
-    cairo_scaled_font_destroy (svg_font->scaled_font);
-    free (svg_font);
-}
-
-static void
-_cairo_svg_document_destroy_font (cairo_svg_document_t *document,
-				  cairo_svg_font_t     *svg_font)
-{
-    _cairo_hash_table_remove (document->fonts, &svg_font->base);
-    _cairo_svg_font_destroy (svg_font);
-}
-
-static cairo_status_t
-_cairo_svg_document_font_find (cairo_svg_document_t  *document,
-			       cairo_scaled_font_t   *scaled_font,
-			       cairo_svg_font_t	    **result)
-{
-    cairo_svg_font_t	 key;
-    cairo_svg_font_t	*svg_font;
-    cairo_status_t	 status;
-
-    _cairo_svg_font_key_init (&key, scaled_font);
-    if (!_cairo_hash_table_lookup (document->fonts, &key.base,
-				   (cairo_hash_entry_t **) &svg_font)) 
-    {
-	svg_font = _cairo_svg_document_font_create (document, scaled_font);
-	if (!svg_font)
-	    return CAIRO_STATUS_NO_MEMORY;
-	status = _cairo_hash_table_insert (document->fonts,
-					   &svg_font->base);
-	if (status)
-	    return status;
-    }
-    *result = svg_font;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
-				cairo_svg_font_t     *svg_font,
-				cairo_svg_glyph_t    *svg_glyph)
+_cairo_svg_document_emit_glyph (cairo_svg_document_t	*document,
+				cairo_scaled_font_t	*scaled_font,
+				unsigned long		 scaled_font_glyph_index,
+				unsigned int		 font_id,
+				unsigned int		 subset_glyph_index)
 {
     cairo_scaled_glyph_t    *scaled_glyph;
     cairo_status_t	     status;
@@ -724,8 +558,8 @@ _cairo_svg_document_emit_glyph (cairo_sv
     xmlNodePtr		     symbol, child;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
     
-    status = _cairo_scaled_glyph_lookup (svg_font->scaled_font,
-					 svg_glyph->base.hash,
+    status = _cairo_scaled_glyph_lookup (scaled_font,
+					 scaled_font_glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_PATH,
 					 &scaled_glyph);
@@ -733,8 +567,8 @@ _cairo_svg_document_emit_glyph (cairo_sv
      * If that fails, try again but ask for an image instead
      */
     if (status)
-	status = _cairo_scaled_glyph_lookup (svg_font->scaled_font,
-					     svg_glyph->base.hash,
+	status = _cairo_scaled_glyph_lookup (scaled_font,
+					     scaled_font_glyph_index,
 					     CAIRO_SCALED_GLYPH_INFO_METRICS|
 					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					     &scaled_glyph);
@@ -755,8 +589,8 @@ _cairo_svg_document_emit_glyph (cairo_sv
     symbol = xmlNewChild (document->xml_node_glyphs, NULL, 
 			  CC2XML ("symbol"), NULL);
     snprintf (buffer, sizeof buffer, "glyph%d-%d", 
-	      svg_font->output_font,
-	      svg_glyph->output_glyph);
+	      font_id,
+	      subset_glyph_index);
     xmlSetProp (symbol, CC2XML ("id"), C2XML (buffer));
     child = xmlNewChild (symbol, NULL, CC2XML ("path"), NULL);
     xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
@@ -767,47 +601,34 @@ _cairo_svg_document_emit_glyph (cairo_sv
     return CAIRO_STATUS_SUCCESS;
 }
 
-typedef struct {
-    cairo_svg_document_t *document;
-    cairo_svg_font_t	 *svg_font;
-} emit_glyph_info_t;
-
-static void
-_emit_glyph (void *entry, void *closure)
-{
-    cairo_svg_glyph_t *svg_glyph = entry;
-    emit_glyph_info_t *info = closure;
-
-    _cairo_svg_document_emit_glyph (info->document,
-				    info->svg_font,
-				    svg_glyph);
-    _cairo_svg_font_destroy_glyph (svg_glyph, info->svg_font);
-}
-
-static void
-_cairo_svg_document_emit_font (void *entry, void *closure)
+static cairo_status_t
+_cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
+				      void				*closure)
 {
-    cairo_svg_font_t	 *svg_font = entry;
     cairo_svg_document_t *document = closure;
-    emit_glyph_info_t	  info;
+    cairo_status_t status;
+    int i;
 
-    info.document = document;
-    info.svg_font = svg_font;
+    for (i = 0; i < font_subset->num_glyphs; i++) {
+	status = _cairo_svg_document_emit_glyph (document,
+						 font_subset->scaled_font,
+						 font_subset->glyphs[i],
+						 font_subset->font_id, i);
+	if (status)
+	    return status;
+    }
 
-    _cairo_hash_table_foreach (svg_font->glyphs, 
-			       _emit_glyph,
-			       &info);
-    _cairo_svg_document_destroy_font (document, svg_font);
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_svg_document_emit_fonts (cairo_svg_document_t *document)
+_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
 {
-    _cairo_hash_table_foreach (document->fonts, 
-			       _cairo_svg_document_emit_font,
-			       document);
-    _cairo_hash_table_destroy (document->fonts);
-    document->fonts = NULL;
+    _cairo_scaled_font_subsets_foreach (document->font_subsets,
+					_cairo_svg_document_emit_font_subset,
+					document);
+    _cairo_scaled_font_subsets_destroy (document->font_subsets);
+    document->font_subsets = NULL;
 }
 
 static cairo_int_status_t
@@ -1813,12 +1634,11 @@ _cairo_svg_surface_show_glyphs (void			*
     cairo_svg_document_t *document = surface->document;
     cairo_path_fixed_t path;
     cairo_status_t status;
-    cairo_svg_font_t *svg_font;
-    cairo_svg_glyph_t *svg_glyph;
     xmlNodePtr glyph_node;
     xmlNodePtr child;
     xmlBufferPtr style;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+    unsigned int font_id, subset_id, subset_glyph_index;
     int i;
     
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -1835,10 +1655,6 @@ _cairo_svg_surface_show_glyphs (void			*
     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
 	goto FALLBACK;
 
-    status = _cairo_svg_document_font_find (document, scaled_font, &svg_font); 
-    if (status)
-	goto FALLBACK;
-
     child = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
     style = xmlBufferCreate ();
     emit_pattern (surface, pattern, style, 0);
@@ -1846,8 +1662,9 @@ _cairo_svg_surface_show_glyphs (void			*
     xmlBufferFree (style);
 
     for (i = 0; i < num_glyphs; i++) {
-	status = _cairo_svg_glyph_find (svg_font, scaled_font, 
-					glyphs[i].index, &svg_glyph);
+	status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
+						       scaled_font, glyphs[i].index,
+						       &font_id, &subset_id, &subset_glyph_index);
 	if (status) {
 	    glyphs += i;
 	    num_glyphs -= i;
@@ -1856,8 +1673,7 @@ _cairo_svg_surface_show_glyphs (void			*
 
 	glyph_node = xmlNewChild (child, NULL, CC2XML ("use"), NULL);
 	snprintf (buffer, sizeof buffer, "#glyph%d-%d", 
-		  svg_font->output_font,
-		  svg_glyph->output_glyph);
+		  font_id, subset_glyph_index);
 	xmlSetProp (glyph_node, CC2XML ("xlink:href"), C2XML (buffer)); 
 	_cairo_dtostr (buffer, sizeof buffer, glyphs[i].x);
 	xmlSetProp (glyph_node, CC2XML ("x"), C2XML (buffer));
@@ -1997,13 +1813,13 @@ _cairo_svg_document_create (cairo_output
 	return NULL;
     }
 
-    document->fonts = _cairo_hash_table_create (_cairo_svg_font_equal);
-    if (!document->fonts) {
+    /* The use of defs for font glyphs imposes no per-subset limit. */
+    document->font_subsets = _cairo_scaled_font_subsets_create (0);
+    if (document->font_subsets == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	free (document);
 	return NULL;
     }
-    document->max_font = 0;
 	
     document->output_stream = output_stream;
     document->refcount = 1;
@@ -2119,7 +1935,7 @@ _cairo_svg_document_finish (cairo_svg_do
     if (document->finished)
 	return CAIRO_STATUS_SUCCESS;
 
-    _cairo_svg_document_emit_fonts (document);
+    _cairo_svg_document_emit_font_subsets (document);
 
     xmlSetProp (document->xml_node_main, CC2XML ("version"), 
 	CC2XML (_cairo_svg_internal_version_strings [document->svg_version]));
diff-tree f459c1f0de1d874da55ab9eff075834c4b8633b8 (from 8a209e6ad9a77b8b922687e08731c4b3bbd5621b)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed May 10 15:12:53 2006 -0700

    Tweak names to match those of cairo-scaled-font-subsets
    
    Also, remove a now obsolete field from cairo_ps_surface_t

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index eea89be..42196b0 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -75,7 +75,6 @@ typedef struct cairo_ps_surface {
     cairo_paginated_mode_t paginated_mode;
 
     cairo_scaled_font_subsets_t *font_subsets;
-    unsigned int max_font;
 
     cairo_array_t dsc_header_comments;
     cairo_array_t dsc_setup_comments;
@@ -372,8 +371,6 @@ _cairo_ps_surface_create_for_stream_inte
     if (! surface->font_subsets)
 	goto CLEANUP_OUTPUT_STREAM;
 
-    surface->max_font = 0;
-    
     surface->width  = width;
     surface->height = height;
     surface->max_width = width;
@@ -1738,8 +1735,8 @@ _cairo_ps_surface_show_glyphs (void		   
     cairo_int_status_t status;
     cairo_path_fixed_t *path;
     int i;
-    int current_sub_font_id = -1;
-    unsigned int font_id, sub_font_id, sub_font_glyph_index;
+    int current_subset_id = -1;
+    unsigned int font_id, subset_id, subset_glyph_index;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _analyze_operation (surface, op, source);
@@ -1755,23 +1752,23 @@ _cairo_ps_surface_show_glyphs (void		   
     for (i = 0; i < num_glyphs; i++) {
 	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
 						       scaled_font, glyphs[i].index,
-						       &font_id, &sub_font_id, &sub_font_glyph_index);
+						       &font_id, &subset_id, &subset_glyph_index);
 	if (status) {
 	    glyphs += i;
 	    num_glyphs -= i;
 	    goto fallback;
 	}
-	if (sub_font_id != current_sub_font_id) {
+	if (subset_id != current_subset_id) {
 	    _cairo_output_stream_printf (surface->stream,
 					 "/CairoFont-%d-%d 1 selectfont\n",
-					 font_id, sub_font_id);
-	    current_sub_font_id = sub_font_id;
+					 font_id, subset_id);
+	    current_subset_id = subset_id;
 	}
 	_cairo_output_stream_printf (surface->stream,
 				     "%f %f M <%c%c> S\n",
 				     glyphs[i].x, glyphs[i].y,
-				     hex_digit (sub_font_glyph_index >> 4),
-				     hex_digit (sub_font_glyph_index));
+				     hex_digit (subset_glyph_index >> 4),
+				     hex_digit (subset_glyph_index));
     }
 	
     return CAIRO_STATUS_SUCCESS;
diff-tree 8a209e6ad9a77b8b922687e08731c4b3bbd5621b (from 0544515279f9051a418f2079dd4fbeafd256b3ac)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed May 10 14:50:31 2006 -0700

    Fix cairo_output_stream_destroy to do nothing on nil stream objects.

diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index e9b5727..4032c39 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -99,6 +99,12 @@ _cairo_output_stream_close (cairo_output
     if (stream->closed)
 	return;
 
+    if (stream == &cairo_output_stream_nil ||
+	stream == &cairo_output_stream_nil_write_error)
+    {
+	return;
+    }
+
     if (stream->close_func) {
 	status = stream->close_func (stream->closure);
 	if (status)
diff-tree 0544515279f9051a418f2079dd4fbeafd256b3ac (from 906a17a6b1ba1fc120d90f9f3cec29b914300a93)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed May 10 14:47:28 2006 -0700

    Generalize font subsetting code in cairo-scaled-font-subsets for use by more than just PS backend

diff --git a/ROADMAP b/ROADMAP
index 1b1204f..50dbb68 100644
--- a/ROADMAP
+++ b/ROADMAP
@@ -71,6 +71,7 @@ We don't expect to release without these
 	   cairo_set_line_width should immediately use CTM
 	   _transform_glyph_bitmap http://lists.freedesktop.org/archives/cairo/2005-October/005564.html
      6759  fontconfig option AntiAlias doesn't work in cairo 1.1.2
+	   PS/PDF subsetting code needs bitmapped-glyph support
 
  Fix memory leaks
      1. Ensure 'make check-valgrind' passes with no leaks
diff --git a/src/Makefile.am b/src/Makefile.am
index 118da2d..6390d32 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
 
 if CAIRO_HAS_PS_SURFACE
 libcairo_ps_headers = cairo-ps.h
-libcairo_ps_sources = cairo-ps-surface.c cairo-ps-font.c cairo-ps-font-private.h
+libcairo_ps_sources = cairo-ps-surface.c cairo-scaled-font-subsets.c cairo-scaled-font-subsets-private.h
 libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
 endif
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index e94ebe2..eea89be 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -39,8 +39,7 @@
 
 #include "cairoint.h"
 #include "cairo-ps.h"
-#include "cairo-ps-font-private.h"
-#include "cairo-font-subset-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 #include "cairo-paginated-surface-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-ft-private.h"
@@ -75,7 +74,7 @@ typedef struct cairo_ps_surface {
 
     cairo_paginated_mode_t paginated_mode;
 
-    cairo_hash_table_t *fonts;
+    cairo_scaled_font_subsets_t *font_subsets;
     unsigned int max_font;
 
     cairo_array_t dsc_header_comments;
@@ -86,7 +85,8 @@ typedef struct cairo_ps_surface {
     
 } cairo_ps_surface_t;
 
-#define PS_SURFACE_DPI_DEFAULT 300.0
+#define PS_SURFACE_DPI_DEFAULT		300.0
+#define PS_SURFACE_MAX_GLYPHS_PER_FONT	256
 
 static cairo_status_t
 _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
@@ -213,51 +213,19 @@ _cairo_ps_surface_emit_header (cairo_ps_
 }
 
 static cairo_status_t
-_cairo_ps_surface_find_ps_font (cairo_ps_surface_t	 *surface,
-				cairo_scaled_font_t	 *scaled_font,
-				cairo_ps_font_t		**result)
-{
-    cairo_ps_font_t	key;
-    cairo_ps_font_t	*ps_font;
-    cairo_status_t	status;
-
-    _cairo_ps_font_key_init (&key, scaled_font);
-    if (!_cairo_hash_table_lookup (surface->fonts, &key.base,
-				   (cairo_hash_entry_t **) &ps_font)) 
-    {
-	ps_font = _cairo_ps_font_create (scaled_font, surface->max_font++);
-	if (!ps_font)
-	    return CAIRO_STATUS_NO_MEMORY;
-	status = _cairo_hash_table_insert (surface->fonts,
-					   &ps_font->base);
-	if (status)
-	    return status;
-    }
-    *result = ps_font;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_ps_surface_destroy_ps_font (cairo_ps_surface_t *surface,
-				   cairo_ps_font_t *ps_font)
-{
-    _cairo_hash_table_remove (surface->fonts, &ps_font->base);
-    _cairo_ps_font_destroy (ps_font);
-}
-
-static cairo_status_t
-_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
-			      cairo_ps_font_t *ps_font,
-			      cairo_ps_glyph_t *ps_glyph)
+_cairo_ps_surface_emit_glyph (cairo_ps_surface_t	*surface,
+			      cairo_scaled_font_t	*scaled_font,
+			      unsigned long		 scaled_font_glyph_index,
+			      unsigned int		 subset_glyph_index)
 {
     cairo_scaled_glyph_t    *scaled_glyph;
     cairo_status_t	    status;
-    
+
     _cairo_output_stream_printf (surface->final_stream,
-				 "\t\t{ %% %d\n", ps_glyph->output_glyph);
-    status = _cairo_scaled_glyph_lookup (ps_font->scaled_font,
-					 ps_glyph->base.hash,
+				 "\t\t{ %% %d\n", subset_glyph_index);
+
+    status = _cairo_scaled_glyph_lookup (scaled_font,
+					 scaled_font_glyph_index,
 					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 					 CAIRO_SCALED_GLYPH_INFO_PATH,
 					 &scaled_glyph);
@@ -265,8 +233,8 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
      * If that fails, try again but ask for an image instead
      */
     if (status)
-	status = _cairo_scaled_glyph_lookup (ps_font->scaled_font,
-					     ps_glyph->base.hash,
+	status = _cairo_scaled_glyph_lookup (scaled_font,
+					     scaled_font_glyph_index,
 					     CAIRO_SCALED_GLYPH_INFO_METRICS|
 					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
 					     &scaled_glyph);
@@ -274,6 +242,10 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
 	_cairo_output_stream_printf (surface->final_stream, "\t\t}\n");
 	return status;
     }
+
+    /* XXX: Need to actually use the image not the path if that's all
+     * we could get... */
+
     _cairo_output_stream_printf (surface->final_stream,
 				 "%f %f %f %f 0 0 setcachedevice\n",
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
@@ -297,70 +269,57 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cairo_ps_surface_emit_font (void *entry, void *closure)
+static cairo_status_t
+_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
+				    void			*closure)
 {
-    cairo_ps_font_t *ps_font = entry;
     cairo_ps_surface_t *surface = closure;
-    cairo_ps_font_glyph_select_t glyph_select;
-    cairo_ps_glyph_t *ps_glyphs[256], *ps_glyph;
-    int glyph, numglyph;
-    int subfont, nsubfont;
+    int i;
 
     _cairo_output_stream_printf (surface->final_stream,
-				 "%% _cairo_ps_surface_emit_font\n");
-    nsubfont = (ps_font->max_glyph >> 8) + 1;
-    for (subfont = 0; subfont < nsubfont; subfont++) {
-	_cairo_output_stream_printf (surface->final_stream,
-				     "/CairoFont-%d-%d <<\n",
-				     ps_font->output_font,
-				     subfont);
-	memset (ps_glyphs, '\0', sizeof (ps_glyphs));
-        glyph_select.glyphs = ps_glyphs;
-	glyph_select.numglyph = 0;
-	glyph_select.subfont = subfont;
-	_cairo_hash_table_foreach (ps_font->glyphs, 
-				   _cairo_ps_font_select_glyphs,
-				   &glyph_select);
-	_cairo_output_stream_printf (surface->final_stream,
-				     "\t/FontType\t3\n"
-				     "\t/FontMatrix\t[1 0 0 1 0 0]\n"
-				     "\t/Encoding\t[0]\n"
-				     "\t/FontBBox\t[0 0 10 10]\n"
-				     "\t/Glyphs [\n");
-	numglyph = glyph_select.numglyph;
-	for (glyph = 0; glyph < numglyph; glyph++) {
-	    ps_glyph = ps_glyphs[glyph];
-	    if (ps_glyph) {
-		_cairo_ps_surface_emit_glyph (surface,
-					      ps_font,
-					      ps_glyph);
-	    } else {
-		_cairo_output_stream_printf (surface->final_stream,
-					     "\t\t{ } %% %d\n", glyph);
-	    }
-	    _cairo_ps_font_destroy_glyph (ps_font, ps_glyph);
-	}
-	_cairo_output_stream_printf (surface->final_stream,
-				     "\t]\n"
-				     "\t/BuildChar {\n"
-				     "\t\texch /Glyphs get\n"
-				     "\t\texch get exec\n"
-				     "\t}\n"
-				     ">> definefont pop\n");
+				 "%% _cairo_ps_surface_emit_font_subset\n");
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "/CairoFont-%d-%d <<\n",
+				 font_subset->font_id,
+				 font_subset->subset_id);
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "\t/FontType\t3\n"
+				 "\t/FontMatrix\t[1 0 0 1 0 0]\n"
+				 "\t/Encoding\t[0]\n"
+				 "\t/FontBBox\t[0 0 10 10]\n"
+				 "\t/Glyphs [\n");
+
+    for (i = 0; i < font_subset->num_glyphs; i++) {
+	_cairo_ps_surface_emit_glyph (surface, 
+				      font_subset->scaled_font,
+				      font_subset->glyphs[i], i);
     }
-    _cairo_ps_surface_destroy_ps_font (surface, ps_font);
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "\t]\n"
+				 "\t/BuildChar {\n"
+				 "\t\texch /Glyphs get\n"
+				 "\t\texch get exec\n"
+				 "\t}\n"
+				 ">> definefont pop\n");
+
+    return _cairo_output_stream_get_status (surface->final_stream);
 }
 
 
 static void
-_cairo_ps_surface_emit_fonts (cairo_ps_surface_t *surface)
+_cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
 {
-    _cairo_hash_table_foreach (surface->fonts, 
-			       _cairo_ps_surface_emit_font,
-			       surface);
-    _cairo_hash_table_destroy (surface->fonts);
-    surface->fonts = NULL;
+    _cairo_output_stream_printf (surface->final_stream,
+				 "%% _cairo_ps_surface_emit_font_subsets\n");
+
+    _cairo_scaled_font_subsets_foreach (surface->font_subsets,
+					_cairo_ps_surface_emit_font_subset,
+					surface);
+    _cairo_scaled_font_subsets_destroy (surface->font_subsets);
+    surface->font_subsets = NULL;
 }
 
 static void
@@ -388,12 +347,12 @@ _cairo_ps_surface_create_for_stream_inte
 					      double		     height)
 {
     cairo_status_t status;
-    cairo_ps_surface_t *surface;
+    cairo_ps_surface_t *surface = NULL;
 
     surface = malloc (sizeof (cairo_ps_surface_t));
     if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP;
     }
 
     _cairo_surface_init (&surface->base, &cairo_ps_surface_backend);
@@ -401,23 +360,18 @@ _cairo_ps_surface_create_for_stream_inte
     surface->final_stream = stream;
 
     surface->tmpfile = tmpfile ();
+    if (surface->tmpfile == NULL)
+	goto CLEANUP_SURFACE;
+
     surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
     status = _cairo_output_stream_get_status (surface->stream);
-    if (status) {
-	fclose (surface->tmpfile);
-	free (surface);
-	_cairo_error (status);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
+    if (status)
+	goto CLEANUP_TMPFILE;
+
+    surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT);
+    if (! surface->font_subsets)
+	goto CLEANUP_OUTPUT_STREAM;
 
-    surface->fonts = _cairo_hash_table_create (_cairo_ps_font_equal);
-    if (!surface->fonts) {
-	_cairo_output_stream_destroy (surface->stream);
-	fclose (surface->tmpfile);
-	free (surface);
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-	return (cairo_surface_t*) &_cairo_surface_nil;
-    }
     surface->max_font = 0;
     
     surface->width  = width;
@@ -440,6 +394,17 @@ _cairo_ps_surface_create_for_stream_inte
 					    CAIRO_CONTENT_COLOR_ALPHA,
 					    width, height,
 					    &cairo_ps_surface_paginated_backend);
+
+
+ CLEANUP_OUTPUT_STREAM:
+    _cairo_output_stream_destroy (surface->stream);
+ CLEANUP_TMPFILE:
+    fclose (surface->tmpfile);
+ CLEANUP_SURFACE:
+    free (surface);
+ CLEANUP:
+    _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    return (cairo_surface_t*) &_cairo_surface_nil;
 }
 
 /**
@@ -955,7 +920,7 @@ _cairo_ps_surface_finish (void *abstract
    
     _cairo_ps_surface_emit_header (surface);
     
-    _cairo_ps_surface_emit_fonts (surface);
+    _cairo_ps_surface_emit_font_subsets (surface);
 
     _cairo_ps_surface_emit_body (surface);
 
@@ -1773,9 +1738,8 @@ _cairo_ps_surface_show_glyphs (void		   
     cairo_int_status_t status;
     cairo_path_fixed_t *path;
     int i;
-    int cur_subfont = -1, subfont;
-    cairo_ps_font_t *ps_font;
-    cairo_ps_glyph_t *ps_glyph;
+    int current_sub_font_id = -1;
+    unsigned int font_id, sub_font_id, sub_font_glyph_index;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _analyze_operation (surface, op, source);
@@ -1784,34 +1748,30 @@ _cairo_ps_surface_show_glyphs (void		   
 
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_show_glyphs\n");
-    status = _cairo_ps_surface_find_ps_font (surface, scaled_font, &ps_font);
-    if (status) 
-	goto fallback;
 
     if (num_glyphs)
 	emit_pattern (surface, source);
 
     for (i = 0; i < num_glyphs; i++) {
-	status = _cairo_ps_font_find_glyph (ps_font, scaled_font,
-					    glyphs[i].index, &ps_glyph);
+	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
+						       scaled_font, glyphs[i].index,
+						       &font_id, &sub_font_id, &sub_font_glyph_index);
 	if (status) {
 	    glyphs += i;
 	    num_glyphs -= i;
 	    goto fallback;
 	}
-	subfont = ps_glyph->output_glyph >> 8;
-	if (subfont != cur_subfont) {
+	if (sub_font_id != current_sub_font_id) {
 	    _cairo_output_stream_printf (surface->stream,
 					 "/CairoFont-%d-%d 1 selectfont\n",
-					 ps_font->output_font,
-					 subfont);
-	    cur_subfont = subfont;
+					 font_id, sub_font_id);
+	    current_sub_font_id = sub_font_id;
 	}
 	_cairo_output_stream_printf (surface->stream,
 				     "%f %f M <%c%c> S\n",
 				     glyphs[i].x, glyphs[i].y,
-				     hex_digit (ps_glyph->output_glyph >> 4),
-				     hex_digit (ps_glyph->output_glyph));
+				     hex_digit (sub_font_glyph_index >> 4),
+				     hex_digit (sub_font_glyph_index));
     }
 	
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 4282179..2c5c0dc 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -1,8 +1,5 @@
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright © 2003 University of Southern California
- * Copyright © 2005 Red Hat, Inc
- * Copyright © 2006 Keith Packard
  * Copyright © 2006 Red Hat, Inc
  *
  * This library is free software; you can redistribute it and/or
@@ -35,67 +32,48 @@
  *
  * Contributor(s):
  *	Carl D. Worth <cworth at cworth.org>
- *	Kristian Høgsberg <krh at redhat.com>
- *	Keith Packard <keithp at keithp.com>
  */
 
-/*
- * Type1 and Type3 PS fonts can hold only 256 glyphs.
- *
- * XXX Work around this by placing each set of 256 glyphs in a separate
- * font. No separate data structure is kept for this; the font name is
- * generated from all but the low 8 bits of the output glyph id.
- */
-
-#ifndef CAIRO_PS_FONT_PRIVATE_H
-#define CAIRO_PS_FONT_PRIVATE_H
+#ifndef CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H
+#define CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H
 
 #include "cairoint.h"
 
-typedef struct cairo_ps_glyph {
-    cairo_hash_entry_t	    base;	    /* font glyph index */
-    unsigned int	    output_glyph;   /* PS sub-font glyph index */
-} cairo_ps_glyph_t;
-
-typedef struct cairo_ps_font {
-    cairo_hash_entry_t	    base;
-    cairo_scaled_font_t	    *scaled_font;
-    unsigned int	    output_font;
-    cairo_hash_table_t	    *glyphs;
-    unsigned int	    max_glyph;
-} cairo_ps_font_t;
-
-typedef struct _cairo_ps_font_glyph_select {
-    cairo_ps_glyph_t	**glyphs;
-    int			subfont;
-    int			numglyph;
-} cairo_ps_font_glyph_select_t;
-
-cairo_private cairo_ps_font_t *
-_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
-		       unsigned int		 id);
-
-cairo_private void
-_cairo_ps_font_destroy (cairo_ps_font_t *ps_font);
+typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
 
-cairo_private void
-_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
-			 cairo_scaled_font_t	*scaled_font);
+typedef struct _cairo_scaled_font_subset {
+    cairo_scaled_font_t *scaled_font;
+    unsigned int font_id;
+    unsigned int subset_id;
+
+    /* Index of glyphs array is subset_glyph_index.
+     * Value of glyphs array is scaled_font_glyph_index.
+     */
+    unsigned long *glyphs;
+    int num_glyphs;
+} cairo_scaled_font_subset_t;
 
-cairo_private void
-_cairo_ps_font_select_glyphs (void *entry, void *closure);
+cairo_private cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create (int max_glyphs_per_subset);
 
 cairo_private void
-_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
-			      cairo_ps_glyph_t	*ps_glyph);
+_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
 
-cairo_private cairo_bool_t
-_cairo_ps_font_equal (const void *key_a, const void *key_b);
+cairo_private cairo_status_t
+_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*font_subsets,
+				      cairo_scaled_font_t		*scaled_font,
+				      unsigned long			 scaled_font_glyph_index,
+				      unsigned int			*font_id,
+				      unsigned int			*subset_id,
+				      unsigned int			*subset_glyph_index);
+
+typedef cairo_status_t
+(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t	*font_subset,
+					     void			*closure);
 
 cairo_private cairo_status_t
-_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
-			   cairo_scaled_font_t   *scaled_font,
-			   unsigned long	  index,
-			   cairo_ps_glyph_t	**result);
+_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t			*font_subsets,
+				    cairo_scaled_font_subset_callback_func_t	 font_subset_callback,
+				    void					*closure);
 
-#endif /* CAIRO_PS_FONT_PRIVATE_H */
+#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 353af5c..12eda92 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -39,143 +39,345 @@
  *	Keith Packard <keithp at keithp.com>
  */
 
+
 #include "cairoint.h"
-#include "cairo-ps-font-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
-static cairo_bool_t
-_cairo_ps_glyph_equal (const void *key_a, const void *key_b)
-{
-    const cairo_ps_glyph_t   *ps_glyph_a = key_a;
-    const cairo_ps_glyph_t   *ps_glyph_b = key_b;
+struct _cairo_scaled_font_subsets {
+    int max_glyphs_per_subset_limit;
+    int max_glyphs_per_subset_used;
+    int num_sub_fonts;
 
-    return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
-}
+    cairo_hash_table_t *sub_fonts;
+};
+
+typedef struct _cairo_sub_font {
+    cairo_hash_entry_t base;
+
+    cairo_scaled_font_subsets_t *parent;
+    cairo_scaled_font_t *scaled_font;
+    unsigned int font_id;
+
+    int current_subset;
+    int num_glyphs_in_current_subset;
+    int max_glyphs_per_subset;
+
+    cairo_hash_table_t *sub_font_glyphs;
+} cairo_sub_font_t;
+
+typedef struct _cairo_sub_font_glyph {
+    cairo_hash_entry_t base;
+
+    unsigned int subset_id;
+    unsigned int subset_glyph_index;
+} cairo_sub_font_glyph_t;
+
+typedef struct _cairo_sub_font_collection {
+    unsigned long *glyphs; /* scaled_font_glyph_index */
+    int glyphs_size;
+    int max_glyph;
+    int num_glyphs;
+
+    unsigned int subset_id;
+
+    cairo_scaled_font_subset_callback_func_t font_subset_callback;
+    void *font_subset_callback_closure;
+} cairo_sub_font_collection_t;
 
 static void
-_cairo_ps_glyph_key_init (cairo_ps_glyph_t  *ps_glyph,
-			  unsigned long	    index)
+_cairo_sub_font_glyph_init_key (cairo_sub_font_glyph_t  *sub_font_glyph,
+				unsigned long		 scaled_font_glyph_index)
 {
-    ps_glyph->base.hash = index;
+    sub_font_glyph->base.hash = scaled_font_glyph_index;
 }
 
-static cairo_ps_glyph_t *
-_cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
-			unsigned long index)
+static cairo_bool_t
+_cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b)
 {
-    cairo_ps_glyph_t	*ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
+    const cairo_sub_font_glyph_t *sub_font_glyph_a = key_a;
+    const cairo_sub_font_glyph_t *sub_font_glyph_b = key_b;
 
-    if (!ps_glyph)
+    return sub_font_glyph_a->base.hash == sub_font_glyph_b->base.hash;
+}
+
+static cairo_sub_font_glyph_t *
+_cairo_sub_font_glyph_create (unsigned long	scaled_font_glyph_index,
+			      unsigned int	subset_id,
+			      unsigned int	subset_glyph_index)
+{
+    cairo_sub_font_glyph_t *sub_font_glyph;
+
+    sub_font_glyph = malloc (sizeof (cairo_sub_font_glyph_t));
+    if (sub_font_glyph == NULL)
 	return NULL;
-    _cairo_ps_glyph_key_init (ps_glyph, index);
-    ps_glyph->output_glyph = ps_font->max_glyph++;
-    return ps_glyph;
+
+    _cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index);
+    sub_font_glyph->subset_id = subset_id;
+    sub_font_glyph->subset_glyph_index = subset_glyph_index;
+
+    return sub_font_glyph;
 }
 
 static void
-_cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
+_cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph)
 {
-    free (ps_glyph);
+    free (sub_font_glyph);
 }
 
-cairo_status_t
-_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
-			   cairo_scaled_font_t	 *scaled_font,
-			   unsigned long	  index,
-			   cairo_ps_glyph_t	**result)
+static void
+_cairo_sub_font_glyph_pluck (void *entry, void *closure)
 {
-    cairo_ps_glyph_t	key;
-    cairo_ps_glyph_t	*ps_glyph;
-    cairo_status_t	status;
+    cairo_sub_font_glyph_t *sub_font_glyph = entry;
+    cairo_hash_table_t *sub_font_glyphs = closure;
 
-    _cairo_ps_glyph_key_init (&key, index);
-    if (! _cairo_hash_table_lookup (font->glyphs,
-				    &key.base,
-				    (cairo_hash_entry_t **) &ps_glyph)) {
-	ps_glyph = _cairo_ps_glyph_create (font, index);
-	if (!ps_glyph)
-	    return CAIRO_STATUS_NO_MEMORY;
-	status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
-	if (status)
-	    return status;
-    }
-    *result = ps_glyph;
-    return CAIRO_STATUS_SUCCESS;
+    _cairo_hash_table_remove (sub_font_glyphs, &sub_font_glyph->base);
+    _cairo_sub_font_glyph_destroy (sub_font_glyph);
 }
 
-cairo_bool_t
-_cairo_ps_font_equal (const void *key_a, const void *key_b)
+static void
+_cairo_sub_font_glyph_collect (void *entry, void *closure)
 {
-    const cairo_ps_font_t   *ps_font_a = key_a;
-    const cairo_ps_font_t   *ps_font_b = key_b;
+    cairo_sub_font_glyph_t *sub_font_glyph = entry;
+    cairo_sub_font_collection_t *collection = closure;
+    unsigned long scaled_font_glyph_index;
+    unsigned int subset_glyph_index;
+
+    if (sub_font_glyph->subset_id != collection->subset_id)
+	return;
 
-    return ps_font_a->scaled_font == ps_font_b->scaled_font;
+    scaled_font_glyph_index = sub_font_glyph->base.hash;
+    subset_glyph_index = sub_font_glyph->subset_glyph_index;
+
+    /* Ensure we don't exceed the allocated bounds. */
+    assert (subset_glyph_index < collection->glyphs_size);
+
+    collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
+    if (subset_glyph_index > collection->max_glyph)
+	collection->max_glyph = subset_glyph_index;
+
+    collection->num_glyphs++;
 }
 
-void
-_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
-			 cairo_scaled_font_t	*scaled_font)
+static cairo_bool_t
+_cairo_sub_fonts_equal (const void *key_a, const void *key_b)
 {
-    ps_font->base.hash = (unsigned long) scaled_font;
-    ps_font->scaled_font = scaled_font;
+    const cairo_sub_font_t *sub_font_a = key_a;
+    const cairo_sub_font_t *sub_font_b = key_b;
+
+    return sub_font_a->scaled_font == sub_font_b->scaled_font;
+}
+
+static void
+_cairo_sub_font_init_key (cairo_sub_font_t	*sub_font,
+			  cairo_scaled_font_t	*scaled_font)
+{
+    sub_font->base.hash = (unsigned long) scaled_font;
+    sub_font->scaled_font = scaled_font;
 }
 
-cairo_ps_font_t *
-_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
-		       unsigned int		 id)
+static cairo_sub_font_t *
+_cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
+			cairo_scaled_font_t		*scaled_font,
+			unsigned int			 font_id,
+			int				 max_glyphs_per_subset)
 {
-    cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
-    if (!ps_font)
+    cairo_sub_font_t *sub_font;
+
+    sub_font = malloc (sizeof (cairo_sub_font_t));
+    if (sub_font == NULL)
 	return NULL;
-    _cairo_ps_font_key_init (ps_font, scaled_font);
-    ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
-    if (!ps_font->glyphs) {
-	free (ps_font);
+
+    _cairo_sub_font_init_key (sub_font, scaled_font);
+
+    sub_font->parent = parent;
+    sub_font->scaled_font = cairo_scaled_font_reference (scaled_font);
+    sub_font->font_id = font_id;
+
+    sub_font->current_subset = 0;
+    sub_font->num_glyphs_in_current_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);
+    if (! sub_font->sub_font_glyphs) {
+	free (sub_font);
 	return NULL;
     }
-    ps_font->max_glyph = 0;
-    ps_font->output_font = id;
-    cairo_scaled_font_reference (ps_font->scaled_font);
-    return ps_font;
+
+    return sub_font;
 }
 
-void
-_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
-			      cairo_ps_glyph_t	*ps_glyph)
+static void
+_cairo_sub_font_destroy (cairo_sub_font_t *sub_font)
 {
-    _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
-    _cairo_ps_glyph_destroy (ps_glyph);
+    _cairo_hash_table_foreach (sub_font->sub_font_glyphs,
+			       _cairo_sub_font_glyph_pluck,
+			       sub_font->sub_font_glyphs);
+    _cairo_hash_table_destroy (sub_font->sub_font_glyphs);
+    cairo_scaled_font_destroy (sub_font->scaled_font);
+    free (sub_font);
 }
 
 static void
-_cairo_ps_font_destroy_glyph_callback (void *entry, void *closure)
+_cairo_sub_font_pluck (void *entry, void *closure)
 {
-    cairo_ps_glyph_t	*ps_glyph = entry;
-    cairo_ps_font_t	*ps_font = closure;
+    cairo_sub_font_t *sub_font = entry;
+    cairo_hash_table_t *sub_fonts = closure;
 
-    _cairo_ps_font_destroy_glyph (ps_font, ps_glyph);
+    _cairo_hash_table_remove (sub_fonts, &sub_font->base);
+    _cairo_sub_font_destroy (sub_font);
 }
 
-void
-_cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
+static cairo_status_t
+_cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
+			   unsigned long	 scaled_font_glyph_index,
+			   unsigned int		*subset_id,
+			   unsigned int		*subset_glyph_index)
+{
+    cairo_sub_font_glyph_t key, *sub_font_glyph;
+    cairo_status_t status;
+
+    _cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
+    if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
+				    (cairo_hash_entry_t **) &sub_font_glyph))
+    {
+	if (sub_font->max_glyphs_per_subset &&
+	    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;
+	}
+	    
+	sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
+						       sub_font->current_subset,
+						       sub_font->num_glyphs_in_current_subset++);
+	if (sub_font_glyph == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
+
+	if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_subset_used)
+	    sub_font->parent->max_glyphs_per_subset_used = sub_font->num_glyphs_in_current_subset;
+
+	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
+	if (status)
+	    return status;
+    }
+
+    *subset_id = sub_font_glyph->subset_id;
+    *subset_glyph_index = sub_font_glyph->subset_glyph_index;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_sub_font_collect (void *entry, void *closure)
 {
-    _cairo_hash_table_foreach (ps_font->glyphs,
-			       _cairo_ps_font_destroy_glyph_callback,
-			       ps_font);
-    _cairo_hash_table_destroy (ps_font->glyphs);
-    cairo_scaled_font_destroy (ps_font->scaled_font);
-    free (ps_font);
+    cairo_sub_font_t *sub_font = entry;
+    cairo_sub_font_collection_t *collection = closure;
+    cairo_scaled_font_subset_t subset;
+    int i;
+
+    for (i = 0; i <= sub_font->current_subset; i++) {
+	collection->subset_id = i;
+
+	collection->num_glyphs = 0;
+	collection->max_glyph = 0;
+
+	_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
+				   _cairo_sub_font_glyph_collect, collection);
+
+	/* Ensure the resulting array has no uninitialized holes */
+	assert (collection->num_glyphs == collection->max_glyph + 1);
+
+	subset.scaled_font = sub_font->scaled_font;
+	subset.font_id = sub_font->font_id;
+	subset.subset_id = i;
+	subset.glyphs = collection->glyphs;
+	subset.num_glyphs = collection->num_glyphs;
+
+	(collection->font_subset_callback) (&subset,
+					    collection->font_subset_callback_closure);
+    }
+}
+
+cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create (int max_glyphs_per_subset)
+{
+    cairo_scaled_font_subsets_t *subsets;
+
+    subsets = malloc (sizeof (cairo_scaled_font_subsets_t));
+    if (subsets == NULL)
+	return NULL;
+
+    subsets->max_glyphs_per_subset_limit = max_glyphs_per_subset;
+    subsets->max_glyphs_per_subset_used = 0;
+    subsets->num_sub_fonts = 0;
+
+    subsets->sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
+    if (! subsets->sub_fonts) {
+	free (subsets);
+	return NULL;
+    }
+
+    return subsets;
 }
 
 void
-_cairo_ps_font_select_glyphs (void *entry, void *closure)
+_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
 {
-    cairo_ps_glyph_t		    *ps_glyph = entry;
-    cairo_ps_font_glyph_select_t    *ps_glyph_select = closure;
+    _cairo_hash_table_foreach (subsets->sub_fonts, _cairo_sub_font_pluck, subsets->sub_fonts);
+    _cairo_hash_table_destroy (subsets->sub_fonts);
+    free (subsets);
+}
+
+cairo_private cairo_status_t
+_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
+				      cairo_scaled_font_t		*scaled_font,
+				      unsigned long			 scaled_font_glyph_index,
+				      unsigned int			*font_id,
+				      unsigned int			*subset_id,
+				      unsigned int			*subset_glyph_index)
+{
+    cairo_sub_font_t key, *sub_font;
+    cairo_status_t status;
+
+    _cairo_sub_font_init_key (&key, scaled_font);
+    if (! _cairo_hash_table_lookup (subsets->sub_fonts, &key.base,
+				    (cairo_hash_entry_t **) &sub_font)) 
+    {
+	sub_font = _cairo_sub_font_create (subsets, scaled_font,
+					   subsets->num_sub_fonts++,
+					   subsets->max_glyphs_per_subset_limit);
+	if (sub_font == NULL)
+	    return CAIRO_STATUS_NO_MEMORY;
 
-    if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
-	unsigned long	sub_glyph = ps_glyph->output_glyph & 0xff;
-	ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
-	if (sub_glyph >= ps_glyph_select->numglyph)
-	    ps_glyph_select->numglyph = sub_glyph + 1;
+	status = _cairo_hash_table_insert (subsets->sub_fonts,
+					   &sub_font->base);
+	if (status)
+	    return status;
     }
+
+    *font_id = sub_font->font_id;
+
+    return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
+						  subset_id, subset_glyph_index);
+}
+
+cairo_private cairo_status_t
+_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t			*font_subsets,
+				    cairo_scaled_font_subset_callback_func_t	 font_subset_callback,
+				    void					*closure)
+{
+    cairo_sub_font_collection_t collection;
+
+    collection.glyphs_size = font_subsets->max_glyphs_per_subset_used;
+    collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
+    if (collection.glyphs == NULL)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    collection.font_subset_callback = font_subset_callback;
+    collection.font_subset_callback_closure = closure;
+
+    _cairo_hash_table_foreach (font_subsets->sub_fonts,
+			       _cairo_sub_font_collect, &collection);
+
+    return CAIRO_STATUS_SUCCESS;
 }
diff-tree 906a17a6b1ba1fc120d90f9f3cec29b914300a93 (from f7f9bdc05bd0afc4b709ab6a83074b7e66b1cc60)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed May 10 14:40:32 2006 -0700

    Rename cairo-ps-font to cairo-scaled-font-subsets (file names only)

diff --git a/src/cairo-ps-font-private.h b/src/cairo-ps-font-private.h
deleted file mode 100644
index 4282179..0000000
--- a/src/cairo-ps-font-private.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2003 University of Southern California
- * Copyright © 2005 Red Hat, Inc
- * Copyright © 2006 Keith Packard
- * Copyright © 2006 Red Hat, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is University of Southern
- * California.
- *
- * Contributor(s):
- *	Carl D. Worth <cworth at cworth.org>
- *	Kristian Høgsberg <krh at redhat.com>
- *	Keith Packard <keithp at keithp.com>
- */
-
-/*
- * Type1 and Type3 PS fonts can hold only 256 glyphs.
- *
- * XXX Work around this by placing each set of 256 glyphs in a separate
- * font. No separate data structure is kept for this; the font name is
- * generated from all but the low 8 bits of the output glyph id.
- */
-
-#ifndef CAIRO_PS_FONT_PRIVATE_H
-#define CAIRO_PS_FONT_PRIVATE_H
-
-#include "cairoint.h"
-
-typedef struct cairo_ps_glyph {
-    cairo_hash_entry_t	    base;	    /* font glyph index */
-    unsigned int	    output_glyph;   /* PS sub-font glyph index */
-} cairo_ps_glyph_t;
-
-typedef struct cairo_ps_font {
-    cairo_hash_entry_t	    base;
-    cairo_scaled_font_t	    *scaled_font;
-    unsigned int	    output_font;
-    cairo_hash_table_t	    *glyphs;
-    unsigned int	    max_glyph;
-} cairo_ps_font_t;
-
-typedef struct _cairo_ps_font_glyph_select {
-    cairo_ps_glyph_t	**glyphs;
-    int			subfont;
-    int			numglyph;
-} cairo_ps_font_glyph_select_t;
-
-cairo_private cairo_ps_font_t *
-_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
-		       unsigned int		 id);
-
-cairo_private void
-_cairo_ps_font_destroy (cairo_ps_font_t *ps_font);
-
-cairo_private void
-_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
-			 cairo_scaled_font_t	*scaled_font);
-
-cairo_private void
-_cairo_ps_font_select_glyphs (void *entry, void *closure);
-
-cairo_private void
-_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
-			      cairo_ps_glyph_t	*ps_glyph);
-
-cairo_private cairo_bool_t
-_cairo_ps_font_equal (const void *key_a, const void *key_b);
-
-cairo_private cairo_status_t
-_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
-			   cairo_scaled_font_t   *scaled_font,
-			   unsigned long	  index,
-			   cairo_ps_glyph_t	**result);
-
-#endif /* CAIRO_PS_FONT_PRIVATE_H */
diff --git a/src/cairo-ps-font.c b/src/cairo-ps-font.c
deleted file mode 100644
index 353af5c..0000000
--- a/src/cairo-ps-font.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2003 University of Southern California
- * Copyright © 2005 Red Hat, Inc
- * Copyright © 2006 Keith Packard
- * Copyright © 2006 Red Hat, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is University of Southern
- * California.
- *
- * Contributor(s):
- *	Carl D. Worth <cworth at cworth.org>
- *	Kristian Høgsberg <krh at redhat.com>
- *	Keith Packard <keithp at keithp.com>
- */
-
-#include "cairoint.h"
-#include "cairo-ps-font-private.h"
-
-static cairo_bool_t
-_cairo_ps_glyph_equal (const void *key_a, const void *key_b)
-{
-    const cairo_ps_glyph_t   *ps_glyph_a = key_a;
-    const cairo_ps_glyph_t   *ps_glyph_b = key_b;
-
-    return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
-}
-
-static void
-_cairo_ps_glyph_key_init (cairo_ps_glyph_t  *ps_glyph,
-			  unsigned long	    index)
-{
-    ps_glyph->base.hash = index;
-}
-
-static cairo_ps_glyph_t *
-_cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
-			unsigned long index)
-{
-    cairo_ps_glyph_t	*ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
-
-    if (!ps_glyph)
-	return NULL;
-    _cairo_ps_glyph_key_init (ps_glyph, index);
-    ps_glyph->output_glyph = ps_font->max_glyph++;
-    return ps_glyph;
-}
-
-static void
-_cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
-{
-    free (ps_glyph);
-}
-
-cairo_status_t
-_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
-			   cairo_scaled_font_t	 *scaled_font,
-			   unsigned long	  index,
-			   cairo_ps_glyph_t	**result)
-{
-    cairo_ps_glyph_t	key;
-    cairo_ps_glyph_t	*ps_glyph;
-    cairo_status_t	status;
-
-    _cairo_ps_glyph_key_init (&key, index);
-    if (! _cairo_hash_table_lookup (font->glyphs,
-				    &key.base,
-				    (cairo_hash_entry_t **) &ps_glyph)) {
-	ps_glyph = _cairo_ps_glyph_create (font, index);
-	if (!ps_glyph)
-	    return CAIRO_STATUS_NO_MEMORY;
-	status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
-	if (status)
-	    return status;
-    }
-    *result = ps_glyph;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_bool_t
-_cairo_ps_font_equal (const void *key_a, const void *key_b)
-{
-    const cairo_ps_font_t   *ps_font_a = key_a;
-    const cairo_ps_font_t   *ps_font_b = key_b;
-
-    return ps_font_a->scaled_font == ps_font_b->scaled_font;
-}
-
-void
-_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
-			 cairo_scaled_font_t	*scaled_font)
-{
-    ps_font->base.hash = (unsigned long) scaled_font;
-    ps_font->scaled_font = scaled_font;
-}
-
-cairo_ps_font_t *
-_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
-		       unsigned int		 id)
-{
-    cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
-    if (!ps_font)
-	return NULL;
-    _cairo_ps_font_key_init (ps_font, scaled_font);
-    ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
-    if (!ps_font->glyphs) {
-	free (ps_font);
-	return NULL;
-    }
-    ps_font->max_glyph = 0;
-    ps_font->output_font = id;
-    cairo_scaled_font_reference (ps_font->scaled_font);
-    return ps_font;
-}
-
-void
-_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
-			      cairo_ps_glyph_t	*ps_glyph)
-{
-    _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
-    _cairo_ps_glyph_destroy (ps_glyph);
-}
-
-static void
-_cairo_ps_font_destroy_glyph_callback (void *entry, void *closure)
-{
-    cairo_ps_glyph_t	*ps_glyph = entry;
-    cairo_ps_font_t	*ps_font = closure;
-
-    _cairo_ps_font_destroy_glyph (ps_font, ps_glyph);
-}
-
-void
-_cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
-{
-    _cairo_hash_table_foreach (ps_font->glyphs,
-			       _cairo_ps_font_destroy_glyph_callback,
-			       ps_font);
-    _cairo_hash_table_destroy (ps_font->glyphs);
-    cairo_scaled_font_destroy (ps_font->scaled_font);
-    free (ps_font);
-}
-
-void
-_cairo_ps_font_select_glyphs (void *entry, void *closure)
-{
-    cairo_ps_glyph_t		    *ps_glyph = entry;
-    cairo_ps_font_glyph_select_t    *ps_glyph_select = closure;
-
-    if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
-	unsigned long	sub_glyph = ps_glyph->output_glyph & 0xff;
-	ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
-	if (sub_glyph >= ps_glyph_select->numglyph)
-	    ps_glyph_select->numglyph = sub_glyph + 1;
-    }
-}
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
new file mode 100644
index 0000000..4282179
--- /dev/null
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -0,0 +1,101 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2003 University of Southern California
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2006 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Kristian Høgsberg <krh at redhat.com>
+ *	Keith Packard <keithp at keithp.com>
+ */
+
+/*
+ * Type1 and Type3 PS fonts can hold only 256 glyphs.
+ *
+ * XXX Work around this by placing each set of 256 glyphs in a separate
+ * font. No separate data structure is kept for this; the font name is
+ * generated from all but the low 8 bits of the output glyph id.
+ */
+
+#ifndef CAIRO_PS_FONT_PRIVATE_H
+#define CAIRO_PS_FONT_PRIVATE_H
+
+#include "cairoint.h"
+
+typedef struct cairo_ps_glyph {
+    cairo_hash_entry_t	    base;	    /* font glyph index */
+    unsigned int	    output_glyph;   /* PS sub-font glyph index */
+} cairo_ps_glyph_t;
+
+typedef struct cairo_ps_font {
+    cairo_hash_entry_t	    base;
+    cairo_scaled_font_t	    *scaled_font;
+    unsigned int	    output_font;
+    cairo_hash_table_t	    *glyphs;
+    unsigned int	    max_glyph;
+} cairo_ps_font_t;
+
+typedef struct _cairo_ps_font_glyph_select {
+    cairo_ps_glyph_t	**glyphs;
+    int			subfont;
+    int			numglyph;
+} cairo_ps_font_glyph_select_t;
+
+cairo_private cairo_ps_font_t *
+_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
+		       unsigned int		 id);
+
+cairo_private void
+_cairo_ps_font_destroy (cairo_ps_font_t *ps_font);
+
+cairo_private void
+_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
+			 cairo_scaled_font_t	*scaled_font);
+
+cairo_private void
+_cairo_ps_font_select_glyphs (void *entry, void *closure);
+
+cairo_private void
+_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
+			      cairo_ps_glyph_t	*ps_glyph);
+
+cairo_private cairo_bool_t
+_cairo_ps_font_equal (const void *key_a, const void *key_b);
+
+cairo_private cairo_status_t
+_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
+			   cairo_scaled_font_t   *scaled_font,
+			   unsigned long	  index,
+			   cairo_ps_glyph_t	**result);
+
+#endif /* CAIRO_PS_FONT_PRIVATE_H */
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
new file mode 100644
index 0000000..353af5c
--- /dev/null
+++ b/src/cairo-scaled-font-subsets.c
@@ -0,0 +1,181 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2003 University of Southern California
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2006 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Kristian Høgsberg <krh at redhat.com>
+ *	Keith Packard <keithp at keithp.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-ps-font-private.h"
+
+static cairo_bool_t
+_cairo_ps_glyph_equal (const void *key_a, const void *key_b)
+{
+    const cairo_ps_glyph_t   *ps_glyph_a = key_a;
+    const cairo_ps_glyph_t   *ps_glyph_b = key_b;
+
+    return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
+}
+
+static void
+_cairo_ps_glyph_key_init (cairo_ps_glyph_t  *ps_glyph,
+			  unsigned long	    index)
+{
+    ps_glyph->base.hash = index;
+}
+
+static cairo_ps_glyph_t *
+_cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
+			unsigned long index)
+{
+    cairo_ps_glyph_t	*ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
+
+    if (!ps_glyph)
+	return NULL;
+    _cairo_ps_glyph_key_init (ps_glyph, index);
+    ps_glyph->output_glyph = ps_font->max_glyph++;
+    return ps_glyph;
+}
+
+static void
+_cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
+{
+    free (ps_glyph);
+}
+
+cairo_status_t
+_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
+			   cairo_scaled_font_t	 *scaled_font,
+			   unsigned long	  index,
+			   cairo_ps_glyph_t	**result)
+{
+    cairo_ps_glyph_t	key;
+    cairo_ps_glyph_t	*ps_glyph;
+    cairo_status_t	status;
+
+    _cairo_ps_glyph_key_init (&key, index);
+    if (! _cairo_hash_table_lookup (font->glyphs,
+				    &key.base,
+				    (cairo_hash_entry_t **) &ps_glyph)) {
+	ps_glyph = _cairo_ps_glyph_create (font, index);
+	if (!ps_glyph)
+	    return CAIRO_STATUS_NO_MEMORY;
+	status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
+	if (status)
+	    return status;
+    }
+    *result = ps_glyph;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_bool_t
+_cairo_ps_font_equal (const void *key_a, const void *key_b)
+{
+    const cairo_ps_font_t   *ps_font_a = key_a;
+    const cairo_ps_font_t   *ps_font_b = key_b;
+
+    return ps_font_a->scaled_font == ps_font_b->scaled_font;
+}
+
+void
+_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
+			 cairo_scaled_font_t	*scaled_font)
+{
+    ps_font->base.hash = (unsigned long) scaled_font;
+    ps_font->scaled_font = scaled_font;
+}
+
+cairo_ps_font_t *
+_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
+		       unsigned int		 id)
+{
+    cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
+    if (!ps_font)
+	return NULL;
+    _cairo_ps_font_key_init (ps_font, scaled_font);
+    ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
+    if (!ps_font->glyphs) {
+	free (ps_font);
+	return NULL;
+    }
+    ps_font->max_glyph = 0;
+    ps_font->output_font = id;
+    cairo_scaled_font_reference (ps_font->scaled_font);
+    return ps_font;
+}
+
+void
+_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
+			      cairo_ps_glyph_t	*ps_glyph)
+{
+    _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
+    _cairo_ps_glyph_destroy (ps_glyph);
+}
+
+static void
+_cairo_ps_font_destroy_glyph_callback (void *entry, void *closure)
+{
+    cairo_ps_glyph_t	*ps_glyph = entry;
+    cairo_ps_font_t	*ps_font = closure;
+
+    _cairo_ps_font_destroy_glyph (ps_font, ps_glyph);
+}
+
+void
+_cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
+{
+    _cairo_hash_table_foreach (ps_font->glyphs,
+			       _cairo_ps_font_destroy_glyph_callback,
+			       ps_font);
+    _cairo_hash_table_destroy (ps_font->glyphs);
+    cairo_scaled_font_destroy (ps_font->scaled_font);
+    free (ps_font);
+}
+
+void
+_cairo_ps_font_select_glyphs (void *entry, void *closure)
+{
+    cairo_ps_glyph_t		    *ps_glyph = entry;
+    cairo_ps_font_glyph_select_t    *ps_glyph_select = closure;
+
+    if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
+	unsigned long	sub_glyph = ps_glyph->output_glyph & 0xff;
+	ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
+	if (sub_glyph >= ps_glyph_select->numglyph)
+	    ps_glyph_select->numglyph = sub_glyph + 1;
+    }
+}
diff-tree f7f9bdc05bd0afc4b709ab6a83074b7e66b1cc60 (from f3703b1806d1086be30323ca0576819b70a47771)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue May 9 10:05:44 2006 -0700

    PS: Put functions in more logical order.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 3e832b1..e94ebe2 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -212,14 +212,6 @@ _cairo_ps_surface_emit_header (cairo_ps_
     }
 }
 
-static void
-_cairo_ps_surface_destroy_ps_font (cairo_ps_surface_t *surface,
-				   cairo_ps_font_t *ps_font)
-{
-    _cairo_hash_table_remove (surface->fonts, &ps_font->base);
-    _cairo_ps_font_destroy (ps_font);
-}
-
 static cairo_status_t
 _cairo_ps_surface_find_ps_font (cairo_ps_surface_t	 *surface,
 				cairo_scaled_font_t	 *scaled_font,
@@ -242,9 +234,18 @@ _cairo_ps_surface_find_ps_font (cairo_ps
 	    return status;
     }
     *result = ps_font;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
+static void
+_cairo_ps_surface_destroy_ps_font (cairo_ps_surface_t *surface,
+				   cairo_ps_font_t *ps_font)
+{
+    _cairo_hash_table_remove (surface->fonts, &ps_font->base);
+    _cairo_ps_font_destroy (ps_font);
+}
+
 static cairo_status_t
 _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
 			      cairo_ps_font_t *ps_font,
diff-tree f3703b1806d1086be30323ca0576819b70a47771 (from 7ebdf4825d677b3b63671eb44298ea2764df2966)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue May 9 09:55:23 2006 -0700

    PS: Move type 3 support out into cairo-ps-font.c
    
    This is in preparation for generalizing this code for sharing among
    several backends.

diff --git a/src/Makefile.am b/src/Makefile.am
index 0aa6e21..118da2d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
 
 if CAIRO_HAS_PS_SURFACE
 libcairo_ps_headers = cairo-ps.h
-libcairo_ps_sources = cairo-ps-surface.c
+libcairo_ps_sources = cairo-ps-surface.c cairo-ps-font.c cairo-ps-font-private.h
 libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
 endif
 
diff --git a/src/cairo-ps-font-private.h b/src/cairo-ps-font-private.h
new file mode 100644
index 0000000..4282179
--- /dev/null
+++ b/src/cairo-ps-font-private.h
@@ -0,0 +1,101 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2003 University of Southern California
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2006 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Kristian Høgsberg <krh at redhat.com>
+ *	Keith Packard <keithp at keithp.com>
+ */
+
+/*
+ * Type1 and Type3 PS fonts can hold only 256 glyphs.
+ *
+ * XXX Work around this by placing each set of 256 glyphs in a separate
+ * font. No separate data structure is kept for this; the font name is
+ * generated from all but the low 8 bits of the output glyph id.
+ */
+
+#ifndef CAIRO_PS_FONT_PRIVATE_H
+#define CAIRO_PS_FONT_PRIVATE_H
+
+#include "cairoint.h"
+
+typedef struct cairo_ps_glyph {
+    cairo_hash_entry_t	    base;	    /* font glyph index */
+    unsigned int	    output_glyph;   /* PS sub-font glyph index */
+} cairo_ps_glyph_t;
+
+typedef struct cairo_ps_font {
+    cairo_hash_entry_t	    base;
+    cairo_scaled_font_t	    *scaled_font;
+    unsigned int	    output_font;
+    cairo_hash_table_t	    *glyphs;
+    unsigned int	    max_glyph;
+} cairo_ps_font_t;
+
+typedef struct _cairo_ps_font_glyph_select {
+    cairo_ps_glyph_t	**glyphs;
+    int			subfont;
+    int			numglyph;
+} cairo_ps_font_glyph_select_t;
+
+cairo_private cairo_ps_font_t *
+_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
+		       unsigned int		 id);
+
+cairo_private void
+_cairo_ps_font_destroy (cairo_ps_font_t *ps_font);
+
+cairo_private void
+_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
+			 cairo_scaled_font_t	*scaled_font);
+
+cairo_private void
+_cairo_ps_font_select_glyphs (void *entry, void *closure);
+
+cairo_private void
+_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
+			      cairo_ps_glyph_t	*ps_glyph);
+
+cairo_private cairo_bool_t
+_cairo_ps_font_equal (const void *key_a, const void *key_b);
+
+cairo_private cairo_status_t
+_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
+			   cairo_scaled_font_t   *scaled_font,
+			   unsigned long	  index,
+			   cairo_ps_glyph_t	**result);
+
+#endif /* CAIRO_PS_FONT_PRIVATE_H */
diff --git a/src/cairo-ps-font.c b/src/cairo-ps-font.c
new file mode 100644
index 0000000..353af5c
--- /dev/null
+++ b/src/cairo-ps-font.c
@@ -0,0 +1,181 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2003 University of Southern California
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2006 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Kristian Høgsberg <krh at redhat.com>
+ *	Keith Packard <keithp at keithp.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-ps-font-private.h"
+
+static cairo_bool_t
+_cairo_ps_glyph_equal (const void *key_a, const void *key_b)
+{
+    const cairo_ps_glyph_t   *ps_glyph_a = key_a;
+    const cairo_ps_glyph_t   *ps_glyph_b = key_b;
+
+    return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
+}
+
+static void
+_cairo_ps_glyph_key_init (cairo_ps_glyph_t  *ps_glyph,
+			  unsigned long	    index)
+{
+    ps_glyph->base.hash = index;
+}
+
+static cairo_ps_glyph_t *
+_cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
+			unsigned long index)
+{
+    cairo_ps_glyph_t	*ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
+
+    if (!ps_glyph)
+	return NULL;
+    _cairo_ps_glyph_key_init (ps_glyph, index);
+    ps_glyph->output_glyph = ps_font->max_glyph++;
+    return ps_glyph;
+}
+
+static void
+_cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
+{
+    free (ps_glyph);
+}
+
+cairo_status_t
+_cairo_ps_font_find_glyph (cairo_ps_font_t	 *font,
+			   cairo_scaled_font_t	 *scaled_font,
+			   unsigned long	  index,
+			   cairo_ps_glyph_t	**result)
+{
+    cairo_ps_glyph_t	key;
+    cairo_ps_glyph_t	*ps_glyph;
+    cairo_status_t	status;
+
+    _cairo_ps_glyph_key_init (&key, index);
+    if (! _cairo_hash_table_lookup (font->glyphs,
+				    &key.base,
+				    (cairo_hash_entry_t **) &ps_glyph)) {
+	ps_glyph = _cairo_ps_glyph_create (font, index);
+	if (!ps_glyph)
+	    return CAIRO_STATUS_NO_MEMORY;
+	status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
+	if (status)
+	    return status;
+    }
+    *result = ps_glyph;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_bool_t
+_cairo_ps_font_equal (const void *key_a, const void *key_b)
+{
+    const cairo_ps_font_t   *ps_font_a = key_a;
+    const cairo_ps_font_t   *ps_font_b = key_b;
+
+    return ps_font_a->scaled_font == ps_font_b->scaled_font;
+}
+
+void
+_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
+			 cairo_scaled_font_t	*scaled_font)
+{
+    ps_font->base.hash = (unsigned long) scaled_font;
+    ps_font->scaled_font = scaled_font;
+}
+
+cairo_ps_font_t *
+_cairo_ps_font_create (cairo_scaled_font_t	*scaled_font,
+		       unsigned int		 id)
+{
+    cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
+    if (!ps_font)
+	return NULL;
+    _cairo_ps_font_key_init (ps_font, scaled_font);
+    ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
+    if (!ps_font->glyphs) {
+	free (ps_font);
+	return NULL;
+    }
+    ps_font->max_glyph = 0;
+    ps_font->output_font = id;
+    cairo_scaled_font_reference (ps_font->scaled_font);
+    return ps_font;
+}
+
+void
+_cairo_ps_font_destroy_glyph (cairo_ps_font_t	*ps_font,
+			      cairo_ps_glyph_t	*ps_glyph)
+{
+    _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
+    _cairo_ps_glyph_destroy (ps_glyph);
+}
+
+static void
+_cairo_ps_font_destroy_glyph_callback (void *entry, void *closure)
+{
+    cairo_ps_glyph_t	*ps_glyph = entry;
+    cairo_ps_font_t	*ps_font = closure;
+
+    _cairo_ps_font_destroy_glyph (ps_font, ps_glyph);
+}
+
+void
+_cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
+{
+    _cairo_hash_table_foreach (ps_font->glyphs,
+			       _cairo_ps_font_destroy_glyph_callback,
+			       ps_font);
+    _cairo_hash_table_destroy (ps_font->glyphs);
+    cairo_scaled_font_destroy (ps_font->scaled_font);
+    free (ps_font);
+}
+
+void
+_cairo_ps_font_select_glyphs (void *entry, void *closure)
+{
+    cairo_ps_glyph_t		    *ps_glyph = entry;
+    cairo_ps_font_glyph_select_t    *ps_glyph_select = closure;
+
+    if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
+	unsigned long	sub_glyph = ps_glyph->output_glyph & 0xff;
+	ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
+	if (sub_glyph >= ps_glyph_select->numglyph)
+	    ps_glyph_select->numglyph = sub_glyph + 1;
+    }
+}
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a8a1730..3e832b1 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -39,6 +39,7 @@
 
 #include "cairoint.h"
 #include "cairo-ps.h"
+#include "cairo-ps-font-private.h"
 #include "cairo-font-subset-private.h"
 #include "cairo-paginated-surface-private.h"
 #include "cairo-meta-surface-private.h"
@@ -50,27 +51,6 @@
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
 
-/*
- * Type1 and Type3 PS fonts can hold only 256 glyphs.
- *
- * XXX Work around this by placing each set of 256 glyphs in a separate
- * font. No separate data structure is kept for this; the font name is
- * generated from all but the low 8 bits of the output glyph id.
- */
-
-typedef struct cairo_ps_glyph {
-    cairo_hash_entry_t	    base;	    /* font glyph index */
-    unsigned int	    output_glyph;   /* PS sub-font glyph index */
-} cairo_ps_glyph_t;
-
-typedef struct cairo_ps_font {
-    cairo_hash_entry_t	    base;
-    cairo_scaled_font_t	    *scaled_font;
-    unsigned int	    output_font;
-    cairo_hash_table_t	    *glyphs;
-    unsigned int	    max_glyph;
-} cairo_ps_font_t;
-
 typedef struct cairo_ps_surface {
     cairo_surface_t base;
 
@@ -232,135 +212,18 @@ _cairo_ps_surface_emit_header (cairo_ps_
     }
 }
 
-static cairo_bool_t
-_cairo_ps_glyph_equal (const void *key_a, const void *key_b)
-{
-    const cairo_ps_glyph_t   *ps_glyph_a = key_a;
-    const cairo_ps_glyph_t   *ps_glyph_b = key_b;
-
-    return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
-}
-
-static void
-_cairo_ps_glyph_key_init (cairo_ps_glyph_t  *ps_glyph,
-			  unsigned long	    index)
-{
-    ps_glyph->base.hash = index;
-}
-
-static cairo_ps_glyph_t *
-_cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
-			unsigned long index)
-{
-    cairo_ps_glyph_t	*ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
-
-    if (!ps_glyph)
-	return NULL;
-    _cairo_ps_glyph_key_init (ps_glyph, index);
-    ps_glyph->output_glyph = ps_font->max_glyph++;
-    return ps_glyph;
-}
-
 static void
-_cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
-{
-    free (ps_glyph);
-}
-
-static cairo_status_t
-_cairo_ps_glyph_find (cairo_ps_font_t	    *font,
-		      cairo_scaled_font_t   *scaled_font,
-		      unsigned long	    index,
-		      cairo_ps_glyph_t	    **result)
-{
-    cairo_ps_glyph_t	key;
-    cairo_ps_glyph_t	*ps_glyph;
-    cairo_status_t	status;
-
-    _cairo_ps_glyph_key_init (&key, index);
-    if (!_cairo_hash_table_lookup (font->glyphs, 
-				   &key.base, 
-				   (cairo_hash_entry_t **) &ps_glyph)) {
-	ps_glyph = _cairo_ps_glyph_create (font, index);
-	if (!ps_glyph)
-	    return CAIRO_STATUS_NO_MEMORY;
-	status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
-	if (status)
-	    return status;
-    }
-    *result = ps_glyph;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-_cairo_ps_font_equal (const void *key_a, const void *key_b)
-{
-    const cairo_ps_font_t   *ps_font_a = key_a;
-    const cairo_ps_font_t   *ps_font_b = key_b;
-
-    return ps_font_a->scaled_font == ps_font_b->scaled_font;
-}
-
-static void
-_cairo_ps_font_key_init (cairo_ps_font_t	*ps_font,
-			 cairo_scaled_font_t	*scaled_font)
-{
-    ps_font->base.hash = (unsigned long) scaled_font;
-    ps_font->scaled_font = scaled_font;
-}
-
-static cairo_ps_font_t *
-_cairo_ps_font_create (cairo_ps_surface_t   *surface,
-		       cairo_scaled_font_t  *scaled_font)
-{
-    cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
-    if (!ps_font)
-	return NULL;
-    _cairo_ps_font_key_init (ps_font, scaled_font);
-    ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
-    if (!ps_font->glyphs) {
-	free (ps_font);
-	return NULL;
-    }
-    ps_font->max_glyph = 0;
-    ps_font->output_font = surface->max_font++;
-    cairo_scaled_font_reference (ps_font->scaled_font);
-    return ps_font;
-}
-
-static void
-_cairo_ps_font_destroy_glyph (void *entry, void *closure)
-{
-    cairo_ps_glyph_t	*ps_glyph = entry;
-    cairo_ps_font_t	*ps_font = closure;
-    
-    _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
-    _cairo_ps_glyph_destroy (ps_glyph);
-}
-
-static void
-_cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
-{
-    _cairo_hash_table_foreach (ps_font->glyphs,
-			       _cairo_ps_font_destroy_glyph,
-			       ps_font);
-    _cairo_hash_table_destroy (ps_font->glyphs);
-    cairo_scaled_font_destroy (ps_font->scaled_font);
-    free (ps_font);
-}
-
-static void
-_cairo_ps_surface_destroy_font (cairo_ps_surface_t *surface,
-				cairo_ps_font_t *ps_font)
+_cairo_ps_surface_destroy_ps_font (cairo_ps_surface_t *surface,
+				   cairo_ps_font_t *ps_font)
 {
     _cairo_hash_table_remove (surface->fonts, &ps_font->base);
     _cairo_ps_font_destroy (ps_font);
 }
 
 static cairo_status_t
-_cairo_ps_font_find (cairo_ps_surface_t	    *surface,
-		     cairo_scaled_font_t    *scaled_font,
-		     cairo_ps_font_t	    **result)
+_cairo_ps_surface_find_ps_font (cairo_ps_surface_t	 *surface,
+				cairo_scaled_font_t	 *scaled_font,
+				cairo_ps_font_t		**result)
 {
     cairo_ps_font_t	key;
     cairo_ps_font_t	*ps_font;
@@ -370,7 +233,7 @@ _cairo_ps_font_find (cairo_ps_surface_t	
     if (!_cairo_hash_table_lookup (surface->fonts, &key.base,
 				   (cairo_hash_entry_t **) &ps_font)) 
     {
-	ps_font = _cairo_ps_font_create (surface, scaled_font);
+	ps_font = _cairo_ps_font_create (scaled_font, surface->max_font++);
 	if (!ps_font)
 	    return CAIRO_STATUS_NO_MEMORY;
 	status = _cairo_hash_table_insert (surface->fonts,
@@ -382,26 +245,6 @@ _cairo_ps_font_find (cairo_ps_surface_t	
     return CAIRO_STATUS_SUCCESS;
 }
 
-typedef struct _cairo_ps_font_glyph_select {
-    cairo_ps_glyph_t	**glyphs;
-    int			subfont;
-    int			numglyph;
-} cairo_ps_font_glyph_select_t;
-
-static void
-_cairo_ps_font_select_glyphs (void *entry, void *closure)
-{
-    cairo_ps_glyph_t		    *ps_glyph = entry;
-    cairo_ps_font_glyph_select_t    *ps_glyph_select = closure;
-
-    if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
-	unsigned long	sub_glyph = ps_glyph->output_glyph & 0xff;
-	ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
-	if (sub_glyph >= ps_glyph_select->numglyph)
-	    ps_glyph_select->numglyph = sub_glyph + 1;
-    }
-}
-
 static cairo_status_t
 _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
 			      cairo_ps_font_t *ps_font,
@@ -495,7 +338,7 @@ _cairo_ps_surface_emit_font (void *entry
 		_cairo_output_stream_printf (surface->final_stream,
 					     "\t\t{ } %% %d\n", glyph);
 	    }
-	    _cairo_ps_font_destroy_glyph (ps_glyph, ps_font);
+	    _cairo_ps_font_destroy_glyph (ps_font, ps_glyph);
 	}
 	_cairo_output_stream_printf (surface->final_stream,
 				     "\t]\n"
@@ -505,7 +348,7 @@ _cairo_ps_surface_emit_font (void *entry
 				     "\t}\n"
 				     ">> definefont pop\n");
     }
-    _cairo_ps_surface_destroy_font (surface, ps_font);
+    _cairo_ps_surface_destroy_ps_font (surface, ps_font);
 }
 
 
@@ -1940,7 +1783,7 @@ _cairo_ps_surface_show_glyphs (void		   
 
     _cairo_output_stream_printf (stream,
 				 "%% _cairo_ps_surface_show_glyphs\n");
-    status = _cairo_ps_font_find (surface, scaled_font, &ps_font);
+    status = _cairo_ps_surface_find_ps_font (surface, scaled_font, &ps_font);
     if (status) 
 	goto fallback;
 
@@ -1948,8 +1791,8 @@ _cairo_ps_surface_show_glyphs (void		   
 	emit_pattern (surface, source);
 
     for (i = 0; i < num_glyphs; i++) {
-	status = _cairo_ps_glyph_find (ps_font, scaled_font, 
-				       glyphs[i].index, &ps_glyph);
+	status = _cairo_ps_font_find_glyph (ps_font, scaled_font,
+					    glyphs[i].index, &ps_glyph);
 	if (status) {
 	    glyphs += i;
 	    num_glyphs -= i;
diff-tree 7ebdf4825d677b3b63671eb44298ea2764df2966 (from 172fd2f6a668b6b0e4a7cbce24e006b65417d9b1)
Author: Carl Worth <cworth at cworth.org>
Date:   Mon May 8 17:47:31 2006 -0700

    PS: Remove stale comment (the stuff TODO is done already)

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 630534b..a8a1730 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -47,13 +47,6 @@
 #include <time.h>
 #include <zlib.h>
 
-/* TODO:
- *
- * - Add document structure convention comments where appropriate.
- *
- * - Create a set of procs to use... specifically a trapezoid proc.
- */
-
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
 


More information about the cairo-commit mailing list