From 8f10a1b0745edca986171a185a8e893e0294154c Mon Sep 17 00:00:00 2001 From: Andrea Zagli Date: Sun, 15 Apr 2007 09:02:02 +0000 Subject: [PATCH] Some bugfixes. Added programmatically report creation test. Static text in text's source attribute must be enclosed into "". Added text's attributes padding*. Added page's attributes margin*. Added RptReport's signal "field-request". git-svn-id: svn+ssh://saetta.homelinux.org/svn/libreptool/trunk@12 3191ed1d-3fce-41bb-ab4a-0cebc0943b59 --- ChangeLog | 24 +++ configure.ac | 2 +- docs/reference/tmpl/rptobjecttext.sgml | 20 ++ docs/reference/tmpl/rptreport.sgml | 12 ++ src/Makefile.am | 8 +- src/libreptool.h | 7 + src/reptool_marshal.list | 1 + src/rptcommon.c | 32 ++-- src/rptcommon.h | 8 +- src/rptmarshal.c | 92 +++++++++ src/rptmarshal.h | 20 ++ src/rptobjectimage.c | 4 +- src/rptobjectline.c | 4 +- src/rptobjectrect.c | 4 +- src/rptobjecttext.c | 114 ++++++++++- src/rptprint.c | 88 +++++++-- src/rptreport.c | 251 +++++++++++++++++++++---- src/rptreport.h | 14 +- tests/Makefile.am | 6 +- tests/test_report.rpt | 13 +- tests/test_report_db.rpt | 9 +- tests/test_rptreport.c | 27 +++ tests/test_rptreport_creation.c | 112 +++++++++++ 23 files changed, 772 insertions(+), 100 deletions(-) create mode 100644 src/reptool_marshal.list create mode 100644 src/rptmarshal.c create mode 100644 src/rptmarshal.h create mode 100644 tests/test_rptreport_creation.c diff --git a/ChangeLog b/ChangeLog index 86684b4..31b4c1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2007-04-15 Andrea Zagli + + * src/rptreport.c: + * src/rptprint.c: managed page's margins + * src/reptool_marshal.list: + * src/rtpmarshal.*: added + * src/rptreport.c: added signal "field-request" + +2007-04-14 Andrea Zagli + + * src/*.c: API documentation + * src/rptobjtext.c: added text's attributes padding* + * src/rptprint.c: managed text's attributes padding* + * src/rptreport.c: static text in text's source attribute must be enclosed + into "" (xml entity "); + added page's attributes margin* + +2007-04-13 Andrea Zagli + + * src/Makefile.am: added -no-undefined + * tests/test_rptreport_creation.c: added report creation test + * src/rptreport.c: changed rpt_report_add_object_to_section()'s prototype + * src/rptcommon.c: bugfix on rpt_common_convert_to_str_color + 2007-04-08 Andrea Zagli * src/rptreport.h: diff --git a/configure.ac b/configure.ac index 83c886f..cfa0c3d 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT([libreptool], [0.0.3], [azagli@inwind.it]) +AC_INIT([libreptool], [0.0.4], [azagli@inwind.it]) AC_CONFIG_SRCDIR([src/rptprint.c]) AC_CONFIG_HEADER([config.h]) diff --git a/docs/reference/tmpl/rptobjecttext.sgml b/docs/reference/tmpl/rptobjecttext.sgml index 15fc9cd..616a8d6 100644 --- a/docs/reference/tmpl/rptobjecttext.sgml +++ b/docs/reference/tmpl/rptobjecttext.sgml @@ -43,6 +43,26 @@ A textual object. + + + + + + + + + + + + + + + + + + + + diff --git a/docs/reference/tmpl/rptreport.sgml b/docs/reference/tmpl/rptreport.sgml index df3e7fc..94045b4 100644 --- a/docs/reference/tmpl/rptreport.sgml +++ b/docs/reference/tmpl/rptreport.sgml @@ -23,6 +23,17 @@ Manage report definition files and produces the xml report/print's file. + + + + + +@rptreport: the object which received the signal. +@arg1: +@arg2: +@arg3: +@Returns: + @@ -154,6 +165,7 @@ Manage report definition files and produces the xml report/print's file. @rpt_report: @rpt_object: @section: +@Returns: diff --git a/src/Makefile.am b/src/Makefile.am index 6854c2f..2715333 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,6 +4,8 @@ AM_CPPFLAGS = $(REPTOOL_CFLAGS) lib_LTLIBRARIES = libreptool.la +libreptool_la_LDFLAGS = -no-undefined + libreptool_la_SOURCES = \ rptobject.c \ rptobjecttext.c \ @@ -13,7 +15,8 @@ libreptool_la_SOURCES = \ rptobjectimage.c \ rptreport.c \ rptprint.c \ - rptcommon.c + rptcommon.c \ + rptmarshal.c include_HEADERS = \ libreptool.h \ @@ -26,3 +29,6 @@ include_HEADERS = \ rptreport.h \ rptprint.h \ rptcommon.h + +noinst_HEADERS = \ + rptmarshal.h diff --git a/src/libreptool.h b/src/libreptool.h index 42526d6..80fd1e7 100644 --- a/src/libreptool.h +++ b/src/libreptool.h @@ -21,6 +21,13 @@ #define __LIBREPTOOL_H__ #include +#include +#include +#include +#include +#include +#include +#include #include #endif /* __LIBREPTOOL_H__ */ diff --git a/src/reptool_marshal.list b/src/reptool_marshal.list new file mode 100644 index 0000000..2f8088f --- /dev/null +++ b/src/reptool_marshal.list @@ -0,0 +1 @@ +STRING:STRING,POINTER,INT diff --git a/src/rptcommon.c b/src/rptcommon.c index 0ca9437..48676e8 100644 --- a/src/rptcommon.c +++ b/src/rptcommon.c @@ -276,49 +276,49 @@ RptBorder border->left_color->b = 0.0; border->left_color->a = 1.0; - prop = xmlGetProp (xnode, "border-top-width"); + prop = (gchar *)xmlGetProp (xnode, "border-top-width"); if (prop != NULL) { border->top_width = strtod (prop, NULL); } - prop = xmlGetProp (xnode, "border-right-width"); + prop = (gchar *)xmlGetProp (xnode, "border-right-width"); if (prop != NULL) { border->right_width = strtod (prop, NULL); } - prop = xmlGetProp (xnode, "border-bottom-width"); + prop = (gchar *)xmlGetProp (xnode, "border-bottom-width"); if (prop != NULL) { border->bottom_width = strtod (prop, NULL); } - prop = xmlGetProp (xnode, "border-left-width"); + prop = (gchar *)xmlGetProp (xnode, "border-left-width"); if (prop != NULL) { border->left_width = strtod (prop, NULL); } - prop = xmlGetProp (xnode, "border-top-color"); + prop = (gchar *)xmlGetProp (xnode, "border-top-color"); if (prop != NULL) { border->top_color = rpt_common_parse_color (prop); } - prop = xmlGetProp (xnode, "border-right-color"); + prop = (gchar *)xmlGetProp (xnode, "border-right-color"); if (prop != NULL) { border->right_color = rpt_common_parse_color (prop); } - prop = xmlGetProp (xnode, "border-bottom-color"); + prop = (gchar *)xmlGetProp (xnode, "border-bottom-color"); if (prop != NULL) { border->bottom_color = rpt_common_parse_color (prop); } - prop = xmlGetProp (xnode, "border-left-color"); + prop = (gchar *)xmlGetProp (xnode, "border-left-color"); if (prop != NULL) { border->left_color = rpt_common_parse_color (prop); @@ -510,8 +510,9 @@ rpt_common_set_stroke (xmlNode *xnode, const RptStroke *stroke) /** * rpt_common_parse_color: - * @str_color: + * @str_color: a color string. * + * Returns: an #RptColor. */ RptColor *rpt_common_parse_color (const gchar *str_color) @@ -557,7 +558,7 @@ RptColor { color->b = strtol (g_strndup (&c[5], 2), NULL, 16) / 255.0; } - if (strlen (c) == 9) + if (strlen (c) == 9 && isxdigit (c[7]) && isxdigit (c[8])) { color->a = strtol (g_strndup (&c[7], 2), NULL, 16) / 255.0; } @@ -569,8 +570,9 @@ RptColor /** * rpt_common_convert_to_str_color: - * @color: + * @color: an #RptColor value. * + * Returns: the color string correspondent to @color. */ gchar *rpt_common_convert_to_str_color (const RptColor *color) @@ -581,10 +583,10 @@ gchar { ret = g_strdup ("#"); - ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)color->r * 255), NULL); - ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)color->g * 255), NULL); - ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)color->b * 255), NULL); - ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)color->a * 255), NULL); + ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)(color->r * 255)), NULL); + ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)(color->g * 255)), NULL); + ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)(color->b * 255)), NULL); + ret = g_strconcat (ret, g_strdup_printf ("%.2X", (gint)(color->a * 255)), NULL); } return ret; diff --git a/src/rptcommon.h b/src/rptcommon.h index 6057130..71ad03f 100644 --- a/src/rptcommon.h +++ b/src/rptcommon.h @@ -30,10 +30,10 @@ G_BEGIN_DECLS /** * RptColor: - * @r: the red channel - * @g: the green channel - * @b: the blue channel - * @a: the alpha channel + * @r: the red channel. + * @g: the green channel. + * @b: the blue channel. + * @a: the alpha channel. */ struct _RptColor { diff --git a/src/rptmarshal.c b/src/rptmarshal.c new file mode 100644 index 0000000..3664552 --- /dev/null +++ b/src/rptmarshal.c @@ -0,0 +1,92 @@ + +#include + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* STRING:STRING,POINTER,INT (reptool_marshal.list:1) */ +void +_rpt_marshal_STRING__STRING_POINTER_INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gchar* (*GMarshalFunc_STRING__STRING_POINTER_INT) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gint arg_3, + gpointer data2); + register GMarshalFunc_STRING__STRING_POINTER_INT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gchar* v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_STRING__STRING_POINTER_INT) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_string (param_values + 1), + g_marshal_value_peek_pointer (param_values + 2), + g_marshal_value_peek_int (param_values + 3), + data2); + + g_value_take_string (return_value, v_return); +} + diff --git a/src/rptmarshal.h b/src/rptmarshal.h new file mode 100644 index 0000000..56bb519 --- /dev/null +++ b/src/rptmarshal.h @@ -0,0 +1,20 @@ + +#ifndef ___rpt_marshal_MARSHAL_H__ +#define ___rpt_marshal_MARSHAL_H__ + +#include + +G_BEGIN_DECLS + +/* STRING:STRING,POINTER,INT (reptool_marshal.list:1) */ +extern void _rpt_marshal_STRING__STRING_POINTER_INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +G_END_DECLS + +#endif /* ___rpt_marshal_MARSHAL_H__ */ + diff --git a/src/rptobjectimage.c b/src/rptobjectimage.c index 8a81f3d..96e27df 100644 --- a/src/rptobjectimage.c +++ b/src/rptobjectimage.c @@ -132,7 +132,9 @@ rpt_obj_image_init (RptObjImage *rpt_obj_image) /** * rpt_obj_image_new: * @name: the #RptObjImage's name. - * @position: + * @position: an #RptPoint. + * + * Creates a new #RptObjImage object and sets its position to @position. * * Returns: the newly created #RptObject object. */ diff --git a/src/rptobjectline.c b/src/rptobjectline.c index c07f608..6df40b4 100644 --- a/src/rptobjectline.c +++ b/src/rptobjectline.c @@ -116,7 +116,9 @@ rpt_obj_line_init (RptObjLine *rpt_obj_line) /** * rpt_obj_line_new: * @name: the #RptObjLine's name. - * @position: + * @position: an #RptPoint. + * + * Creates a new #RptObjLine object and sets its position to @position. * * Returns: the newly created #RptObject object. */ diff --git a/src/rptobjectrect.c b/src/rptobjectrect.c index 947d3db..ae4609a 100644 --- a/src/rptobjectrect.c +++ b/src/rptobjectrect.c @@ -105,7 +105,9 @@ rpt_obj_rect_init (RptObjRect *rpt_obj_rect) /** * rpt_obj_rect_new: * @name: the #RptObjRect's name. - * @position: + * @position: an #RptPoint. + * + * Creates a new #RptObjRect object and sets its position to @position. * * Returns: the newly created #RptObject object. */ diff --git a/src/rptobjecttext.c b/src/rptobjecttext.c index a1c17fc..a8abc7b 100644 --- a/src/rptobjecttext.c +++ b/src/rptobjecttext.c @@ -27,7 +27,11 @@ enum PROP_FONT, PROP_ALIGN, PROP_SOURCE, - PROP_BACKGROUND_COLOR + PROP_BACKGROUND_COLOR, + PROP_PADDING_TOP, + PROP_PADDING_RIGHT, + PROP_PADDING_BOTTOM, + PROP_PADDING_LEFT }; static void rpt_obj_text_class_init (RptObjTextClass *klass); @@ -54,6 +58,10 @@ struct _RptObjTextPrivate RptAlign *align; gchar *source; RptColor *background_color; + gdouble padding_top; + gdouble padding_right; + gdouble padding_bottom; + gdouble padding_left; }; GType @@ -128,6 +136,30 @@ rpt_obj_text_class_init (RptObjTextClass *klass) "Background Color", "The text's background color.", G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_PADDING_TOP, + g_param_spec_double ("padding-top", + "Padding Top", + "Padding Top", + 0, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_PADDING_RIGHT, + g_param_spec_double ("padding-right", + "Padding Right", + "Padding Right", + 0, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_PADDING_BOTTOM, + g_param_spec_double ("padding-bottom", + "Padding Bottom", + "Padding Bottom", + 0, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_PADDING_LEFT, + g_param_spec_double ("padding-left", + "Padding Left", + "Padding Left", + 0, G_MAXDOUBLE, 0, + G_PARAM_READWRITE)); } static void @@ -148,7 +180,9 @@ rpt_obj_text_init (RptObjText *rpt_obj_text) /** * rpt_obj_text_new: * @name: the #RptObjText's name. - * @position: + * @position: an #RptPoint. + * + * Creates a new #RptObjText object and sets its position to @position. * * Returns: the newly created #RptObject object. */ @@ -174,7 +208,7 @@ RptObject /** * rpt_obj_text_new_from_xml: - * @xnode: + * @xnode: an #xmlNode. * * Returns: the newly created #RptObject object. */ @@ -215,6 +249,27 @@ RptObject color = rpt_common_parse_color (g_strstrip (prop)); g_object_set (rpt_obj_text, "background-color", color, NULL); } + + prop = (gchar *)xmlGetProp (xnode, "padding-top"); + if (prop != NULL) + { + g_object_set (rpt_obj_text, "padding-top", strtod (prop, NULL), NULL); + } + prop = (gchar *)xmlGetProp (xnode, "padding-right"); + if (prop != NULL) + { + g_object_set (rpt_obj_text, "padding-right", strtod (prop, NULL), NULL); + } + prop = (gchar *)xmlGetProp (xnode, "padding-bottom"); + if (prop != NULL) + { + g_object_set (rpt_obj_text, "padding-bottom", strtod (prop, NULL), NULL); + } + prop = (gchar *)xmlGetProp (xnode, "padding-left"); + if (prop != NULL) + { + g_object_set (rpt_obj_text, "padding-left", strtod (prop, NULL), NULL); + } } } @@ -223,8 +278,8 @@ RptObject /** * rpt_obj_text_get_xml: - * @rpt_objtext: - * @xnode: + * @rpt_objtext: an #RptObjText object. + * @xnode: an #xmlNode. * */ void @@ -245,6 +300,23 @@ rpt_obj_text_get_xml (RptObject *rpt_objtext, xmlNode *xnode) { xmlSetProp (xnode, "background-color", rpt_common_convert_to_str_color (priv->background_color)); } + + if (priv->padding_top != 0.0) + { + xmlSetProp (xnode, "padding-top", g_strdup_printf ("%f", priv->padding_top)); + } + if (priv->padding_right != 0.0) + { + xmlSetProp (xnode, "padding-right", g_strdup_printf ("%f", priv->padding_right)); + } + if (priv->padding_bottom != 0.0) + { + xmlSetProp (xnode, "padding-bottom", g_strdup_printf ("%f", priv->padding_bottom)); + } + if (priv->padding_left != 0.0) + { + xmlSetProp (xnode, "padding-left", g_strdup_printf ("%f", priv->padding_left)); + } } static void @@ -280,6 +352,22 @@ rpt_obj_text_set_property (GObject *object, guint property_id, const GValue *val priv->background_color = g_memdup (g_value_get_pointer (value), sizeof (RptColor)); break; + case PROP_PADDING_TOP: + priv->padding_top = g_value_get_double (value); + break; + + case PROP_PADDING_RIGHT: + priv->padding_right = g_value_get_double (value); + break; + + case PROP_PADDING_BOTTOM: + priv->padding_bottom = g_value_get_double (value); + break; + + case PROP_PADDING_LEFT: + priv->padding_left = g_value_get_double (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -319,6 +407,22 @@ rpt_obj_text_get_property (GObject *object, guint property_id, GValue *value, GP g_value_set_pointer (value, g_memdup (priv->background_color, sizeof (RptColor))); break; + case PROP_PADDING_TOP: + g_value_set_double (value, priv->padding_top); + break; + + case PROP_PADDING_RIGHT: + g_value_set_double (value, priv->padding_right); + break; + + case PROP_PADDING_BOTTOM: + g_value_set_double (value, priv->padding_bottom); + break; + + case PROP_PADDING_LEFT: + g_value_set_double (value, priv->padding_left); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; diff --git a/src/rptprint.c b/src/rptprint.c index 35abb3e..696ebe0 100644 --- a/src/rptprint.c +++ b/src/rptprint.c @@ -74,8 +74,13 @@ static void rpt_print_border (RptPrint *rpt_print, typedef struct _RptPrintPrivate RptPrintPrivate; struct _RptPrintPrivate { - gint width; - gint height; + gdouble width; + gdouble height; + gdouble margin_top; + gdouble margin_right; + gdouble margin_bottom; + gdouble margin_left; + cairo_surface_t *surface; cairo_t *cr; }; @@ -130,11 +135,14 @@ rpt_print_init (RptPrint *rpt_print) * @output_type: * @out_filename: * + * Creates a new #RptPrint object. + * * Returns: the newly created #RptPrint object. */ RptPrint *rpt_print_new_from_xml (xmlDoc *xdoc, RptPrintOutputType output_type, const gchar *out_filename) { + gchar *prop; RptPrint *rpt_print = NULL; xmlNode *cur = xmlDocGetRootElement (xdoc); @@ -168,8 +176,36 @@ RptPrint { npage++; - priv->width = atol (xmlGetProp (cur, (const xmlChar *)"width")); - priv->height = atol (xmlGetProp (cur, (const xmlChar *)"height")); + prop = xmlGetProp (cur, (const xmlChar *)"width"); + if (prop != NULL) + { + priv->width = strtod (prop, NULL); + } + prop = xmlGetProp (cur, (const xmlChar *)"height"); + if (prop != NULL) + { + priv->height = strtod (prop, NULL); + } + prop = xmlGetProp (cur, (const xmlChar *)"margin-top"); + if (prop != NULL) + { + priv->margin_top = strtod (prop, NULL); + } + prop = xmlGetProp (cur, (const xmlChar *)"margin-right"); + if (prop != NULL) + { + priv->margin_right = strtod (prop, NULL); + } + prop = xmlGetProp (cur, (const xmlChar *)"margin-bottom"); + if (prop != NULL) + { + priv->margin_bottom = strtod (prop, NULL); + } + prop = xmlGetProp (cur, (const xmlChar *)"margin-left"); + if (prop != NULL) + { + priv->margin_left = strtod (prop, NULL); + } if (priv->width != 0 && priv->height != 0) { @@ -178,19 +214,19 @@ RptPrint switch (output_type) { case RPTP_OUTPUT_PNG: - priv->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, priv->width, priv->height); + priv->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, (int)priv->width, (int)priv->height); break; case RPTP_OUTPUT_PDF: - priv->surface = cairo_pdf_surface_create (out_filename, (double)priv->width, (double)priv->height); + priv->surface = cairo_pdf_surface_create (out_filename, priv->width, priv->height); break; case RPTP_OUTPUT_PS: - priv->surface = cairo_ps_surface_create (out_filename, (double)priv->width, (double)priv->height); + priv->surface = cairo_ps_surface_create (out_filename, priv->width, priv->height); break; case RPTP_OUTPUT_SVG: - priv->surface = cairo_svg_surface_create (out_filename, (double)priv->width, (double)priv->height); + priv->surface = cairo_svg_surface_create (out_filename, priv->width, priv->height); break; } } @@ -273,6 +309,8 @@ RptPrint * @output_type: * @out_filename: * + * Creates a new #RptPrint object. + * * Returns: the newly created #RptPrint object. */ RptPrint @@ -326,6 +364,14 @@ rpt_print_page (RptPrint *rpt_print, xmlNode *xnode) xmlNode *cur = xnode->children; + /* clipping region for page's margins */ + cairo_rectangle (priv->cr, + priv->margin_left, + priv->margin_top, + priv->width - priv->margin_left - priv->margin_right, + priv->height - priv->margin_top - priv->margin_bottom); + cairo_clip (priv->cr); + while (cur != NULL) { cairo_save (priv->cr); @@ -376,10 +422,10 @@ rpt_print_text_xml (RptPrint *rpt_print, xmlNode *xnode) gchar *prop; gchar *str_font; - gdouble pad_top; - gdouble pad_right; - gdouble pad_bottom; - gdouble pad_left; + gdouble padding_top = 0.0; + gdouble padding_right = 0.0; + gdouble padding_bottom = 0.0; + gdouble padding_left = 0.0; position = rpt_common_get_position (xnode); size = rpt_common_get_size (xnode); @@ -391,29 +437,29 @@ rpt_print_text_xml (RptPrint *rpt_print, xmlNode *xnode) prop = xmlGetProp (xnode, (const xmlChar *)"padding-top"); if (prop != NULL) { - pad_top = atof (prop); + padding_top = atof (prop); } prop = xmlGetProp (xnode, (const xmlChar *)"padding-right"); if (prop != NULL) { - pad_right= atof (prop); + padding_right= atof (prop); } prop = xmlGetProp (xnode, (const xmlChar *)"padding-bottom"); if (prop != NULL) { - pad_bottom= atof (prop); + padding_bottom= atof (prop); } prop = xmlGetProp (xnode, (const xmlChar *)"padding-left"); if (prop != NULL) { - pad_left= atof (prop); + padding_left= atof (prop); } /* creating pango layout */ playout = pango_cairo_create_layout (priv->cr); if (size != NULL) { - pango_layout_set_width (playout, size->width * PANGO_SCALE); + pango_layout_set_width (playout, (size->width - padding_left - padding_right) * PANGO_SCALE); } str_font = g_strdup (font->name); @@ -522,7 +568,11 @@ rpt_print_text_xml (RptPrint *rpt_print, xmlNode *xnode) /* setting clipping region */ if (position != NULL && size != NULL) { - cairo_rectangle (priv->cr, position->x, position->y, size->width, size->height); + cairo_rectangle (priv->cr, + position->x + padding_left, + position->y + padding_top, + size->width - padding_left - padding_right, + size->height - padding_top - padding_bottom); cairo_clip (priv->cr); } @@ -540,7 +590,7 @@ rpt_print_text_xml (RptPrint *rpt_print, xmlNode *xnode) } if (position != NULL) { - cairo_move_to (priv->cr, position->x, position->y); + cairo_move_to (priv->cr, position->x + padding_left, position->y + padding_top); } pango_layout_set_text (playout, text, -1); pango_cairo_show_layout (priv->cr, playout); diff --git a/src/rptreport.c b/src/rptreport.c index 075ca6c..e68f0a0 100644 --- a/src/rptreport.c +++ b/src/rptreport.c @@ -20,7 +20,6 @@ #include #include -#include #include #ifdef HAVE_CONFIG_H @@ -35,6 +34,8 @@ #include "rptobjectellipse.h" #include "rptobjectimage.h" +#include "rptmarshal.h" + typedef struct { gchar *provider_id; @@ -49,6 +50,10 @@ typedef struct typedef struct { RptSize *size; + gdouble margin_top; + gdouble margin_right; + gdouble margin_bottom; + gdouble margin_left; } Page; typedef struct @@ -181,6 +186,29 @@ rpt_report_class_init (RptReportClass *klass) object_class->set_property = rpt_report_set_property; object_class->get_property = rpt_report_get_property; + + /** + * RptReport::field-request: + * @rpt_report: an #RptReport object that recieved the signal. + * @field_name: the name of the field requested. + * @data_model: a #GdaDataModel; or NULL if there's no database source. + * @row: the current @data_model's row; -1 if @data_model is NULL. + * + * The signal is emitted each time there's into text's source + * attribute a field that doesn't exists. + */ + klass->field_request_signal_id = g_signal_new ("field-request", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + _rpt_marshal_STRING__STRING_POINTER_INT, + G_TYPE_STRING, + 3, + G_TYPE_STRING, + G_TYPE_POINTER, + G_TYPE_INT); } static void @@ -209,6 +237,8 @@ rpt_report_init (RptReport *rpt_report) /** * rpt_report_new: * + * Creates a new #RptReport object. + * * Returns: the newly created #RptReport object. */ RptReport @@ -319,10 +349,37 @@ RptReport xnodeset = xpresult->nodesetval; if (xnodeset->nodeNr == 1) { + gchar *prop; + gdouble margin_top = 0.0; + gdouble margin_right = 0.0; + gdouble margin_bottom = 0.0; + gdouble margin_left = 0.0; RptSize *size; size = rpt_common_get_size (xnodeset->nodeTab[0]); rpt_report_set_page_size (rpt_report, *size); + + prop = xmlGetProp (xnodeset->nodeTab[0], "margin-top"); + if (prop != NULL) + { + margin_top = strtod (prop, NULL); + } + prop = xmlGetProp (xnodeset->nodeTab[0], "margin-right"); + if (prop != NULL) + { + margin_right = strtod (prop, NULL); + } + prop = xmlGetProp (xnodeset->nodeTab[0], "margin-bottom"); + if (prop != NULL) + { + margin_bottom = strtod (prop, NULL); + } + prop = xmlGetProp (xnodeset->nodeTab[0], "margin-left"); + if (prop != NULL) + { + margin_left = strtod (prop, NULL); + } + rpt_report_set_page_margins (rpt_report, margin_top, margin_right, margin_bottom, margin_left); } else { @@ -456,6 +513,7 @@ rpt_report_set_database (RptReport *rpt_report, * @rpt_report: an #RptReport object. * @size: an #RptSize. * + * Sets page's size. */ void rpt_report_set_page_size (RptReport *rpt_report, @@ -467,12 +525,38 @@ rpt_report_set_page_size (RptReport *rpt_report, priv->page->size->height = size.height; } +/** + * rpt_report_set_page_margins: + * @rpt_report: + * @top: + * @right: + * @bottom: + * @left: + * + * Sets page's margins. + */ +void +rpt_report_set_page_margins (RptReport *rpt_report, + gdouble top, + gdouble right, + gdouble bottom, + gdouble left) +{ + RptReportPrivate *priv = RPT_REPORT_GET_PRIVATE (rpt_report); + + priv->page->margin_top = top; + priv->page->margin_right = right; + priv->page->margin_bottom = bottom; + priv->page->margin_left = left; +} + /** * rpt_report_set_section_height: * @rpt_report: an #RptReport object. * @section: * @height: the section's height. * + * Sets @section's height. */ void rpt_report_set_section_height (RptReport *rpt_report, @@ -619,6 +703,22 @@ xmlDoc xnode = xmlNewNode (NULL, "page"); rpt_common_set_size (xnode, priv->page->size); + if (priv->page->margin_top != 0.0) + { + xmlSetProp (xnode, "margin-top", g_strdup_printf ("%f", priv->page->margin_top)); + } + if (priv->page->margin_right != 0.0) + { + xmlSetProp (xnode, "margin-right", g_strdup_printf ("%f", priv->page->margin_right)); + } + if (priv->page->margin_bottom != 0.0) + { + xmlSetProp (xnode, "margin-bottom", g_strdup_printf ("%f", priv->page->margin_bottom)); + } + if (priv->page->margin_left != 0.0) + { + xmlSetProp (xnode, "margin-left", g_strdup_printf ("%f", priv->page->margin_left)); + } xmlAddChild (xroot, xnode); xreport = xmlNewNode (NULL, "report"); @@ -700,6 +800,8 @@ xmlDoc priv->db->gda_datamodel = gda_connection_execute_single_command (priv->db->gda_conn, command, NULL); if (priv->db->gda_datamodel == NULL) { + /* TO DO */ + g_warning ("Unable to create the datamodel."); return NULL; } @@ -712,20 +814,20 @@ xmlDoc { if (row == 0 || priv->body->new_page_after || - (priv->page_footer != NULL && (cur_y + priv->body->height > priv->page->size->height - (priv->page_footer != NULL ? priv->page_footer->height: 0.0))) || - cur_y > priv->page->size->height) + (priv->page_footer != NULL && (cur_y + priv->body->height > priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom - (priv->page_footer != NULL ? priv->page_footer->height: 0.0))) || + cur_y > (priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom)) { if (priv->cur_page > 0 && priv->page_footer != NULL) { if ((priv->cur_page == 1 && priv->page_footer->first_page) || priv->cur_page > 1) { - cur_y = priv->page->size->height - priv->page_footer->height; + cur_y = priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom - priv->page_footer->height; rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER, row - 1); } } - cur_y = 0.0; + cur_y = priv->page->margin_top; xpage = rpt_report_rptprint_new_page (rpt_report, xroot); if (priv->cur_page == 1 && priv->report_header != NULL) @@ -752,16 +854,16 @@ xmlDoc if (priv->cur_page > 0 && priv->report_footer != NULL) { - if ((cur_y + priv->report_footer->height > priv->page->size->height - (priv->page_footer != NULL ? priv->page_footer->height : 0.0)) || + if ((cur_y + priv->report_footer->height > priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom - (priv->page_footer != NULL ? priv->page_footer->height : 0.0)) || priv->report_footer->new_page_before) { if (priv->cur_page > 0 && priv->page_footer != NULL) { - cur_y = priv->page->size->height - priv->page_footer->height; + cur_y = priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom - priv->page_footer->height; rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER, row - 1); } - cur_y = 0.0; + cur_y = priv->page->margin_top; xpage = rpt_report_rptprint_new_page (rpt_report, xroot); if (priv->page_header != NULL) @@ -773,13 +875,14 @@ xmlDoc } if (priv->cur_page > 0 && priv->page_footer != NULL && priv->page_footer->last_page) { - cur_y = priv->page->size->height - priv->page_footer->height; + cur_y = priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom - priv->page_footer->height; rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER, row - 1); } } else { priv->cur_page++; + cur_y = priv->page->margin_top; xpage = rpt_report_rptprint_new_page (rpt_report, xroot); if (priv->report_header != NULL) @@ -799,7 +902,7 @@ xmlDoc } if (priv->page_footer != NULL) { - cur_y = priv->page->size->height - priv->page_footer->height; + cur_y = priv->page->size->height - priv->page->margin_top - priv->page->margin_bottom - priv->page_footer->height; rpt_report_rptprint_section (rpt_report, xpage, &cur_y, RPTREPORT_SECTION_PAGE_FOOTER, -1); } } @@ -813,34 +916,52 @@ xmlDoc * @rpt_object: an #RptObject object. * @section: * + * Returns: FALSE if already exists an #RptObject with the same @rpt_object's + * name; TRUE otherwise. */ -void +gboolean rpt_report_add_object_to_section (RptReport *rpt_report, RptObject *rpt_object, RptReportSection section) { + gboolean ret = FALSE; + gchar *objname; + RptReportPrivate *priv = RPT_REPORT_GET_PRIVATE (rpt_report); - switch (section) + g_object_get (rpt_object, "name", &objname, NULL); + if (rpt_report_get_object_from_name (rpt_report, objname) == NULL) { - case RPTREPORT_SECTION_REPORT_HEADER: - priv->report_header->objects = g_list_append (priv->report_header->objects, rpt_object);; - break; + switch (section) + { + case RPTREPORT_SECTION_REPORT_HEADER: + priv->report_header->objects = g_list_append (priv->report_header->objects, rpt_object);; + break; - case RPTREPORT_SECTION_REPORT_FOOTER: - priv->report_footer->objects = g_list_append (priv->report_footer->objects, rpt_object);; - break; + case RPTREPORT_SECTION_REPORT_FOOTER: + priv->report_footer->objects = g_list_append (priv->report_footer->objects, rpt_object);; + break; - case RPTREPORT_SECTION_PAGE_HEADER: - priv->page_header->objects = g_list_append (priv->page_header->objects, rpt_object);; - break; + case RPTREPORT_SECTION_PAGE_HEADER: + priv->page_header->objects = g_list_append (priv->page_header->objects, rpt_object);; + break; - case RPTREPORT_SECTION_PAGE_FOOTER: - priv->page_footer->objects = g_list_append (priv->page_footer->objects, rpt_object);; - break; + case RPTREPORT_SECTION_PAGE_FOOTER: + priv->page_footer->objects = g_list_append (priv->page_footer->objects, rpt_object);; + break; - case RPTREPORT_SECTION_BODY: - priv->body->objects = g_list_append (priv->body->objects, rpt_object);; - break; + case RPTREPORT_SECTION_BODY: + priv->body->objects = g_list_append (priv->body->objects, rpt_object);; + break; + } + + ret = TRUE; } + else + { + /* TO DO */ + g_warning ("An object with name \"%s\" already exists.", objname); + } + + return ret; } /** @@ -1208,17 +1329,7 @@ rpt_report_xml_parse_section (RptReport *rpt_report, xmlNode *xnode, RptReportSe if (rptobj != NULL) { - g_object_get (rptobj, "name", &objname, NULL); - - if (rpt_report_get_object_from_name (rpt_report, objname) == NULL) - { - rpt_report_add_object_to_section (rpt_report, rptobj, section); - } - else - { - /* TO DO */ - g_warning ("An object with name \"%s\" already exists.", objname); - } + rpt_report_add_object_to_section (rpt_report, rptobj, section); } cur = cur->next; @@ -1320,6 +1431,22 @@ static xmlNode xmlAddChild (xroot, xnode); rpt_common_set_size (xnode, priv->page->size); + if (priv->page->margin_top != 0.0) + { + xmlSetProp (xnode, "margin-top", g_strdup_printf ("%f", priv->page->margin_top)); + } + if (priv->page->margin_right != 0.0) + { + xmlSetProp (xnode, "margin-right", g_strdup_printf ("%f", priv->page->margin_right)); + } + if (priv->page->margin_bottom != 0.0) + { + xmlSetProp (xnode, "margin-bottom", g_strdup_printf ("%f", priv->page->margin_bottom)); + } + if (priv->page->margin_left != 0.0) + { + xmlSetProp (xnode, "margin-left", g_strdup_printf ("%f", priv->page->margin_left)); + } priv->cur_page++; @@ -1373,6 +1500,16 @@ rpt_report_rptprint_section (RptReport *rpt_report, xmlNode *xpage, gdouble *cur xmlRemoveProp (attr); } + if (priv->page->margin_left != 0.0) + { + prop = (gchar *)xmlGetProp (xnode, "x"); + if (prop == NULL) + { + prop = g_strdup ("0.0"); + } + xmlSetProp (xnode, "x", g_strdup_printf ("%f", strtod (prop, NULL) + priv->page->margin_left)); + } + prop = (gchar *)xmlGetProp (xnode, "y"); if (prop == NULL) { @@ -1448,14 +1585,40 @@ rpt_report_rptprint_parse_text_source (RptReport *rpt_report, RptObject *rptobj, } else { - /* TO DO */ /* ask value */ + gchar *ret; + RptReportClass *klass = RPT_REPORT_GET_CLASS (rpt_report); + + g_signal_emit (rpt_report, klass->field_request_signal_id, + 0, field, priv->db->gda_datamodel, row, &ret); + if (ret != NULL) + { + source = g_strdup (ret); + } + else + { + source = g_strdup (""); + } } } else if (source[0] == '[' && source[strlen (source) - 1] == ']') { - /* TO DO */ /* ask value */ + gchar *ret; + gchar *field; + RptReportClass *klass = RPT_REPORT_GET_CLASS (rpt_report); + + field = g_strstrip (g_strndup (source + 1, strlen (source) - 2)); + g_signal_emit (rpt_report, klass->field_request_signal_id, + 0, field, NULL, row, &ret); + if (ret != NULL) + { + source = g_strdup (ret); + } + else + { + source = g_strdup (""); + } } else if (source[0] == '@') { @@ -1483,6 +1646,14 @@ rpt_report_rptprint_parse_text_source (RptReport *rpt_report, RptObject *rptobj, source = g_strdup_printf ("%s", &date); } } + else if (source[0] = '"' && source[strlen (source) - 1] == '"') + { + source = g_strndup (source + 1, strlen (source) - 2); + } + else + { + source = g_strdup (""); + } xmlNodeSetContent (xnode, source); } diff --git a/src/rptreport.h b/src/rptreport.h index 04d8843..5be4f23 100644 --- a/src/rptreport.h +++ b/src/rptreport.h @@ -22,6 +22,7 @@ #include #include +#include #include #include "rptobject.h" @@ -48,6 +49,8 @@ struct _RptReport struct _RptReportClass { GObjectClass parent_class; + + guint field_request_signal_id; }; GType rpt_report_get_type (void) G_GNUC_CONST; @@ -74,6 +77,11 @@ void rpt_report_set_database (RptReport *rpt_report, void rpt_report_set_page_size (RptReport *rpt_report, RptSize size); +void rpt_report_set_page_margins (RptReport *rpt_report, + gdouble top, + gdouble right, + gdouble bottom, + gdouble left); void rpt_report_set_section_height (RptReport *rpt_report, RptReportSection section, @@ -95,9 +103,9 @@ xmlDoc *rpt_report_get_xml (RptReport *rpt_report); xmlDoc *rpt_report_get_xml_rptprint (RptReport *rpt_report); -void rpt_report_add_object_to_section (RptReport *rpt_report, - RptObject *rpt_object, - RptReportSection section); +gboolean rpt_report_add_object_to_section (RptReport *rpt_report, + RptObject *rpt_object, + RptReportSection section); void rpt_report_remove_object (RptReport *rpt_report, RptObject *rpt_object); diff --git a/tests/Makefile.am b/tests/Makefile.am index ccd4a53..b491e5a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -5,8 +5,10 @@ AM_CPPFLAGS = $(REPTOOL_CFLAGS) \ libreptool = $(top_builddir)/src/libreptool.la -noinst_PROGRAMS = test_rptprint \ - test_rptreport +noinst_PROGRAMS = \ + test_rptreport \ + test_rptprint \ + test_rptreport_creation LDADD = $(libreptool) diff --git a/tests/test_report.rpt b/tests/test_report.rpt index 41299a2..b95fc60 100644 --- a/tests/test_report.rpt +++ b/tests/test_report.rpt @@ -1,12 +1,19 @@ - + - - + + + + + + diff --git a/tests/test_report_db.rpt b/tests/test_report_db.rpt index 1709557..40b7594 100644 --- a/tests/test_report_db.rpt +++ b/tests/test_report_db.rpt @@ -11,26 +11,27 @@ - + - + + - + - + diff --git a/tests/test_rptreport.c b/tests/test_rptreport.c index 1b27f07..f5e9d71 100644 --- a/tests/test_rptreport.c +++ b/tests/test_rptreport.c @@ -19,6 +19,31 @@ #include #include +gchar +*field_request (RptReport *rpt_report, + gchar *field_name, + GdaDataModel *data_model, + gint row, + gpointer user_data) +{ + gchar *ret = NULL; + + if (strcmp (field_name, "field_to_request") == 0) + { + ret = g_strdup ("the field requested"); + } + else if (strcmp (field_name, "nonexistent") == 0 && + data_model != NULL && + row > -1) + { + ret = g_strdup_printf ("%s - %s", + gda_value_stringify ((GdaValue *)gda_data_model_get_value_at (data_model, 0, row)), + gda_value_stringify ((GdaValue *)gda_data_model_get_value_at (data_model, 1, row))); + } + + return ret; +} + int main (int argc, char **argv) { @@ -29,6 +54,8 @@ main (int argc, char **argv) rptr = rpt_report_new_from_file (argv[1]); + g_signal_connect (rptr, "field-request", G_CALLBACK (field_request), NULL); + if (rptr != NULL) { xmlDoc *report = rpt_report_get_xml (rptr); diff --git a/tests/test_rptreport_creation.c b/tests/test_rptreport_creation.c new file mode 100644 index 0000000..0e0652c --- /dev/null +++ b/tests/test_rptreport_creation.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2007 Andrea Zagli + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA + */ + +#include + +int +main (int argc, char **argv) +{ + RptReport *rptr; + RptObject *obj; + RptPoint point; + RptSize size; + RptStroke stroke; + RptColor *color; + + g_type_init (); + + rptr = rpt_report_new (); + + if (rptr != NULL) + { + size.width = 500; + size.height = 500; + rpt_report_set_page_size (rptr, size); + + point.x = 10; + point.y = 10; + obj = rpt_obj_text_new ("text1", point); + size.width = 480; + size.height = 50; + g_object_set (obj, + "source", "The first object inserted.", + "size", &size, + NULL); + rpt_report_add_object_to_section (rptr, obj, RPTREPORT_SECTION_BODY); + + point.x = 10; + point.y = 60; + obj = rpt_obj_line_new ("line1", point); + size.width = 480; + size.height = 0; + stroke.color = rpt_common_parse_color ("#FF0000"); + g_object_set (obj, + "size", &size, + "stroke", &stroke, + NULL); + rpt_report_add_object_to_section (rptr, obj, RPTREPORT_SECTION_BODY); + + point.x = 0; + point.y = 0; + obj = rpt_obj_line_new ("line2", point); + size.width = 500; + size.height = 500; + stroke.color = rpt_common_parse_color ("#000000AA"); + g_object_set (obj, + "size", &size, + "stroke", &stroke, + NULL); + rpt_report_add_object_to_section (rptr, obj, RPTREPORT_SECTION_BODY); + + point.x = 500; + point.y = 0; + obj = rpt_obj_line_new ("line3", point); + size.width = -500; + size.height = 500; + stroke.color = rpt_common_parse_color ("#000000AA"); + g_object_set (obj, + "size", &size, + "stroke", &stroke, + NULL); + rpt_report_add_object_to_section (rptr, obj, RPTREPORT_SECTION_BODY); + + point.x = 250; + point.y = 250; + obj = rpt_obj_ellipse_new ("circle1", point); + size.width = 100; + size.height = 100; + color = rpt_common_parse_color ("#00FF0099"); + stroke.color = rpt_common_parse_color ("#00FF00AA"); + g_object_set (obj, + "size", &size, + "stroke", &stroke, + "fill-color", color, + NULL); + rpt_report_add_object_to_section (rptr, obj, RPTREPORT_SECTION_BODY); + + xmlDoc *report = rpt_report_get_xml (rptr); + xmlSaveFormatFile ("test_report.rpt", report, 2); + + xmlDoc *rptprint = rpt_report_get_xml_rptprint (rptr); + xmlSaveFormatFile ("test_report.rptr", rptprint, 2); + + rpt_print_new_from_xml (rptprint, RPTP_OUTPUT_PDF, "test.pdf"); + } + + return 0; +} -- 2.49.0