diff --git a/.cvsignore b/.cvsignore
index 9710292..a34b453 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1 +1 @@
-pango-1.23.0.tar.bz2
+pango-1.24.0.tar.bz2
diff --git a/pango-1.23.0-g5317893.patch b/pango-1.23.0-g5317893.patch
deleted file mode 100644
index 39d9d11..0000000
--- a/pango-1.23.0-g5317893.patch
+++ /dev/null
@@ -1,1928 +0,0 @@
-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,6 +17,7 @@ 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
-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 d1abeb9..67950a0 100644
--- a/pango.spec
+++ b/pango.spec
@@ -8,11 +8,11 @@
Summary: System for layout and rendering of internationalized text
Name: pango
-Version: 1.23.0
-Release: 4.g5317893%{?dist}
+Version: 1.24.0
+Release: 1%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
-Source: http://download.gnome.org/sources/pango/1.23/pango-%{version}.tar.bz2
+Source: http://download.gnome.org/sources/pango/1.24/pango-%{version}.tar.bz2
URL: http://www.pango.org
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -39,8 +39,6 @@ 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,
@@ -77,8 +75,6 @@ for the pango package.
%patch0 -p1 -b .lib64
-%patch1 -p1 -b .git
-
%build
%configure --enable-gtk-doc --enable-doc-cross-references --with-included-modules=basic-fc
@@ -212,6 +208,7 @@ fi
%{_libdir}/libpango*-*.so.*
%{_bindir}/pango-querymodules*
%{_bindir}/pango-view
+%{_datadir}/man/man1/pango-view.1.gz
%{_libdir}/pango
%doc %{_mandir}/man1/*
@@ -228,6 +225,10 @@ fi
%changelog
+* Mon Mar 16 2009 Behdad Esfahbod - 1.24.0-1
+- Update to 1.24.0
+- Package pango-view.1.gz
+
* Wed Mar 11 2009 Behdad Esfahbod - 1.23.0-4.g5317893
- Push changes from git
diff --git a/sources b/sources
index 39f7e53..cb05e99 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-358a87607c0a5b4889bab52b1cf5e921 pango-1.23.0.tar.bz2
+d209f41079833cd2ef2c5e580ab9c5ee pango-1.24.0.tar.bz2