[cairo-commit] src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-scaled-font-subsets-private.h src/cairo-svg-surface.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Tue Feb 20 06:05:21 PST 2007


 src/cairo-pdf-surface.c                 |   24 ++-
 src/cairo-ps-surface.c                  |   24 ++-
 src/cairo-scaled-font-subsets-private.h |   61 +++++++-
 src/cairo-scaled-font-subsets.c         |  235 ++++++++++++++++++++++++++------
 src/cairo-svg-surface.c                 |    8 -
 5 files changed, 288 insertions(+), 64 deletions(-)

New commits:
diff-tree 641f0919d53691e561aa665d31cc43524d861215 (from f65c33edbecc1f0e285814995dc1a51748310e36)
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Feb 21 00:32:07 2007 +1030

    PDF/PS: Don't embed multiple copies of the same font
    
    cairo-scaled-font-subsets stores two sets of subsets -
    scaled and unscaled. The first time each glyph is mapped,
    _cairo_scaled_glyph_lookup() is called to determine if
    the glyph is bitmap or outline. Outline glyphs are put
    in the unscaled subsets. Bitmap glyphs are put in the
    scaled subsets. The unscaled subsets hash table keyed is
    the scaled_font->font_face to ensure only one font for
    each font face is created. The scaled subsets hash
    table is keyed by scaled_font.
    
    _cairo_scaled_font_subsets_create() now takes two arguments
    to specify the maximum size of the scaled and unscaled subsets.
    If the unscaled max size is set to 0 all glyphs are mapped
    to scaled subsets.
    
    A separate foreach function is provided for scaled and unscaled
    subsets. The PDF and PS backends iterate over the unscaled
    subsets to emit CFF, TrueType, and Type1 fonts. The scaled
    subsets are iterated to emit Type3 bitmap fonts.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 15ef4fc..fa6c830 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -277,7 +277,8 @@ _cairo_pdf_surface_create_for_stream_int
     _cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
     _cairo_array_init (&surface->alphas, sizeof (double));
 
-    surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT);
+    surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT,
+                                                               PDF_SURFACE_MAX_GLYPHS_PER_FONT);
     if (! surface->font_subsets) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	free (surface);
@@ -2383,8 +2384,8 @@ _cairo_pdf_surface_emit_type3_font_subse
 }
 
 static void
-_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
-				     void			*closure)
+_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
+                                              void			 *closure)
 {
     cairo_pdf_surface_t *surface = closure;
     cairo_status_t status;
@@ -2406,6 +2407,14 @@ _cairo_pdf_surface_emit_font_subset (cai
     status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
+}
+
+static void
+_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
+                                            void		       *closure)
+{
+    cairo_pdf_surface_t *surface = closure;
+    cairo_status_t status;
 
     status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@@ -2417,9 +2426,12 @@ _cairo_pdf_surface_emit_font_subsets (ca
 {
     cairo_status_t status;
 
-    status = _cairo_scaled_font_subsets_foreach (surface->font_subsets,
-						 _cairo_pdf_surface_emit_font_subset,
-						 surface);
+    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
+                                                          _cairo_pdf_surface_emit_unscaled_font_subset,
+                                                          surface);
+    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
+                                                        _cairo_pdf_surface_emit_scaled_font_subset,
+                                                        surface);
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
     surface->font_subsets = NULL;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 3da530e..e279824 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -709,8 +709,8 @@ _cairo_ps_surface_emit_type3_font_subset
 
 
 static void
-_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
-				    void			*closure)
+_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t	*font_subset,
+				            void			*closure)
 {
     cairo_ps_surface_t *surface = closure;
     cairo_status_t status;
@@ -728,6 +728,14 @@ _cairo_ps_surface_emit_font_subset (cair
     status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
+}
+
+static void
+_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
+                                           void			      *closure)
+{
+    cairo_ps_surface_t *surface = closure;
+    cairo_status_t status;
 
     status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@@ -742,9 +750,12 @@ _cairo_ps_surface_emit_font_subsets (cai
     _cairo_output_stream_printf (surface->final_stream,
 				 "%% _cairo_ps_surface_emit_font_subsets\n");
 
-    status = _cairo_scaled_font_subsets_foreach (surface->font_subsets,
-						 _cairo_ps_surface_emit_font_subset,
-						 surface);
+    status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
+                                                          _cairo_ps_surface_emit_unscaled_font_subset,
+                                                          surface);
+    status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
+                                                        _cairo_ps_surface_emit_scaled_font_subset,
+                                                        surface);
     _cairo_scaled_font_subsets_destroy (surface->font_subsets);
     surface->font_subsets = NULL;
 
@@ -798,7 +809,8 @@ _cairo_ps_surface_create_for_stream_inte
     if (status)
 	goto CLEANUP_TMPFILE;
 
-    surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT);
+    surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
+                                                               PS_SURFACE_MAX_GLYPHS_PER_FONT);
     if (! surface->font_subsets)
 	goto CLEANUP_OUTPUT_STREAM;
 
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 88dbfbb..5104340 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -43,9 +43,15 @@ typedef struct _cairo_scaled_font_subset
 
 /**
  * _cairo_scaled_font_subsets_create:
- * @max_glyphs_per_subset: the maximum number of glyphs that should
- * appear in any subset. A value of 0 indicates that there is no limit
- * to the number of glyphs per subset.
+ *
+ * @max_glyphs_per_unscaled_subset: the maximum number of glyphs that
+ * should appear in any unscaled subset. A value of 0 indicates that
+ * no unscaled subset will be created. All glyphs will mapped to
+ * scaled subsets.
+ *
+ * @max_glyphs_per_scaled_subset: the maximum number of glyphs that
+ * should appear in any scaled subset. A value of 0 indicates that
+ * no scaled subset will be created.
  *
  * Create a new #cairo_scaled_font_subsets_t object which can be used
  * to create subsets of any number of cairo_scaled_font_t
@@ -54,12 +60,16 @@ typedef struct _cairo_scaled_font_subset
  * subsets with glyph indices packed into the range
  * [0 .. max_glyphs_per_subset).
  *
+ * @max_glyphs_per_unscaled_subset and @max_glyphs_per_scaled_subset
+ * cannot both be 0.
+ *
  * Return value: a pointer to the newly creates font subsets. The
  * caller owns this object and should call
  * _cairo_scaled_font_subsets_destroy() when done with it.
  **/
 cairo_private cairo_scaled_font_subsets_t *
-_cairo_scaled_font_subsets_create (int max_glyphs_per_subset);
+_cairo_scaled_font_subsets_create (int max_glyphs_unscaled_per_subset,
+                                   int max_glyphs_scaled_per_subset);
 
 /**
  * _cairo_scaled_font_subsets_destroy:
@@ -138,7 +148,42 @@ typedef void
  * @font_subset_callback: a function to be called for each font subset
  * @closure: closure data for the callback function
  *
- * Iterate over each unique font subset as created by calls to
+ * Iterate over each unique scaled font subset as created by calls to
+ * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
+ * unique pairs of (font_id, subset_id) as returned by
+ * _cairo_scaled_font_subsets_map_glyph().
+ *
+ * For each subset, @font_subset_callback will be called and will be
+ * provided with both a #cairo_scaled_font_subset_t object containing
+ * all the glyphs in the subset as well as the value of @closure.
+ *
+ * The #cairo_scaled_font_subset_t object contains the scaled_font,
+ * the font_id, and the subset_id corresponding to all glyphs
+ * belonging to the subset. In addition, it contains an array providing
+ * a mapping between subset glyph indices and the original scaled font
+ * glyph indices.
+ *
+ * The index of the array corresponds to subset_glyph_index values
+ * returned by _cairo_scaled_font_subsets_map_glyph() while the
+ * values of the array correspond to the scaled_font_glyph_index
+ * values passed as input to the same function.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
+ * value indicating an error. Possible errors include
+ * CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t		    *font_subsets,
+				           cairo_scaled_font_subset_callback_func_t  font_subset_callback,
+				           void					    *closure);
+
+/**
+ * _cairo_scaled_font_subsets_foreach_unscaled:
+ * @font_subsets: a #cairo_scaled_font_subsets_t
+ * @font_subset_callback: a function to be called for each font subset
+ * @closure: closure data for the callback function
+ *
+ * Iterate over each unique unscaled font subset as created by calls to
  * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
  * unique pairs of (font_id, subset_id) as returned by
  * _cairo_scaled_font_subsets_map_glyph().
@@ -163,9 +208,9 @@ typedef void
  * CAIRO_STATUS_NO_MEMORY.
  **/
 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_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t              *font_subsets,
+                                             cairo_scaled_font_subset_callback_func_t  font_subset_callback,
+				             void				      *closure);
 
 typedef struct _cairo_cff_subset {
     char *base_font;
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 68a662a..838e757 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -43,16 +43,21 @@
 #include "cairo-scaled-font-subsets-private.h"
 
 struct _cairo_scaled_font_subsets {
-    int max_glyphs_per_subset_limit;
-    int max_glyphs_per_subset_used;
-    int num_sub_fonts;
+    int max_glyphs_per_unscaled_subset_limit;
+    int max_glyphs_per_unscaled_subset_used;
+    cairo_hash_table_t *unscaled_sub_fonts;
+
+    int max_glyphs_per_scaled_subset_limit;
+    int max_glyphs_per_scaled_subset_used;
+    cairo_hash_table_t *scaled_sub_fonts;
 
-    cairo_hash_table_t *sub_fonts;
+    int num_sub_fonts;
 };
 
 typedef struct _cairo_sub_font {
     cairo_hash_entry_t base;
 
+    cairo_bool_t is_scaled;
     cairo_scaled_font_subsets_t *parent;
     cairo_scaled_font_t *scaled_font;
     unsigned int font_id;
@@ -163,22 +168,34 @@ _cairo_sub_fonts_equal (const void *key_
     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;
+    if (sub_font_a->is_scaled)
+        return sub_font_a->scaled_font == sub_font_b->scaled_font;
+    else
+        return sub_font_a->scaled_font->font_face == sub_font_b->scaled_font->font_face;
 }
 
 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;
+    if (sub_font->is_scaled)
+    {
+        sub_font->base.hash = (unsigned long) scaled_font;
+        sub_font->scaled_font = scaled_font;
+    }
+    else
+    {
+        sub_font->base.hash = (unsigned long) scaled_font->font_face;
+        sub_font->scaled_font = scaled_font;
+    }
 }
 
 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)
+			int				 max_glyphs_per_subset,
+                        cairo_bool_t                     is_scaled)
 {
     cairo_sub_font_t *sub_font;
 
@@ -186,6 +203,7 @@ _cairo_sub_font_create (cairo_scaled_fon
     if (sub_font == NULL)
 	return NULL;
 
+    sub_font->is_scaled = is_scaled;
     _cairo_sub_font_init_key (sub_font, scaled_font);
 
     sub_font->parent = parent;
@@ -227,6 +245,27 @@ _cairo_sub_font_pluck (void *entry, void
 }
 
 static cairo_status_t
+_cairo_sub_font_lookup_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_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))
+    {
+        *subset_id = sub_font_glyph->subset_id;
+        *subset_glyph_index = sub_font_glyph->subset_glyph_index;
+
+        return CAIRO_STATUS_SUCCESS;
+    }
+
+    return CAIRO_STATUS_NULL_POINTER;
+}
+
+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,
@@ -239,8 +278,7 @@ _cairo_sub_font_map_glyph (cairo_sub_fon
     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)
+	if (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;
@@ -252,8 +290,16 @@ _cairo_sub_font_map_glyph (cairo_sub_fon
 	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;
+        if (sub_font->is_scaled)
+        {
+            if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used)
+                sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset;
+        }
+        else
+        {
+            if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used)
+                sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset;
+        }
 
 	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
 	if (status)
@@ -309,7 +355,8 @@ _cairo_sub_font_collect (void *entry, vo
 }
 
 cairo_scaled_font_subsets_t *
-_cairo_scaled_font_subsets_create (int max_glyphs_per_subset)
+_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
+                                   int max_glyphs_per_scaled_subset)
 {
     cairo_scaled_font_subsets_t *subsets;
 
@@ -317,12 +364,23 @@ _cairo_scaled_font_subsets_create (int m
     if (subsets == NULL)
 	return NULL;
 
-    subsets->max_glyphs_per_subset_limit = max_glyphs_per_subset;
-    subsets->max_glyphs_per_subset_used = 0;
+    subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset;
+    subsets->max_glyphs_per_unscaled_subset_used = 0;
+
+    subsets->max_glyphs_per_scaled_subset_limit = max_glyphs_per_scaled_subset;
+    subsets->max_glyphs_per_scaled_subset_used = 0;
+
     subsets->num_sub_fonts = 0;
 
-    subsets->sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
-    if (! subsets->sub_fonts) {
+    subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
+    if (! subsets->unscaled_sub_fonts) {
+	free (subsets);
+	return NULL;
+    }
+
+    subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
+    if (! subsets->scaled_sub_fonts) {
+        free (subsets->unscaled_sub_fonts);
 	free (subsets);
 	return NULL;
     }
@@ -333,8 +391,11 @@ _cairo_scaled_font_subsets_create (int m
 void
 _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
 {
-    _cairo_hash_table_foreach (subsets->sub_fonts, _cairo_sub_font_pluck, subsets->sub_fonts);
-    _cairo_hash_table_destroy (subsets->sub_fonts);
+    _cairo_hash_table_foreach (subsets->scaled_sub_fonts, _cairo_sub_font_pluck, subsets->scaled_sub_fonts);
+    _cairo_hash_table_destroy (subsets->scaled_sub_fonts);
+
+    _cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts);
+    _cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
     free (subsets);
 }
 
@@ -347,38 +408,106 @@ _cairo_scaled_font_subsets_map_glyph (ca
 				      unsigned int			*subset_glyph_index)
 {
     cairo_sub_font_t key, *sub_font;
+    cairo_scaled_glyph_t *scaled_glyph;
     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;
+    /* Lookup glyph in unscaled subsets */
+    if (subsets->max_glyphs_per_unscaled_subset_limit > 0) {
+        key.is_scaled = FALSE;
+        _cairo_sub_font_init_key (&key, scaled_font);
+        if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
+                                        (cairo_hash_entry_t **) &sub_font))
+        {
+            status =  _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
+                                                  subset_id, subset_glyph_index);
+            if (status == CAIRO_STATUS_SUCCESS) {
+                *font_id = sub_font->font_id;
+                return CAIRO_STATUS_SUCCESS;
+            }
+        }
+    }
 
-	status = _cairo_hash_table_insert (subsets->sub_fonts,
-					   &sub_font->base);
-	if (status)
-	    return status;
+    /* Lookup glyph in scaled subsets */
+    if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
+        key.is_scaled = TRUE;
+        _cairo_sub_font_init_key (&key, scaled_font);
+        if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
+                                      (cairo_hash_entry_t **) &sub_font))
+        {
+            status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
+                                                subset_id, subset_glyph_index);
+            if (status == CAIRO_STATUS_SUCCESS) {
+                *font_id = sub_font->font_id;
+                return CAIRO_STATUS_SUCCESS;
+            }
+        }
     }
 
+    /* Glyph not found. Determine whether the glyph is outline or
+     * bitmap and add to the appropriate subset */
+    status = _cairo_scaled_glyph_lookup (scaled_font,
+                                         scaled_font_glyph_index,
+					 CAIRO_SCALED_GLYPH_INFO_PATH,
+                                         &scaled_glyph);
+    if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) {
+        /* Path available. Add to unscaled subset. */
+        key.is_scaled = FALSE;
+        _cairo_sub_font_init_key (&key, scaled_font);
+        if (! _cairo_hash_table_lookup (subsets->unscaled_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_unscaled_subset_limit,
+                                               FALSE);
+            if (sub_font == NULL)
+                return CAIRO_STATUS_NO_MEMORY;
+
+            status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
+                                               &sub_font->base);
+            if (status)
+                return status;
+        }
+    } else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
+        /* No path available. Add to scaled subset. */
+        key.is_scaled = TRUE;
+        _cairo_sub_font_init_key (&key, scaled_font);
+        if (! _cairo_hash_table_lookup (subsets->scaled_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_scaled_subset_limit,
+                                               TRUE);
+            if (sub_font == NULL)
+                return CAIRO_STATUS_NO_MEMORY;
+
+            status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
+                                               &sub_font->base);
+            if (status)
+                return status;
+        }
+    } else {
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
     *font_id = sub_font->font_id;
 
     return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
-						  subset_id, subset_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)
+static cairo_status_t
+_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t              *font_subsets,
+                                             cairo_scaled_font_subset_callback_func_t  font_subset_callback,
+                                             void				      *closure,
+                                             cairo_bool_t                              is_scaled)
 {
     cairo_sub_font_collection_t collection;
 
-    collection.glyphs_size = font_subsets->max_glyphs_per_subset_used;
+    if (is_scaled)
+        collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
+    else
+        collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used;
     collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
     if (collection.glyphs == NULL)
 	return CAIRO_STATUS_NO_MEMORY;
@@ -386,10 +515,36 @@ _cairo_scaled_font_subsets_foreach (cair
     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);
+    if (is_scaled)
+        _cairo_hash_table_foreach (font_subsets->scaled_sub_fonts,
+                                   _cairo_sub_font_collect, &collection);
+    else
+        _cairo_hash_table_foreach (font_subsets->unscaled_sub_fonts,
+                                   _cairo_sub_font_collect, &collection);
 
     free (collection.glyphs);
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+cairo_private cairo_status_t
+_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t		    *font_subsets,
+                                           cairo_scaled_font_subset_callback_func_t  font_subset_callback,
+                                           void					    *closure)
+{
+    return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
+                                                        font_subset_callback,
+                                                        closure,
+                                                        TRUE);
+}
+
+cairo_private cairo_status_t
+_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t		    *font_subsets,
+                                           cairo_scaled_font_subset_callback_func_t  font_subset_callback,
+                                           void					    *closure)
+{
+    return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
+                                                        font_subset_callback,
+                                                        closure,
+                                                        FALSE);
+}
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5f25015..1ef5e4c 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -709,9 +709,9 @@ _cairo_svg_document_emit_font_subset (ca
 static void
 _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
 {
-    _cairo_scaled_font_subsets_foreach (document->font_subsets,
-					_cairo_svg_document_emit_font_subset,
-					document);
+    _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
+                                               _cairo_svg_document_emit_font_subset,
+                                               document);
     _cairo_scaled_font_subsets_destroy (document->font_subsets);
     document->font_subsets = NULL;
 }
@@ -1774,7 +1774,7 @@ _cairo_svg_document_create (cairo_output
     }
 
     /* The use of defs for font glyphs imposes no per-subset limit. */
-    document->font_subsets = _cairo_scaled_font_subsets_create (0);
+    document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX);
     if (document->font_subsets == NULL) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
 	free (document);


More information about the cairo-commit mailing list