diff options
Diffstat (limited to 'src/glibext/gbuffersegment.c')
-rw-r--r-- | src/glibext/gbuffersegment.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c new file mode 100644 index 0000000..bcafa97 --- /dev/null +++ b/src/glibext/gbuffersegment.c @@ -0,0 +1,391 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * gbuffersegment.c - concentration d'un fragment de caractères aux propriétés communes + * + * Copyright (C) 2010 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 "gbuffersegment.h" + + +#include <stdbool.h> + + + + + + +/* Fragment de caractères aux propriétés communes (instance) */ +struct _GBufferSegment +{ + GObject parent; /* A laisser en premier */ + + PangoGlyphString *glyphs; /* Caractères traités */ + PangoFont *font; /* Police utilisée à l'analyse */ + + PangoRectangle logical; /* Dimension du texte */ + +}; + +/* Fragment de caractères aux propriétés communes (classe) */ +struct _GBufferSegmentClass +{ + GObjectClass parent; /* A laisser en premier */ + + PangoGlyphString *ascii_glyphs; /* Caractères ASCII prêts */ + PangoFont *ascii_font; /* Police utilisée pour ASCII */ + bool ascii_ready; /* Utilisation possible ? */ + + bool ascii_init_done; /* Initialisation tentée ? */ + +}; + + +/* Procède à l'initialisation d'une classe de fragment de texte. */ +static void g_buffer_segment_class_init(GBufferSegmentClass *); + +/* Procède à l'initialisation d'un fragment de texte. */ +static void g_buffer_segment_init(GBufferSegment *); + + + + + + + + + + +static bool ascii_glyph_table_init(GBufferSegmentClass *class, PangoContext *context) +{ + gint i; /* Boucle de parcours */ + char ascii_chars[128]; /* Table de caractères ASCII */ + PangoAttrList *attribs; /* Liste d'attributs (vide) */ + GList *list; /* Liste d'éléments distincts */ + + if (!class->ascii_init_done) + { + class->ascii_init_done = true; + + /* Construction d'une chaîne adéquate */ + + for (i = 0; i < 128; ++i) + switch (i) + { + case 0 ... 31: + ascii_chars[i] = '?'; + break; + case 32 ... 127: + ascii_chars[i] = i; + break; + default: + ascii_chars[i] = '?'; + break; + } + + /* Analyse de la chaîne créée */ + + attribs = pango_attr_list_new(); + list = pango_itemize(context, ascii_chars, 0, 128, attribs, NULL); + + class->ascii_ready = (list != NULL && list->next == NULL); + + if (class->ascii_ready) + { + PangoItem *item; + int width; + + item = (PangoItem *)list->data; + //width = gui.char_width * PANGO_SCALE; + + /* Remember the shape engine used for ASCII. */ + //default_shape_engine = item->analysis.shape_engine; + + class->ascii_font = item->analysis.font; + g_object_ref(class->ascii_font); + + class->ascii_glyphs = pango_glyph_string_new(); + + pango_shape(ascii_chars, 128, &item->analysis, class->ascii_glyphs); + + class->ascii_ready = (class->ascii_glyphs->num_glyphs == 128); + + + +#if 0 + for (i = 0; i < class->ascii_glyphs->num_glyphs; i++) + { + PangoGlyphGeometry *geom; + + geom = &class->ascii_glyphs->glyphs[i].geometry; + //geom->x_offset += MAX(0, width - geom->width) / 2; + //geom->width = /*width*/8 * PANGO_SCALE; + } +#endif + + } + + g_list_foreach(list, (GFunc)&pango_item_free, NULL); + g_list_free(list); + + pango_attr_list_unref(attribs); + + } + + return class->ascii_ready; + +} + + + + + + + +/****************************************************************************** +* * +* Paramètres : context = contexte Pango pour l'analyse des caractères. * +* attribs = propriétés de la zone de texte. * +* text = chaîne de caractères à traiter. * +* length = quantité de ces caractères. * +* * +* Description : Crée un nouveau fragment de texte avec des propriétés. * +* * +* Retour : Composant GTK créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *context, PangoAttrList *attribs, const char *text, size_t length) +{ + PangoGlyphString *glyphs; /* Caractères traités */ + + GList *item_list; + PangoItem *item; + + PangoRectangle logical; + + + char *max; + char *iter; + + GBufferSegmentClass *class; + + size_t i; + + PangoGlyphInfo *info; + gint *log_clusters; + PangoGlyphInfo *ref; + + glyphs = pango_glyph_string_new(); + + + + + /** + * Petite astuce empruntée à Vim... + * (cf. src/gui_gtk_x11.c, fonction gui_gtk2_draw_string()). + * On essaie de traiter à la main les morceaux de + * texte. Pour ceux en ASCII pur, le gain est non négligeable. + */ + + max = text + length; + + for (iter = text; iter < max; iter++) + if (*iter & 0x80) + goto not_ascii; + + class = G_BUFFER_SEGMENT_GET_CLASS(segment); + + if (!ascii_glyph_table_init(class, context)) + goto not_ascii; + + pango_glyph_string_set_size(glyphs, length); + + info = glyphs->glyphs; + log_clusters = glyphs->log_clusters; + ref = class->ascii_glyphs->glyphs; + + for (i = 0; i < length; i++) + { + info[i] = ref[text[i]]; + log_clusters[i] = i; + } + + goto next; + + not_ascii: + + item_list = pango_itemize(context, text, 0, length, attribs, NULL); + + /* + if (!(item_list != NULL && item_list->next == NULL)) + printf("ouich\n"); + */ + + item = (PangoItem *)item_list->data; + pango_shape(text, length, &item->analysis, glyphs); + + //segment->font = item->analysis.font;/* TODO : ref ! */ + + + next: + + + //pango_shape(text, length, &item->analysis, glyphs); + + + pango_glyph_string_extents(glyphs, class->ascii_font, NULL, &segment->logical); + + segment->logical.y /= PANGO_SCALE; + segment->logical.width /= PANGO_SCALE; + segment->logical.height /= PANGO_SCALE; + + segment->glyphs = glyphs; + +} + + + + + + + + + + + + + + +/* Détermine le type du fragment de caractères aux propriétés communes. */ +G_DEFINE_TYPE(GBufferSegment, g_buffer_segment, G_TYPE_OBJECT); + + + +/****************************************************************************** +* * +* Paramètres : class = classe de composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation d'une classe de fragment de texte.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_buffer_segment_class_init(GBufferSegmentClass *class) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : segment = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation d'un fragment de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +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. * +* text = chaîne de caractères à traiter. * +* length = quantité de ces caractères. * +* * +* Description : Crée un nouveau fragment de texte avec des propriétés. * +* * +* Retour : Composant GTK créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferSegment *g_buffer_segment_new(PangoContext *context, 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); + + g_buffer_segment_prepare(result, context, attribs, text, length); + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : segment = fragment de texte à consulter. * +* * +* Description : Fournit la quantité de pixels requise pour l'impression. * +* * +* Retour : Largeur requise par la colonne, en pixel. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_buffer_segment_get_width(const GBufferSegment *segment) +{ + return segment->logical.width; + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Description : Imprime le fragment de texte représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_segment_draw(GBufferSegment *segment, GdkDrawable *drawable, GdkGC *gc, gint *x, gint y) +{ + gdk_draw_glyphs(drawable, gc, G_BUFFER_SEGMENT_GET_CLASS(segment)->ascii_font, + *x, y - segment->logical.y, segment->glyphs); + + *x += segment->logical.width; + +} |