[goffice] Add support for svg images.
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Add support for svg images.
- Date: Wed, 26 Oct 2011 10:08:37 +0000 (UTC)
commit 6924d264ae12c9ed4c76c1039e376e616759d9ab
Author: Jean Brefort <jean brefort normalesup org>
Date: Wed Oct 26 12:06:48 2011 +0200
Add support for svg images.
ChangeLog | 4 +
goffice/app/go-doc.c | 24 ++-
goffice/app/go-doc.h | 2 +-
goffice/canvas/goc-arc.c | 4 +-
goffice/canvas/goc-circle.c | 3 +-
goffice/canvas/goc-ellipse.c | 5 +-
goffice/canvas/goc-path.c | 4 +-
goffice/canvas/goc-pixbuf.c | 17 +--
goffice/canvas/goc-polygon.c | 8 +-
goffice/canvas/goc-rectangle.c | 5 +-
goffice/component/go-component.c | 30 ++--
goffice/goffice.c | 24 +--
goffice/graph/gog-error-bar.c | 46 -----
goffice/graph/gog-object-xml.c | 37 +----
goffice/graph/gog-renderer.c | 22 +--
goffice/gtk/goffice-gtk.c | 13 ++
goffice/utils/Makefile.am | 2 +
goffice/utils/go-image.c | 393 ++++++++-----------------------------
goffice/utils/go-image.h | 36 +++-
goffice/utils/go-persist.c | 7 -
goffice/utils/go-persist.h | 2 -
goffice/utils/go-pixbuf.c | 270 +++++++++++++++++++++++++
goffice/utils/go-pixbuf.h | 10 +
goffice/utils/go-style-prefs.ui | 3 +
goffice/utils/go-style.c | 402 ++++++++------------------------------
goffice/utils/go-style.h | 7 +-
goffice/utils/go-styled-object.c | 22 +--
goffice/utils/go-styled-object.h | 3 +-
goffice/utils/go-svg.c | 182 +++++++++++++++++
goffice/utils/go-svg.h | 40 ++++
goffice/utils/goffice-utils.h | 3 +
31 files changed, 788 insertions(+), 842 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index eed51a8..44f890b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2011-10-26 Jean Brefort <jean brefort normalesup org>
+
+ * all files: add support for svg images using librsvg.
+
2011-10-25 Morten Welinder <terra gnome org>
* goffice/gtk/goffice-gtk.c (apply_ui_from_file): Add filename
diff --git a/goffice/app/go-doc.c b/goffice/app/go-doc.c
index a2b9111..3d44e88 100644
--- a/goffice/app/go-doc.c
+++ b/goffice/app/go-doc.c
@@ -324,7 +324,7 @@ go_doc_update_meta_data (GODoc *doc)
*
* Returns: the #GOImage is one exist with name @id. The caller does not own a
* reference.
- */
+ **/
GOImage *
go_doc_get_image (GODoc *doc, char const *id)
{
@@ -342,7 +342,7 @@ go_doc_get_image (GODoc *doc, char const *id)
* the returned image might be different from @id, even if given.
* Returns: either @image, in which case the document adds a reference on it, or
* an identical image for which the owner does not own a reference.
- */
+ **/
GOImage *
go_doc_add_image (GODoc *doc, char const *id, GOImage *image)
{
@@ -359,7 +359,7 @@ go_doc_add_image (GODoc *doc, char const *id, GOImage *image)
/* check if the image is already there */
g_hash_table_iter_init (&iter, doc->images);
while (g_hash_table_iter_next (&iter, (void**) &key, (void**) &img))
- if (go_image_same_pixbuf (image, img))
+ if (!go_image_differ (image, img))
return img;
if (!id || !*id)
@@ -445,15 +445,19 @@ static void
load_image (GsfXMLIn *xin, xmlChar const **attrs)
{
GODoc *doc = GO_DOC (xin->user_state);
- GOImage *image;
+ GOImage *image = NULL;
xmlChar const **attr = attrs;
+ GType type = 0;
if (!*attr)
return;
- while (*attr && strcmp (*attr, "name"))
- attr += 2;
- image = (GOImage *) g_hash_table_lookup (doc->imagebuf, attr[1]);
+ for (attr = attrs; *attr; attr += 2)
+ if (!strcmp (*attr, "name"))
+ image = (GOImage *) g_hash_table_lookup (doc->imagebuf, attr[1]);
+ else if (!strcmp (*attr, "type"))
+ type = g_type_from_name (attr[1]);
if (!image) /* this should not occur, but if it does, we might want to load the image? */
return;
+ g_return_if_fail (type == 0 || G_OBJECT_TYPE (image) == type);
go_image_load_attrs (image, xin, attrs);
g_object_set_data (G_OBJECT (doc), "new image", image);
}
@@ -522,15 +526,15 @@ go_doc_end_read (GODoc *doc)
* This function must be called after a call to go_doc_init_read(), otherwise
* it will emit a critical and return NULL.
* Returns: the found or created #GOImage.
- */
+ **/
GOImage *
-go_doc_image_fetch (GODoc *doc, char const *id)
+go_doc_image_fetch (GODoc *doc, char const *id, GType type)
{
GOImage *image;
g_return_val_if_fail (doc && doc->imagebuf, NULL);
image = g_hash_table_lookup (doc->imagebuf, id);
if (!image) {
- image = g_object_new (GO_TYPE_IMAGE, NULL);
+ image = g_object_new (type, NULL);
go_image_set_name (image, id);
g_hash_table_replace (doc->imagebuf,
g_strdup (go_image_get_name (image)),
diff --git a/goffice/app/go-doc.h b/goffice/app/go-doc.h
index 69e5d01..a9c10ef 100644
--- a/goffice/app/go-doc.h
+++ b/goffice/app/go-doc.h
@@ -71,7 +71,7 @@ void go_doc_save_image (GODoc *doc, char const *id);
void go_doc_init_read (GODoc *doc, GsfInput *input);
void go_doc_read (GODoc *doc, GsfXMLIn *xin, xmlChar const **attrs);
void go_doc_end_read (GODoc *doc);
-GOImage *go_doc_image_fetch (GODoc *doc, char const *id);
+GOImage *go_doc_image_fetch (GODoc *doc, char const *id, GType type);
G_END_DECLS
diff --git a/goffice/canvas/goc-arc.c b/goffice/canvas/goc-arc.c
index 300270e..f8e1c56 100644
--- a/goffice/canvas/goc-arc.c
+++ b/goffice/canvas/goc-arc.c
@@ -389,8 +389,8 @@ goc_arc_draw (GocItem const *item, cairo_t *cr)
cairo_save(cr);
if (goc_arc_prepare_draw (item, cr, 1)) {
- if (arc->type > 0 && go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
+ if (arc->type > 0)
+ go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr)) {
cairo_stroke (cr);
} else {
diff --git a/goffice/canvas/goc-circle.c b/goffice/canvas/goc-circle.c
index 8c58ea5..47e8395 100644
--- a/goffice/canvas/goc-circle.c
+++ b/goffice/canvas/goc-circle.c
@@ -117,8 +117,7 @@ goc_circle_draw (GocItem const *item, cairo_t *cr)
cairo_arc (cr, 0., 0., 1., 0., 2 * M_PI);
cairo_restore (cr);
/* Fill the shape */
- if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
+ go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
/* Draw the line */
if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr))
cairo_stroke (cr);
diff --git a/goffice/canvas/goc-ellipse.c b/goffice/canvas/goc-ellipse.c
index ec3b5d4..f1d6a7a 100644
--- a/goffice/canvas/goc-ellipse.c
+++ b/goffice/canvas/goc-ellipse.c
@@ -141,7 +141,7 @@ goc_ellipse_update_bounds (GocItem *item)
if (goc_ellipse_prepare_draw (item, cr, 0)) {
if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr))
cairo_stroke_extents (cr, &item->x0, &item->y0, &item->x1, &item->y1);
- else if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
+ else if (go_style_is_fill_visible (go_styled_object_get_style (GO_STYLED_OBJECT (item))))
cairo_fill_extents (cr, &item->x0, &item->y0, &item->x1, &item->y1);
else {
item->x0 = item->y0 = G_MAXDOUBLE;
@@ -199,8 +199,7 @@ goc_ellipse_draw (GocItem const *item, cairo_t *cr)
{
cairo_save(cr);
if (goc_ellipse_prepare_draw (item, cr, 1)) {
- if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
+ go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr)) {
cairo_stroke (cr);
} else {
diff --git a/goffice/canvas/goc-path.c b/goffice/canvas/goc-path.c
index e7d310d..570ff83 100644
--- a/goffice/canvas/goc-path.c
+++ b/goffice/canvas/goc-path.c
@@ -191,8 +191,8 @@ goc_path_draw (GocItem const *item, cairo_t *cr)
cairo_save(cr);
if (goc_path_prepare_draw (item, cr, 1)) {
- if (path->closed && go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
+ if (path->closed)
+ go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr)) {
cairo_stroke (cr);
} else {
diff --git a/goffice/canvas/goc-pixbuf.c b/goffice/canvas/goc-pixbuf.c
index 14338a1..22a1422 100644
--- a/goffice/canvas/goc-pixbuf.c
+++ b/goffice/canvas/goc-pixbuf.c
@@ -177,17 +177,14 @@ goc_pixbuf_draw (GocItem const *item, cairo_t *cr)
{
GocPixbuf *pixbuf = GOC_PIXBUF (item);
GOImage * image;
- cairo_pattern_t *pat;
double height, width;
double scalex = 1., scaley = 1.;
int x;
- cairo_matrix_t mat;
if (pixbuf->pixbuf == NULL || pixbuf->width == 0. || pixbuf->height == 0.)
return;
- image = go_image_new_from_pixbuf (pixbuf->pixbuf);
- pat = go_image_create_cairo_pattern (image);
+ image = GO_IMAGE (go_pixbuf_new_from_pixbuf (pixbuf->pixbuf));
if (pixbuf->width < 0.)
width = gdk_pixbuf_get_width (pixbuf->pixbuf);
else {
@@ -205,14 +202,10 @@ goc_pixbuf_draw (GocItem const *item, cairo_t *cr)
pixbuf->x + pixbuf->width: pixbuf->x;
goc_group_cairo_transform (item->parent, cr, x, (int) pixbuf->y);
cairo_rotate (cr, pixbuf->rotation);
- if (scalex != 1. || scaley != 1.) {
- cairo_matrix_init_scale (&mat, 1. / scalex, 1. /scaley);
- cairo_pattern_set_matrix (pat, &mat);
- }
- cairo_rectangle (cr, 0., 0., ceil (width), ceil (height));
- cairo_set_source (cr, pat);
- cairo_pattern_destroy (pat);
- cairo_fill (cr);
+ if (scalex != 1. || scaley != 1.)
+ cairo_scale (cr, scalex, scaley);
+ cairo_move_to (cr, 0, 0);
+ go_image_draw (image, cr);
cairo_restore (cr);
g_object_unref (image);
}
diff --git a/goffice/canvas/goc-polygon.c b/goffice/canvas/goc-polygon.c
index 7c8ac08..cfcc52b 100644
--- a/goffice/canvas/goc-polygon.c
+++ b/goffice/canvas/goc-polygon.c
@@ -220,7 +220,7 @@ goc_polygon_update_bounds (GocItem *item)
cr = cairo_create (surface);
if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr))
mode = 1;
- else if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
+ else if (go_style_is_fill_visible (go_styled_object_get_style (GO_STYLED_OBJECT (item))))
mode = 2;
if (mode && goc_polygon_prepare_path (item, cr, 0)) {
if (mode == 1)
@@ -258,8 +258,7 @@ goc_polygon_distance (GocItem *item, double x, double y, GocItem **near_item)
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cr = cairo_create (surface);
goc_polygon_prepare_path (item, cr, 0);
- if (style->fill.type != GO_STYLE_FILL_NONE) {
- go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr);
+ if (go_style_is_fill_visible (style)) {
if (cairo_in_fill (cr, x, y))
res = 0;
else if ((item->x1 - item->x0 < 5 || item->y1 - item->y0 < 5) && style->line.dash_type == GO_LINE_NONE) {
@@ -285,8 +284,7 @@ goc_polygon_draw (GocItem const *item, cairo_t *cr)
{
cairo_save (cr);
if (goc_polygon_prepare_path (item, cr, 1)) {
- if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
+ go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr))
cairo_stroke (cr);
diff --git a/goffice/canvas/goc-rectangle.c b/goffice/canvas/goc-rectangle.c
index 285ec5a..decff6b 100644
--- a/goffice/canvas/goc-rectangle.c
+++ b/goffice/canvas/goc-rectangle.c
@@ -215,7 +215,7 @@ goc_rectangle_update_bounds (GocItem *item)
if (goc_rectangle_prepare_draw (item, cr, 0)) {
if (go_styled_object_set_cairo_line (GO_STYLED_OBJECT (item), cr))
cairo_stroke_extents (cr, &item->x0, &item->y0, &item->x1, &item->y1);
- else if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
+ else if (go_style_is_fill_visible (go_styled_object_get_style (GO_STYLED_OBJECT (item))))
cairo_fill_extents (cr, &item->x0, &item->y0, &item->x1, &item->y1);
else {
item->x0 = item->y0 = G_MAXDOUBLE;
@@ -273,8 +273,7 @@ goc_rectangle_draw (GocItem const *item, cairo_t *cr)
{
cairo_save(cr);
if (goc_rectangle_prepare_draw (item, cr, 1)) {
- if (go_styled_object_set_cairo_fill (GO_STYLED_OBJECT (item), cr))
- cairo_fill_preserve (cr);
+ go_styled_object_fill (GO_STYLED_OBJECT (item), cr, TRUE);
if (goc_styled_item_set_cairo_line (GOC_STYLED_ITEM (item), cr)) {
cairo_stroke (cr);
} else {
diff --git a/goffice/component/go-component.c b/goffice/component/go-component.c
index 77df27c..3b93371 100644
--- a/goffice/component/go-component.c
+++ b/goffice/component/go-component.c
@@ -249,7 +249,7 @@ go_component_snapshot_render (GOComponent *component, cairo_t *cr,
GOComponentSnapshot *snapshot = (GOComponentSnapshot *) component;
switch (component->snapshot_type) {
case GO_SNAPSHOT_SVG:
-#if defined(GOFFICE_WITH_RSVG)
+ /* NOTE: we might use lasem here, and also use a GOSvg image */
if (snapshot->image == NULL) {
GError *err = NULL;
snapshot->image = (void *) rsvg_handle_new_from_data (
@@ -275,11 +275,7 @@ go_component_snapshot_render (GOComponent *component, cairo_t *cr,
cairo_restore (cr);
}
break;
-#elif defined(GOFFICE_WITH_LASEM)
- /* TODO: implement a Lasem based svg rendering when possible */
-#endif
case GO_SNAPSHOT_PNG: {
- cairo_pattern_t *pattern;
if (snapshot->image == NULL) {
GInputStream *in = g_memory_input_stream_new_from_data (
component->snapshot_data,
@@ -290,28 +286,26 @@ go_component_snapshot_render (GOComponent *component, cairo_t *cr,
if (err) {
g_error_free (err);
} else
- snapshot->image = (void *) go_image_new_from_pixbuf (pixbuf);
+ snapshot->image = (void *) go_pixbuf_new_from_pixbuf (pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
}
- cairo_rectangle (cr, 0, 0, width, height);
if (snapshot->image != NULL) {
int w, h;
double scalex = 1., scaley = 1.;
- cairo_matrix_t matrix;
- pattern = go_image_create_cairo_pattern (GO_IMAGE (snapshot->image));
+ cairo_save (cr);
g_object_get (snapshot->image, "width", &w, "height", &h, NULL);
cairo_user_to_device_distance (cr, &scalex, &scaley);
- cairo_matrix_init_scale (&matrix,
- w / width * scalex,
- h / height * scaley);
- cairo_pattern_set_matrix (pattern, &matrix);
- } else
- pattern = cairo_pattern_create_rgba (1, 1, 1, 1);
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
- cairo_fill (cr);
+ cairo_scale (cr, width / w / scalex, height / h / scaley);
+ cairo_move_to (cr, 0, 0);
+ go_image_draw (GO_IMAGE (snapshot->image), cr);
+ cairo_restore (cr);
+ } else {
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_set_source_rgb (cr, 1., 1., 1.);
+ cairo_fill (cr);
+ }
break;
}
default:
diff --git a/goffice/goffice.c b/goffice/goffice.c
index df9f3a8..ccef860 100644
--- a/goffice/goffice.c
+++ b/goffice/goffice.c
@@ -22,28 +22,6 @@
#include <goffice/goffice-config.h>
#include <goffice/goffice.h>
#include <goffice/goffice-priv.h>
-#include <goffice/graph/gog-series.h>
-#include <goffice/graph/gog-plot.h>
-#include <goffice/graph/gog-plot-engine.h>
-#include <goffice/graph/gog-chart.h>
-#include <goffice/graph/gog-graph.h>
-#include <goffice/graph/gog-axis.h>
-#include <goffice/graph/gog-legend.h>
-#include <goffice/graph/gog-label.h>
-#include <goffice/graph/gog-grid.h>
-#include <goffice/graph/gog-grid-line.h>
-#include <goffice/graph/gog-theme.h>
-#include <goffice/graph/gog-error-bar.h>
-#include <goffice/graph/gog-series-lines.h>
-#include <goffice/graph/gog-3d-box.h>
-#include <goffice/data/go-data-simple.h>
-#include <goffice/math/go-distribution.h>
-#include <goffice/math/go-math.h>
-#include <goffice/utils/go-format.h>
-#include <goffice/utils/go-font.h>
-#include <goffice/app/go-conf.h>
-#include <goffice/app/go-plugin-service.h>
-#include <goffice/component/go-component-factory.h>
#include <gsf/gsf-utils.h>
#include "goffice-paths.h"
@@ -235,6 +213,8 @@ libgoffice_init (void)
(void) GO_TYPE_DATA_SCALAR_VAL;
(void) GO_TYPE_DATA_SCALAR_STR;
(void) GOG_3D_BOX_TYPE;
+ (void) GO_TYPE_PIXBUF;
+ (void) GO_TYPE_SVG;
_gog_themes_init ();
_go_number_format_init ();
_go_currency_date_format_init ();
diff --git a/goffice/graph/gog-error-bar.c b/goffice/graph/gog-error-bar.c
index 3b34923..5a4ab33 100644
--- a/goffice/graph/gog-error-bar.c
+++ b/goffice/graph/gog-error-bar.c
@@ -359,51 +359,6 @@ gog_error_bar_class_init (GogErrorBarClass *klass)
gobject_klass->finalize = gog_error_bar_finalize;
}
-static gboolean
-gog_error_bar_persist_dom_load (GOPersist *gp, xmlNode *node)
-{
- GogErrorBar *bar = GOG_ERROR_BAR (gp);
-
- gchar* str;
- str = xmlGetProp (node, CC2XML ("error_type"));
- if (str) {
- if (!strcmp (str, "absolute"))
- bar->type = GOG_ERROR_BAR_TYPE_ABSOLUTE;
- else if (!strcmp (str, "relative"))
- bar->type = GOG_ERROR_BAR_TYPE_RELATIVE;
- else if (!strcmp (str, "percent"))
- bar->type = GOG_ERROR_BAR_TYPE_PERCENT;
- xmlFree (str);
- }
- str = xmlGetProp (node, CC2XML ("display"));
- if (str) {
- if (!strcmp (str, "none"))
- bar->display = GOG_ERROR_BAR_DISPLAY_NONE;
- else if (!strcmp (str, "positive"))
- bar->display = GOG_ERROR_BAR_DISPLAY_POSITIVE;
- else if (!strcmp (str, "negative"))
- bar->display = GOG_ERROR_BAR_DISPLAY_NEGATIVE;
- xmlFree (str);
- }
- str = xmlGetProp (node, CC2XML ("width"));
- if (str) {
- bar->width = g_strtod (str, NULL);
- xmlFree (str);
- }
- str = xmlGetProp (node, CC2XML ("line_width"));
- if (str) {
- bar->style->line.width = g_strtod (str, NULL);
- xmlFree (str);
- }
- str = xmlGetProp (node, CC2XML ("color"));
- if (str != NULL) {
- go_color_from_str (str, &bar->style->line.color);
- xmlFree (str);
- }
-
- return TRUE;
-}
-
static void
gog_error_bar_persist_sax_save (GOPersist const *gp, GsfXMLOut *output)
{
@@ -472,7 +427,6 @@ gog_error_bar_persist_prep_sax (GOPersist *gp, GsfXMLIn *xin, xmlChar const **at
static void
gog_error_bar_persist_init (GOPersistClass *iface)
{
- iface->dom_load = gog_error_bar_persist_dom_load;
iface->prep_sax = gog_error_bar_persist_prep_sax;
iface->sax_save = gog_error_bar_persist_sax_save;
}
diff --git a/goffice/graph/gog-object-xml.c b/goffice/graph/gog-object-xml.c
index 7997b45..8f72ed6 100644
--- a/goffice/graph/gog-object-xml.c
+++ b/goffice/graph/gog-object-xml.c
@@ -39,8 +39,8 @@
#define GOG_BACKPLANE_OLD_ROLE_NAME "Grid"
#define GOG_BACKPLANE_NEW_ROLE_NAME "Backplane"
-static void
-gog_object_set_arg_full (char const *name, char const *val, GogObject *obj, xmlNode *xml_node)
+void
+gog_object_set_arg (char const *name, char const *val, GogObject *obj)
{
GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (obj), name);
GType prop_type;
@@ -60,32 +60,7 @@ gog_object_set_arg_full (char const *name, char const *val, GogObject *obj, xmlN
g_type_name (prop_type), pspec->name);
return;
}
-
- if (G_TYPE_FUNDAMENTAL (prop_type) == G_TYPE_OBJECT) {
- g_value_init (&res, prop_type);
- if (g_type_is_a (prop_type, G_TYPE_OBJECT)) {
- xmlChar *type_name;
- GType type = 0;
- GObject *val_obj;
-
- success = FALSE;
- type_name = xmlGetProp (xml_node,
- (xmlChar const *) "type");
- if (type_name != NULL) {
- type = g_type_from_name (type_name);
- }
- xmlFree (type_name);
- if (type != 0) {
- val_obj = g_object_new (type, NULL);
- if (GO_IS_PERSIST (val_obj) &&
- go_persist_dom_load (GO_PERSIST (val_obj), xml_node)) {
- g_value_set_object (&res, val_obj);
- success = TRUE;
- }
- g_object_unref (val_obj);
- }
- }
- } else if (!gsf_xml_gvalue_from_str (&res, prop_type, val))
+ if (!gsf_xml_gvalue_from_str (&res, prop_type, val))
success = FALSE;
if (!success) {
@@ -96,12 +71,6 @@ gog_object_set_arg_full (char const *name, char const *val, GogObject *obj, xmlN
g_value_unset (&res);
}
-void
-gog_object_set_arg (char const *name, char const *val, GogObject *obj)
-{
- gog_object_set_arg_full (name, val, obj, NULL);
-}
-
static void
gog_object_write_property_sax (GogObject const *obj, GParamSpec *pspec, GsfXMLOut *output)
{
diff --git a/goffice/graph/gog-renderer.c b/goffice/graph/gog-renderer.c
index bc2ee2f..4b19214 100644
--- a/goffice/graph/gog-renderer.c
+++ b/goffice/graph/gog-renderer.c
@@ -221,23 +221,7 @@ emit_line (GogRenderer *rend, gboolean preserve, GOPathOptions options)
static void
emit_fill (GogRenderer *rend, gboolean preserve)
{
- GOStyle const *style = rend->cur_style;
- cairo_t *cr = rend->cairo;
- cairo_pattern_t *cr_pattern = NULL;
-
- cr_pattern = go_style_create_cairo_pattern (style, cr);
- if (cr_pattern == NULL) {
- if (!preserve)
- cairo_new_path (cr);
- return;
- }
- cairo_set_source (cr, cr_pattern);
- cairo_pattern_destroy (cr_pattern);
-
- if (preserve)
- cairo_fill_preserve (cr);
- else
- cairo_fill (cr);
+ go_style_fill (rend->cur_style, rend->cairo, preserve);
}
static void
@@ -1524,8 +1508,10 @@ gog_renderer_export_image (GogRenderer *rend, GOImageFormat format,
cairo_surface_t *surface = NULL;
gboolean status;
GdkPixbuf *pixbuf;
+#ifdef GOFFICE_WITH_GTK
GdkPixbuf *output_pixbuf;
gboolean result;
+#endif
double width_in_pts, height_in_pts;
g_return_val_if_fail (GOG_IS_RENDERER (rend), FALSE);
@@ -1592,6 +1578,7 @@ do_export_vectorial:
if (pixbuf == NULL)
return FALSE;
format_info = go_image_get_format_info (format);
+#ifdef GOFFICE_WITH_GTK
if (!format_info->alpha_support)
output_pixbuf = gdk_pixbuf_composite_color_simple
(pixbuf,
@@ -1609,6 +1596,7 @@ do_export_vectorial:
if (!format_info->alpha_support)
g_object_unref (output_pixbuf);
return result;
+#endif
}
return FALSE;
diff --git a/goffice/gtk/goffice-gtk.c b/goffice/gtk/goffice-gtk.c
index 578ec90..4015b33 100644
--- a/goffice/gtk/goffice-gtk.c
+++ b/goffice/gtk/goffice-gtk.c
@@ -161,6 +161,7 @@ go_gtk_builder_new (char const *uifile,
GtkBuilder *gui;
GError *error = NULL;
gboolean ok = FALSE;
+ gboolean need_grid_update = (gtk_check_version (3, 2, 0) != NULL); /* remove when we require 3.2.0 or later */
g_return_val_if_fail (uifile != NULL, NULL);
@@ -202,6 +203,18 @@ go_gtk_builder_new (char const *uifile,
} else if (error)
g_error_free (error);
+ if (need_grid_update && gui) { /* remove when we require gtk+-3.2.0 or later */
+ GSList *l = gtk_builder_get_objects (gui), *ptr;
+ int rsep, csep;
+ ptr = l;
+ while (ptr) {
+ if (GTK_IS_GRID (ptr->data)) {
+ g_object_get (ptr->data, "row-spacing", &csep, "column-spacing", &rsep, NULL);
+ g_object_set (ptr->data, "row-spacing", rsep, "column-spacing", csep, NULL);
+ }
+ ptr = ptr->next;
+ }
+ }
return gui;
}
diff --git a/goffice/utils/Makefile.am b/goffice/utils/Makefile.am
index c193e6a..6142123 100644
--- a/goffice/utils/Makefile.am
+++ b/goffice/utils/Makefile.am
@@ -13,6 +13,7 @@ libgoffice_utils_la_SOURCES = \
go-gradient.c \
go-image.c \
go-pixbuf.c \
+ go-svg.c \
go-line.c \
go-locale.c \
go-marker.c \
@@ -46,6 +47,7 @@ libgoffice_utils_la_HEADERS = \
go-gradient.h \
go-image.h \
go-pixbuf.h \
+ go-svg.h \
go-line.h \
go-locale.h \
go-marker.h \
diff --git a/goffice/utils/go-image.c b/goffice/utils/go-image.c
index ff16327..929a7e4 100644
--- a/goffice/utils/go-image.c
+++ b/goffice/utils/go-image.c
@@ -80,9 +80,7 @@ go_image_format_to_mime (char const *format)
{
char *ret = NULL;
guint i;
-#ifdef GOFFICE_WITH_GTK
GSList *ptr, *pixbuf_fmts;
-#endif
static const char* const formats[] = {
"svg", "image/svg,image/svg+xml",
"wmf", "image/x-wmf",
@@ -99,7 +97,6 @@ go_image_format_to_mime (char const *format)
if (strcmp (format, formats[i]) == 0)
return g_strdup (formats[i + 1]);
-#ifdef GOFFICE_WITH_GTK
/* Not a format we have special knowledge about - ask gdk-pixbuf */
pixbuf_fmts = gdk_pixbuf_get_formats ();
for (ptr = pixbuf_fmts; ptr != NULL; ptr = ptr->next) {
@@ -116,7 +113,6 @@ go_image_format_to_mime (char const *format)
}
}
g_slist_free (pixbuf_fmts);
-#endif
return ret;
}
@@ -143,7 +139,6 @@ static GOImageFormatInfo const image_format_infos[GO_IMAGE_FORMAT_UNKNOWN] = {
static void
go_image_build_pixbuf_format_infos (void)
{
-#ifdef GOFFICE_WITH_GTK
GdkPixbufFormat *fmt;
GSList *l, *pixbuf_fmts;
GOImageFormatInfo *format_info;
@@ -190,7 +185,6 @@ go_image_build_pixbuf_format_infos (void)
}
g_slist_free (pixbuf_fmts);
-#endif /* GOFFICE_WITH_GTK */
pixbuf_format_done = TRUE;
}
@@ -281,64 +275,13 @@ go_image_get_formats_with_pixbuf_saver (void)
static GObjectClass *parent_klass;
-struct _GOImage {
- GObject parent;
- guint8 *data;
- guint width, height, rowstride;
- gboolean target_cairo;
- cairo_t *cairo;
-#ifdef GOFFICE_WITH_GTK
- GdkPixbuf *pixbuf, *thumbnail;
-#else
- void *pixbuf;
-#endif
- char *name;
-};
-
enum {
IMAGE_PROP_0,
IMAGE_PROP_WIDTH,
- IMAGE_PROP_HEIGHT,
-#ifdef GOFFICE_WITH_GTK
- IMAGE_PROP_PIXBUF,
-#endif
+ IMAGE_PROP_HEIGHT
};
static void
-pixbuf_to_cairo (GOImage *image)
-{
-#ifdef GOFFICE_WITH_GTK
- unsigned char *src, *dst;
-
- g_return_if_fail (GO_IS_IMAGE (image) && image->data && image->pixbuf);
-
- src = gdk_pixbuf_get_pixels (image->pixbuf);
- dst = image->data;
-
- g_return_if_fail (gdk_pixbuf_get_rowstride (image->pixbuf) == (int) image->rowstride);
-
- go_cairo_convert_data_from_pixbuf (dst, src, image->width, image->height, image->rowstride);
-#endif
-}
-
-#ifdef GOFFICE_WITH_GTK
-static void
-cairo_to_pixbuf (GOImage *image)
-{
- unsigned char *src, *dst;
-
- g_return_if_fail (GO_IS_IMAGE (image) && image->data && image->pixbuf);
-
- dst = gdk_pixbuf_get_pixels (image->pixbuf);
- src = image->data;
-
- g_return_if_fail (gdk_pixbuf_get_rowstride (image->pixbuf) == (int) image->rowstride);
-
- go_cairo_convert_data_to_pixbuf (dst, src, image->width, image->height, image->rowstride);
-}
-#endif
-
-static void
go_image_set_property (GObject *obj, guint param_id,
GValue const *value, GParamSpec *pspec)
{
@@ -361,46 +304,14 @@ go_image_set_property (GObject *obj, guint param_id,
size_changed = TRUE;
}
break;
-#ifdef GOFFICE_WITH_GTK
- case IMAGE_PROP_PIXBUF: {
- GdkPixbuf *pixbuf = GDK_PIXBUF (g_value_get_object (value));
- if (!GDK_IS_PIXBUF (pixbuf))
- break;
- if (!gdk_pixbuf_get_has_alpha (pixbuf))
- pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
- else
- g_object_ref (pixbuf);
- if (image->pixbuf)
- g_object_unref (image->pixbuf);
- image->pixbuf = pixbuf;
- g_free (image->data);
- image->data = NULL;
- image->width = gdk_pixbuf_get_width (pixbuf);
- image->height = gdk_pixbuf_get_height (pixbuf);
- image->rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- image->target_cairo = FALSE;
- if (image->thumbnail) {
- g_object_unref (image->thumbnail);
- image->thumbnail = NULL;
- }
- }
- break;
-#endif
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
return; /* NOTE : RETURN */
}
if (size_changed) {
- if (image->pixbuf) {
- g_object_unref (image->pixbuf);
- image->pixbuf = NULL;
- }
g_free (image->data);
- /* GOImage only supports pixbuf with alpha values at the moment */
- image->rowstride = image->width * 4;
- image->data = g_new0 (guint8, image->height * image->rowstride);
- image->target_cairo = TRUE;
+ image->data = NULL;
}
}
@@ -417,15 +328,6 @@ go_image_get_property (GObject *obj, guint param_id,
case IMAGE_PROP_HEIGHT:
g_value_set_uint (value, image->height);
break;
-#ifdef GOFFICE_WITH_GTK
- case IMAGE_PROP_PIXBUF:
- if (image->target_cairo && image->pixbuf) {
- cairo_to_pixbuf (image);
- image->target_cairo = FALSE;
- }
- g_value_set_object (value, image->pixbuf);
- break;
-#endif
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
return; /* NOTE : RETURN */
@@ -437,20 +339,14 @@ go_image_finalize (GObject *obj)
{
GOImage *image = GO_IMAGE (obj);
g_free (image->data);
-#ifdef GOFFICE_WITH_GTK
- if (image->pixbuf)
- g_object_unref (image->pixbuf);
if (image->thumbnail)
g_object_unref (image->thumbnail);
-#endif
g_free (image->name);
(parent_klass->finalize) (obj);
}
-typedef GObjectClass GOImageClass;
-
static void
-go_image_class_init (GOImageClass *klass)
+go_image_class_init (GObjectClass *klass)
{
klass->finalize = go_image_finalize;
klass->set_property = go_image_set_property;
@@ -464,164 +360,90 @@ go_image_class_init (GOImageClass *klass)
g_param_spec_uint ("height", _("Height"),
_("Image height in pixels"),
0, G_MAXUINT16, 0, G_PARAM_READWRITE));
-#ifdef GOFFICE_WITH_GTK
- g_object_class_install_property (klass, IMAGE_PROP_PIXBUF,
- g_param_spec_object ("pixbuf", _("Pixbuf"),
- _("GdkPixbuf object from which the GOImage is built"),
- GDK_TYPE_PIXBUF, G_PARAM_READWRITE));
-#endif
}
-GSF_CLASS (GOImage, go_image,
- go_image_class_init, NULL,
- G_TYPE_OBJECT)
+GSF_CLASS_FULL (GOImage, go_image,
+ NULL, NULL,
+ go_image_class_init, NULL, NULL,
+ G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {})
-cairo_t *
-go_image_get_cairo (GOImage *image)
+void
+go_image_draw (GOImage *image, cairo_t *cr)
{
- cairo_surface_t *surface ;
- cairo_t *cairo;
-
- g_return_val_if_fail (GO_IS_IMAGE (image), NULL);
- if (image->data == NULL && image->pixbuf == NULL)
- return NULL;
- if (image->data == NULL) {
- /* image built from a pixbuf */
- image->data = g_new0 (guint8, image->height * image->rowstride);
- }
- if (!image->target_cairo) {
- pixbuf_to_cairo (image);
- image->target_cairo = TRUE;
- }
- surface = cairo_image_surface_create_for_data (
- image->data,
- CAIRO_FORMAT_ARGB32,
- image->width, image->height,
- image->rowstride);
- cairo = cairo_create (surface);
- cairo_surface_destroy (surface);
- image->target_cairo = TRUE;
- return cairo;
+ g_return_if_fail (GO_IS_IMAGE (image));
+ ((GOImageClass *) G_OBJECT_GET_CLASS (image))->draw (image, cr);
}
-static void
-cb_surface_destroyed (void *data)
-{
- GOImage *image = GO_IMAGE (data);
- /* We no longer need image->data. */
- g_object_unref (image);
-}
+#define GO_THUMBNAIL_SIZE 64
-/**
- * go_image_create_cairo_pattern:
- * @image: a GOImage.
- *
- * returns: a cairo_pattern usable for cairo_set_source.
- *
- * Note: this function has lifespan issues. The resulting pattern in only
- * valid until (a) a pixbuf is set for the, or (b) a pixbuf is _read_ from
- * the image. In either of these cases, the pattern must have been
- * destroyed beforehand. In particular, if the pattern has been attached
- * to a surface, that surface must either be finished itself, or have had
- * a new pattern attached. See #632439.
- */
-cairo_pattern_t *
-go_image_create_cairo_pattern (GOImage *image)
-{
- cairo_surface_t *surface ;
- cairo_pattern_t *pat;
- static const cairo_user_data_key_t key;
-
- g_return_val_if_fail (GO_IS_IMAGE (image), NULL);
- if (image->data == NULL && image->pixbuf == NULL)
- return NULL;
- if (image->data == NULL) {
- /* image built from a pixbuf */
- image->data = g_new0 (guint8, image->height * image->rowstride);
- }
- if (!image->target_cairo) {
- pixbuf_to_cairo (image);
- image->target_cairo = TRUE;
- }
- surface = cairo_image_surface_create_for_data
- (image->data,
- CAIRO_FORMAT_ARGB32,
- image->width, image->height,
- image->rowstride);
- g_object_ref (image);
- cairo_surface_set_user_data (surface, &key,
- image, cb_surface_destroyed);
- pat = cairo_pattern_create_for_surface (surface);
- cairo_surface_destroy (surface);
- return pat;
-}
-
-#ifdef GOFFICE_WITH_GTK
-GOImage *
-go_image_new_from_pixbuf (GdkPixbuf *pixbuf)
+GdkPixbuf const *
+go_image_get_thumbnail (GOImage *image)
{
- return g_object_new (GO_TYPE_IMAGE, "pixbuf", pixbuf, NULL);
+ g_return_val_if_fail (image != NULL, NULL);
+ if (image->thumbnail == NULL)
+ image->thumbnail = go_image_get_scaled_pixbuf (image, GO_THUMBNAIL_SIZE, GO_THUMBNAIL_SIZE);
+ return image->thumbnail;
}
-
GdkPixbuf *
go_image_get_pixbuf (GOImage *image)
{
- g_return_val_if_fail (image != NULL, NULL);
- if (!image->pixbuf) {
- if (image->width == 0 || image->height == 0 || image->data == NULL)
- return NULL;
- image->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- image->width, image->height);
- }
- if (image->target_cairo) {
- cairo_to_pixbuf (image);
- image->target_cairo = FALSE;
- }
- return image->pixbuf;
+ return ((GOImageClass *) G_OBJECT_GET_CLASS (image))->get_pixbuf (image);
}
-#define THUMBNAIL_SIZE 64
GdkPixbuf *
-go_image_get_thumbnail (GOImage *image)
+go_image_get_scaled_pixbuf (GOImage *image, int width, int height)
{
- g_return_val_if_fail (image != NULL, NULL);
- if (!image->pixbuf)
- go_image_get_pixbuf (image);
- if (!image->pixbuf)
- return NULL;
- if (!image->thumbnail) {
- int w, h;
- if (image->width <= THUMBNAIL_SIZE && image->height <= THUMBNAIL_SIZE)
- return image->pixbuf;
- if (image->width >= image->height) {
- w = THUMBNAIL_SIZE;
- h = THUMBNAIL_SIZE * image->height / image->width;
+ if (image->width > width || image->height > height) {
+ if (image->width * height > image->height * width) {
+ height = width * image->height / image->width;
} else {
- h = THUMBNAIL_SIZE;
- w = THUMBNAIL_SIZE * image->width / image->height;
+ width = height * image->width / image->height;
}
- image->thumbnail = gdk_pixbuf_scale_simple (image->pixbuf, w, h, GDK_INTERP_HYPER);
- }
- return image->thumbnail;
+ } else
+ return ((GOImageClass *) G_OBJECT_GET_CLASS (image))->get_pixbuf (image);
+ return ((GOImageClass *) G_OBJECT_GET_CLASS (image))->get_scaled_pixbuf (image, width, height);
}
-#endif
GOImage *
go_image_new_from_file (const char *filename, GError **error)
{
-#ifdef GOFFICE_WITH_GTK
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, error);
- if (pixbuf) {
- GOImage *image = g_object_new (GO_TYPE_IMAGE,
- "pixbuf", pixbuf,
- NULL);
- g_object_unref (pixbuf);
- image->target_cairo = FALSE;
- return image;
+ char *mime, *name;
+ GOImageFormat format;
+
+ if (!filename) {
+ return NULL;
+ }
+ mime = go_get_mime_type (filename);
+ if (!mime) {
+ return NULL;
+ }
+ name = go_mime_to_image_format (mime);
+ g_free (mime);
+ if (!name) {
+ return NULL;
+ }
+ format = go_image_get_format_from_name (name);
+ g_free (name);
+ switch (format) {
+ case GO_IMAGE_FORMAT_SVG:
+ return GO_IMAGE (go_svg_new_from_file (filename, error));
+ case GO_IMAGE_FORMAT_PDF:
+ case GO_IMAGE_FORMAT_PS:
+ case GO_IMAGE_FORMAT_EMF:
+ case GO_IMAGE_FORMAT_WMF:
+ case GO_IMAGE_FORMAT_EPS:
+ break;
+ case GO_IMAGE_FORMAT_UNKNOWN:
+ break;
+ default: {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, error);
+ if (pixbuf) {
+ GOImage *image = (GOImage *) go_pixbuf_new_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+ return image;
+ }
+ }
}
-#else
- g_warning ("go_image_new_from_file not implemented!");
-#endif
return NULL;
}
@@ -632,34 +454,6 @@ go_image_get_pixels (GOImage *image)
return image->data;
}
-int
-go_image_get_rowstride (GOImage *image)
-{
- g_return_val_if_fail (image, 0);
- return image->rowstride;
-}
-
-void
-go_image_fill (GOImage *image, GOColor color)
-{
- guint32 val;
- guint8 *dst;
- unsigned i, j;
- g_return_if_fail (image);
-
- dst = image->data;
- if (image->target_cairo)
- val = (GO_COLOR_UINT_R (color) << 8) + (GO_COLOR_UINT_G (color) << 16)
- + (GO_COLOR_UINT_B (color) << 24) + GO_COLOR_UINT_A (color);
- else
- val = color;
- for (i = 0; i < image->height; i++) {
- for (j = 0; j < image->width; j++)
- *((guint32*) dst) = val;
- dst += image->rowstride - image->width * 4;
- }
-}
-
void
go_image_set_name (GOImage *image, char const *name)
{
@@ -675,40 +469,15 @@ go_image_get_name (GOImage *image)
}
gboolean
-go_image_same_pixbuf (GOImage *first, GOImage *second)
+go_image_differ (GOImage *first, GOImage *second)
{
-#ifdef GOFFICE_WITH_GTK
- void *pixels1, *pixels2;
- int size;
g_return_val_if_fail (GO_IS_IMAGE (first), FALSE);
g_return_val_if_fail (GO_IS_IMAGE (second), FALSE);
- if (!first->pixbuf)
- go_image_get_pixbuf (first);
- if (!second->pixbuf)
- go_image_get_pixbuf (second);
- if (!first->pixbuf || !second->pixbuf)
- return FALSE;
- if (gdk_pixbuf_get_n_channels (first->pixbuf) != gdk_pixbuf_get_n_channels (second->pixbuf))
- return FALSE;
- if (gdk_pixbuf_get_colorspace (first->pixbuf) != gdk_pixbuf_get_colorspace (second->pixbuf))
- return FALSE;
- if (gdk_pixbuf_get_bits_per_sample (first->pixbuf) != gdk_pixbuf_get_bits_per_sample (second->pixbuf))
- return FALSE;
- if (gdk_pixbuf_get_has_alpha (first->pixbuf) != gdk_pixbuf_get_has_alpha (second->pixbuf))
- return FALSE;
- if (gdk_pixbuf_get_width (first->pixbuf) != gdk_pixbuf_get_width (second->pixbuf))
- return FALSE;
- if (gdk_pixbuf_get_height (first->pixbuf) != gdk_pixbuf_get_height (second->pixbuf))
- return FALSE;
- if (gdk_pixbuf_get_rowstride (first->pixbuf) != gdk_pixbuf_get_rowstride (second->pixbuf))
- return FALSE;
- pixels1 = gdk_pixbuf_get_pixels (first->pixbuf);
- pixels2 = gdk_pixbuf_get_pixels (second->pixbuf);
- size = gdk_pixbuf_get_rowstride (first->pixbuf) * gdk_pixbuf_get_height (first->pixbuf);
- return !memcmp (pixels1, pixels2, size);
-#else
- return FALSE;
-#endif
+ if (G_OBJECT_TYPE (first) != G_OBJECT_TYPE (second))
+ return TRUE;
+ if (first->width != second->width || first->height != second->height)
+ return TRUE;
+ return ((GOImageClass *) G_OBJECT_GET_CLASS (first))->differ (first, second);
}
void
@@ -717,11 +486,10 @@ go_image_save (GOImage *image, GsfXMLOut *output)
g_return_if_fail (GO_IS_IMAGE (image) && image->name);
gsf_xml_out_start_element (output, "GOImage");
gsf_xml_out_add_cstr (output, "name", image->name);
+ gsf_xml_out_add_cstr (output, "type", G_OBJECT_TYPE_NAME (image));
gsf_xml_out_add_int (output, "width", image->width);
gsf_xml_out_add_int (output, "height", image->height);
- gsf_xml_out_add_int (output, "rowstride", image->rowstride);
- gsf_xml_out_add_base64 (output, NULL,
- go_image_get_pixels (image), image->height * image->rowstride);
+ ((GOImageClass *) G_OBJECT_GET_CLASS (image))->save (image, output);
gsf_xml_out_end_element (output);
}
@@ -735,16 +503,23 @@ go_image_load_attrs (GOImage *image, GsfXMLIn *xin, xmlChar const **attrs)
image->width = strtol (attr[1], NULL, 10);
else if (0 == strcmp (attr[0], "height"))
image->height= strtol (attr[1], NULL, 10);
- else if (0 == strcmp (attr[0], "rowstride"))
- image->rowstride = strtol (attr[1], NULL, 10);
+ else
+ ((GOImageClass *) G_OBJECT_GET_CLASS (image))->load_attr (image, attr[0], attr[1]);
}
void
go_image_load_data (GOImage *image, GsfXMLIn *xin)
{
- int length;
- length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
- image->data = g_memdup (xin->content->str, length);
- image->target_cairo = TRUE;
+ ((GOImageClass *) G_OBJECT_GET_CLASS (image))->load_data (image, xin);
}
+void
+_go_image_changed (GOImage *image, double width, double height)
+{
+ image->width = width;
+ image->height = height;
+ if (image->thumbnail) {
+ g_object_unref (image->thumbnail);
+ image->thumbnail = NULL;
+ }
+}
diff --git a/goffice/utils/go-image.h b/goffice/utils/go-image.h
index 466109b..b44619b 100644
--- a/goffice/utils/go-image.h
+++ b/goffice/utils/go-image.h
@@ -68,29 +68,49 @@ GSList *go_image_get_formats_with_pixbuf_saver (void);
GType go_image_get_type (void);
-cairo_t *go_image_get_cairo (GOImage *image);
-cairo_pattern_t *go_image_create_cairo_pattern (GOImage *image);
+struct _GOImage {
+ GObject parent;
+ guint8 *data;
+ double width, height;
+ GdkPixbuf *thumbnail;
+ char *name;
+};
+
+typedef struct {
+ GObjectClass parent_klass;
+
+ GdkPixbuf *(*get_pixbuf) (GOImage *image);
+ GdkPixbuf *(*get_scaled_pixbuf) (GOImage *image, int width, int height);
+ gboolean (*same_content) (GOImage *img1, GOImage *img2);
+ void (*save) (GOImage *image, GsfXMLOut *output);
+ void (*load_attr) (GOImage *image, xmlChar const *attr_name, xmlChar const *attr_value);
+ void (*load_data) (GOImage *image, GsfXMLIn *xin);
+ void (*draw) (GOImage *image, cairo_t *cr);
+ gboolean (*differ) (GOImage *first, GOImage *second);
+} GOImageClass;
-#ifdef GOFFICE_WITH_GTK
GOImage *go_image_new_from_pixbuf (GdkPixbuf *pixbuf);
-GdkPixbuf *go_image_get_pixbuf (GOImage *image);
-GdkPixbuf *go_image_get_thumbnail (GOImage *image);
-#endif
+GdkPixbuf const *go_image_get_thumbnail (GOImage *image);
+GdkPixbuf *go_image_get_pixbuf (GOImage *image);
+GdkPixbuf *go_image_get_scaled_pixbuf (GOImage *image, int width, int height);
+void go_image_draw (GOImage *image, cairo_t *cr);
GOImage *go_image_new_from_file (const char *filename, GError **error);
guint8 *go_image_get_pixels (GOImage *image);
-int go_image_get_rowstride (GOImage *image);
void go_image_fill (GOImage *image, GOColor color);
void go_image_set_name (GOImage *image, char const *name);
char const *go_image_get_name (GOImage *image);
-gboolean go_image_same_pixbuf (GOImage *first, GOImage *second);
+gboolean go_image_differ (GOImage *first, GOImage *second);
void go_image_save (GOImage *image, GsfXMLOut *output);
void go_image_load_attrs (GOImage *image, GsfXMLIn *xin, xmlChar const **attrs);
void go_image_load_data (GOImage *image, GsfXMLIn *xin);
+/* Protected */
+void _go_image_changed (GOImage *image, double width, double height);
+
G_END_DECLS
#endif /* GO_IMAGE_H */
diff --git a/goffice/utils/go-persist.c b/goffice/utils/go-persist.c
index 422ce07..246be4b 100644
--- a/goffice/utils/go-persist.c
+++ b/goffice/utils/go-persist.c
@@ -41,13 +41,6 @@ go_persist_get_type (void)
return go_persist_type;
}
-gboolean
-go_persist_dom_load (GOPersist *gp, xmlNode *node)
-{
- g_return_val_if_fail (GO_IS_PERSIST (gp), FALSE);
- return GO_PERSIST_GET_CLASS (gp)->dom_load (gp, node);
-}
-
void
go_persist_sax_save (GOPersist const *gp, GsfXMLOut *output)
{
diff --git a/goffice/utils/go-persist.h b/goffice/utils/go-persist.h
index 556d260..e85d3ee 100644
--- a/goffice/utils/go-persist.h
+++ b/goffice/utils/go-persist.h
@@ -32,7 +32,6 @@ typedef struct _GOPersist GOPersist;
typedef struct {
GTypeInterface base;
- gboolean (*dom_load) (GOPersist *gp, xmlNode *node);
void (*prep_sax) (GOPersist *gp, GsfXMLIn *xin, xmlChar const **attrs);
void (*sax_save) (GOPersist const *gp, GsfXMLOut *output);
} GOPersistClass;
@@ -46,7 +45,6 @@ typedef struct {
GType go_persist_get_type (void);
-gboolean go_persist_dom_load (GOPersist *gp, xmlNode *node);
void go_persist_sax_save (GOPersist const *gp, GsfXMLOut *output);
void go_persist_prep_sax (GOPersist *gp,
GsfXMLIn *xin, xmlChar const **attrs);
diff --git a/goffice/utils/go-pixbuf.c b/goffice/utils/go-pixbuf.c
index 44c228a..6a9a234 100644
--- a/goffice/utils/go-pixbuf.c
+++ b/goffice/utils/go-pixbuf.c
@@ -3,6 +3,7 @@
* go-pixbuf.c
*
* Copyright (C) 2000-2004 Jody Goldberg (jody gnome org)
+ * Copyright (C) 2011 Jean Brefort (jean brefort normalesup org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -23,6 +24,10 @@
#include "go-pixbuf.h"
#include <goffice/goffice-priv.h>
+#include <string.h>
+#include <gsf/gsf-utils.h>
+#include <gsf/gsf-impl-utils.h>
+#include <glib/gi18n-lib.h>
/**
* go_gdk_pixbuf_intelligent_scale:
@@ -206,3 +211,268 @@ go_gdk_pixbuf_tile (GdkPixbuf const *src, guint w, guint h)
return dst;
}
+
+/* GOPixbuf implementation */
+
+
+struct _GOPixbuf {
+ GOImage parent;
+ unsigned rowstride;
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
+};
+
+typedef GOImageClass GOPixbufClass;
+
+static GObjectClass *parent_klass;
+
+enum {
+ PIXBUF_PROP_0,
+ PIXBUF_PROP_PIXBUF
+};
+
+static void
+pixbuf_to_cairo (GOPixbuf *pixbuf)
+{
+ unsigned char *src, *dst;
+ GOImage *image = GO_IMAGE (pixbuf);
+
+ g_return_if_fail (GO_IS_PIXBUF (pixbuf) && image->data && pixbuf->pixbuf);
+
+ src = gdk_pixbuf_get_pixels (pixbuf->pixbuf);
+ dst = image->data;
+
+ g_return_if_fail (gdk_pixbuf_get_rowstride (pixbuf->pixbuf) == (int) pixbuf->rowstride);
+
+ go_cairo_convert_data_from_pixbuf (dst, src, image->width, image->height, pixbuf->rowstride);
+}
+
+static void
+cairo_to_pixbuf (GOPixbuf *pixbuf)
+{
+ unsigned char *src, *dst;
+ GOImage *image = GO_IMAGE (pixbuf);
+
+ g_return_if_fail (GO_IS_PIXBUF (pixbuf) && image->data && pixbuf->pixbuf);
+
+ dst = gdk_pixbuf_get_pixels (pixbuf->pixbuf);
+ src = image->data;
+
+ g_return_if_fail (gdk_pixbuf_get_rowstride (pixbuf->pixbuf) == (int) pixbuf->rowstride);
+
+ go_cairo_convert_data_to_pixbuf (dst, src, image->width, image->height, pixbuf->rowstride);
+}
+
+static void
+go_pixbuf_save (GOImage *image, GsfXMLOut *output)
+{
+ GOPixbuf *pixbuf;
+ g_return_if_fail (GO_IS_PIXBUF (image));
+ pixbuf = GO_PIXBUF (image);
+ gsf_xml_out_add_int (output, "rowstride", pixbuf->rowstride);
+ gsf_xml_out_add_base64 (output, NULL,
+ image->data, image->height * pixbuf->rowstride);
+}
+
+static void
+go_pixbuf_load_attr (GOImage *image, xmlChar const *attr_name, xmlChar const *attr_value)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (image);
+ g_return_if_fail (pixbuf);
+ if (!strcmp (attr_name, "rowstride"))
+ pixbuf->rowstride = strtol (attr_value, NULL, 10);
+}
+
+static void
+go_pixbuf_load_data (GOImage *image, GsfXMLIn *xin)
+{
+ int length;
+ length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+ image->data = g_memdup (xin->content->str, length);
+}
+
+static void
+go_pixbuf_draw (GOImage *image, cairo_t *cr)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (image);
+ g_return_if_fail (pixbuf);
+ if (pixbuf->surface == NULL) {
+ if (image->data == NULL) {
+ /* image built from a pixbuf */
+ image->data = g_new0 (guint8, image->height * pixbuf->rowstride);
+ pixbuf_to_cairo (pixbuf);
+ }
+ pixbuf->surface = cairo_image_surface_create_for_data (image->data,
+ CAIRO_FORMAT_ARGB32,
+ image->width,
+ image->height,
+ pixbuf->rowstride);
+ }
+ cairo_save (cr);
+ cairo_set_source_surface (cr, pixbuf->surface, 0., 0.);
+ cairo_rectangle (cr, 0., 0., image->width, image->height);
+ cairo_fill (cr);
+ cairo_restore (cr);
+}
+
+static GdkPixbuf *
+go_pixbuf_get_pixbuf (GOImage *image)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (image);
+ g_return_val_if_fail (pixbuf, NULL);
+ if (!pixbuf->pixbuf) {
+ if (image->width == 0 || image->height == 0 || image->data == NULL)
+ return NULL;
+ pixbuf->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ image->width, image->height);
+ cairo_to_pixbuf (pixbuf);
+ }
+ return g_object_ref (pixbuf->pixbuf);
+}
+
+static GdkPixbuf *
+go_pixbuf_get_scaled_pixbuf (GOImage *image, int width, int height)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (image);
+ g_return_val_if_fail (pixbuf, NULL);
+ if (!pixbuf->pixbuf) {
+ if (image->width == 0 || image->height == 0 || image->data == NULL)
+ return NULL;
+ pixbuf->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ image->width, image->height);
+ cairo_to_pixbuf (pixbuf);
+ }
+ return gdk_pixbuf_scale_simple (pixbuf->pixbuf, width, height, GDK_INTERP_HYPER);
+}
+
+static gboolean
+go_pixbuf_differ (GOImage *first, GOImage *second)
+{
+ void *pixels1, *pixels2;
+ int size;
+ GOPixbuf *pfirst = GO_PIXBUF (first), *psecond = GO_PIXBUF (second);
+ if (!pfirst->pixbuf)
+ go_pixbuf_get_pixbuf (first);
+ if (!psecond->pixbuf)
+ go_pixbuf_get_pixbuf (second);
+ if (!pfirst->pixbuf || !psecond->pixbuf)
+ return TRUE; /* this should not happen */
+ if (gdk_pixbuf_get_n_channels (pfirst->pixbuf) != gdk_pixbuf_get_n_channels (psecond->pixbuf))
+ return TRUE;
+ if (gdk_pixbuf_get_colorspace (pfirst->pixbuf) != gdk_pixbuf_get_colorspace (psecond->pixbuf))
+ return TRUE;
+ if (gdk_pixbuf_get_bits_per_sample (pfirst->pixbuf) != gdk_pixbuf_get_bits_per_sample (psecond->pixbuf))
+ return TRUE;
+ if (gdk_pixbuf_get_has_alpha (pfirst->pixbuf) != gdk_pixbuf_get_has_alpha (psecond->pixbuf))
+ return TRUE;
+ if (gdk_pixbuf_get_width (pfirst->pixbuf) != gdk_pixbuf_get_width (psecond->pixbuf))
+ return TRUE;
+ if (gdk_pixbuf_get_height (pfirst->pixbuf) != gdk_pixbuf_get_height (psecond->pixbuf))
+ return TRUE;
+ if (gdk_pixbuf_get_rowstride (pfirst->pixbuf) != gdk_pixbuf_get_rowstride (psecond->pixbuf))
+ return TRUE;
+ pixels1 = gdk_pixbuf_get_pixels (pfirst->pixbuf);
+ pixels2 = gdk_pixbuf_get_pixels (psecond->pixbuf);
+ size = gdk_pixbuf_get_rowstride (pfirst->pixbuf) * gdk_pixbuf_get_height (pfirst->pixbuf);
+ return memcmp (pixels1, pixels2, size);
+}
+
+static void
+go_pixbuf_set_property (GObject *obj, guint param_id,
+ GValue const *value, GParamSpec *pspec)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (obj);
+ GOImage *image = GO_IMAGE (obj);
+
+ switch (param_id) {
+ case PIXBUF_PROP_PIXBUF: {
+ GdkPixbuf *pix = GDK_PIXBUF (g_value_get_object (value));
+ if (!GDK_IS_PIXBUF (pix))
+ break;
+ if (!gdk_pixbuf_get_has_alpha (pix))
+ pix = gdk_pixbuf_add_alpha (pix, FALSE, 0, 0, 0);
+ else
+ g_object_ref (pix);
+ if (pixbuf->pixbuf)
+ g_object_unref (pixbuf->pixbuf);
+ pixbuf->pixbuf = pix;
+ g_free (image->data); /* this should be in GOPixbuf */
+ image->data = NULL; /* this should be in GOPixbuf */
+ _go_image_changed (image, gdk_pixbuf_get_width (pix), gdk_pixbuf_get_height (pix));
+ pixbuf->rowstride = gdk_pixbuf_get_rowstride (pix); /* this should be in GOPixbuf */
+ }
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+ return; /* NOTE : RETURN */
+ }
+}
+
+static void
+go_pixbuf_get_property (GObject *obj, guint param_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (obj);
+
+ switch (param_id) {
+ case PIXBUF_PROP_PIXBUF:
+ g_value_set_object (value, pixbuf->pixbuf);
+ break;
+
+ default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
+ return; /* NOTE : RETURN */
+ }
+}
+
+static void
+go_pixbuf_finalize (GObject *obj)
+{
+ GOPixbuf *pixbuf = GO_PIXBUF (obj);
+ if (pixbuf->pixbuf)
+ g_object_unref (pixbuf->pixbuf);
+ if (pixbuf->surface)
+ cairo_surface_destroy (pixbuf->surface);
+ (parent_klass->finalize) (obj);
+}
+
+static void
+go_pixbuf_class_init (GObjectClass *klass)
+{
+ GOImageClass *image_klass = (GOImageClass *) klass;
+
+ klass->finalize = go_pixbuf_finalize;
+ klass->set_property = go_pixbuf_set_property;
+ klass->get_property = go_pixbuf_get_property;
+ parent_klass = g_type_class_peek_parent (klass);
+
+ image_klass->save = go_pixbuf_save;
+ image_klass->load_attr = go_pixbuf_load_attr;
+ image_klass->load_data = go_pixbuf_load_data;
+ image_klass->get_pixbuf = go_pixbuf_get_pixbuf;
+ image_klass->get_scaled_pixbuf = go_pixbuf_get_scaled_pixbuf;
+ image_klass->draw = go_pixbuf_draw;
+ image_klass->differ = go_pixbuf_differ;
+
+ g_object_class_install_property (klass, PIXBUF_PROP_PIXBUF,
+ g_param_spec_object ("pixbuf", _("Pixbuf"),
+ _("GdkPixbuf object from which the GOPixbuf is built"),
+ GDK_TYPE_PIXBUF, G_PARAM_READWRITE));
+}
+
+GSF_CLASS (GOPixbuf, go_pixbuf,
+ go_pixbuf_class_init, NULL,
+ GO_TYPE_IMAGE)
+
+
+GOPixbuf *
+go_pixbuf_new_from_pixbuf (GdkPixbuf *pixbuf)
+{
+ return g_object_new (GO_TYPE_PIXBUF, "pixbuf", pixbuf, NULL);
+}
+
+int
+go_pixbuf_get_rowstride (GOPixbuf *pixbuf)
+{
+ g_return_val_if_fail (GO_IS_PIXBUF (pixbuf), 0);
+ return pixbuf->rowstride;
+}
diff --git a/goffice/utils/go-pixbuf.h b/goffice/utils/go-pixbuf.h
index 3f8452f..524969d 100644
--- a/goffice/utils/go-pixbuf.h
+++ b/goffice/utils/go-pixbuf.h
@@ -20,6 +20,7 @@
#ifndef GO_PIXBUF_H
#define GO_PIXBUF_H
+#include <goffice/goffice.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
G_BEGIN_DECLS
@@ -31,6 +32,15 @@ GdkPixbuf *go_gdk_pixbuf_get_from_cache (char const *filename);
GdkPixbuf *go_gdk_pixbuf_tile (GdkPixbuf const *src,
guint w, guint h);
+#define GO_TYPE_PIXBUF (go_pixbuf_get_type ())
+#define GO_PIXBUF(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GO_TYPE_PIXBUF, GOPixbuf))
+#define GO_IS_PIXBUF(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GO_TYPE_PIXBUF))
+
+GType go_pixbuf_get_type (void);
+
+GOPixbuf *go_pixbuf_new_from_pixbuf (GdkPixbuf *pixbuf);
+int go_pixbuf_get_rowstride (GOPixbuf *pixbuf);
+
G_END_DECLS
#endif
diff --git a/goffice/utils/go-style-prefs.ui b/goffice/utils/go-style-prefs.ui
index b065094..b457617 100644
--- a/goffice/utils/go-style-prefs.ui
+++ b/goffice/utils/go-style-prefs.ui
@@ -547,6 +547,7 @@
<object class="GtkBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="valign">start</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
@@ -859,6 +860,7 @@
</child>
<child>
<object class="GtkButton" id="fill_image_select_picture">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -933,6 +935,7 @@
<item translatable="yes">stretched</item>
<item translatable="yes">wallpaper</item>
<item translatable="yes">centered</item>
+ <item translatable="yes">centered wallpaper</item>
</items>
</object>
<packing>
diff --git a/goffice/utils/go-style.c b/goffice/utils/go-style.c
index 6551a21..dc7b109 100644
--- a/goffice/utils/go-style.c
+++ b/goffice/utils/go-style.c
@@ -142,7 +142,7 @@ go_style_set_image_preview (GOImage *pix, StylePrefState *state)
w = go_gtk_builder_get_widget (state->gui, "fill_image_sample");
- scaled = go_gdk_pixbuf_intelligent_scale (go_image_get_pixbuf (pix), HSCALE, VSCALE);
+ scaled = go_image_get_scaled_pixbuf (pix, HSCALE, VSCALE);
gtk_image_set_from_pixbuf (GTK_IMAGE (w), scaled);
g_object_unref (scaled);
@@ -1273,20 +1273,6 @@ static struct {
};
static gboolean
-bool_prop (xmlNode *node, char const *name, gboolean *res)
-{
- char *str = xmlGetProp (node, name);
- if (str != NULL) {
- *res = g_ascii_tolower (*str) == 't' ||
- g_ascii_tolower (*str) == 'y' ||
- strtol (str, NULL, 0);
- xmlFree (str);
- return TRUE;
- }
- return FALSE;
-}
-
-static gboolean
bool_sax_prop (char const *name, char const *id, char const *val, gboolean *res)
{
if (0 == strcmp (name, id)) {
@@ -1340,39 +1326,6 @@ image_tiling_as_str (GOImageType fstyle)
}
static void
-go_style_line_load (xmlNode *node, GOStyleLine *line)
-{
- char *str;
- gboolean tmp;
-
- str = xmlGetProp (node, "dash");
- if (str != NULL) {
- line->dash_type = go_line_dash_from_str (str);
- xmlFree (str);
- }
- if (bool_prop (node, "auto-dash", &tmp))
- line->auto_dash = tmp;
- str = xmlGetProp (node, "width");
- if (str != NULL) {
- line->width = g_strtod (str, NULL);
- /* For compatibility with older graphs, when dash_type
- * didn't exist */
- if (line->width < 0.) {
- line->width = 0.;
- line->dash_type = GO_LINE_NONE;
- }
- xmlFree (str);
- }
- str = xmlGetProp (node, "color");
- if (str != NULL) {
- go_color_from_str (str, &line->color);
- xmlFree (str);
- }
- if (bool_prop (node, "auto-color", &tmp))
- line->auto_color = tmp;
-}
-
-static void
go_style_line_sax_save (GsfXMLOut *output, char const *name,
GOStyleLine const *line)
{
@@ -1445,6 +1398,7 @@ go_style_fill_sax_save (GsfXMLOut *output, GOStyle const *style)
gsf_xml_out_add_cstr_unchecked (output, "type",
image_tiling_as_str (style->fill.image.type));
gsf_xml_out_add_cstr (output, "name", go_image_get_name (style->fill.image.image));
+ gsf_xml_out_add_cstr (output, "type-name", G_OBJECT_TYPE_NAME (style->fill.image.image));
go_doc_save_image ((GODoc *) g_object_get_data (G_OBJECT (gsf_xml_out_get_output (output)), "document"), go_image_get_name (style->fill.image.image));
gsf_xml_out_end_element (output);
break;
@@ -1455,153 +1409,6 @@ go_style_fill_sax_save (GsfXMLOut *output, GOStyle const *style)
}
static void
-go_style_gradient_load (xmlNode *node, GOStyle *style)
-{
- char *str = xmlGetProp (node, "direction");
- if (str != NULL) {
- style->fill.gradient.dir
- = go_gradient_dir_from_str (str);
- xmlFree (str);
- }
- str = xmlGetProp (node, "start-color");
- if (str != NULL) {
- go_color_from_str (str, &style->fill.pattern.back);
- xmlFree (str);
- }
- str = xmlGetProp (node, "brightness");
- if (str != NULL) {
- go_style_set_fill_brightness (style, g_strtod (str, NULL));
- xmlFree (str);
- } else {
- str = xmlGetProp (node, "end-color");
- if (str != NULL) {
- go_color_from_str (str, &style->fill.pattern.fore);
- xmlFree (str);
- }
- }
-}
-
-static void
-go_style_image_load (xmlNode *node, GOStyle *style)
-{
- char *str = xmlGetProp (node, "type");
- if (str != NULL) {
- style->fill.image.type = str_as_image_tiling (str);
- xmlFree (str);
- }
- /* TODO: load the pixels */
-}
-
-static void
-go_style_fill_load (xmlNode *node, GOStyle *style)
-{
- xmlNode *ptr;
- gboolean tmp;
- char *str = xmlGetProp (node, "type");
-
- if (str == NULL)
- return;
- style->fill.type = str_as_fill_style (str);
- xmlFree (str);
-
- style->fill.auto_type = FALSE;
-
- if (bool_prop (node, "auto-type", &tmp))
- style->fill.auto_type = tmp;
- if (bool_prop (node, "is-auto", &tmp))
- style->fill.auto_back = tmp;
- if (bool_prop (node, "auto-fore", &tmp))
- style->fill.auto_fore = tmp;
-
- switch (style->fill.type) {
- case GO_STYLE_FILL_PATTERN:
- for (ptr = node->xmlChildrenNode ;
- ptr != NULL ; ptr = ptr->next) {
- if (xmlIsBlankNode (ptr) || ptr->name == NULL)
- continue;
- if (strcmp (ptr->name, "pattern") == 0) {
- str = xmlGetProp (ptr, "type");
- if (str != NULL) {
- style->fill.pattern.pattern
- = go_pattern_from_str (str);
- xmlFree (str);
- }
- str = xmlGetProp (ptr, "fore");
- if (str != NULL) {
- go_color_from_str (str, &style->fill.pattern.fore);
- xmlFree (str);
- }
- str = xmlGetProp (ptr, "back");
- if (str != NULL) {
- go_color_from_str (str, &style->fill.pattern.back);
- xmlFree (str);
- }
- }
- }
- break;
- case GO_STYLE_FILL_GRADIENT:
- for (ptr = node->xmlChildrenNode ;
- ptr != NULL ; ptr = ptr->next) {
- if (xmlIsBlankNode (ptr) || ptr->name == NULL)
- continue;
- if (strcmp (ptr->name, "gradient") == 0)
- go_style_gradient_load (ptr, style);
- }
- break;
- case GO_STYLE_FILL_IMAGE:
- for (ptr = node->xmlChildrenNode ;
- ptr != NULL ; ptr = ptr->next) {
- if (xmlIsBlankNode (ptr) || ptr->name == NULL)
- continue;
- if (strcmp (ptr->name, "image") == 0) {
- go_style_image_load (ptr, style);
- }
- }
- break;
- default:
- break;
- }
-}
-
-static void
-go_style_marker_load (xmlNode *node, GOStyle *style)
-{
- char *str;
- GOColor c;
- GOMarker *marker = go_marker_dup (style->marker.mark);
-
- str = xmlGetProp (node, "shape");
- if (str != NULL) {
- style->marker.auto_shape = TRUE;
- bool_prop (node, "auto-shape", &style->marker.auto_shape);
- go_marker_set_shape (marker, go_marker_shape_from_str (str));
- xmlFree (str);
- }
- str = xmlGetProp (node, "outline-color");
- if (str != NULL) {
- style->marker.auto_outline_color = TRUE;
- bool_prop (node, "auto-outline", &style->marker.auto_outline_color);
- if (go_color_from_str (str, &c))
- go_marker_set_outline_color (marker, c);
- xmlFree (str);
- }
- str = xmlGetProp (node, "fill-color");
- if (str != NULL) {
- style->marker.auto_fill_color = TRUE;
- bool_prop (node, "auto-fill", &style->marker.auto_fill_color);
- if (go_color_from_str (str, &c))
- go_marker_set_fill_color (marker, c);
- xmlFree (str);
- }
- str = xmlGetProp (node, "size");
- if (str != NULL) {
- go_marker_set_size (marker, g_strtod (str, NULL));
- xmlFree (str);
- }
- go_style_set_marker (style, marker);
-}
-
-static void
go_style_marker_sax_save (GsfXMLOut *output, GOStyle const *style)
{
gsf_xml_out_start_element (output, "marker");
@@ -1621,30 +1428,6 @@ go_style_marker_sax_save (GsfXMLOut *output, GOStyle const *style)
}
static void
-go_style_font_load (xmlNode *node, GOStyle *style)
-{
- char *str;
- gboolean tmp;
-
- str = xmlGetProp (node, "color");
- if (str != NULL) {
- go_color_from_str (str, &style->font.color);
- xmlFree (str);
- }
- str = xmlGetProp (node, "font");
- if (str != NULL) {
- PangoFontDescription *desc;
-
- desc = pango_font_description_from_string (str);
- if (desc != NULL)
- go_style_set_font_desc (style, desc);
- xmlFree (str);
- }
- if (bool_prop (node, "auto-scale", &tmp))
- style->font.auto_scale = tmp;
-}
-
-static void
go_style_font_sax_save (GsfXMLOut *output, GOStyle const *style)
{
char *str;
@@ -1658,18 +1441,6 @@ go_style_font_sax_save (GsfXMLOut *output, GOStyle const *style)
}
static void
-go_style_text_layout_load (xmlNode *node, GOStyle *style)
-{
- char *str;
-
- str = xmlGetProp (node, "angle");
- if (str != NULL) {
- go_style_set_text_angle (style, g_strtod (str, NULL));
- xmlFree (str);
- }
-}
-
-static void
go_style_text_layout_sax_save (GsfXMLOut *output, GOStyle const *style)
{
gsf_xml_out_start_element (output, "text_layout");
@@ -1678,32 +1449,6 @@ go_style_text_layout_sax_save (GsfXMLOut *output, GOStyle const *style)
gsf_xml_out_end_element (output);
}
-static gboolean
-go_style_persist_dom_load (GOPersist *gp, xmlNode *node)
-{
- GOStyle *style = GO_STYLE (gp);
- xmlNode *ptr;
-
- /* while reloading no need to reapply settings */
- for (ptr = node->xmlChildrenNode ; ptr != NULL ; ptr = ptr->next) {
- if (xmlIsBlankNode (ptr) || ptr->name == NULL)
- continue;
- if (strcmp (ptr->name, "outline") == 0)
- go_style_line_load (ptr, &style->line);
- else if (strcmp (ptr->name, "line") == 0)
- go_style_line_load (ptr, &style->line);
- else if (strcmp (ptr->name, "fill") == 0)
- go_style_fill_load (ptr, style);
- else if (strcmp (ptr->name, "marker") == 0)
- go_style_marker_load (ptr, style);
- else if (strcmp (ptr->name, "font") == 0)
- go_style_font_load (ptr, style);
- else if (strcmp (ptr->name, "text_layout") == 0)
- go_style_text_layout_load (ptr, style);
- }
- return TRUE;
-}
-
static void
go_style_sax_load_line (GsfXMLIn *xin, xmlChar const **attrs)
{
@@ -1764,14 +1509,21 @@ go_style_sax_load_fill_image (GsfXMLIn *xin, xmlChar const **attrs)
{
GOStyle *style = GO_STYLE (xin->user_state);
GODoc *doc = (GODoc *) g_object_get_data (G_OBJECT (gsf_xml_in_get_input (xin)), "document");
+ xmlChar const *name = NULL, *type_name = NULL;
+ GType type;
g_return_if_fail (style->fill.type == GO_STYLE_FILL_NONE);
g_return_if_fail (GO_IS_DOC (doc));
/* TODO: load the pixels */
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
- if (0 == strcmp (attrs[0], "type")) {
+ if (0 == strcmp (attrs[0], "type"))
style->fill.image.type = str_as_image_tiling (attrs[1]);
- } else if (0 == strcmp (attrs[0], "name"))
- style->fill.image.image = g_object_ref (go_doc_image_fetch (doc, attrs[1]));
+ else if (0 == strcmp (attrs[0], "name"))
+ name = attrs[1];
+ else if (0 == strcmp (attrs[0], "type-name"))
+ type_name = attrs[1];
+ type = type_name? g_type_from_name (type_name): GO_TYPE_PIXBUF;
+ if (name && type_name)
+ style->fill.image.image = g_object_ref (go_doc_image_fetch (doc, name, type));
if (style->fill.image.image != NULL)
style->fill.type = GO_STYLE_FILL_IMAGE;
}
@@ -1925,7 +1677,6 @@ go_style_persist_prep_sax (GOPersist *gp, GsfXMLIn *xin, xmlChar const **attrs)
static void
go_style_persist_init (GOPersistClass *iface)
{
- iface->dom_load = go_style_persist_dom_load;
iface->prep_sax = go_style_persist_prep_sax;
iface->sax_save = go_style_persist_sax_save;
}
@@ -2109,22 +1860,10 @@ go_style_set_text_angle (GOStyle *style, double angle)
style->text_layout.auto_angle = FALSE;
}
-/**
- * go_style_create_cairo_pattern:
- * @style : #GOStyle
- * @cr: a cairo context
- *
- * Create a cairo_patern_t using the current style settings for filling.
- * A pattern will be created only if the style has the corresponding field
- * and if it is not set to a none constant.
- *
- * Returns: the pattern or NULL if it could not be created.
- **/
-cairo_pattern_t *
-go_style_create_cairo_pattern (GOStyle const *style, cairo_t *cr)
+void
+go_style_fill (GOStyle const *style, cairo_t *cr, gboolean preserve)
{
- cairo_pattern_t *cr_pattern;
- cairo_matrix_t cr_matrix;
+ cairo_pattern_t *cr_pattern = NULL;
double x[3], y[3];
int w, h;
@@ -2147,19 +1886,19 @@ go_style_create_cairo_pattern (GOStyle const *style, cairo_t *cr)
{2, 2, 0, 1}
};
- g_return_val_if_fail (GO_IS_STYLE (style), NULL);
-
- if (style->fill.type == GO_STYLE_FILL_NONE)
- return NULL;
-
cairo_fill_extents (cr, &x[0], &y[0], &x[1], &y[1]);
- if (go_sub_epsilon (fabs (x[0] - x[1])) <=0.0 ||
- go_sub_epsilon (fabs (y[0] - y[1])) <=0.0)
- return NULL;
+ if (!GO_IS_STYLE (style) ||
+ go_sub_epsilon (fabs (x[0] - x[1])) <=0.0 ||
+ go_sub_epsilon (fabs (y[0] - y[1])) <=0.0) {
+ if (!preserve)
+ cairo_new_path (cr);
+ return;
+ }
switch (style->fill.type) {
case GO_STYLE_FILL_PATTERN:
- return go_pattern_create_cairo_pattern (&style->fill.pattern, cr);
+ cr_pattern = go_pattern_create_cairo_pattern (&style->fill.pattern, cr);
+ break;
case GO_STYLE_FILL_GRADIENT:
x[2] = (x[1] - x[0]) / 2.0 + x[0];
@@ -2174,48 +1913,71 @@ go_style_create_cairo_pattern (GOStyle const *style, cairo_t *cr)
GO_COLOR_TO_CAIRO (style->fill.pattern.back));
cairo_pattern_add_color_stop_rgba (cr_pattern, 1,
GO_COLOR_TO_CAIRO (style->fill.pattern.fore));
- return cr_pattern;
+ break;
case GO_STYLE_FILL_IMAGE:
- if (style->fill.image.image == NULL)
- return cairo_pattern_create_rgba (1, 1, 1, 1);
-
- cr_pattern = go_image_create_cairo_pattern (style->fill.image.image);
- if (cr_pattern == NULL) {
- /* don't reference anymore an invalid image */
- ((GOStyle *) style)->fill.image.image = NULL;
- return cairo_pattern_create_rgba (1, 1, 1, 1);
- }
- g_object_get (style->fill.image.image, "width", &w, "height", &h, NULL);
- switch (style->fill.image.type) {
- case GO_IMAGE_CENTERED:
- cairo_pattern_set_extend (cr_pattern, CAIRO_EXTEND_NONE);
- cairo_matrix_init_translate (&cr_matrix,
- -(x[1] - x[0] - w) / 2 - x[0],
- -(y[1] - y[0] - h) / 2 - y[0]);
- cairo_pattern_set_matrix (cr_pattern, &cr_matrix);
- break;
- case GO_IMAGE_STRETCHED:
- cairo_pattern_set_extend (cr_pattern, CAIRO_EXTEND_NONE);
- cairo_matrix_init_scale (&cr_matrix,
- w / (x[1] - x[0]),
- h / (y[1] - y[0]));
- cairo_matrix_translate (&cr_matrix, -x[0], -y[0]);
- cairo_pattern_set_matrix (cr_pattern, &cr_matrix);
- break;
- case GO_IMAGE_WALLPAPER:
- cairo_pattern_set_extend (cr_pattern, CAIRO_EXTEND_REPEAT);
- cairo_matrix_init_translate (&cr_matrix, -x[0], -y[0]);
- cairo_pattern_set_matrix (cr_pattern, &cr_matrix);
- break;
+ if (!GO_IS_IMAGE (style->fill.image.image))
+ cr_pattern = cairo_pattern_create_rgba (1, 1, 1, 1);
+ else {
+ cairo_save (cr);
+ if (preserve)
+ cairo_clip_preserve (cr);
+ else
+ cairo_clip (cr);
+ g_object_get (style->fill.image.image, "width", &w, "height", &h, NULL);
+ switch (style->fill.image.type) {
+ case GO_IMAGE_CENTERED:
+ cairo_translate (cr,
+ (x[1] - x[0] - w) / 2 + x[0],
+ (y[1] - y[0] - h) / 2 + y[0]);
+ go_image_draw (style->fill.image.image, cr);
+ break;
+ case GO_IMAGE_STRETCHED:
+ cairo_translate (cr, x[0], y[0]);
+ cairo_scale (cr, (x[1] - x[0]) / w, (y[1] - y[0]) / h);
+ go_image_draw (style->fill.image.image, cr);
+ break;
+ case GO_IMAGE_CENTERED_WALLPAPER: {
+ int n = go_fake_floor ((x[1] - x[0]) / w);
+ x[0] -= w - (x[1] - x[0] - n * w) / 2.;
+ n = go_fake_floor ((y[1] - y[0]) / h);
+ y[0] -= h - (y[1] - y[0] - n * h) / 2.;
+ }
+ case GO_IMAGE_WALLPAPER: {
+ double cx = x[0], cy;
+ while (cx < x[1]) {
+ cy = y[0];
+ while (cy < y[1]) {
+ cairo_save (cr);
+ cairo_translate (cr, cx, cy);
+ go_image_draw (style->fill.image.image, cr);
+ cairo_restore (cr);
+ cy += h;
+ }
+ cx += w;
+ }
+ break;
+ }
+ }
+ cairo_restore (cr);
+ return;
}
- return cr_pattern;
case GO_STYLE_FILL_NONE:
- return NULL;
+ if (!preserve)
+ cairo_new_path (cr);
+ break;
}
- return NULL;
+ if (cr_pattern) {
+ cairo_set_source (cr, cr_pattern);
+ cairo_pattern_destroy (cr_pattern);
+
+ if (preserve)
+ cairo_fill_preserve (cr);
+ else
+ cairo_fill (cr);
+ }
}
gboolean
diff --git a/goffice/utils/go-style.h b/goffice/utils/go-style.h
index 419509d..17e9347 100644
--- a/goffice/utils/go-style.h
+++ b/goffice/utils/go-style.h
@@ -54,7 +54,8 @@ typedef enum {
typedef enum {
GO_IMAGE_STRETCHED,
GO_IMAGE_WALLPAPER,
- GO_IMAGE_CENTERED
+ GO_IMAGE_CENTERED,
+ GO_IMAGE_CENTERED_WALLPAPER
} GOImageType;
typedef struct {
@@ -154,8 +155,8 @@ gpointer go_style_get_editor (GOStyle *style,
GObject *object_with_style);
#endif
-cairo_pattern_t *go_style_create_cairo_pattern (GOStyle const *style,
- cairo_t *cr);
+void go_style_fill (GOStyle const *style, cairo_t *cr,
+ gboolean preserve);
gboolean go_style_set_cairo_line (GOStyle const *style, cairo_t *cr);
G_END_DECLS
diff --git a/goffice/utils/go-styled-object.c b/goffice/utils/go-styled-object.c
index 6aee6b3..edfadc0 100644
--- a/goffice/utils/go-styled-object.c
+++ b/goffice/utils/go-styled-object.c
@@ -223,30 +223,22 @@ go_styled_object_set_cairo_line (GOStyledObject const *so, cairo_t *cr)
}
/**
- * go_styled_object_set_cairo_fill :
+ * go_styled_object_fill :
* @so: #GOStyledObject
* @cr: #cairo_t
+ * @preserve: whether the current path should be preserved
*
- * Prepares the cairo context @cr to fill a shape according to the
+ * fills the current path according to the
* item style and canvas scale.
*
- * Returns: %TRUE if the filling is not invisible.
**/
-gboolean
-go_styled_object_set_cairo_fill (GOStyledObject const *so, cairo_t *cr)
+void
+go_styled_object_fill (GOStyledObject const *so, cairo_t *cr, gboolean preserve)
{
GOStyle const *style;
- cairo_pattern_t *pat = NULL;
- g_return_val_if_fail (GO_IS_STYLED_OBJECT (so), FALSE);
+ g_return_if_fail (GO_IS_STYLED_OBJECT (so));
style = go_styled_object_get_style (GO_STYLED_OBJECT (so));
- if (style->fill.type == GO_STYLE_FILL_NONE)
- return FALSE;
- pat = go_style_create_cairo_pattern (style, cr);
- if (pat) {
- cairo_set_source (cr, pat);
- cairo_pattern_destroy (pat);
- }
- return TRUE;
+ go_style_fill (style, cr, preserve);
}
diff --git a/goffice/utils/go-styled-object.h b/goffice/utils/go-styled-object.h
index 53fb62d..7ad3402 100644
--- a/goffice/utils/go-styled-object.h
+++ b/goffice/utils/go-styled-object.h
@@ -54,7 +54,8 @@ void go_styled_object_style_changed (GOStyledObject *gso);
void go_styled_object_apply_theme (GOStyledObject *gso, GOStyle *style);
GODoc *go_styled_object_get_document (GOStyledObject *gso);
gboolean go_styled_object_set_cairo_line (GOStyledObject const *so, cairo_t *cr);
-gboolean go_styled_object_set_cairo_fill (GOStyledObject const *so, cairo_t *cr);
+void go_styled_object_fill (GOStyledObject const *so, cairo_t *cr, gboolean preserve);
+gboolean go_styled_object_is_filled (GOStyledObject *gso);
G_END_DECLS
#endif
diff --git a/goffice/utils/go-svg.c b/goffice/utils/go-svg.c
new file mode 100644
index 0000000..c2c84a3
--- /dev/null
+++ b/goffice/utils/go-svg.c
@@ -0,0 +1,182 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-svg.c - SVG image support
+ *
+ * Copyright (C) 2011 Jean Brefort (jean brefort normalesup org)
+ *
+ * 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 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 St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include <goffice/goffice-config.h>
+#include "go-svg.h"
+#include <librsvg/rsvg.h>
+#include <librsvg/rsvg-cairo.h>
+#include <gsf/gsf-utils.h>
+#include <gsf/gsf-impl-utils.h>
+#include <gsf/gsf-input-stdio.h>
+#include <string.h>
+
+struct _GOSvg {
+ GOImage parent;
+ RsvgHandle *handle;
+ gsize data_length;
+};
+
+typedef GOImageClass GOSvgClass;
+
+static GObjectClass *parent_klass;
+
+static void
+go_svg_save (GOImage *image, GsfXMLOut *output)
+{
+ GOSvg *svg = GO_SVG (image);
+ g_return_if_fail (svg);
+ gsf_xml_out_add_base64 (output, NULL,
+ image->data, svg->data_length);
+}
+
+static void
+go_svg_load_attr (G_GNUC_UNUSED GOImage *image, G_GNUC_UNUSED xmlChar const *attr_name, G_GNUC_UNUSED xmlChar const *attr_value)
+{
+ /* nothing to do */
+}
+
+static void
+go_svg_load_data (GOImage *image, GsfXMLIn *xin)
+{
+ GOSvg *svg = GO_SVG (image);
+ svg->data_length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
+ image->data = g_malloc (svg->data_length);
+ memcpy (image->data, xin->content->str, svg->data_length);
+ svg->handle = rsvg_handle_new_from_data (image->data, svg->data_length, NULL);
+}
+
+static void
+go_svg_draw (GOImage *image, cairo_t *cr)
+{
+ GOSvg *svg = GO_SVG (image);
+ rsvg_handle_render_cairo (svg->handle, cr);
+}
+
+static GdkPixbuf *
+go_svg_get_pixbuf (GOImage *image)
+{
+ GOSvg *svg = GO_SVG (image);
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ GdkPixbuf *res = NULL;
+ g_return_val_if_fail (svg != NULL, NULL);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, image->width, image->height);
+ cr = cairo_create (surface);
+ rsvg_handle_render_cairo (svg->handle, cr);
+ cairo_destroy (cr);
+ res = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, image->width, image->height);
+ go_cairo_convert_data_from_pixbuf (gdk_pixbuf_get_pixels (res),
+ cairo_image_surface_get_data (surface),
+ image->width, image->height,
+ cairo_image_surface_get_stride (surface));
+ return res;
+}
+
+static GdkPixbuf *
+go_svg_get_scaled_pixbuf (GOImage *image, int width, int height)
+{
+ GOSvg *svg = GO_SVG (image);
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ GdkPixbuf *res = NULL;
+ g_return_val_if_fail (svg != NULL, NULL);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ cr = cairo_create (surface);
+ cairo_scale (cr, width / image->width, height / image->height);
+ rsvg_handle_render_cairo (svg->handle, cr);
+ cairo_destroy (cr);
+ res = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+ go_cairo_convert_data_from_pixbuf (gdk_pixbuf_get_pixels (res),
+ cairo_image_surface_get_data (surface),
+ width, height,
+ cairo_image_surface_get_stride (surface));
+ return res;
+}
+
+static gboolean
+go_svg_differ (GOImage *first, GOImage *second)
+{
+ GOSvg *sfirst = GO_SVG (first), *ssecond = GO_SVG (second);
+ if (sfirst->data_length != ssecond->data_length)
+ return TRUE;
+ return memcmp (first->data, second->data, sfirst->data_length);
+}
+
+static void
+go_svg_finalize (GObject *obj)
+{
+ GOSvg *svg = GO_SVG (obj);
+ if (svg->handle)
+ g_object_unref (svg->handle);
+ (parent_klass->finalize) (obj);
+}
+
+static void
+go_svg_class_init (GObjectClass *klass)
+{
+ GOImageClass *image_klass = (GOImageClass *) klass;
+
+ klass->finalize = go_svg_finalize;
+ parent_klass = g_type_class_peek_parent (klass);
+
+ image_klass->save = go_svg_save;
+ image_klass->load_attr = go_svg_load_attr;
+ image_klass->load_data = go_svg_load_data;
+ image_klass->get_pixbuf = go_svg_get_pixbuf;
+ image_klass->get_scaled_pixbuf = go_svg_get_scaled_pixbuf;
+ image_klass->draw = go_svg_draw;
+ image_klass->differ = go_svg_differ;
+}
+
+GSF_CLASS (GOSvg, go_svg,
+ go_svg_class_init, NULL,
+ GO_TYPE_IMAGE)
+
+
+GOSvg *
+go_svg_new_from_file (char const *filename, GError **error)
+{
+ GOSvg *svg = g_object_new (GO_TYPE_SVG, NULL);
+ guint8 *data;
+ GsfInput *input = gsf_input_stdio_new (filename, error);
+ RsvgDimensionData dim;
+ GOImage *image;
+ if (!input)
+ return NULL;
+ svg->data_length = gsf_input_size (input);
+ data = g_malloc (svg->data_length);
+ if (!data || !gsf_input_read (input, svg->data_length, data)) {
+ g_object_unref (svg);
+ return NULL;
+ }
+ image = GO_IMAGE (svg);
+ image->data = data;
+ svg->handle = rsvg_handle_new_from_data (data, svg->data_length, error);
+ if (svg->handle == NULL) {
+ g_object_unref (svg);
+ return NULL;
+ }
+ rsvg_handle_get_dimensions (svg->handle, &dim);
+ image->width = dim.width;
+ image->height = dim.height;
+ return svg;
+}
diff --git a/goffice/utils/go-svg.h b/goffice/utils/go-svg.h
new file mode 100644
index 0000000..baa8395
--- /dev/null
+++ b/goffice/utils/go-svg.h
@@ -0,0 +1,40 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-svg.h - SVG image support
+ *
+ * Copyright (C) 2011 Jean Brefort (jean brefort normalesup org)
+ *
+ * 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 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 St, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#ifndef GO_SVG_H
+#define GO_SVG_H
+
+#include <goffice/goffice.h>
+
+G_BEGIN_DECLS
+
+#define GO_TYPE_SVG (go_svg_get_type ())
+#define GO_SVG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GO_TYPE_SVG, GOSvg))
+#define GO_IS_SVG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GO_TYPE_SVG))
+
+GType go_svg_get_type (void);
+
+GOSvg *go_svg_new_from_file (char const *filename, GError **error);
+
+G_END_DECLS
+
+#endif /* GO_SVG_H */
diff --git a/goffice/utils/goffice-utils.h b/goffice/utils/goffice-utils.h
index bbd819c..58208f2 100644
--- a/goffice/utils/goffice-utils.h
+++ b/goffice/utils/goffice-utils.h
@@ -35,6 +35,8 @@ typedef struct _GOMarker GOMarker;
typedef struct _GOFormat GOFormat;
typedef struct _GODateConventions GODateConventions;
typedef struct _GOImage GOImage;
+typedef struct _GOPixbuf GOPixbuf;
+typedef struct _GOSvg GOSvg;
typedef struct _GOPath GOPath;
typedef struct _GOString GOString;
typedef struct _GOStyle GOStyle;
@@ -114,6 +116,7 @@ G_END_DECLS
#include <goffice/utils/go-gradient.h>
#include <goffice/utils/go-image.h>
#include <goffice/utils/go-pixbuf.h>
+#include <goffice/utils/go-svg.h>
#include <goffice/utils/go-libxml-extras.h>
#include <goffice/utils/go-line.h>
#include <goffice/utils/go-locale.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]