summaryrefslogtreecommitdiff
path: root/src/glibext/gbuffersegment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext/gbuffersegment.c')
-rw-r--r--src/glibext/gbuffersegment.c391
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;
+
+}