From e30cd617c89fa7511d2002a155d4ccdfa2ec9aa9 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 13 May 2008 21:41:56 +0930 Subject: [PATCH] Make font subsetting output fonts in order of the font subset id This ensures that PS/PDF output is always the same for the same cairo input. Previously the order of the embedded fonts depended on the hash key of the fonts which depended on the memory location of fonts. --- src/cairo-scaled-font-subsets.c | 58 +++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c index ee29f89aa..79bc0975e 100644 --- a/src/cairo-scaled-font-subsets.c +++ b/src/cairo-scaled-font-subsets.c @@ -53,18 +53,6 @@ typedef enum { CAIRO_SUBSETS_COMPOSITE } cairo_subsets_type_t; -struct _cairo_scaled_font_subsets { - cairo_subsets_type_t type; - - int max_glyphs_per_unscaled_subset_used; - cairo_hash_table_t *unscaled_sub_fonts; - - int max_glyphs_per_scaled_subset_used; - cairo_hash_table_t *scaled_sub_fonts; - - int num_sub_fonts; -}; - typedef struct _cairo_sub_font { cairo_hash_entry_t base; @@ -79,8 +67,25 @@ typedef struct _cairo_sub_font { int max_glyphs_per_subset; cairo_hash_table_t *sub_font_glyphs; + struct _cairo_sub_font *next; } cairo_sub_font_t; +struct _cairo_scaled_font_subsets { + cairo_subsets_type_t type; + + int max_glyphs_per_unscaled_subset_used; + cairo_hash_table_t *unscaled_sub_fonts; + cairo_sub_font_t *unscaled_sub_fonts_list; + cairo_sub_font_t *unscaled_sub_fonts_list_end; + + int max_glyphs_per_scaled_subset_used; + cairo_hash_table_t *scaled_sub_fonts; + cairo_sub_font_t *scaled_sub_fonts_list; + cairo_sub_font_t *scaled_sub_fonts_list_end; + + int num_sub_fonts; +}; + typedef struct _cairo_sub_font_glyph { cairo_hash_entry_t base; @@ -252,6 +257,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, free (sub_font); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } + sub_font->next = NULL; /* Reserve first glyph in subset for the .notdef glyph */ status = _cairo_sub_font_map_glyph (sub_font, 0, &subset_glyph); @@ -461,6 +467,8 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) free (subsets); return NULL; } + subsets->unscaled_sub_fonts_list = NULL; + subsets->unscaled_sub_fonts_list_end = NULL; subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal); if (! subsets->scaled_sub_fonts) { @@ -468,6 +476,8 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) free (subsets); return NULL; } + subsets->scaled_sub_fonts_list = NULL; + subsets->scaled_sub_fonts_list_end = NULL; return subsets; } @@ -611,11 +621,16 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts, &sub_font->base); + if (status) { _cairo_sub_font_destroy (sub_font); return status; } - + if (!subsets->unscaled_sub_fonts_list) + subsets->unscaled_sub_fonts_list = sub_font; + else + subsets->unscaled_sub_fonts_list_end->next = sub_font; + subsets->unscaled_sub_fonts_list_end = sub_font; subsets->num_sub_fonts++; } } else { @@ -650,7 +665,11 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, _cairo_sub_font_destroy (sub_font); return status; } - + if (!subsets->scaled_sub_fonts_list) + subsets->scaled_sub_fonts_list = sub_font; + else + subsets->scaled_sub_fonts_list_end->next = sub_font; + subsets->scaled_sub_fonts_list_end = sub_font; subsets->num_sub_fonts++; } } @@ -667,6 +686,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t cairo_bool_t is_scaled) { cairo_sub_font_collection_t collection; + cairo_sub_font_t *sub_font; if (is_scaled) collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used; @@ -685,12 +705,14 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t collection.status = CAIRO_STATUS_SUCCESS; if (is_scaled) - _cairo_hash_table_foreach (font_subsets->scaled_sub_fonts, - _cairo_sub_font_collect, &collection); + sub_font = font_subsets->scaled_sub_fonts_list; else - _cairo_hash_table_foreach (font_subsets->unscaled_sub_fonts, - _cairo_sub_font_collect, &collection); + sub_font = font_subsets->unscaled_sub_fonts_list; + while (sub_font) { + _cairo_sub_font_collect (sub_font, &collection); + sub_font = sub_font->next; + } free (collection.glyphs); return collection.status;