[libgda] Report engine can now render rich text to HTML as well as DocBook
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Report engine can now render rich text to HTML as well as DocBook
- Date: Wed, 18 Jan 2012 17:46:16 +0000 (UTC)
commit aaed3a5d8a4f80cafa580016f507c4432ad1c1a0
Author: Vivien Malerba <malerba gnome-db org>
Date: Wed Jan 18 18:40:25 2012 +0100
Report engine can now render rich text to HTML as well as DocBook
libgda-report/engine/gda-report-engine.c | 5 +
libgda-report/engine/rt-parser.c | 218 +++++++++++++++++++++++++++++-
libgda-report/engine/rt-parser.h | 1 +
3 files changed, 217 insertions(+), 7 deletions(-)
---
diff --git a/libgda-report/engine/gda-report-engine.c b/libgda-report/engine/gda-report-engine.c
index 32879bd..dae61b5 100644
--- a/libgda-report/engine/gda-report-engine.c
+++ b/libgda-report/engine/gda-report-engine.c
@@ -1239,6 +1239,11 @@ value_to_node (G_GNUC_UNUSED GdaReportEngine *engine, G_GNUC_UNUSED RunContext *
parse_rich_text_to_docbook (retnode, str);
converted = TRUE;
}
+ else if (array[1] && !strcmp (array[1], "html")) {
+ retnode = xmlNewNode (NULL, BAD_CAST "p");
+ parse_rich_text_to_html (retnode, str);
+ converted = TRUE;
+ }
}
}
}
diff --git a/libgda-report/engine/rt-parser.c b/libgda-report/engine/rt-parser.c
index 2ad35ca..edb1335 100644
--- a/libgda-report/engine/rt-parser.c
+++ b/libgda-report/engine/rt-parser.c
@@ -264,8 +264,13 @@ get_markup_token (const gchar *alltext, const gchar *start, gint *out_nb_spaces_
ptr++;
c = *ptr;
if (c == '/') {
- SET_OUT;
- return MARKUP_ITALIC;
+ const gchar *bptr;
+ bptr = ptr-2;
+ if ((bptr > alltext) && (*bptr == ':')) {}
+ else {
+ SET_OUT;
+ return MARKUP_ITALIC;
+ }
}
}
else if (c == '_') {
@@ -1070,21 +1075,29 @@ rt_parse_text (const gchar *text)
return retnode;
}
+
/*
- * DocBook rendering
+ *
+ * Rendering
+ *
+ */
+
+/*
+ * @hash: key = rtnode, value = corresponding xmlNodePtr
*/
static gint file_nb = 0;
typedef struct {
GHashTable *hash;
gchar *file_path;
gchar *file_prefix;
-} ContextDocbook;
+} RenderingContext;
+
/*
- * @hash: key = rtnode, value = corresponding xmlNodePtr
+ * DocBook rendering
*/
static void
-rich_text_node_to_docbook (ContextDocbook *context, xmlNodePtr top_parent, RtNode *rtnode, xmlNodePtr parent)
+rich_text_node_to_docbook (RenderingContext *context, xmlNodePtr top_parent, RtNode *rtnode, xmlNodePtr parent)
{
xmlNodePtr pattach = NULL, cattach = NULL;
gchar *realtext;
@@ -1268,7 +1281,7 @@ void
parse_rich_text_to_docbook (xmlNodePtr top, const gchar *text)
{
RtNode *rtnode;
- ContextDocbook context;
+ RenderingContext context;
context.hash = g_hash_table_new (NULL, NULL);
context.file_path = ".";
@@ -1280,3 +1293,194 @@ parse_rich_text_to_docbook (xmlNodePtr top, const gchar *text)
g_hash_table_destroy (context.hash);
rt_free_node (rtnode);
}
+
+/*
+ * HTML rendering
+ */
+static void
+rich_text_node_to_html (RenderingContext *context, xmlNodePtr top_parent, RtNode *rtnode, xmlNodePtr parent)
+{
+ xmlNodePtr pattach = NULL, cattach = NULL;
+ gchar *realtext;
+ g_assert (parent);
+ g_assert (context);
+
+ if (rtnode->text) {
+ gchar *optr, *nptr;
+ gint len;
+ len = strlen ((gchar*) rtnode->text);
+ realtext = g_new (gchar, len + 1);
+ for (optr = (gchar*) rtnode->text, nptr = realtext; *optr; optr++) {
+ if (*optr != '\n') {
+ *nptr = *optr;
+ nptr++;
+ }
+ }
+ *nptr = 0;
+ }
+ else
+ realtext = (gchar *) rtnode->text;
+
+ switch (rtnode->markup) {
+ case RT_MARKUP_NONE:
+ if (parent) {
+ xmlNodeAddContent (parent, BAD_CAST realtext);
+ cattach = parent;
+ }
+ else {
+ cattach = xmlNewNode (NULL, BAD_CAST "para");
+ xmlNodeAddContent (cattach, BAD_CAST realtext);
+ }
+ break;
+ case RT_MARKUP_BOLD:
+ cattach = xmlNewChild (parent, NULL, BAD_CAST "b", BAD_CAST realtext);
+ break;
+ case RT_MARKUP_PARA:
+ pattach = parent;
+ if ((parent != top_parent) &&
+ ! strcmp ((gchar*) parent->name, "p"))
+ pattach = parent->parent;
+ cattach = xmlNewChild (pattach, NULL, BAD_CAST "p", BAD_CAST realtext);
+ parent = cattach;
+ break;
+ case RT_MARKUP_TT:
+ case RT_MARKUP_VERBATIM:
+ case RT_MARKUP_ITALIC:
+ cattach = xmlNewChild (parent, NULL, BAD_CAST "i", BAD_CAST realtext);
+ break;
+ case RT_MARKUP_STRIKE:
+ cattach = xmlNewChild (parent, NULL, BAD_CAST "del", BAD_CAST realtext);
+ break;
+ case RT_MARKUP_UNDERLINE:
+ cattach = xmlNewChild (parent, NULL, BAD_CAST "ins", BAD_CAST realtext);
+ break;
+ case RT_MARKUP_PICTURE: {
+ gboolean saved = FALSE;
+ gint type = 2; /* 0 for image, 1 for TXT and 2 for general binary */
+ gchar *file, *tmp;
+ tmp = g_strdup_printf ("%s_%04d.jpg", context->file_prefix,
+ file_nb ++);
+ file = g_build_filename (context->file_path, tmp, NULL);
+ g_free (tmp);
+
+#ifdef HAVE_GDKPIXBUF
+ GdkPixdata pixdata;
+ if (rtnode->binary.data &&
+ gdk_pixdata_deserialize (&pixdata, rtnode->binary.binary_length,
+ (guint8*) rtnode->binary.data, NULL)) {
+ GdkPixbuf *pixbuf;
+ pixbuf = gdk_pixbuf_from_pixdata (&pixdata, TRUE, NULL);
+ if (pixbuf) {
+ /* write to file */
+ if (gdk_pixbuf_save (pixbuf, file, "jpeg", NULL,
+ "quality", "100", NULL)) {
+ g_print ("Writen JPG file '%s'\n", file);
+ saved = TRUE;
+ type = 0;
+ }
+
+ g_object_unref (pixbuf);
+ }
+ }
+#endif
+
+ if (!saved) {
+ if (rtnode->binary.data &&
+ g_file_set_contents (file, (gchar*) rtnode->binary.data,
+ rtnode->binary.binary_length, NULL)) {
+ g_print ("Writen BIN file '%s'\n", file);
+ saved = TRUE;
+ type = 2;
+ }
+ else if (rtnode->text)
+ type = 1;
+ }
+ if (! saved && (type != 1))
+ TO_IMPLEMENT;
+ else {
+ switch (type) {
+ case 0:
+ pattach = xmlNewChild (parent, NULL, BAD_CAST "img",
+ NULL);
+ xmlSetProp (cattach, BAD_CAST "src", BAD_CAST file);
+ break;
+ case 1:
+ xmlNodeAddContent (parent, BAD_CAST (rtnode->text));
+ break;
+ case 2:
+ cattach = xmlNewChild (parent, NULL, BAD_CAST "ulink",
+ BAD_CAST _("link"));
+ xmlSetProp (cattach, BAD_CAST "url", BAD_CAST file);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ g_free (file);
+ break;
+ }
+ case RT_MARKUP_TITLE: {
+ gchar *sect;
+ pattach = parent;
+ if (!strcmp ((gchar*) parent->name, "para"))
+ pattach = parent->parent;
+ sect = g_strdup_printf ("h%d", rtnode->offset + 1);
+ cattach = xmlNewChild (pattach, NULL, BAD_CAST sect, BAD_CAST realtext);
+ g_free (sect);
+ break;
+ }
+ case RT_MARKUP_LIST: {
+ xmlNodePtr tmp = NULL;
+
+ if (rtnode->prev &&
+ (rtnode->prev->markup == RT_MARKUP_LIST)) {
+ tmp = g_hash_table_lookup (context->hash, rtnode->prev);
+ g_assert (tmp);
+ /* use the same <itemizedlist> */
+ g_assert (!strcmp ((gchar*) tmp->name, "ul"));
+ g_assert (rtnode->prev->offset == rtnode->offset);
+ g_hash_table_insert (context->hash, rtnode, tmp);
+ tmp = xmlNewChild (tmp, NULL, BAD_CAST "li", NULL);
+ cattach = xmlNewChild (tmp, NULL, BAD_CAST "p", BAD_CAST realtext);
+ }
+ else {
+ pattach = xmlNewChild (parent, NULL, BAD_CAST "ul", NULL);
+ g_hash_table_insert (context->hash, rtnode, pattach);
+ pattach = xmlNewChild (pattach, NULL, BAD_CAST "li", NULL);
+ cattach = xmlNewChild (pattach, NULL, BAD_CAST "p", BAD_CAST realtext);
+ }
+ break;
+ }
+ default:
+ if (rtnode->parent)
+ g_assert_not_reached ();
+ else
+ cattach = parent;
+ break;
+ }
+
+ if (rtnode->text)
+ g_free (realtext);
+
+ if (rtnode->child)
+ rich_text_node_to_html (context, top_parent, rtnode->child, cattach);
+ if (rtnode->next)
+ rich_text_node_to_html (context, top_parent, rtnode->next, parent);
+}
+
+void
+parse_rich_text_to_html (xmlNodePtr top, const gchar *text)
+{
+ RtNode *rtnode;
+ RenderingContext context;
+
+ context.hash = g_hash_table_new (NULL, NULL);
+ context.file_path = ".";
+ context.file_prefix = "IMG";
+
+ rtnode = rt_parse_text (text);
+ /*rt_dump_tree (rtnode);*/
+ rich_text_node_to_html (&context, top, rtnode, top);
+ g_hash_table_destroy (context.hash);
+ rt_free_node (rtnode);
+}
diff --git a/libgda-report/engine/rt-parser.h b/libgda-report/engine/rt-parser.h
index 6b0b2a4..7b8da38 100644
--- a/libgda-report/engine/rt-parser.h
+++ b/libgda-report/engine/rt-parser.h
@@ -64,6 +64,7 @@ void rt_dump_tree (RtNode *tree);
gchar *rt_dump_to_string (RtNode *tree);
void parse_rich_text_to_docbook (xmlNodePtr top, const gchar *text);
+void parse_rich_text_to_html (xmlNodePtr top, const gchar *text);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]