From e79360e45a697c6c615061129bb5cd81063d7f02 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 11 Mar 2009 17:28:28 +0000 Subject: [PATCH] - Push changes from git --- pango-1.23.0-g5317893.patch | 1937 +++++++++++++++++++++++++++++++++++ pango.spec | 9 +- 2 files changed, 1945 insertions(+), 1 deletion(-) create mode 100644 pango-1.23.0-g5317893.patch diff --git a/pango-1.23.0-g5317893.patch b/pango-1.23.0-g5317893.patch new file mode 100644 index 0000000..f56277b --- /dev/null +++ b/pango-1.23.0-g5317893.patch @@ -0,0 +1,1937 @@ +diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt +index 7ed853c..0fbdc22 100644 +--- a/docs/pango-sections.txt ++++ b/docs/pango-sections.txt +@@ -919,6 +919,7 @@ PangoFcFontMapClass + pango_fc_font_map_create_context + PangoFcDecoderFindFunc + pango_fc_font_map_add_decoder_find_func ++pango_fc_font_map_find_decoder + pango_fc_font_map_cache_clear + pango_fc_font_map_shutdown + pango_fc_font_description_from_pattern +diff --git a/docs/tmpl/pangofc-font.sgml b/docs/tmpl/pangofc-font.sgml +index 95ac1dd..a1b055c 100644 +--- a/docs/tmpl/pangofc-font.sgml ++++ b/docs/tmpl/pangofc-font.sgml +@@ -40,6 +40,11 @@ Fontconfig-based backend involves deriving from both + + + ++ ++ ++ ++ ++ + + + +diff --git a/docs/tmpl/pangofc-fontmap.sgml b/docs/tmpl/pangofc-fontmap.sgml +index bcfae81..ee6cca0 100644 +--- a/docs/tmpl/pangofc-fontmap.sgml ++++ b/docs/tmpl/pangofc-fontmap.sgml +@@ -86,6 +86,16 @@ Fontconfig-based backend involves deriving from both + @dnotify: + + ++ ++ ++ ++ ++ ++@fcfontmap: ++@pattern: ++@Returns: ++ ++ + + + +diff --git a/pango-view/Makefile.am b/pango-view/Makefile.am +index 9780c14..c406975 100644 +--- a/pango-view/Makefile.am ++++ b/pango-view/Makefile.am +@@ -23,7 +23,6 @@ TEST_TEXTS = \ + GLASS.txt + + EXTRA_DIST = \ +- viewer-win32.c \ + $(TEST_TEXTS) + + CLEANFILES = pangorc +diff --git a/pango-view/viewer-win32.c b/pango-view/viewer-win32.c +deleted file mode 100644 +index 468a6cc..0000000 +--- a/pango-view/viewer-win32.c ++++ /dev/null +@@ -1,748 +0,0 @@ +-/* Pango +- * viewer-win32.c: Example program to view a UTF-8 encoding file +- * using Pango to render result. +- * +- * Copyright (C) 1999 Red Hat Software +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * Library General Public License for more details. +- * +- * You should have received a copy of the GNU Library General Public +- * License along with this library; if not, write to the +- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, +- * Boston, MA 02111-1307, USA. +- */ +-#include "config.h" +-#include +-#include +- +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#define BUFSIZE 1024 +- +-typedef struct _Paragraph Paragraph; +- +-/* Structure representing a paragraph +- */ +-struct _Paragraph { +- char *text; +- int length; +- int height; /* Height, in pixels */ +- PangoLayout *layout; +-}; +- +-GList *paragraphs; +- +-static PangoFontDescription *font_description; +-static Paragraph *highlight_para; +-static int highlight_offset; +- +-GtkWidget *styles_combo; +- +-static GtkWidget *message_label; +-GtkWidget *layout; +- +-PangoContext *context; +- +-static void fill_styles_combo (GtkWidget *combo); +- +-/* Read an entire file into a string +- */ +-static char * +-read_file(char *name) +-{ +- GString *inbuf; +- FILE *file; +- char *text; +- char buffer[BUFSIZE]; +- +- file = fopen (name, "r"); +- if (!file) +- { +- fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname (), name); +- return NULL; +- } +- +- inbuf = g_string_new (NULL); +- while (1) +- { +- char *bp = fgets (buffer, BUFSIZE-1, file); +- if (ferror (file)) +- { +- fprintf (stderr, "%s: Error reading %s\n", g_get_prgname (), name); +- g_string_free (inbuf, TRUE); +- return NULL; +- } +- else if (bp == NULL) +- break; +- +- g_string_append (inbuf, buffer); +- } +- +- fclose (file); +- +- text = inbuf->str; +- g_string_free (inbuf, FALSE); +- +- return text; +-} +- +-/* Take a UTF8 string and break it into paragraphs on \n characters +- */ +-static GList * +-split_paragraphs (char *text) +-{ +- char *p = text; +- char *next; +- gunichar wc; +- GList *result = NULL; +- char *last_para = text; +- +- while (*p) +- { +- wc = g_utf8_get_char (p); +- next = g_utf8_next_char (p); +- if (wc == (gunichar)-1) +- { +- fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ()); +- g_list_foreach (result, (GFunc)g_free, NULL); +- return NULL; +- } +- if (!*p || !wc || wc == '\n') +- { +- Paragraph *para = g_new (Paragraph, 1); +- para->text = last_para; +- para->length = p - last_para; +- para->layout = pango_layout_new (context); +- pango_layout_set_text (para->layout, para->text, para->length); +- para->height = 0; +- +- last_para = next; +- +- result = g_list_prepend (result, para); +- } +- if (!wc) /* incomplete character at end */ +- break; +- p = next; +- } +- +- return g_list_reverse (result); +-} +- +-/* Given an x-y position, return the paragraph and offset +- * within the paragraph of the click. +- */ +-gboolean +-xy_to_cp (int width, int x, int y, Paragraph **para_return, int *index) +-{ +- GList *para_list; +- int height = 0; +- +- *para_return = NULL; +- +- para_list = paragraphs; +- while (para_list && height < y) +- { +- Paragraph *para = para_list->data; +- +- if (height + para->height >= y) +- { +- gboolean result = pango_layout_xy_to_index (para->layout, +- x * PANGO_SCALE, +- (y - height) * PANGO_SCALE, +- index, NULL); +- if (result && para_return) +- *para_return = para; +- +- return result; +- } +- +- height += para->height; +- para_list = para_list->next; +- } +- +- return FALSE; +-} +- +-/* Given a paragraph and offset in that paragraph, find the +- * bounding rectangle for the character at the offset. +- */ +-void +-char_bounds (Paragraph *para, int index, int width, PangoRectangle *rect) +-{ +- GList *para_list; +- +- int height = 0; +- +- para_list = paragraphs; +- while (para_list) +- { +- Paragraph *cur_para = para_list->data; +- +- if (cur_para == para) +- { +- PangoRectangle pos; +- +- pango_layout_index_to_pos (cur_para->layout, index, &pos); +- +- rect->x = PANGO_PIXELS (MIN (pos.x, pos.x + pos.width)); +- rect->width = PANGO_PIXELS (ABS (pos.width)); +- rect->y = height + PANGO_PIXELS (pos.y); +- rect->height = PANGO_PIXELS (pos.height); +- } +- +- height += cur_para->height; +- para_list = para_list->next; +- } +-} +- +-/* XOR a rectangle over a given character +- */ +-void +-xor_char (GtkWidget *layout, GdkRectangle *clip_rect, +- Paragraph *para, int offset) +-{ +- static GdkGC *gc; +- PangoRectangle rect; /* GdkRectangle in 1.2 is too limited +- */ +- if (!gc) +- { +- GdkGCValues values; +- values.foreground = layout->style->white.pixel ? +- layout->style->white : layout->style->black; +- values.function = GDK_XOR; +- gc = gdk_gc_new_with_values (GTK_LAYOUT (layout)->bin_window, +- &values, +- GDK_GC_FOREGROUND | GDK_GC_FUNCTION); +- } +- +- gdk_gc_set_clip_rectangle (gc, clip_rect); +- +- char_bounds (para, offset, layout->allocation.width, &rect); +- +- rect.y -= GTK_LAYOUT (layout)->yoffset; +- +- if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height)) +- gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE, +- rect.x, rect.y, rect.width, rect.height); +-} +- +-/* Handle a size allocation by re-laying-out each paragraph to +- * the new width, setting the new size for the layout and +- * then queing a redraw +- */ +-void +-size_allocate (GtkWidget *layout, GtkAllocation *allocation) +-{ +- GList *tmp_list; +- guint height = 0; +- PangoDirection base_dir = pango_context_get_base_dir (context); +- +- tmp_list = paragraphs; +- while (tmp_list) +- { +- Paragraph *para = tmp_list->data; +- PangoRectangle logical_rect; +- +- tmp_list = tmp_list->next; +- +- pango_layout_set_alignment (para->layout, +- base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); +- pango_layout_set_width (para->layout, layout->allocation.width * PANGO_SCALE); +- +- pango_layout_get_extents (para->layout, NULL, &logical_rect); +- para->height = PANGO_PIXELS (logical_rect.height); +- +- height += para->height; +- } +- +- gtk_layout_set_size (GTK_LAYOUT (layout), allocation->width, height); +- +- if (GTK_LAYOUT (layout)->yoffset + allocation->height > height) +- gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, (float)(height - allocation->height)); +-} +- +-/* Handle a draw/expose by finding the paragraphs that intersect +- * the region and reexposing them. +- */ +-void +-draw (GtkWidget *layout, GdkRectangle *area) +-{ +- GList *tmp_list; +- guint height = 0; +- HDC hdc; +- const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND|GDK_GC_FONT; +- +- gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, +- layout->style->base_gc[layout->state], +- TRUE, +- area->x, area->y, +- area->width, area->height); +- +- gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area); +- +- hdc = gdk_win32_hdc_get (GTK_LAYOUT (layout)->bin_window, +- layout->style->text_gc[GTK_STATE_NORMAL], +- mask); +- tmp_list = paragraphs; +- while (tmp_list && +- height < area->y + area->height + GTK_LAYOUT (layout)->yoffset) +- { +- Paragraph *para = tmp_list->data; +- tmp_list = tmp_list->next; +- +- if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y) +- pango_win32_render_layout (hdc, para->layout, +- 0, height - GTK_LAYOUT (layout)->yoffset); +- height += para->height; +- } +- +- gdk_win32_hdc_release (GTK_LAYOUT (layout)->bin_window, +- layout->style->text_gc[GTK_STATE_NORMAL], +- mask); +- gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL); +- +- if (highlight_para) +- xor_char (layout, area, highlight_para, highlight_offset); +-} +- +-gboolean +-expose (GtkWidget *layout, GdkEventExpose *event) +-{ +- if (event->window == GTK_LAYOUT (layout)->bin_window) +- draw (layout, &event->area); +- +- return TRUE; +-} +- +-void +-button_press (GtkWidget *layout, GdkEventButton *event) +-{ +- Paragraph *para = NULL; +- int offset; +- gchar *message; +- +- xy_to_cp (layout->allocation.width, +- event->x, event->y + GTK_LAYOUT (layout)->yoffset, +- ¶, &offset); +- +- if (highlight_para) +- xor_char (layout, NULL, highlight_para, highlight_offset); +- +- highlight_para = para; +- highlight_offset = offset; +- +- if (para) +- { +- gunichar wc; +- +- wc = g_utf8_get_char (para->text + offset); +- message = g_strdup_printf ("Current char: U%04x", wc); +- +- xor_char (layout, NULL, highlight_para, highlight_offset); +- } +- else +- message = g_strdup_printf ("Current char:"); +- +- gtk_label_set_text (GTK_LABEL (message_label), message); +- g_free (message); +-} +- +-static void +-checkbutton_toggled (GtkWidget *widget, gpointer data) +-{ +- GList *para_list; +- +- pango_context_set_base_dir (context, GTK_TOGGLE_BUTTON (widget)->active ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); +- +- para_list = paragraphs; +- while (para_list) +- { +- Paragraph *para = para_list->data; +- +- pango_layout_context_changed (para->layout); +- para_list = para_list->next; +- } +- +- gtk_widget_queue_resize (layout); +-} +- +-static void +-reload_font () +-{ +- GList *para_list; +- +- pango_context_set_font_description (context, font_description); +- +- para_list = paragraphs; +- while (para_list) +- { +- Paragraph *para = para_list->data; +- +- pango_layout_context_changed (para->layout); +- para_list = para_list->next; +- } +- +- if (layout) +- gtk_widget_queue_resize (layout); +-} +- +-void +-set_family (GtkWidget *entry, gpointer data) +-{ +- gchar *family_name = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); +- if (!family_name || family_name[0] == '\0') +- return; +- pango_font_description_set_family(font_description, family_name); +- fill_styles_combo (styles_combo); +-} +- +-void +-set_style (GtkWidget *entry, gpointer data) +-{ +- char *str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); +- PangoFontDescription *tmp_desc; +- +- tmp_desc = pango_font_description_from_string (str); +- +- pango_font_description_set_style(font_description, pango_font_description_get_style(tmp_desc)); +- pango_font_description_set_variant(font_description, pango_font_description_get_variant(tmp_desc)); +- pango_font_description_set_weight(font_description, pango_font_description_get_weight(tmp_desc)); +- pango_font_description_set_stretch(font_description, pango_font_description_get_stretch(tmp_desc)); +- +- pango_font_description_free (tmp_desc); +- g_free (str); +- +- reload_font (); +-} +- +-void +-font_size_changed (GtkAdjustment *adj) +-{ +- pango_font_description_set_size(font_description, (int)(adj->value * PANGO_SCALE + 0.5)); +- reload_font(); +-} +- +-static int +-compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b) +-{ +- int val = strcmp (pango_font_description_get_family(a), pango_font_description_get_family(b)); +- if (val != 0) +- return val; +- +- if (pango_font_description_get_weight(a) != pango_font_description_get_weight(b)) +- return pango_font_description_get_weight(a) - pango_font_description_get_weight(b); +- +- if (pango_font_description_get_style(a) != pango_font_description_get_style(b)) +- return pango_font_description_get_style(a) - pango_font_description_get_style(b); +- +- if (pango_font_description_get_stretch(a) != pango_font_description_get_stretch(b)) +- return pango_font_description_get_stretch(a) - pango_font_description_get_stretch(b); +- +- if (pango_font_description_get_stretch(a) != pango_font_description_get_stretch(b)) +- return pango_font_description_get_stretch(a) - pango_font_description_get_stretch(b); +- +- return 0; +-} +- +-static int +-font_description_sort_func (const void *a, const void *b) +-{ +- return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b); +-} +- +-typedef struct +-{ +- PangoFontDescription **descs; +- int n_descs; +-} FontDescInfo; +- +-static void +-free_info (FontDescInfo *info) +-{ +- pango_font_descriptions_free (info->descs, info->n_descs); +-} +- +-static void +-fill_styles_combo (GtkWidget *combo) +-{ +- int i; +- GList *style_list = NULL; +- PangoFontFace **faces; +- PangoFontFamily *family, **families; +- FontDescInfo *info; +- int n_families; +- const char *family_name = pango_font_description_get_family(font_description); +- +- /* +- * Now map back the given family name to the family. There are more efficient +- * ways to handle this but it should not matter much ... +- */ +- pango_context_list_families (context, &families, &n_families); +- g_assert(n_families > 0); +- family = families[0]; /* just in case */ +- for (i = 0; i < n_families; i++) +- { +- if (0 == g_strcasecmp(pango_font_family_get_name(families[i]), family_name)) +- { +- family = families[i]; +- break; +- } +- } +- g_free (families); +- +- info = g_new (FontDescInfo, 1); +- pango_font_family_list_faces (family, &faces, &info->n_descs); +- +- info->descs = g_new0 (PangoFontDescription*, info->n_descs); +- for (i = 0; i < info->n_descs; i++) +- { +- info->descs[i] = pango_font_face_describe(faces[i]); +- } +- g_free (faces); +- +- gtk_object_set_data_full (GTK_OBJECT (combo), "descs", info, (GtkDestroyNotify)free_info); +- +- qsort (info->descs, info->n_descs, sizeof(PangoFontDescription *), font_description_sort_func); +- +- for (i=0; in_descs; i++) +- { +- char *str; +- +- PangoFontDescription *tmp_desc; +- +- tmp_desc = info->descs[i]; +- pango_font_description_set_family(tmp_desc, NULL); +- pango_font_description_unset_fields(tmp_desc, PANGO_FONT_MASK_SIZE); +- +- str = pango_font_description_to_string (tmp_desc); +- style_list = g_list_prepend (style_list, str); +- } +- +- style_list = g_list_reverse (style_list); +- +- gtk_combo_set_popdown_strings (GTK_COMBO (combo), style_list); +- g_list_foreach (style_list, (GFunc)g_free, NULL); +-} +- +-static GtkWidget * +-make_styles_combo () +-{ +- GtkWidget *combo; +- +- combo = gtk_combo_new (); +- gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE); +- gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE); +- +- gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed", +- GTK_SIGNAL_FUNC (set_style), NULL); +- +- styles_combo = combo; +- fill_styles_combo (combo); +- +- return combo; +-} +- +-static int +-cmp_families (const PangoFontFamily** a, const PangoFontFamily** b) +-{ +- return strcmp (pango_font_family_get_name (*a), pango_font_family_get_name (*b)); +-} +- +-GtkWidget * +-make_families_menu () +-{ +- GtkWidget *combo; +- int n_families; +- PangoFontFamily **families; +- GList *family_list = NULL; +- int i; +- +- pango_context_list_families (context, &families, &n_families); +- qsort (families, n_families, sizeof(char *), cmp_families); +- +- for (i=0; ientry), FALSE); +- +- gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), pango_font_description_get_family(font_description)); +- +- gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed", +- GTK_SIGNAL_FUNC (set_family), NULL); +- +- g_list_free (family_list); +- +- return combo; +-} +- +- +-GtkWidget * +-make_font_selector (void) +-{ +- GtkWidget *hbox; +- GtkWidget *util_hbox; +- GtkWidget *label; +- GtkWidget *option_menu; +- GtkWidget *spin_button; +- GtkAdjustment *adj; +- +- hbox = gtk_hbox_new (FALSE, 4); +- +- util_hbox = gtk_hbox_new (FALSE, 2); +- label = gtk_label_new ("Family:"); +- gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0); +- option_menu = make_families_menu (); +- gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0); +- +- gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0); +- +- util_hbox = gtk_hbox_new (FALSE, 2); +- label = gtk_label_new ("Style:"); +- gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0); +- option_menu = make_styles_combo (); +- gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0); +- +- gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0); +- +- util_hbox = gtk_hbox_new (FALSE, 2); +- label = gtk_label_new ("Size:"); +- gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0); +- spin_button = gtk_spin_button_new (NULL, 1., 0); +- gtk_box_pack_start (GTK_BOX (util_hbox), spin_button, FALSE, FALSE, 0); +- +- gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0); +- +- adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin_button)); +- adj->value = PANGO_PIXELS (pango_font_description_get_size(font_description)); +- adj->lower = 0; +- adj->upper = 1024; +- adj->step_increment = 1; +- adj->page_size = 10; +- gtk_adjustment_changed (adj); +- gtk_adjustment_value_changed (adj); +- +- gtk_signal_connect (GTK_OBJECT (adj), "value_changed", +- GTK_SIGNAL_FUNC (font_size_changed), NULL); +- +- return hbox; +-} +- +-int +-main (int argc, char **argv) +-{ +- char *text; +- GtkWidget *window; +- GtkWidget *scrollwin; +- GtkWidget *vbox, *hbox; +- GtkWidget *frame; +- GtkWidget *checkbutton; +- +- gtk_init (&argc, &argv); +- +- if (argc != 2) +- { +- fprintf (stderr, "Usage: %s FILE\n", g_get_prgname ()); +- exit(1); +- } +- +- /* Create the list of paragraphs from the supplied file +- */ +- text = read_file (argv[1]); +- if (!text) +- exit(1); +- +- context = pango_win32_get_context (); +- +- paragraphs = split_paragraphs (text); +- +- pango_context_set_language (context, pango_language_from_string ("en_US")); +- pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); +- +- font_description = pango_font_description_new (); +- pango_font_description_set_family(font_description, "sans"); +- pango_font_description_set_size(font_description, 16 * PANGO_SCALE); +-#if 0 /* default init ok? */ +- font_description.style = PANGO_STYLE_NORMAL; +- font_description.variant = PANGO_VARIANT_NORMAL; +- font_description.weight = 500; +- font_description.stretch = PANGO_STRETCH_NORMAL; +-#endif +- +- pango_context_set_font_description (context, font_description); +- +- /* Create the user interface +- */ +- window = gtk_window_new (GTK_WINDOW_TOPLEVEL); +- gtk_window_set_default_size (GTK_WINDOW (window), 400, 400); +- +- gtk_signal_connect (GTK_OBJECT (window), "destroy", +- GTK_SIGNAL_FUNC (gtk_main_quit), NULL); +- +- vbox = gtk_vbox_new (FALSE, 4); +- gtk_container_add (GTK_CONTAINER (window), vbox); +- +- hbox = make_font_selector (); +- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); +- +- scrollwin = gtk_scrolled_window_new (NULL, NULL); +- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin), +- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); +- +- gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0); +- +- layout = gtk_layout_new (NULL, NULL); +- gtk_widget_set_events (layout, GDK_BUTTON_PRESS_MASK); +- gtk_widget_set_app_paintable (layout, TRUE); +- +- gtk_signal_connect (GTK_OBJECT (layout), "size_allocate", +- GTK_SIGNAL_FUNC (size_allocate), paragraphs); +- gtk_signal_connect (GTK_OBJECT (layout), "expose_event", +- GTK_SIGNAL_FUNC (expose), paragraphs); +- gtk_signal_connect (GTK_OBJECT (layout), "draw", +- GTK_SIGNAL_FUNC (draw), paragraphs); +- gtk_signal_connect (GTK_OBJECT (layout), "button_press_event", +- GTK_SIGNAL_FUNC (button_press), paragraphs); +-#if GTK_CHECK_VERSION (1,3,2) +- gtk_widget_set_double_buffered (layout, FALSE); +-#endif +- gtk_container_add (GTK_CONTAINER (scrollwin), layout); +- +- frame = gtk_frame_new (NULL); +- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); +- gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); +- +- message_label = gtk_label_new ("Current char:"); +- gtk_misc_set_padding (GTK_MISC (message_label), 1, 1); +- gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5); +- gtk_container_add (GTK_CONTAINER (frame), message_label); +- +- checkbutton = gtk_check_button_new_with_label ("Use RTL global direction"); +- gtk_signal_connect (GTK_OBJECT (checkbutton), "toggled", +- GTK_SIGNAL_FUNC (checkbutton_toggled), NULL); +- gtk_box_pack_start (GTK_BOX (vbox), checkbutton, FALSE, FALSE, 0); +- +- gtk_widget_show_all (window); +- +- gtk_main (); +- +- return 0; +-} +diff --git a/pango/glyphstring.c b/pango/glyphstring.c +index 42601d5..8fb7031 100644 +--- a/pango/glyphstring.c ++++ b/pango/glyphstring.c +@@ -61,14 +61,28 @@ pango_glyph_string_set_size (PangoGlyphString *string, gint new_len) + while (new_len > string->space) + { + if (string->space == 0) +- string->space = 1; ++ { ++ string->space = 4; ++ } + else +- string->space *= 2; +- +- if (string->space < 0) + { +- g_warning ("glyph string length overflows maximum integer size, truncated"); +- new_len = string->space = G_MAXINT - 8; ++ const guint max_space = ++ MIN (G_MAXINT, G_MAXSIZE / MAX (sizeof(PangoGlyphInfo), sizeof(gint))); ++ ++ guint more_space = (guint)string->space * 2; ++ ++ if (more_space > max_space) ++ { ++ more_space = max_space; ++ ++ if ((guint)new_len > max_space) ++ { ++ g_error ("%s: failed to allocate glyph string of length %i\n", ++ G_STRLOC, new_len); ++ } ++ } ++ ++ string->space = more_space; + } + } + +diff --git a/pango/opentype/Makefile.am b/pango/opentype/Makefile.am +index 5cf0f13..b845eb6 100644 +--- a/pango/opentype/Makefile.am ++++ b/pango/opentype/Makefile.am +@@ -1,8 +1,8 @@ + ## Process this file with automake to produce Makefile.in + + INCLUDES = \ +- $(FREETYPE_CFLAGS) \ +- -I $(srcdir) ++ -I $(srcdir) \ ++ $(FREETYPE_CFLAGS) + + noinst_LTLIBRARIES = libharfbuzz-1.la + +diff --git a/pango/opentype/harfbuzz-gpos.c b/pango/opentype/harfbuzz-gpos.c +index 2961940..c78dcba 100644 +--- a/pango/opentype/harfbuzz-gpos.c ++++ b/pango/opentype/harfbuzz-gpos.c +@@ -2080,9 +2080,13 @@ static void Free_BaseArray( HB_BaseArray* ba, + if ( ba->BaseRecord ) + { + br = ba->BaseRecord; +- bans = br[0].BaseAnchor; + +- FREE( bans ); ++ if ( ba->BaseCount ) ++ { ++ bans = br[0].BaseAnchor; ++ FREE( bans ); ++ } ++ + FREE( br ); + } + } +@@ -2811,9 +2815,13 @@ static void Free_Mark2Array( HB_Mark2Array* m2a, + if ( m2a->Mark2Record ) + { + m2r = m2a->Mark2Record; +- m2ans = m2r[0].Mark2Anchor; + +- FREE( m2ans ); ++ if ( m2a->Mark2Count ) ++ { ++ m2ans = m2r[0].Mark2Anchor; ++ FREE( m2ans ); ++ } ++ + FREE( m2r ); + } + } +@@ -3857,6 +3865,9 @@ static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi, + if ( error ) + return error; + ++ if (cpf2->MaxContextLength < 1) ++ return HB_Err_Not_Covered; ++ + if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, HB_UShort ) ) + return error; + +@@ -5139,6 +5150,9 @@ static HB_Error Lookup_ChainContextPos2( + return error; + known_backtrack_classes = 0; + ++ if (ccpf2->MaxInputLength < 1) ++ return HB_Err_Not_Covered; ++ + if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, HB_UShort ) ) + goto End3; + known_input_classes = 1; +diff --git a/pango/opentype/harfbuzz-gsub.c b/pango/opentype/harfbuzz-gsub.c +index f504bf0..c05f20d 100644 +--- a/pango/opentype/harfbuzz-gsub.c ++++ b/pango/opentype/harfbuzz-gsub.c +@@ -1896,6 +1896,9 @@ static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub, + if ( error ) + return error; + ++ if (csf2->MaxContextLength < 1) ++ return HB_Err_Not_Covered; ++ + if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) ) + return error; + +@@ -3159,6 +3162,9 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub, + return error; + known_backtrack_classes = 0; + ++ if (ccsf2->MaxInputLength < 1) ++ return HB_Err_Not_Covered; ++ + if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) ) + goto End3; + known_input_classes = 1; +diff --git a/pango/opentype/harfbuzz-impl.c b/pango/opentype/harfbuzz-impl.c +index a3a5589..ffcef80 100644 +--- a/pango/opentype/harfbuzz-impl.c ++++ b/pango/opentype/harfbuzz-impl.c +@@ -30,7 +30,7 @@ + + + HB_INTERNAL HB_Pointer +-_hb_alloc( HB_UInt size, ++_hb_alloc( size_t size, + HB_Error *perror ) + { + HB_Error error = 0; +@@ -50,7 +50,7 @@ _hb_alloc( HB_UInt size, + + HB_INTERNAL HB_Pointer + _hb_realloc( HB_Pointer block, +- HB_UInt new_size, ++ size_t new_size, + HB_Error *perror ) + { + HB_Pointer block2 = NULL; +diff --git a/pango/opentype/harfbuzz-impl.h b/pango/opentype/harfbuzz-impl.h +index 0442e4e..f886e67 100644 +--- a/pango/opentype/harfbuzz-impl.h ++++ b/pango/opentype/harfbuzz-impl.h +@@ -32,6 +32,8 @@ + + #include "harfbuzz-global.h" + ++#include ++ + HB_BEGIN_HEADER + + #ifndef HB_INTERNAL +@@ -95,12 +97,12 @@ HB_BEGIN_HEADER + + + HB_INTERNAL HB_Pointer +-_hb_alloc( HB_UInt size, ++_hb_alloc( size_t size, + HB_Error *perror_ ); + + HB_INTERNAL HB_Pointer + _hb_realloc( HB_Pointer block, +- HB_UInt new_size, ++ size_t new_size, + HB_Error *perror_ ); + + HB_INTERNAL void +diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c +index 73fb147..7637117 100644 +--- a/pango/pango-coverage.c ++++ b/pango/pango-coverage.c +@@ -42,7 +42,6 @@ struct _PangoCoverage + { + guint ref_count; + int n_blocks; +- int data_size; + + PangoBlockInfo *blocks; + }; +@@ -145,7 +144,7 @@ pango_coverage_unref (PangoCoverage *coverage) + if (g_atomic_int_dec_and_test ((int *) &coverage->ref_count)) + { + for (i=0; in_blocks; i++) +- g_free (coverage->blocks[i].data); ++ g_slice_free1 (64, coverage->blocks[i].data); + + g_free (coverage->blocks); + g_slice_free (PangoCoverage, coverage); +@@ -236,7 +235,7 @@ pango_coverage_set (PangoCoverage *coverage, + if (level == coverage->blocks[block_index].level) + return; + +- data = g_new (guchar, 64); ++ data = g_slice_alloc (64); + coverage->blocks[block_index].data = data; + + byte = coverage->blocks[block_index].level | +@@ -393,15 +392,18 @@ pango_coverage_to_bytes (PangoCoverage *coverage, + guchar *data = coverage->blocks[i].data; + guchar first_val = data[0]; + +- for (j = 1 ; j < 64; j++) +- if (data[j] != first_val) +- break; +- +- if (j == 64) ++ if (first_val == 0 || first_val == 0xff) + { +- g_free (data); +- coverage->blocks[i].data = NULL; +- coverage->blocks[i].level = first_val & 0x3; ++ for (j = 1 ; j < 64; j++) ++ if (data[j] != first_val) ++ break; ++ ++ if (j == 64) ++ { ++ g_slice_free1 (64, data); ++ coverage->blocks[i].data = NULL; ++ coverage->blocks[i].level = first_val & 0x3; ++ } + } + } + +diff --git a/pango/pango-language.c b/pango/pango-language.c +index cae27ef..bfde308 100644 +--- a/pango/pango-language.c ++++ b/pango/pango-language.c +@@ -688,7 +688,7 @@ pango_language_includes_script (PangoLanguage *language, + static PangoLanguage ** + parse_default_languages (void) + { +- char *p; ++ char *p, *p_copy; + gboolean done = FALSE; + GArray *langs; + +@@ -700,7 +700,7 @@ parse_default_languages (void) + if (p == NULL) + return NULL; + +- p = g_strdup (p); ++ p_copy = p = g_strdup (p); + + langs = g_array_new (TRUE, FALSE, sizeof (PangoLanguage *)); + +@@ -727,6 +727,8 @@ parse_default_languages (void) + p = end + 1; + } + ++ g_free (p_copy); ++ + return (PangoLanguage **) g_array_free (langs, FALSE); + } + +diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c +index 3039f9f..3ac166e 100644 +--- a/pango/pangocairo-fcfont.c ++++ b/pango/pangocairo-fcfont.c +@@ -223,6 +223,7 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, + + cffont = g_object_new (PANGO_TYPE_CAIRO_FC_FONT, + "pattern", pattern, ++ "fontmap", cffontmap, + NULL); + + size = get_font_size (pattern) / +diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c +index 133a4df..976b0d8 100644 +--- a/pango/pangofc-font.c ++++ b/pango/pangofc-font.c +@@ -34,22 +34,8 @@ + + enum { + PROP_0, +- PROP_PATTERN +-}; +- +-typedef struct _GUnicharToGlyphCacheEntry GUnicharToGlyphCacheEntry; +- +-/* An entry in the fixed-size cache for the gunichar -> glyph mapping. +- * The cache is indexed by the lower N bits of the gunichar (see +- * GLYPH_CACHE_NUM_ENTRIES). For scripts with few code points, +- * this should provide pretty much instant lookups. +- * +- * The "ch" field is zero if that cache entry is invalid. +- */ +-struct _GUnicharToGlyphCacheEntry +-{ +- gunichar ch; +- PangoGlyph glyph; ++ PROP_PATTERN, ++ PROP_FONTMAP + }; + + typedef struct _PangoFcFontPrivate PangoFcFontPrivate; +@@ -58,12 +44,9 @@ struct _PangoFcFontPrivate + { + PangoFcDecoder *decoder; + PangoFcFontKey *key; +- GUnicharToGlyphCacheEntry *char_to_glyph_cache; ++ PangoFcCmapCache *cmap_cache; + }; + +-#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */ +-#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1) +- + static gboolean pango_fc_font_real_has_char (PangoFcFont *font, + gunichar wc); + static guint pango_fc_font_real_get_glyph (PangoFcFont *font, +@@ -121,6 +104,13 @@ pango_fc_font_class_init (PangoFcFontClass *class) + "The fontconfig pattern for this font", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property (object_class, PROP_FONTMAP, ++ g_param_spec_object ("fontmap", ++ "Font Map", ++ "The PangoFc font map this font is associated with", ++ PANGO_TYPE_FC_FONT_MAP, ++ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS)); + + g_type_class_add_private (object_class, sizeof (PangoFcFontPrivate)); + } +@@ -158,7 +148,8 @@ pango_fc_font_finalize (GObject *object) + if (priv->decoder) + _pango_fc_font_set_decoder (fcfont, NULL); + +- g_free (priv->char_to_glyph_cache); ++ if (priv->cmap_cache) ++ _pango_fc_cmap_cache_unref (priv->cmap_cache); + + G_OBJECT_CLASS (pango_fc_font_parent_class)->finalize (object); + } +@@ -203,11 +194,12 @@ pango_fc_font_set_property (GObject *object, + const GValue *value, + GParamSpec *pspec) + { ++ PangoFcFont *fcfont = PANGO_FC_FONT (object); ++ + switch (prop_id) + { + case PROP_PATTERN: + { +- PangoFcFont *fcfont = PANGO_FC_FONT (object); + FcPattern *pattern = g_value_get_pointer (value); + + g_return_if_fail (pattern != NULL); +@@ -219,11 +211,30 @@ pango_fc_font_set_property (GObject *object, + fcfont->is_hinted = pattern_is_hinted (pattern); + fcfont->is_transformed = pattern_is_transformed (pattern); + } +- break; ++ goto set_decoder; ++ ++ case PROP_FONTMAP: ++ { ++ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (g_value_get_object (value)); ++ ++ g_return_if_fail (fcfont->fontmap == NULL); ++ fcfont->fontmap = (PangoFontMap *) fcfontmap; ++ if (fcfont->fontmap) ++ g_object_add_weak_pointer (G_OBJECT (fcfont->fontmap), (gpointer *) (gpointer) &fcfont->fontmap); ++ } ++ goto set_decoder; ++ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +- break; ++ return; + } ++ ++set_decoder: ++ /* set decoder if both pattern and fontmap are set now */ ++ if (fcfont->font_pattern && fcfont->fontmap) ++ _pango_fc_font_set_decoder (fcfont, ++ pango_fc_font_map_find_decoder ((PangoFcFontMap *) fcfont->fontmap, ++ fcfont->font_pattern)); + } + + static void +@@ -240,6 +251,12 @@ pango_fc_font_get_property (GObject *object, + g_value_set_pointer (value, fcfont->font_pattern); + } + break; ++ case PROP_FONTMAP: ++ { ++ PangoFcFont *fcfont = PANGO_FC_FONT (object); ++ g_value_set_object (value, fcfont->fontmap); ++ } ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -585,23 +602,25 @@ static guint + pango_fc_font_real_get_glyph (PangoFcFont *font, + gunichar wc) + { ++ PangoFcFontPrivate *priv = font->priv; + FT_Face face; + FT_UInt index; + + guint idx; +- GUnicharToGlyphCacheEntry *entry; ++ PangoFcCmapCacheEntry *entry; + +- PangoFcFontPrivate *priv = font->priv; + +- if (G_UNLIKELY (priv->char_to_glyph_cache == NULL)) ++ if (G_UNLIKELY (priv->cmap_cache == NULL)) + { +- priv->char_to_glyph_cache = g_new0 (GUnicharToGlyphCacheEntry, GLYPH_CACHE_NUM_ENTRIES); +- /* Make sure all cache entries are invalid initially */ +- priv->char_to_glyph_cache[0].ch = 1; /* char 1 cannot happen in bucket 0 */ ++ priv->cmap_cache = _pango_fc_font_map_get_cmap_cache ((PangoFcFontMap *) font->fontmap, ++ font); ++ ++ if (G_UNLIKELY (!priv->cmap_cache)) ++ return 0; + } + +- idx = wc & GLYPH_CACHE_MASK; +- entry = priv->char_to_glyph_cache + idx; ++ idx = wc & CMAP_CACHE_MASK; ++ entry = priv->cmap_cache->entries + idx; + + if (entry->ch != wc) + { +diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c +index 491b912..28acdf7 100644 +--- a/pango/pangofc-fontmap.c ++++ b/pango/pangofc-fontmap.c +@@ -19,7 +19,7 @@ + * Boston, MA 02111-1307, USA. + */ + +-#define FONTSET_CACHE_SIZE 64 ++#define FONTSET_CACHE_SIZE 256 + + #include "config.h" + #include +@@ -31,7 +31,7 @@ + #include "modules.h" + #include "pango-enum-types.h" + +-typedef struct _PangoFcCoverageKey PangoFcCoverageKey; ++typedef struct _PangoFcFontFaceData PangoFcFontFaceData; + typedef struct _PangoFcFace PangoFcFace; + typedef struct _PangoFcFamily PangoFcFamily; + typedef struct _PangoFcFindFuncInfo PangoFcFindFuncInfo; +@@ -64,7 +64,7 @@ struct _PangoFcFontMapPrivate + */ + GHashTable *pattern_hash; + +- GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */ ++ GHashTable *font_face_data_hash; /* Maps font file name/id -> data */ + + /* List of all families availible */ + PangoFcFamily **families; +@@ -78,10 +78,16 @@ struct _PangoFcFontMapPrivate + guint closed : 1; + }; + +-struct _PangoFcCoverageKey ++struct _PangoFcFontFaceData + { ++ /* Key */ + char *filename; + int id; /* needed to handle TTC files with multiple faces */ ++ ++ /* Data */ ++ FcPattern *pattern; /* Referenced pattern that owns filename */ ++ PangoCoverage *coverage; ++ PangoFcCmapCache *cmap_cache; + }; + + struct _PangoFcFace +@@ -137,9 +143,9 @@ static PangoFont *pango_fc_font_map_new_font (PangoFcFontMap *fontmap, + PangoFcFontsetKey *fontset_key, + FcPattern *match); + +-static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key); +-static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, +- PangoFcCoverageKey *key2); ++static guint pango_fc_font_face_data_hash (PangoFcFontFaceData *key); ++static gboolean pango_fc_font_face_data_equal (PangoFcFontFaceData *key1, ++ PangoFcFontFaceData *key2); + + static void pango_fc_fontset_key_init (PangoFcFontsetKey *key, + PangoFcFontMap *fcfontmap, +@@ -184,16 +190,31 @@ get_gravity_class (void) + } + + static guint +-pango_fc_coverage_key_hash (PangoFcCoverageKey *key) ++pango_fc_font_face_data_hash (PangoFcFontFaceData *key) + { + return g_str_hash (key->filename) ^ key->id; + } + + static gboolean +-pango_fc_coverage_key_equal (PangoFcCoverageKey *key1, +- PangoFcCoverageKey *key2) ++pango_fc_font_face_data_equal (PangoFcFontFaceData *key1, ++ PangoFcFontFaceData *key2) ++{ ++ return key1->id == key2->id && ++ (key1 == key2 || 0 == strcmp (key1->filename, key2->filename)); ++} ++ ++static void ++pango_fc_font_face_data_free (PangoFcFontFaceData *data) + { +- return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0; ++ FcPatternDestroy (data->pattern); ++ ++ if (data->coverage) ++ pango_coverage_unref (data->coverage); ++ ++ if (data->cmap_cache) ++ _pango_fc_cmap_cache_unref (data->cmap_cache); ++ ++ g_slice_free (PangoFcFontFaceData, data); + } + + /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) +@@ -839,7 +860,11 @@ pango_fc_fontset_finalize (GObject *object) + unsigned int i; + + for (i = 0; i < fontset->fonts->len; i++) +- g_object_unref (g_ptr_array_index(fontset->fonts, i)); ++ { ++ PangoFont *font = g_ptr_array_index(fontset->fonts, i); ++ if (font) ++ g_object_unref (font); ++ } + g_ptr_array_free (fontset->fonts, TRUE); + + for (i = 0; i < fontset->coverages->len; i++) +@@ -977,10 +1002,10 @@ pango_fc_font_map_init (PangoFcFontMap *fcfontmap) + (GDestroyNotify) FcPatternDestroy, + NULL); + +- priv->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash, +- (GEqualFunc)pango_fc_coverage_key_equal, +- (GDestroyNotify)g_free, +- (GDestroyNotify)pango_coverage_unref); ++ priv->font_face_data_hash = g_hash_table_new_full ((GHashFunc)pango_fc_font_face_data_hash, ++ (GEqualFunc)pango_fc_font_face_data_equal, ++ (GDestroyNotify)pango_fc_font_face_data_free, ++ NULL); + priv->dpi = -1; + } + +@@ -1002,8 +1027,8 @@ pango_fc_font_map_fini (PangoFcFontMap *fcfontmap) + g_hash_table_destroy (priv->font_hash); + priv->font_hash = NULL; + +- g_hash_table_destroy (priv->coverage_hash); +- priv->coverage_hash = NULL; ++ g_hash_table_destroy (priv->font_face_data_hash); ++ priv->font_face_data_hash = NULL; + + g_hash_table_destroy (priv->pattern_hash); + priv->pattern_hash = NULL; +@@ -1054,9 +1079,13 @@ pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, + gpointer user_data, + GDestroyNotify dnotify) + { +- PangoFcFontMapPrivate *priv = fcfontmap->priv; ++ PangoFcFontMapPrivate *priv; + PangoFcFindFuncInfo *info; + ++ g_return_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap)); ++ ++ priv = fcfontmap->priv; ++ + info = g_slice_new (PangoFcFindFuncInfo); + + info->findfunc = findfunc; +@@ -1066,6 +1095,41 @@ pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, + priv->findfuncs = g_slist_append (priv->findfuncs, info); + } + ++/** ++ * pango_fc_font_map_find_decoder: ++ * @fcfontmap: The #PangoFcFontMap to use. ++ * @pattern: The #FcPattern to find the decoder for. ++ * ++ * Finds the decoder to use for @pattern. Decoders can be added to ++ * a font map using pango_fc_font_map_add_decoder_find_func(). ++ * ++ * Returns: a newly created #PangoFcDecoder object or %NULL if ++ * no decoder is set for @pattern. ++ * ++ * Since: 1.24. ++ **/ ++PangoFcDecoder * ++pango_fc_font_map_find_decoder (PangoFcFontMap *fcfontmap, ++ FcPattern *pattern) ++{ ++ GSList *l; ++ ++ g_return_val_if_fail (PANGO_IS_FC_FONT_MAP (fcfontmap), NULL); ++ g_return_val_if_fail (pattern != NULL, NULL); ++ ++ for (l = fcfontmap->priv->findfuncs; l && l->data; l = l->next) ++ { ++ PangoFcFindFuncInfo *info = l->data; ++ PangoFcDecoder *decoder; ++ ++ decoder = info->findfunc (pattern, info->user_data); ++ if (decoder) ++ return decoder; ++ } ++ ++ return NULL; ++} ++ + static void + pango_fc_font_map_finalize (GObject *object) + { +@@ -1085,13 +1149,6 @@ pango_fc_font_map_add (PangoFcFontMap *fcfontmap, + PangoFcFontMapPrivate *priv = fcfontmap->priv; + PangoFcFontKey *key_copy; + +- g_assert (fcfont->fontmap == NULL); +- fcfont->fontmap = (PangoFontMap *) fcfontmap; +- /* In other fontmaps we add a weak pointer on ->fontmap so the +- * field is unset when fontmap is finalized. We don't need it +- * here though as PangoFcFontMap already cleans up fcfont->fontmap +- * as part of it's caching scheme. */ +- + key_copy = pango_fc_font_key_copy (key); + _pango_fc_font_set_font_key (fcfont, key_copy); + g_hash_table_insert (priv->font_hash, key_copy, fcfont); +@@ -1105,8 +1162,6 @@ _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, + PangoFcFontMapPrivate *priv = fcfontmap->priv; + PangoFcFontKey *key; + +- fcfont->fontmap = NULL; +- + key = _pango_fc_font_get_font_key (fcfont); + if (key) + { +@@ -1407,7 +1462,6 @@ pango_fc_font_map_new_font (PangoFcFontMap *fcfontmap, + PangoFcFontMapPrivate *priv = fcfontmap->priv; + FcPattern *pattern; + PangoFcFont *fcfont; +- GSList *l; + PangoFcFontKey key; + + if (priv->closed) +@@ -1458,25 +1512,9 @@ pango_fc_font_map_new_font (PangoFcFontMap *fcfontmap, + + fcfont->matrix = key.matrix; + ++ /* cache it on fontmap */ + pango_fc_font_map_add (fcfontmap, &key, fcfont); + +- /* +- * Give any custom decoders a crack at this font now that it's been +- * created. +- */ +- for (l = priv->findfuncs; l && l->data; l = l->next) +- { +- PangoFcFindFuncInfo *info = l->data; +- PangoFcDecoder *decoder; +- +- decoder = info->findfunc (match, info->user_data); +- if (decoder) +- { +- _pango_fc_font_set_decoder (fcfont, decoder); +- break; +- } +- } +- + return (PangoFont *)fcfont; + } + +@@ -1682,21 +1720,85 @@ pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap) + pango_fc_font_map_init (fcfontmap); + } + +-static void +-pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap, +- PangoFcCoverageKey *key, +- PangoCoverage *coverage) ++static PangoFcFontFaceData * ++pango_fc_font_map_get_font_face_data (PangoFcFontMap *fcfontmap, ++ FcPattern *font_pattern) + { + PangoFcFontMapPrivate *priv = fcfontmap->priv; +- PangoFcCoverageKey *key_dup; ++ PangoFcFontFaceData key; ++ PangoFcFontFaceData *data; + +- key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1); +- key_dup->id = key->id; +- key_dup->filename = (char *) (key_dup + 1); +- strcpy (key_dup->filename, key->filename); ++ if (FcPatternGetString (font_pattern, FC_FILE, 0, (FcChar8 **)(void*)&key.filename) != FcResultMatch) ++ return NULL; ++ ++ if (FcPatternGetInteger (font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch) ++ return NULL; ++ ++ data = g_hash_table_lookup (priv->font_face_data_hash, &key); ++ if (G_LIKELY (data)) ++ return data; ++ ++ data = g_slice_new0 (PangoFcFontFaceData); ++ data->filename = key.filename; ++ data->id = key.id; ++ ++ data->pattern = font_pattern; ++ FcPatternReference (data->pattern); ++ ++ g_hash_table_insert (priv->font_face_data_hash, data, data); ++ ++ return data; ++} ++ ++PangoFcCmapCache * ++_pango_fc_cmap_cache_ref (PangoFcCmapCache *cmap_cache) ++{ ++ g_atomic_int_inc ((int *) &cmap_cache->ref_count); ++ ++ return cmap_cache; ++} ++ ++void ++_pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache) ++{ ++ g_return_if_fail (cmap_cache->ref_count > 0); ++ ++ if (g_atomic_int_dec_and_test ((int *) &cmap_cache->ref_count)) ++ { ++ g_free (cmap_cache); ++ } ++} ++ ++PangoFcCmapCache * ++_pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap, ++ PangoFcFont *fcfont) ++{ ++ PangoFcFontMapPrivate *priv; ++ PangoFcFontFaceData *data; ++ PangoFcCmapCache *cmap_cache; ++ ++ if (G_UNLIKELY (fcfontmap == NULL)) ++ return NULL; ++ ++ if (G_UNLIKELY (!fcfont->font_pattern)) ++ return NULL; ++ ++ priv = fcfontmap->priv; ++ ++ data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); ++ if (G_UNLIKELY (!data)) ++ return NULL; ++ ++ if (G_UNLIKELY (data->cmap_cache == NULL)) ++ { ++ data->cmap_cache = g_new0 (PangoFcCmapCache, 1); ++ data->cmap_cache->ref_count = 1; + +- g_hash_table_insert (priv->coverage_hash, +- key_dup, pango_coverage_ref (coverage)); ++ /* Make sure all cache entries are invalid initially */ ++ data->cmap_cache->entries[0].ch = 1; /* char 1 cannot happen in bucket 0 */ ++ } ++ ++ return _pango_fc_cmap_cache_ref (data->cmap_cache); + } + + PangoCoverage * +@@ -1704,37 +1806,30 @@ _pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont) + { + PangoFcFontMapPrivate *priv = fcfontmap->priv; +- PangoFcCoverageKey key; ++ PangoFcFontFaceData *data; + PangoCoverage *coverage; + FcCharSet *charset; + +- /* +- * Assume that coverage information is identified by +- * a filename/index pair; there shouldn't be any reason +- * this isn't true, but it's not specified anywhere +- */ +- if (FcPatternGetString (fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)(void*)&key.filename) != FcResultMatch) +- return NULL; +- +- if (FcPatternGetInteger (fcfont->font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch) ++ if (G_UNLIKELY (!fcfont->font_pattern)) + return NULL; + +- coverage = g_hash_table_lookup (priv->coverage_hash, &key); +- if (G_LIKELY (coverage)) +- return pango_coverage_ref (coverage); +- +- /* +- * Pull the coverage out of the pattern, this +- * doesn't require loading the font +- */ +- if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch) ++ data = pango_fc_font_map_get_font_face_data (fcfontmap, fcfont->font_pattern); ++ if (G_UNLIKELY (!data)) + return NULL; + +- coverage = _pango_fc_font_map_fc_to_coverage (charset); ++ if (G_UNLIKELY (data->coverage == NULL)) ++ { ++ /* ++ * Pull the coverage out of the pattern, this ++ * doesn't require loading the font ++ */ ++ if (FcPatternGetCharSet (fcfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch) ++ return NULL; + +- pango_fc_font_map_set_coverage (fcfontmap, &key, coverage); ++ data->coverage = _pango_fc_font_map_fc_to_coverage (charset); ++ } + +- return coverage; ++ return pango_coverage_ref (data->coverage); + } + + /** +@@ -1821,9 +1916,15 @@ pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap) + + static void + shutdown_font (gpointer key G_GNUC_UNUSED, +- PangoFcFont *fcfont) ++ PangoFcFont *fcfont, ++ PangoFcFontMap *fcfontmap) + { + _pango_fc_font_shutdown (fcfont); ++ ++ /* While _pango_fc_font_shutdown() tries to call the following ++ * function, it's too late as the fontmap weakref has already ++ * NULL'ed fcfont->fontmap, so we do it ourselves. */ ++ _pango_fc_font_map_remove (fcfontmap, fcfont); + } + + /** +@@ -1848,7 +1949,7 @@ pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap) + if (priv->closed) + return; + +- g_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, NULL); ++ g_hash_table_foreach (priv->font_hash, (GHFunc) shutdown_font, fcfontmap); + for (i = 0; i < priv->n_families; i++) + priv->families[i]->fontmap = NULL; + +diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h +index d3f113a..8d496eb 100644 +--- a/pango/pangofc-fontmap.h ++++ b/pango/pangofc-fontmap.h +@@ -213,6 +213,8 @@ void pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, + PangoFcDecoderFindFunc findfunc, + gpointer user_data, + GDestroyNotify dnotify); ++PangoFcDecoder *pango_fc_font_map_find_decoder (PangoFcFontMap *fcfontmap, ++ FcPattern *pattern); + + PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern, + gboolean include_size); +diff --git a/pango/pangofc-private.h b/pango/pangofc-private.h +index bc67ffb..0612a69 100644 +--- a/pango/pangofc-private.h ++++ b/pango/pangofc-private.h +@@ -27,6 +27,7 @@ + + G_BEGIN_DECLS + ++ + typedef struct _PangoFcMetricsInfo PangoFcMetricsInfo; + + struct _PangoFcMetricsInfo +@@ -35,6 +36,26 @@ struct _PangoFcMetricsInfo + PangoFontMetrics *metrics; + }; + ++ ++typedef struct _PangoFcCmapCacheEntry PangoFcCmapCacheEntry; ++typedef struct _PangoFcCmapCache PangoFcCmapCache; ++ ++#define CMAP_CACHE_NUM_ENTRIES 256 /* should be power of two */ ++#define CMAP_CACHE_MASK (CMAP_CACHE_NUM_ENTRIES - 1) ++ ++struct _PangoFcCmapCacheEntry ++{ ++ gunichar ch; ++ PangoGlyph glyph; ++}; ++ ++struct _PangoFcCmapCache ++{ ++ guint ref_count; ++ PangoFcCmapCacheEntry entries[CMAP_CACHE_NUM_ENTRIES]; ++}; ++ ++ + #define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) + #define PANGO_PIXELS_26_6(d) \ + (((d) >= 0) ? \ +@@ -46,10 +67,15 @@ void _pango_fc_font_shutdown (PangoFcFont *fcfont); + + void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont); ++ + PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont); + PangoCoverage *_pango_fc_font_map_fc_to_coverage (FcCharSet *charset); + ++PangoFcCmapCache *_pango_fc_font_map_get_cmap_cache (PangoFcFontMap *fcfontmap, ++ PangoFcFont *fcfont); ++void _pango_fc_cmap_cache_unref (PangoFcCmapCache *cmap_cache); ++ + PangoFcDecoder *_pango_fc_font_get_decoder (PangoFcFont *font); + void _pango_fc_font_set_decoder (PangoFcFont *font, + PangoFcDecoder *decoder); +diff --git a/pango/pangoft2.c b/pango/pangoft2.c +index d13dc69..224f6a0 100644 +--- a/pango/pangoft2.c ++++ b/pango/pangoft2.c +@@ -73,6 +73,7 @@ _pango_ft2_font_new (PangoFT2FontMap *ft2fontmap, + + ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT, + "pattern", pattern, ++ "fontmap", fontmap, + NULL); + + if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch) +diff --git a/pango/pangoft2.def b/pango/pangoft2.def +index f22d4ec..4cfa0d1 100644 +--- a/pango/pangoft2.def ++++ b/pango/pangoft2.def +@@ -17,9 +17,16 @@ EXPORTS + pango_fc_font_map_add_decoder_find_func + pango_fc_font_map_cache_clear + pango_fc_font_map_create_context ++ pango_fc_font_map_find_decoder + pango_fc_font_map_get_type + pango_fc_font_map_shutdown + pango_fc_font_unlock_face ++ pango_fc_fontset_key_get_absolute_size ++ pango_fc_fontset_key_get_context_key ++ pango_fc_fontset_key_get_description ++ pango_fc_fontset_key_get_language ++ pango_fc_fontset_key_get_matrix ++ pango_fc_fontset_key_get_resolution + pango_ft2_font_get_coverage + pango_ft2_font_get_face + pango_ft2_font_get_kerning +diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c +index 28e0ebd..833219a 100644 +--- a/pango/pangowin32-fontmap.c ++++ b/pango/pangowin32-fontmap.c +@@ -1069,63 +1069,9 @@ pango_win32_font_description_from_logfontw (const LOGFONTW *lfp) + gchar *family; + PangoStyle style; + PangoVariant variant; +- PangoWeight weight, name_weight; ++ PangoWeight weight; + PangoStretch stretch; + +- static const struct { +- const char *marker; +- int marker_len; +- int remove_len; +- PangoWeight weight; +- } weight_names[] = { +-#define ENTRY(n, s) ENTRY2 (n, sizeof (#n) - 1, s) +-#define ENTRY2(n, l, s) ENTRY3 (n, l, l, s) +-#define ENTRY3(n, marker_len, remove_len, s) { #n, marker_len, remove_len, PANGO_WEIGHT_##s } +- ENTRY (Ultra Light, ULTRALIGHT), +- ENTRY (UltraLight, ULTRALIGHT), +- ENTRY (Light, LIGHT), +- ENTRY (Medium, NORMAL), +- ENTRY (Demi Bold, SEMIBOLD), +- ENTRY (Demi, SEMIBOLD), +- ENTRY (Ultra Bold, ULTRABOLD), +- ENTRY (Extra Bold, ULTRABOLD), +- ENTRY (SemiBold, SEMIBOLD), +- ENTRY (DemiBold, SEMIBOLD), +- ENTRY (UltraBold, ULTRABOLD), +- ENTRY (ExtraBold, ULTRABOLD), +- ENTRY (Bold, BOLD), +- ENTRY (Heavy, HEAVY), +- ENTRY (Black, HEAVY), +-#undef ENTRY +-#undef ENTRY2 +-#undef ENTRY3 +- }; +- +- static const struct { +- const char *marker; +- int marker_len; +- PangoStretch stretch; +- } stretch_names[] = { +-#define ENTRY(n, s) { #n, sizeof (#n) - 1, PANGO_STRETCH_##s } +- ENTRY (Ext Condensed, EXTRA_CONDENSED), +- ENTRY (Extra Condensed, EXTRA_CONDENSED), +- ENTRY (UltraCondensed, ULTRA_CONDENSED), +- ENTRY (ExtraCondensed, EXTRA_CONDENSED), +- ENTRY (Condensed, CONDENSED), +- ENTRY (Cond, CONDENSED), +- ENTRY (Narrow, CONDENSED), +- ENTRY (Ext Expanded, EXTRA_EXPANDED), +- ENTRY (Extra Expanded, EXTRA_EXPANDED), +- ENTRY (Ultra Expanded, ULTRA_EXPANDED), +- ENTRY (ExtraExpanded, EXTRA_EXPANDED), +- ENTRY (UltraExpanded, ULTRA_EXPANDED), +- ENTRY (Expanded, EXPANDED), +-#undef ENTRY +- }; +- +- int i; +- char *p; +- + family = get_family_nameW (lfp); + + if ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN && lfp->lfItalic) +@@ -1158,51 +1104,9 @@ pango_win32_font_description_from_logfontw (const LOGFONTW *lfp) + else + weight = PANGO_WEIGHT_HEAVY; + +- name_weight = 0; +- +- p = family; +- while ((p = strchr (p, ' ')) != NULL) +- { +- for (i = 0; i < G_N_ELEMENTS (weight_names); i++) +- { +- if (g_ascii_strncasecmp (p + 1, weight_names[i].marker, weight_names[i].marker_len) == 0 && +- (p[1 + weight_names[i].marker_len] == '\0' || +- p[1 + weight_names[i].marker_len] == ' ')) +- { +- strcpy (p, p + 1 + weight_names[i].remove_len); +- name_weight = weight_names[i].weight; +- break; +- } +- } +- if (i < G_N_ELEMENTS (weight_names)) +- break; +- p++; +- } +- +- if (weight == PANGO_WEIGHT_NORMAL && name_weight > 0) +- weight = name_weight; +- ++ /* XXX No idea how to figure out the stretch */ + stretch = PANGO_STRETCH_NORMAL; + +- p = family; +- while ((p = strchr (p, ' ')) != NULL) +- { +- for (i = 0; i < G_N_ELEMENTS (stretch_names); i++) +- { +- if (g_ascii_strncasecmp (p + 1, stretch_names[i].marker, stretch_names[i].marker_len) == 0 && +- (p[1 + stretch_names[i].marker_len] == '\0' || +- p[1 + stretch_names[i].marker_len] == ' ')) +- { +- strcpy (p, p + 1 + stretch_names[i].marker_len); +- stretch = stretch_names[i].stretch; +- break; +- } +- } +- if (i < G_N_ELEMENTS (stretch_names)) +- break; +- p++; +- } +- + description = pango_font_description_new (); + pango_font_description_set_family (description, family); + g_free(family); +diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c +index ce633f7..6865490 100644 +--- a/pango/pangoxft-font.c ++++ b/pango/pangoxft-font.c +@@ -92,6 +92,7 @@ _pango_xft_font_new (PangoXftFontMap *xftfontmap, + + xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT, + "pattern", pattern, ++ "fontmap", fontmap, + NULL); + + /* Hack to force hinting of vertical metrics; hinting off for +diff --git a/tests/gen-all-unicode.c b/tests/gen-all-unicode.c +index 90ff4db..4139f23 100644 +--- a/tests/gen-all-unicode.c ++++ b/tests/gen-all-unicode.c +@@ -2,7 +2,8 @@ + #include + + int +-main (int argc, char **argv) ++main (int argc G_GNUC_UNUSED, ++ char **argv G_GNUC_UNUSED) + { + gunichar i; + gint j; diff --git a/pango.spec b/pango.spec index 0ab45ed..d85fd5b 100644 --- a/pango.spec +++ b/pango.spec @@ -9,7 +9,7 @@ Summary: System for layout and rendering of internationalized text Name: pango Version: 1.23.0 -Release: 3%{?dist} +Release: 4.g5317893%{?dist} License: LGPLv2+ Group: System Environment/Libraries Source: http://download.gnome.org/sources/pango/1.23/pango-%{version}.tar.bz2 @@ -39,6 +39,8 @@ BuildRequires: gtk-doc # Look for pango.modules in an arch-specific directory Patch0: pango-1.21.4-lib64.patch +Patch1: pango-1.23.0-g5317893.patch + %description Pango is a library for laying out and rendering of text, with an emphasis on internationalization. Pango can be used anywhere that text layout is needed, @@ -75,6 +77,8 @@ for the pango package. %patch0 -p1 -b .lib64 +%patch0 -p1 -b .git + %build %configure --enable-gtk-doc --enable-doc-cross-references --with-included-modules=basic-fc @@ -224,6 +228,9 @@ fi %changelog +* Wed Mar 11 2009 Behdad Esfahbod - 1.23.0-4.g5317893 +- Push changes from git + * Thu Feb 26 2009 Fedora Release Engineering - 1.23.0-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild