From 42420cfa1f406a5f0a9f062b258ece72098635b5 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 9 Dec 2012 23:22:46 +0000
Subject: Used Cairo for rendering text and tried to deal properly with Pango
 context / fonts.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@298 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                    |  22 ++++
 src/glibext/Makefile.am      |   1 +
 src/glibext/gbufferline.c    |  51 +++-----
 src/glibext/gbufferline.h    |   2 +-
 src/glibext/gbuffersegment.c |  85 ++++++++-----
 src/glibext/gbuffersegment.h |   7 +-
 src/glibext/gcodebuffer.c    |  17 ++-
 src/glibext/gfontcache.c     | 294 +++++++++++++++++++++++++++++++++++++++++++
 src/glibext/gfontcache.h     |  79 ++++++++++++
 src/main.c                   |   4 +
 10 files changed, 491 insertions(+), 71 deletions(-)
 create mode 100644 src/glibext/gfontcache.c
 create mode 100644 src/glibext/gfontcache.h

diff --git a/ChangeLog b/ChangeLog
index 95b54c0..6733926 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+12-12-10  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/glibext/gbufferline.c:
+	* src/glibext/gbufferline.h:
+	* src/glibext/gbuffersegment.c:
+	* src/glibext/gbuffersegment.h:
+	* src/glibext/gcodebuffer.c:
+	Use Cairo for rendering text. Try to avoid a bug when dealing with
+	fonts / Pango context ; still need to be properly fixed. Avoid a memory
+	leak for the PangoContext singleton used in the program.
+
+	* src/glibext/gfontcache.c:
+	* src/glibext/gfontcache.h:
+	New entries: try to centralize all the things needing for text
+	rendering here ; still need to be digged / improved...
+
+	* src/glibext/Makefile.am:
+	Add the 'gfontcache.[ch]' files to libglibext_la_SOURCES.
+
+	* src/main.c:
+	Create and delete the PangoContext singleton used in the program.
+
 12-12-08  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index 2365190..d5235c8 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -7,6 +7,7 @@ libglibext_la_SOURCES =					\
 	gbufferline.h gbufferline.c			\
 	gbuffersegment.h gbuffersegment.c	\
 	gcodebuffer.h gcodebuffer.c			\
+	gfontcache.h gfontcache.c			\
 	gnhash.h gnhash.c					\
 	proto.h
 
diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c
index cef34ef..562aded 100644
--- a/src/glibext/gbufferline.c
+++ b/src/glibext/gbufferline.c
@@ -67,7 +67,7 @@ static GBufferSegment *get_segment_at(const buffer_line_column *, gint);
 GSList *highlight_all_same_segments(const buffer_line_column *, GSList *, const GBufferSegment *);
 
 /* Imprime le contenu d'une colonne de ligne de texte. */
-static void draw_segments_of_column(buffer_line_column *, GdkDrawable *, GdkGC *, gint, gint);
+static void draw_segments_of_column(buffer_line_column *, cairo_t *, GFontCache *, gint, gint);
 
 
 
@@ -94,7 +94,6 @@ struct _GBufferLineClass
 {
     GObjectClass parent;                    /* A laisser en premier        */
 
-    PangoContext *context;                  /* Contexte graphique Pango    */
     PangoAttrList *attribs[RTT_COUNT];      /* Décorateurs pour tampons    */
 
 };
@@ -264,11 +263,11 @@ GSList *highlight_all_same_segments(const buffer_line_column *column, GSList *li
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : column   = colonne de ligne de texte à manipuler.            *
-*                drawable = surface de rendu où travailler.                   *
-*                gc       = contexte graphique à utiliser pour les pinceaux.  *
-*                x_init   = abscisse du point d'impression de départ.         *
-*                y        = ordonnée du point d'impression.                   *
+*  Paramètres  : column = colonne de ligne de texte à manipuler.              *
+*                cairo  = contexte graphique à utiliser pour les pinceaux.    *
+*                fcache = gestionnaire des polices pour l'impression.         *
+*                x_init = abscisse du point d'impression de départ.           *
+*                y      = ordonnée du point d'impression.                     *
 *                                                                             *
 *  Description : Imprime le contenu d'une colonne de ligne de texte.          *
 *                                                                             *
@@ -278,7 +277,7 @@ GSList *highlight_all_same_segments(const buffer_line_column *column, GSList *li
 *                                                                             *
 ******************************************************************************/
 
-static void draw_segments_of_column(buffer_line_column *column, GdkDrawable *drawable, GdkGC *gc, gint x_init, gint y)
+static void draw_segments_of_column(buffer_line_column *column, cairo_t *cairo, GFontCache *fcache, gint x_init, gint y)
 {
     gint x;
     size_t i;
@@ -286,7 +285,7 @@ static void draw_segments_of_column(buffer_line_column *column, GdkDrawable *dra
     x = x_init;
 
     for (i = 0; i < column->count; i++)
-        g_buffer_segment_draw(column->segments[i], drawable, gc, &x, y);
+        g_buffer_segment_draw(column->segments[i], cairo, fcache, &x, y);
 
 }
 
@@ -316,21 +315,8 @@ G_DEFINE_TYPE(GBufferLine, g_buffer_line, G_TYPE_OBJECT);
 
 static void g_buffer_line_class_init(GBufferLineClass *class)
 {
-    GdkScreen *screen;                      /* Ecran pour GDK              */
-    PangoFontDescription *font_desc;        /* Police de caractère         */
     PangoAttribute *attrib;                 /* Propriété de rendu          */
 
-    /* Base des exportations */
-
-    screen = gdk_screen_get_default();
-    class->context = gdk_pango_context_get_for_screen(screen);
-
-    font_desc = pango_font_description_from_string("mono 10");
-    pango_context_set_font_description(class->context, font_desc);
-
-    pango_context_set_base_dir(class->context, PANGO_DIRECTION_LTR);
-    pango_context_set_language(class->context, gtk_get_default_language());
-
     /* RTT_RAW */
 
     class->attribs[RTT_RAW] = pango_attr_list_new();
@@ -641,14 +627,17 @@ void g_buffer_line_insert_text(GBufferLine *line, BufferLineColumn column, const
     GBufferLineClass *class;                /* Stockage de briques de base */ 
     GBufferSegment *segment;                /* Portion de texte à ajouter  */
 
-    class = G_BUFFER_LINE_GET_CLASS(line);
-
     if (column == BLC_LAST_USED)
         column = line->last_used;
     else
         line->last_used = column;
 
-    segment = g_buffer_segment_new(class->context, class->attribs[type], text, length);
+    if (length == 0)
+        return;
+
+    class = G_BUFFER_LINE_GET_CLASS(line);
+
+    segment = g_buffer_segment_new(class->attribs[type], text, length);
     g_buffer_line_add_segment(line, column, segment);
 
 }
@@ -756,13 +745,13 @@ void g_buffer_line_start_merge_at(GBufferLine *line, BufferLineColumn start)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : line       = ligne de texte à manipuler.                     *
-*                drawable   = surface de rendu où travailler.                 *
-*                gc         = contexte graphique à utiliser pour les pinceaux.*
+*                cairo      = contexte graphique à utiliser pour les pinceaux.*
+*                fcache     = gestionnaire des polices pour l'impression.     *
 *                max_widths = largeurs de colonne à respecter.                *
 *                x_init     = abscisse du point d'impression de départ.       *
 *                y          = ordonnée du point d'impression.                 *
-*                addr   = indique si les positions doivent être affichées.    *
-*                code   = indique si le code binaire doit être affiché.       *
+*                addr       = indique si les positions doivent être affichées.*
+*                code       = indique si le code binaire doit être affiché.   *
 *                                                                             *
 *  Description : Imprime la ligne de texte représentée.                       *
 *                                                                             *
@@ -772,7 +761,7 @@ void g_buffer_line_start_merge_at(GBufferLine *line, BufferLineColumn start)
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_line_draw(GBufferLine *line, GdkDrawable *drawable, GdkGC *gc, const gint max_widths[BLC_COUNT], gint x_init, gint y, bool addr, bool code)
+void g_buffer_line_draw(GBufferLine *line, cairo_t *cairo, GFontCache *fcache, const gint max_widths[BLC_COUNT], gint x_init, gint y, bool addr, bool code)
 {
     gint x;                                 /* Point de départ d'impression*/
     BufferLineColumn i;                     /* Boucle de parcours          */
@@ -784,7 +773,7 @@ void g_buffer_line_draw(GBufferLine *line, GdkDrawable *drawable, GdkGC *gc, con
         if (i == BLC_ADDRESS && !addr) continue;
         if (i == BLC_BINARY && !code) continue;
 
-        draw_segments_of_column(&line->columns[i], drawable, gc, x, y);
+        draw_segments_of_column(&line->columns[i], cairo, fcache, x, y);
 
         if (i < line->merge_start)
             x += max_widths[i] + COL_MARGIN;
diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h
index f1be296..028ae8e 100644
--- a/src/glibext/gbufferline.h
+++ b/src/glibext/gbufferline.h
@@ -149,7 +149,7 @@ gint g_buffer_line_get_width(GBufferLine *, BufferLineColumn);
 void g_buffer_line_start_merge_at(GBufferLine *, BufferLineColumn);
 
 /* Imprime la ligne de texte représentée. */
-void g_buffer_line_draw(GBufferLine *, GdkDrawable *, GdkGC *, const gint [BLC_COUNT], gint, gint, bool, bool);
+void g_buffer_line_draw(GBufferLine *, cairo_t *, GFontCache *, const gint [BLC_COUNT], gint, gint, bool, bool);
 
 /* Exporte la ligne de texte représentée. */
 void g_buffer_line_export(GBufferLine *, int, BufferExportType, bool, bool, bool);
diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c
index 9510fa2..861c7cb 100644
--- a/src/glibext/gbuffersegment.c
+++ b/src/glibext/gbuffersegment.c
@@ -55,7 +55,7 @@ struct _GBufferSegment
     GdkColor *cache_used_fg;                /* Couleur d'impression utile  */
 
     PangoGlyphString *glyphs;               /* Caractères traités          */
-    PangoFont *font;                        /* Police utilisée à l'analyse */
+    PangoFontDescription *desc;             /* Description de police       */
 
     PangoRectangle logical;                 /* Dimension du texte          */
 
@@ -127,7 +127,7 @@ static bool ascii_glyph_table_init(GBufferSegmentClass *class, PangoContext *con
         if (class->ascii_ready)
         {
             PangoItem   *item;
-            int         width;
+            //int         width;
 
             item  = (PangoItem *)list->data;
             //width = gui.char_width * PANGO_SCALE;
@@ -159,10 +159,10 @@ static bool ascii_glyph_table_init(GBufferSegmentClass *class, PangoContext *con
 
         }
 
-        g_list_foreach(list, (GFunc)&pango_item_free, NULL);
-        g_list_free(list);
+        //g_list_foreach(list, (GFunc)&pango_item_free, NULL);
+        //g_list_free(list);
 
-        pango_attr_list_unref(attribs);
+        //pango_attr_list_unref(attribs);
 
     }
 
@@ -201,11 +201,11 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *cont
     GList           *item_list;
     PangoItem   *item;
 
-    PangoRectangle logical;
+    //PangoRectangle logical;
 
 
-    char *max;
-    char *iter;
+    const char *max;
+    const char *iter;
 
     GBufferSegmentClass *class;
 
@@ -215,6 +215,12 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *cont
     gint *log_clusters;
     PangoGlyphInfo *ref;
 
+    PangoFont *font;                        /* Modèle de police            */
+    PangoFontDescription *desc;             /* Description de cette police */
+
+
+
+
     glyphs = pango_glyph_string_new();
 
 
@@ -255,6 +261,8 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *cont
 
     max = text + length;
 
+    goto not_ascii;
+
     for (iter = text; iter < max; iter++)
         if (*iter & 0x80)
             goto not_ascii;
@@ -272,13 +280,11 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *cont
 
     for (i = 0; i < length; i++)
     {
-        info[i] = ref[text[i]];
+        info[i] = ref[(unsigned int)text[i]];
         log_clusters[i] = i;
     }
  
-    segment->font = class->ascii_font;
-
-    pango_glyph_string_extents(glyphs, class->ascii_font, NULL, &segment->logical);
+    font = class->ascii_font;
 
     goto next;
 
@@ -294,13 +300,14 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *cont
     item  = (PangoItem *)item_list->data;
     pango_shape(text, length, &item->analysis, glyphs);
 
-    segment->font = item->analysis.font;/* TODO : ref ! */
-
-    pango_glyph_string_extents(glyphs, item->analysis.font, NULL, &segment->logical);
-
+    font = item->analysis.font;
 
  next:
 
+    desc = pango_font_describe(font);
+    segment->desc = pango_font_description_copy(desc);
+
+    pango_glyph_string_extents(glyphs, font, NULL, &segment->logical);
 
     //pango_shape(text, length, &item->analysis, glyphs);
 
@@ -371,8 +378,7 @@ static void g_buffer_segment_init(GBufferSegment *segment)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : context = contexte Pango pour l'analyse des caractères.      *
-*                attribs = propriétés de la zone de texte.                    *
+*  Paramètres  : attribs = propriétés de la zone de texte.                    *
 *                text    = chaîne de caractères à traiter.                    *
 *                length  = quantité de ces caractères.                        *
 *                                                                             *
@@ -384,19 +390,18 @@ static void g_buffer_segment_init(GBufferSegment *segment)
 *                                                                             *
 ******************************************************************************/
 
-GBufferSegment *g_buffer_segment_new(PangoContext *context, PangoAttrList *attribs, const char *text, size_t length)
+GBufferSegment *g_buffer_segment_new(PangoAttrList *attribs, const char *text, size_t length)
 {
     GBufferSegment *result;                 /* Composant à retourner       */
 
     result = g_object_new(G_TYPE_BUFFER_SEGMENT, NULL);
-    //result = g_new(GBufferSegment, 1);
 
     result->text = strdup(text);
     result->hash = fnv_64a_hash(text);
 
     result->attribs = pango_attr_list_ref(attribs);
 
-    g_buffer_segment_prepare(result, context, attribs, text, length);
+    g_buffer_segment_prepare(result, get_global_pango_context(), attribs, text, length);
 
     g_buffer_segment_cache_colors(result);
 
@@ -556,11 +561,11 @@ void g_buffer_segment_set_style(GBufferSegment *segment, SegRenderingStyle style
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : segment  = fragment de texte à manipuler.                    *
-*                drawable = surface de rendu où travailler.                   *
-*                gc       = contexte graphique à utiliser pour les pinceaux.  *
-*                x        = abscisse du point d'impression (à maj). [OUT]     *
-*                y        = ordonnée du point d'impression.                   *
+*  Paramètres  : segment = fragment de texte à manipuler.                     *
+*                cairo   = contexte graphique à utiliser pour les pinceaux.   *
+*                fcache  = gestionnaire des polices pour l'impression.        *
+*                x       = abscisse du point d'impression (à maj). [OUT]      *
+*                y       = ordonnée du point d'impression.                    *
 *                                                                             *
 *  Description : Imprime le fragment de texte représenté.                     *
 *                                                                             *
@@ -570,27 +575,41 @@ void g_buffer_segment_set_style(GBufferSegment *segment, SegRenderingStyle style
 *                                                                             *
 ******************************************************************************/
 
-void g_buffer_segment_draw(GBufferSegment *segment, GdkDrawable *drawable, GdkGC *gc, gint *x, gint y)
+void g_buffer_segment_draw(GBufferSegment *segment, cairo_t *cairo, GFontCache *fcache, gint *x, gint y)
 {
+    PangoFont *font;                        /* Police d'impression         */
+
+    /* FIXME */
+    g_buffer_segment_prepare(segment, get_global_pango_context(),
+                             segment->attribs, segment->text, strlen(segment->text));
+
     /* Fond du texte */
     if (segment->style != SRS_CLASSIC)
     {
-        gdk_gc_set_rgb_fg_color(gc, &segment->cache_bg);
+        cairo_set_source_rgb(cairo,
+                             segment->cache_bg.red / 65535.0,
+                             segment->cache_bg.green / 65535.0,
+                             segment->cache_bg.blue / 65535.0);
 
-        gdk_draw_rectangle(drawable, gc, TRUE,
-                      *x, y, segment->logical.width, segment->logical.height);
+        cairo_rectangle(cairo, *x, y, segment->logical.width, segment->logical.height);
+        cairo_fill(cairo);
 
     }
 
     /* Couleur d'impression */
 
     if (segment->cache_fg.pixel == COLOR_SET)
-        gdk_gc_set_rgb_fg_color(gc, segment->cache_used_fg);
+        cairo_set_source_rgb(cairo,
+                             segment->cache_used_fg->red / 65535.0,
+                             segment->cache_used_fg->green / 65535.0,
+                             segment->cache_used_fg->blue / 65535.0);
 
     /* Impression du texte */
 
-    gdk_draw_glyphs(drawable, gc, segment->font,
-                    *x, y - segment->logical.y, segment->glyphs);
+    cairo_move_to(cairo, *x, y - segment->logical.y);
+
+    font = g_font_cache_lookup(fcache, segment->desc);
+    pango_cairo_show_glyph_string(cairo, font, segment->glyphs);
 
     *x += segment->logical.width;
 
diff --git a/src/glibext/gbuffersegment.h b/src/glibext/gbuffersegment.h
index edbf44c..96011bb 100644
--- a/src/glibext/gbuffersegment.h
+++ b/src/glibext/gbuffersegment.h
@@ -31,6 +31,9 @@
 #include <pango/pango.h>
 
 
+#include "gfontcache.h"
+
+
 
 #define G_TYPE_BUFFER_SEGMENT                  (g_buffer_segment_get_type())
 #define G_BUFFER_SEGMENT(obj)                  (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_BUFFER_SEGMENT, GBufferSegment))
@@ -72,7 +75,7 @@ typedef struct _GBufferSegmentClass GBufferSegmentClass;
 GType g_buffer_segment_get_type(void);
 
 /* Crée un nouveau fragment de texte avec des propriétés. */
-GBufferSegment *g_buffer_segment_new(PangoContext *, PangoAttrList *, const char *, size_t);
+GBufferSegment *g_buffer_segment_new(PangoAttrList *, const char *, size_t);
 
 /* Indique si les textes de deux segments sont identiques. */
 bool g_buffer_segment_compare(const GBufferSegment *, const GBufferSegment *);
@@ -90,7 +93,7 @@ void g_buffer_segment_cache_colors(GBufferSegment *);
 void g_buffer_segment_set_style(GBufferSegment *, SegRenderingStyle);
 
 /* Imprime le fragment de texte représenté. */
-void g_buffer_segment_draw(GBufferSegment *, GdkDrawable *, GdkGC *, gint *, gint);
+void g_buffer_segment_draw(GBufferSegment *, cairo_t *, GFontCache *, gint *, gint);
 
 
 
diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c
index 4ffc15a..4302f14 100644
--- a/src/glibext/gcodebuffer.c
+++ b/src/glibext/gcodebuffer.c
@@ -140,6 +140,8 @@ struct _GBufferView
     vmpa_t start;                           /* Première ligne intégrée     */
     vmpa_t end;                             /* Dernière ligne intégrée     */
 
+    GFontCache *fcache;                     /* Cache pour les polices      */
+
     gint line_height;                       /* Hauteur maximale des lignes */
     gint max_widths[BLC_COUNT];             /* Taille cachée des colonnes  */
     gint left_margin;                       /* Marge gauche + espace       */
@@ -709,6 +711,7 @@ static void g_buffer_view_class_init(GBufferViewClass *class)
 
 static void g_buffer_view_init(GBufferView *buffer)
 {
+    buffer->fcache = g_font_cache_new();
 
 }
 
@@ -716,6 +719,7 @@ static void g_buffer_view_init(GBufferView *buffer)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : buffer = tampon à représenter à l'écran.                     *
+*                widget = composant GTK de destination pour le rendu.         *
 *                                                                             *
 *  Description : Crée une nouvelle vue d'un tampon pour code désassemblé.     *
 *                                                                             *
@@ -1088,7 +1092,7 @@ void g_buffer_view_define_extra_drawing(GBufferView *view, buffer_line_draw_fc m
 
 void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, GdkGC *gc, gint fake_x, gint fake_y, bool addr, bool code)
 {
-    GdkDrawable *drawable;                  /* Surface de dessin           */
+    cairo_t *cairo;                         /* Gestionnaire de rendu       */
     gint real_x;                            /* Abscisse réelle pour tampon */
     gint real_y;                            /* Ordonnée réelle pour tampon */
 
@@ -1102,8 +1106,9 @@ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, Gd
     size_t i;                               /* Boucle de parcours          */
 
 
-    drawable = GDK_DRAWABLE(event->window);
+    cairo = gdk_cairo_create(event->window);
 
+    gdk_cairo_region(cairo, event->region);
 
     real_x = fake_x + view->left_text;
     real_y = fake_y + event->area.y;
@@ -1127,16 +1132,20 @@ void g_buffer_view_draw(const GBufferView *view, const GdkEventExpose *event, Gd
         for (i = first; i <= last; i++)
         {
             /* TODO : skip if... */
-
+            /*
             if (view->drawing_extra != NULL)
                 view->drawing_extra(lines[i], drawable, gc, fake_x, y, view->drawing_data);
+            */
 
-            g_buffer_line_draw(lines[i], drawable, gc, view->max_widths, real_x, y, addr, code);
+            g_buffer_line_draw(lines[i], cairo, view->fcache,
+                               view->max_widths, real_x, y, addr, code);
 
             y += view->line_height;
 
         }
 
+    cairo_destroy(cairo);
+
 }
 
 
diff --git a/src/glibext/gfontcache.c b/src/glibext/gfontcache.c
new file mode 100644
index 0000000..2441d27
--- /dev/null
+++ b/src/glibext/gfontcache.c
@@ -0,0 +1,294 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gfontcache.c - mise en cache avec actualisation des polices
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "gfontcache.h"
+
+
+
+/* ----------------------- MISE EN PLACE D'UN CONTEXTE GLOBAL ----------------------- */
+
+
+/* Utilisable par toutes les impressions. */
+static PangoContext *_context = NULL;
+
+
+
+/* ---------------------------- CACHE DE POLICES PAR VUE ---------------------------- */
+
+
+/* Description d'un cache pour polices (instance) */
+struct _GFontCache
+{
+    GObject parent;                         /* A laisser en premier        */
+
+    GHashTable *table;                      /* Associations desc./police   */
+
+    GtkWidget *widget;
+
+};
+
+/* Description d'un cache pour polices (classe) */
+struct _GFontCacheClass
+{
+    GObjectClass parent;                    /* A laisser en premier        */
+
+};
+
+
+/* Initialise la classe des caches pour polices. */
+static void g_font_cache_class_init(GFontCacheClass *);
+
+/* Initialise un cache pour polices. */
+static void g_font_cache_init(GFontCache *);
+
+/* Supprime toutes les références externes. */
+static void g_font_cache_dispose(GFontCache *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_font_cache_finalize(GFontCache *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         MISE EN PLACE D'UN CONTEXTE GLOBAL                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Initialise le contexte Pango pour la gestion des textes.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_global_pango_context(void)
+{
+    PangoFontDescription *desc;             /* Police de caractères        */
+
+    _context = gdk_pango_context_get();
+
+    desc = pango_font_description_from_string("mono 10");
+    pango_context_set_font_description(_context, desc);
+    pango_font_description_free(desc);
+
+    pango_context_set_base_dir(_context, PANGO_DIRECTION_LTR);
+    pango_context_set_language(_context, gtk_get_default_language());
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit le contexte Pango global  pour l'impression.         *
+*                                                                             *
+*  Retour      : Contexte prêt à emploi.                                      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PangoContext *get_global_pango_context(void)
+{
+    return _context;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Supprime le contexte Pango pour la gestion des textes.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void exit_global_pango_context(void)
+{
+    g_object_unref(G_OBJECT(_context));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                              CACHE DE POLICES PAR VUE                              */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+/* Indique le type défini pour un cache pour polices. */
+G_DEFINE_TYPE(GFontCache, g_font_cache, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : class = classe à initialiser.                                *
+*                                                                             *
+*  Description : Initialise la classe des caches pour polices.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_font_cache_class_init(GFontCacheClass *class)
+{
+    GObjectClass *object;                   /* Autre version de la classe  */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)g_font_cache_dispose;
+    object->finalize = (GObjectFinalizeFunc)g_font_cache_finalize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fcache = instance à initialiser.                             *
+*                                                                             *
+*  Description : Initialise un cache pour polices.                            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_font_cache_init(GFontCache *fcache)
+{
+    fcache->table = g_hash_table_new_full((GHashFunc)pango_font_description_hash,
+                                          (GEqualFunc)pango_font_description_equal,
+                                          (GDestroyNotify)pango_font_description_free,
+                                          (GDestroyNotify)g_object_unref);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fcache = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_font_cache_dispose(GFontCache *fcache)
+{
+    g_hash_table_destroy(fcache->table);
+
+    G_OBJECT_CLASS(g_font_cache_parent_class)->dispose(G_OBJECT(fcache));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fcache = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Procède à la libération totale de la mémoire.                *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_font_cache_finalize(GFontCache *fcache)
+{
+    G_OBJECT_CLASS(g_font_cache_parent_class)->finalize(G_OBJECT(fcache));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un bloc virtuel d'instructions.                         *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GFontCache *g_font_cache_new(void)
+{
+    GFontCache *result;                     /* Structure à retourner       */
+
+    result = g_object_new(G_TYPE_FONT_CACHE, NULL);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : fcache = instance à consulter, voire compléter.              *
+*                desc   = description de la police recherchée.                *
+*                                                                             *
+*  Description : Fournit une police utilisable répondant au besoin.           *
+*                                                                             *
+*  Retour      : Police prête à usage.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PangoFont *g_font_cache_lookup(GFontCache *fcache, const PangoFontDescription *desc)
+{
+    PangoFont *result;                      /* Instance à retourner        */
+    PangoFontDescription *key;              /* Copie de la description     */
+
+    result = (PangoFont *)g_hash_table_lookup(fcache->table, desc);
+
+    if (result == NULL)
+    {
+        result = pango_context_load_font(get_global_pango_context(), desc);
+
+        key = pango_font_description_copy(desc);
+        g_hash_table_insert(fcache->table, key, result);
+
+    }
+
+    return result;
+
+}
diff --git a/src/glibext/gfontcache.h b/src/glibext/gfontcache.h
new file mode 100644
index 0000000..e6ef2d6
--- /dev/null
+++ b/src/glibext/gfontcache.h
@@ -0,0 +1,79 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * gfontcache.h - prototypes pour la mise en cache avec actualisation des polices
+ *
+ * Copyright (C) 2012 Cyrille Bagard
+ *
+ *  This file is part of OpenIDA.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_GFONTCACHE_H
+#define _GLIBEXT_GFONTCACHE_H
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+#include <pango/pango-context.h>
+#include <pango/pango-font.h>
+
+
+
+/* ----------------------- MISE EN PLACE D'UN CONTEXTE GLOBAL ----------------------- */
+
+
+/* Initialise le contexte Pango pour la gestion des textes. */
+void init_global_pango_context(void);
+
+/* Fournit le contexte Pango global  pour l'impression. */
+PangoContext *get_global_pango_context(void);
+
+/* Supprime le contexte Pango pour la gestion des textes. */
+void exit_global_pango_context(void);
+
+
+
+/* ---------------------------- CACHE DE POLICES PAR VUE ---------------------------- */
+
+
+#define G_TYPE_FONT_CACHE               g_font_cache_get_type()
+#define G_FONT_CACHE(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_font_cache_get_type(), GFontCache))
+#define G_IS_FONT_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_font_cache_get_type()))
+#define G_FONT_CACHE_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_FONT_CACHE, GFontCacheClass))
+#define G_IS_FONT_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_FONT_CACHE))
+#define G_FONT_CACHE_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_FONT_CACHE, GFontCacheClass))
+
+
+/* Description d'un cache pour polices (instance) */
+typedef struct _GFontCache GFontCache;
+
+/* Description d'un cache pour polices (classe) */
+typedef struct _GFontCacheClass GFontCacheClass;
+
+
+/* Indique le type défini pour un cache pour polices. */
+GType g_font_cache_get_type(void);
+
+/* Crée un bloc virtuel d'instructions. */
+GFontCache *g_font_cache_new(void);
+
+/* Fournit une police utilisable répondant au besoin. */
+PangoFont *g_font_cache_lookup(GFontCache *, const PangoFontDescription *);
+
+
+
+#endif  /* _GLIBEXT_GFONTCACHE_H */
diff --git a/src/main.c b/src/main.c
index 6e06e98..09d9998 100644
--- a/src/main.c
+++ b/src/main.c
@@ -35,6 +35,7 @@
 #include "arch/processor.h"
 #include "format/format.h"
 #include "glibext/delayed.h"
+#include "glibext/gfontcache.h"
 #include "gtkext/support.h"
 #include "plugins/pglist.h"
 #include "../revision.h"
@@ -134,6 +135,7 @@ int main(int argc, char **argv)
     /* Initialisation du programme */
     init_all_processors();
     init_all_formats();
+    init_global_pango_context();
 
     /* Création de l'interface */
 
@@ -162,6 +164,8 @@ int main(int argc, char **argv)
     gtk_main();
     //gdk_threads_leave();
 
+    exit_global_pango_context();
+
     unload_configuration(config);
 
     return EXIT_SUCCESS;
-- 
cgit v0.11.2-87-g4458