From 42420cfa1f406a5f0a9f062b258ece72098635b5 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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 + + * 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 * 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 +#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 . + */ + + +#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 . + */ + + +#ifndef _GLIBEXT_GFONTCACHE_H +#define _GLIBEXT_GFONTCACHE_H + + +#include +#include +#include +#include +#include + + + +/* ----------------------- 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