[libgda] Report engine can now render rich text to HTML as well as DocBook



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]