Hi,
Please find attached a patch that adds experimental PDF/PS export
support via cairo renderer (if cairo is compiled with PDF/PS backends,
of course, which should be the default for next stable release...).
In the process, I've moved some image format related code from gnumeric
to goffice.
Ok to commit ?
Emmanuel.
? po/fr.po.autosave
? src/gnm-graph-window.c
? src/gnm-graph-window.h
Index: src/sheet-object-graph.c
===================================================================
RCS file: /cvs/gnome/gnumeric/src/sheet-object-graph.c,v
retrieving revision 1.74
diff -u -p -r1.74 sheet-object-graph.c
--- src/sheet-object-graph.c 18 Nov 2005 15:54:51 -0000 1.74
+++ src/sheet-object-graph.c 29 Nov 2005 15:24:24 -0000
@@ -221,24 +221,9 @@ gnm_sog_get_object_target_list (SheetObj
return tl;
}
-static gboolean
-sog_gsf_gdk_pixbuf_save (const gchar *buf,
- gsize count,
- GError **error,
- gpointer data)
-{
- GsfOutput *output = GSF_OUTPUT (data);
- gboolean ok = gsf_output_write (output, count, buf);
-
- if (!ok && error)
- *error = g_error_copy (gsf_output_error (output));
-
- return ok;
-}
-
static void
gnm_sog_write_image (SheetObject const *so, const char *format,
- GsfOutput *output, GError **err)
+ GsfOutput *output, GError **err)
{
SheetObjectGraph *sog = SHEET_OBJECT_GRAPH (so);
gboolean res = FALSE;
@@ -258,20 +243,10 @@ gnm_sog_write_image (SheetObject const *
g_return_if_fail (w > 0 && h > 0);
- if (strcmp (format, "svg") == 0) {
- res = gog_graph_export_to_svg (sog->graph, output, w, h, 1.0);
- } else {
- GdkPixbuf *pixbuf = gog_renderer_get_pixbuf (sog->renderer);
-
- if (!pixbuf) {
- gog_renderer_update (sog->renderer, w, h, 1.);
- pixbuf = gog_renderer_get_pixbuf (sog->renderer);
- }
- res = gdk_pixbuf_save_to_callback (pixbuf,
- sog_gsf_gdk_pixbuf_save,
- output, format,
- err, NULL);
- }
+ /* FIXME Add a dpi editor. Default dpi to 150 for now */
+ res = gog_graph_export_image (sog->graph, go_image_get_format_from_name (format),
+ output, 150.0, 150.0);
+
if (!res && err && *err == NULL)
*err = g_error_new (gsf_output_error_id (), 0,
_("Unknown failure while saving image"));
@@ -308,49 +283,34 @@ gnm_sog_write_object (SheetObject const
g_free (old_num_locale);
}
-/*
- * The following are useful formats to save in:
- * png
- * svg
- * eps
- *
- * TODO: Possibly add an eps renderer. We may also use a new instance of
- * pixbufrenderer to save as png. This would allow the user to specify size of
- * the saved image, if that's wanted.
- */
static void
sog_cb_save_as (SheetObject *so, SheetControl *sc)
{
- static GOImageType const fmts[] = {
- {(char *) "svg", (char *) N_("SVG (vector graphics)"), (char *) "svg", FALSE},
- {(char *) "png", (char *) N_("PNG (raster graphics)"), (char *) "png", TRUE},
- {(char *) "jpeg", (char *) N_("JPEG (photograph)"), (char *) "jpg", TRUE}
- };
-
WorkbookControlGUI *wbcg;
char *uri;
GError *err = NULL;
GsfOutput *output;
- GSList *l = NULL;
- GOImageType const *sel_fmt = &fmts[0];
- guint i;
+ GSList *l;
+ GOImageFormat selected_format;
+ GOImageFormatInfo const *format_info;
SheetObjectGraph *sog = SHEET_OBJECT_GRAPH (so);
g_return_if_fail (sog != NULL);
- for (i = 0; i < G_N_ELEMENTS (fmts); i++)
- l = g_slist_prepend (l, (gpointer) (fmts + i));
- l = g_slist_reverse (l);
+ l = gog_graph_get_supported_image_formats ();
+ g_return_if_fail (l != NULL);
+ selected_format = GPOINTER_TO_UINT (l->data);
#warning "This violates model gui barrier"
wbcg = scg_get_wbcg (SHEET_CONTROL_GUI (sc));
- uri = gui_get_image_save_info (wbcg_toplevel (wbcg), l, &sel_fmt);
+ uri = gui_get_image_save_info (wbcg_toplevel (wbcg), l, &selected_format);
if (!uri)
goto out;
output = go_file_create (uri, &err);
if (!output)
goto out;
- sheet_object_write_image (so, sel_fmt->name, output, &err);
+ format_info = go_image_get_format_info (selected_format);
+ sheet_object_write_image (so, format_info->name, output, &err);
g_object_unref (output);
if (err != NULL)
Index: src/sheet-object-image.c
===================================================================
RCS file: /cvs/gnome/gnumeric/src/sheet-object-image.c,v
retrieving revision 1.61
diff -u -p -r1.61 sheet-object-image.c
--- src/sheet-object-image.c 7 Nov 2005 04:44:02 -0000 1.61
+++ src/sheet-object-image.c 29 Nov 2005 15:24:24 -0000
@@ -138,9 +138,9 @@ enum {
void
sheet_object_image_set_image (SheetObjectImage *soi,
char const *type,
- guint8 *data,
+ guint8 *data,
unsigned data_len,
- gboolean copy_data)
+ gboolean copy_data)
{
g_return_if_fail (IS_SHEET_OBJECT_IMAGE (soi));
g_return_if_fail (soi->bytes.data == NULL && soi->bytes.len == 0);
@@ -345,77 +345,14 @@ soi_gdk_pixbuf_save (const gchar *buf,
return ok;
}
-static GOImageType const std_fmts[] = {
- {(char *) "png", (char *) N_("PNG (raster graphics)"),
- (char *) "png", TRUE},
- {(char *) "jpeg", (char *) N_("JPEG (photograph)"),
- (char *) "jpg", TRUE},
- {(char *) "svg", (char *) N_("SVG (vector graphics)"),
- (char *) "svg", FALSE},
- {(char *) "emf", (char *) N_("EMF (extended metafile)"),
- (char *) "emf", FALSE},
- {(char *) "wmf", (char *) N_("WMF (windows metafile)"),
- (char *) "wmf", FALSE}
+static GOImageFormat const standard_formats[] = {
+ GO_IMAGE_FORMAT_PNG,
+ GO_IMAGE_FORMAT_JPG,
+ GO_IMAGE_FORMAT_SVG,
+ GO_IMAGE_FORMAT_EMF,
+ GO_IMAGE_FORMAT_WMF
};
-static GOImageType *
-soi_get_image_fmt (SheetObjectImage *soi)
-{
- GOImageType *ret = g_new0 (GOImageType, 1);
- GSList *l, *pixbuf_fmts;
- guint i;
-
- ret->name = g_strdup (soi->type);
- for (i = 0; i < G_N_ELEMENTS (std_fmts); i++) {
- GOImageType const *fmt = &std_fmts[i];
-
- if (strcmp (soi->type, fmt->name) == 0) {
- ret->desc = g_strdup (fmt->desc);
- ret->ext = g_strdup (fmt->ext);
- ret->has_pixbuf_saver = fmt->has_pixbuf_saver;
- return ret;
- }
- }
-
- ret->desc = g_ascii_strup (ret->name, -1);
- ret->has_pixbuf_saver = FALSE;
-
- /* Not found in standard formats - look in gdk-pixbuf */
- pixbuf_fmts = gdk_pixbuf_get_formats ();
- for (l = pixbuf_fmts; l != NULL; l = l->next) {
- GdkPixbufFormat *fmt = (GdkPixbufFormat *)l->data;
- gchar *name = gdk_pixbuf_format_get_name (fmt);
- int cmp = strcmp (soi->type, name);
-
- g_free (name);
- if (cmp == 0) {
- gchar **exts;
-
- exts = gdk_pixbuf_format_get_extensions (fmt);
- ret->ext = g_strdup (exts[0]);
- g_strfreev (exts);
- break;
- }
- }
- g_slist_free (pixbuf_fmts);
-
- if (ret->ext == NULL)
- ret->ext = g_strdup (ret->name);
-
- return ret;
-}
-
-static void
-soi_free_image_fmt (gpointer data)
-{
- GOImageType *fmt = (GOImageType *) data;
-
- g_free (fmt->name);
- g_free (fmt->desc);
- g_free (fmt->ext);
- g_free (fmt);
-}
-
static GtkTargetList *
gnm_soi_get_target_list (SheetObject const *so)
{
@@ -447,14 +384,13 @@ gnm_soi_get_target_list (SheetObject con
static void
gnm_soi_write_image (SheetObject const *so, const char *format,
- GsfOutput *output, GError **err)
+ GsfOutput *output, GError **err)
{
SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
- GOImageType const *orig_fmt = soi_get_image_fmt (soi);
gboolean res = FALSE;
GdkPixbuf *pixbuf = soi_get_pixbuf (soi, 1.0);
- if (strcmp (format, orig_fmt->name) == 0)
+ if (strcmp (format, soi->type) == 0)
res = gsf_output_write (output,
soi->bytes.len, soi->bytes.data);
else if (pixbuf)
@@ -476,36 +412,21 @@ soi_cb_save_as (SheetObject *so, SheetCo
char *uri;
GsfOutput *output;
GSList *l = NULL;
- GOImageType const *orig_fmt, *sel_fmt;
- GOImageType *fmt;
+ GOImageFormat sel_fmt;
+ GOImageFormatInfo const *format_info;
GdkPixbuf *pixbuf = NULL;
- guint i;
GError *err = NULL;
SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
g_return_if_fail (soi != NULL);
- /* Put original format of image first in menu. */
- orig_fmt = soi_get_image_fmt (soi);
- sel_fmt = orig_fmt;
- l = g_slist_prepend (l, (gpointer)orig_fmt);
-
- /* Put jpeg and png in menu if we were able to render */
- if ((pixbuf = soi_get_pixbuf (soi, 1.0)) != NULL) {
- for (i = 0; i < G_N_ELEMENTS (std_fmts); i++) {
- if (strcmp (soi->type, std_fmts[i].name) != 0 &&
- std_fmts[i].has_pixbuf_saver) {
- fmt = g_new0 (GOImageType, 1);
- fmt->name = g_strdup (std_fmts[i].name);
- fmt->desc = g_strdup (std_fmts[i].desc);
- fmt->ext = g_strdup (std_fmts[i].ext);
- fmt->has_pixbuf_saver = TRUE;
- l = g_slist_prepend (l, fmt);
- }
- }
- l = g_slist_reverse (l);
- }
-
+ sel_fmt = go_image_get_format_from_name (soi->type);
+ if ((pixbuf = soi_get_pixbuf (soi, 1.0)) != NULL)
+ l = go_image_get_formats_with_pixbuf_saver ();
+ /* Move original format first in menu */
+ l = g_slist_remove (l, GUINT_TO_POINTER (sel_fmt));
+ l = g_slist_prepend (l, GUINT_TO_POINTER (sel_fmt));
+
wbcg = scg_get_wbcg (SHEET_CONTROL_GUI (sc));
uri = gui_get_image_save_info (wbcg_toplevel (wbcg), l, &sel_fmt);
@@ -515,7 +436,8 @@ soi_cb_save_as (SheetObject *so, SheetCo
output = go_file_create (uri, &err);
if (!output)
goto out;
- sheet_object_write_image (so, sel_fmt->name, output, &err);
+ format_info = go_image_get_format_info (sel_fmt);
+ sheet_object_write_image (so, format_info->name, output, &err);
gsf_output_close (output);
g_object_unref (output);
@@ -526,7 +448,7 @@ out:
if (pixbuf)
g_object_unref (pixbuf);
g_free (uri);
- go_slist_free_custom (l, soi_free_image_fmt);
+ g_slist_free (l);
}
static void
? jhgen
? goffice/graph/.gog-renderer-cairo.c.swp
? goffice/graph/.gog-renderer-pixbuf.c.swp
? goffice/gtk/go-marshal.c
? goffice/gtk/go-marshal.h
? goffice/gtk/go-marshal.list
Index: configure.in
===================================================================
RCS file: /cvs/gnome/goffice/configure.in,v
retrieving revision 1.73
diff -u -p -r1.73 configure.in
--- configure.in 27 Nov 2005 18:35:37 -0000 1.73
+++ configure.in 29 Nov 2005 15:24:10 -0000
@@ -86,7 +86,7 @@ goffice_reqs="
pangoft2 >= 1.8.1
"
goffice_cairo_reqs="
- cairo >= 0.5.0
+ cairo >= 1.0.0
"
goffice_gtk_reqs="
gtk+-2.0 >= 2.6.0
Index: goffice/graph/goffice-graph.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/goffice-graph.h,v
retrieving revision 1.32
diff -u -p -r1.32 goffice-graph.h
--- goffice/graph/goffice-graph.h 15 Nov 2005 15:56:23 -0000 1.32
+++ goffice/graph/goffice-graph.h 29 Nov 2005 15:24:10 -0000
@@ -93,6 +93,7 @@ typedef enum {
GOG_AXIS_PSEUDO_3D,
GOG_AXIS_TYPES
} GogAxisType;
+
typedef enum {
GOG_AXIS_SET_UNKNOWN = -1,
GOG_AXIS_SET_NONE = 0,
Index: goffice/graph/gog-graph.c
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-graph.c,v
retrieving revision 1.38
diff -u -p -r1.38 gog-graph.c
--- goffice/graph/gog-graph.c 20 Nov 2005 15:29:08 -0000 1.38
+++ goffice/graph/gog-graph.c 29 Nov 2005 15:24:10 -0000
@@ -23,6 +23,7 @@
#include <goffice/graph/gog-graph-impl.h>
#include <goffice/graph/gog-chart-impl.h>
#include <goffice/graph/gog-renderer.h>
+#include <goffice/graph/gog-renderer-cairo.h>
#include <goffice/graph/gog-style.h>
#include <goffice/graph/gog-theme.h>
#include <goffice/data/go-data.h>
@@ -865,4 +866,46 @@ gog_graph_view_set_selection (GogGraphVi
g_signal_emit (G_OBJECT (gview),
gog_graph_view_signals [GRAPH_VIEW_SELECTION_CHANGED],
0, gobj);
+}
+
+GSList *
+gog_graph_get_supported_image_formats (void)
+{
+ static GOImageFormat supported_formats[] = {
+#ifdef CAIRO_HAS_PS_SURFACE
+ GO_IMAGE_FORMAT_PS,
+#endif
+#ifdef CAIRO_HAS_PDF_SURFACE
+ GO_IMAGE_FORMAT_PDF,
+#endif
+ GO_IMAGE_FORMAT_JPG,
+ GO_IMAGE_FORMAT_PNG,
+ GO_IMAGE_FORMAT_SVG
+ };
+ GSList *list = NULL;
+ unsigned i;
+
+ for (i = 0; i < G_N_ELEMENTS (supported_formats); i++)
+ list = g_slist_prepend (list, GUINT_TO_POINTER (supported_formats[i]));
+
+ return list;
+}
+
+gboolean
+gog_graph_export_image (GogGraph *graph, GOImageFormat format, GsfOutput *output,
+ double x_dpi, double y_dpi)
+{
+ GogRenderer *renderer;
+ gboolean result;
+
+ g_return_val_if_fail (IS_GOG_GRAPH (graph), FALSE);
+ g_return_val_if_fail (format != GO_IMAGE_FORMAT_UNKNOWN, FALSE);
+
+ renderer = gog_renderer_new_for_format (graph, format);
+ g_return_val_if_fail (renderer != NULL, FALSE);
+
+ result = gog_renderer_export_image (renderer, format, output, x_dpi, y_dpi);
+ g_object_unref (renderer);
+
+ return result;
}
Index: goffice/graph/gog-graph.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-graph.h,v
retrieving revision 1.9
diff -u -p -r1.9 gog-graph.h
--- goffice/graph/gog-graph.h 15 Nov 2005 15:56:23 -0000 1.9
+++ goffice/graph/gog-graph.h 29 Nov 2005 15:24:10 -0000
@@ -23,8 +23,10 @@
#include <goffice/graph/goffice-graph.h>
#include <goffice/graph/gog-view.h>
-
#include <goffice/data/goffice-data.h>
+#include <goffice/gtk/goffice-gtk.h>
+
+#include <gsf/gsf.h>
#include <glib-object.h>
@@ -66,6 +68,11 @@ void gog_graph_view_handle_event (Go
GogView *gog_graph_view_get_selection (GogGraphView *view);
void gog_graph_view_set_selection (GogGraphView *gview, GogObject *gobj);
+
+GSList *gog_graph_get_supported_image_formats (void);
+gboolean gog_graph_export_image (GogGraph *graph, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi);
+
G_END_DECLS
#endif /* GOG_GRAPH_H */
Index: goffice/graph/gog-renderer-cairo.c
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer-cairo.c,v
retrieving revision 1.7
diff -u -p -r1.7 gog-renderer-cairo.c
--- goffice/graph/gog-renderer-cairo.c 18 Nov 2005 15:50:56 -0000 1.7
+++ goffice/graph/gog-renderer-cairo.c 29 Nov 2005 15:24:10 -0000
@@ -46,9 +46,13 @@
#include <libart_lgpl/art_render_svp.h>
#include <libart_lgpl/art_render_mask.h>
#include <pango/pangoft2.h>
+
#include <gsf/gsf-impl-utils.h>
+#include <gsf/gsf-output-stdio.h>
-#include <cairo/cairo.h>
+#include <cairo.h>
+#include <cairo-pdf.h>
+#include <cairo-ps.h>
#include <math.h>
@@ -79,11 +83,8 @@ static void
gog_renderer_cairo_finalize (GObject *obj)
{
GogRendererCairo *crend = GOG_RENDERER_CAIRO (obj);
- cairo_surface_t *surface;
if (crend->cairo != NULL){
- surface = cairo_get_target (crend->cairo);
- cairo_surface_destroy (surface);
cairo_destroy (crend->cairo);
crend->cairo = NULL;
}
@@ -617,6 +618,101 @@ gog_renderer_cairo_pop_style (GogRendere
}
}
+static gboolean
+gcr_gsf_gdk_pixbuf_save (const gchar *buf,
+ gsize count,
+ GError **error,
+ gpointer data)
+{
+ GsfOutput *output = GSF_OUTPUT (data);
+ gboolean ok = gsf_output_write (output, count, buf);
+
+ if (!ok && error)
+ *error = g_error_copy (gsf_output_error (output));
+
+ return ok;
+}
+
+static cairo_status_t
+cairo_write_func (void *closure,
+ unsigned char *data,
+ unsigned int length)
+{
+ gboolean result;
+ GsfOutput *output = GSF_OUTPUT (closure);
+
+ result = gsf_output_write (output, length, data);
+
+ return result ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
+}
+
+static gboolean
+gog_renderer_cairo_export_image (GogRenderer *renderer, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi)
+{
+ GogRendererCairo *crend = GOG_RENDERER_CAIRO (renderer);
+ GogViewAllocation allocation;
+ GOImageFormatInfo const *format_info;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ GdkPixbuf *pixbuf;
+ double width_in_pts, height_in_pts;
+
+ gog_graph_get_size (renderer->model, &width_in_pts, &height_in_pts);
+
+ switch (format) {
+ case GO_IMAGE_FORMAT_PNG:
+ case GO_IMAGE_FORMAT_JPG:
+ gog_renderer_cairo_update (crend,
+ width_in_pts * x_dpi / 72.0,
+ height_in_pts * y_dpi / 72.0, 1.0);
+ pixbuf = gog_renderer_cairo_get_pixbuf (crend);
+ if (pixbuf == NULL)
+ return FALSE;
+ format_info = go_image_get_format_info (format);
+ return gdk_pixbuf_save_to_callback (pixbuf,
+ gcr_gsf_gdk_pixbuf_save,
+ output, format_info->name,
+ NULL, NULL);
+ break;
+ case GO_IMAGE_FORMAT_PDF:
+ case GO_IMAGE_FORMAT_PS:
+ crend->base.scale = 1.0;
+ if (format == GO_IMAGE_FORMAT_PDF) {
+ surface = cairo_pdf_surface_create_for_stream (cairo_write_func, output,
+ width_in_pts, height_in_pts);
+ } else {
+ surface = cairo_ps_surface_create_for_stream (cairo_write_func, output,
+ width_in_pts, height_in_pts);
+ }
+ crend->cairo = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ cairo_set_line_join (crend->cairo, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_cap (crend->cairo, CAIRO_LINE_CAP_ROUND);
+ crend->w = width_in_pts;
+ crend->h = height_in_pts;
+
+ allocation.x = 0.;
+ allocation.y = 0.;
+ allocation.w = width_in_pts;
+ allocation.h = height_in_pts;
+ gog_view_size_allocate (crend->base.view, &allocation);
+ gog_view_render (crend->base.view, NULL);
+
+ cairo_show_page (crend->cairo);
+ status = cairo_status (crend->cairo);
+
+ cairo_destroy (crend->cairo);
+ crend->cairo = NULL;
+
+ return status == CAIRO_STATUS_SUCCESS;
+ break;
+ default:
+ g_warning ("[GogRendererCairo:export_image] unsupported format");
+ return FALSE;
+ }
+}
+
static void
gog_renderer_cairo_class_init (GogRendererClass *rend_klass)
{
@@ -637,6 +733,7 @@ gog_renderer_cairo_class_init (GogRender
rend_klass->draw_marker = gog_renderer_cairo_draw_marker;
rend_klass->get_text_OBR = gog_renderer_cairo_get_text_OBR;
rend_klass->line_size = gog_renderer_cairo_line_size;
+ rend_klass->export_image = gog_renderer_cairo_export_image;
}
static void
@@ -653,55 +750,6 @@ GSF_CLASS (GogRendererCairo, gog_rendere
gog_renderer_cairo_class_init, gog_renderer_cairo_init,
GOG_RENDERER_TYPE)
-GdkPixbuf *
-gog_renderer_cairo_get_pixbuf (GogRendererCairo *crend)
-{
- g_return_val_if_fail (crend != NULL, NULL);
-
- return crend->pixbuf;
-}
-
-static gboolean
-grc_cairo_setup (GogRendererCairo *crend, int w, int h)
-{
- cairo_surface_t *surface;
-
- if (w == crend->w && h == crend->h)
- return (w != 0 && h!= 0);
-
- if (crend->cairo != NULL) {
- surface = cairo_get_target (crend->cairo);
- cairo_surface_destroy (surface);
- cairo_destroy (crend->cairo);
- crend->cairo = NULL;
- }
- if (crend->pixbuf != NULL) {
- g_object_unref (crend->pixbuf);
- crend->pixbuf = NULL;
- }
- crend->w = w;
- crend->h = h;
-
- if (w ==0 || h == 0)
- return FALSE;
-
- crend->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, crend->w, crend->h);
- if (crend->pixbuf == NULL) {
- g_warning ("GogRendererCairo::cairo_setup: chart is too large");
- return FALSE;
- }
-
- surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (crend->pixbuf),
- CAIRO_FORMAT_ARGB32,
- crend->w, crend->h,
- gdk_pixbuf_get_rowstride (crend->pixbuf));
- crend->cairo = cairo_create (surface);
- cairo_set_line_join (crend->cairo, CAIRO_LINE_JOIN_ROUND);
- cairo_set_line_cap (crend->cairo, CAIRO_LINE_CAP_ROUND);
-
- return TRUE;
-}
-
/**
* gog_renderer_update :
* @prend :
@@ -716,22 +764,47 @@ gog_renderer_cairo_update (GogRendererCa
GogGraph *graph;
GogView *view;
GogViewAllocation allocation;
+ cairo_surface_t *surface;
gboolean redraw = TRUE;
gboolean size_changed;
- g_return_val_if_fail (crend != NULL, FALSE);
- g_return_val_if_fail (crend->base.view != NULL, FALSE);
+ g_return_val_if_fail (IS_GOG_RENDERER_CAIRO (crend), FALSE);
+ g_return_val_if_fail (IS_GOG_VIEW (crend->base.view), FALSE);
size_changed = crend->w != w || crend->h != h;
+ if (size_changed) {
+ if (crend->pixbuf != NULL)
+ g_object_unref (crend->pixbuf);
+ crend->pixbuf = NULL;
+ if (w == 0 || h == 0)
+ return FALSE;
+ crend->w = w;
+ crend->h = h;
+ crend->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, crend->w, crend->h);
+ if (crend->pixbuf == NULL) {
+ crend->w = 0;
+ crend->h = 0;
+ g_warning ("GogRendererCairo::cairo_setup: chart is too large");
+ return FALSE;
+ }
+ }
+ if (w == 0 || h == 0)
+ return FALSE;
view = crend->base.view;
graph = GOG_GRAPH (view->model);
gog_graph_force_update (graph);
+
allocation.x = allocation.y = 0.;
allocation.w = w;
allocation.h = h;
- if (!grc_cairo_setup (crend, w, h))
- return redraw;
+
+ surface = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (crend->pixbuf),
+ CAIRO_FORMAT_ARGB32,
+ crend->w, crend->h,
+ gdk_pixbuf_get_rowstride (crend->pixbuf));
+ crend->cairo = cairo_create (surface);
+ cairo_surface_destroy (surface);
if (size_changed) {
crend->base.scale_x = w / graph->width;
@@ -755,6 +828,9 @@ gog_renderer_cairo_update (GogRendererCa
crend->base.needs_update = FALSE;
if (redraw) {
+ cairo_set_line_join (crend->cairo, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_cap (crend->cairo, CAIRO_LINE_CAP_ROUND);
+
cairo_rectangle (crend->cairo, 0, 0, w, h);
cairo_set_source_rgba (crend->cairo, 1, 1, 1, 0);
cairo_fill (crend->cairo);
@@ -765,5 +841,16 @@ gog_renderer_cairo_update (GogRendererCa
gdk_pixbuf_get_rowstride (crend->pixbuf));
}
+ cairo_destroy (crend->cairo);
+ crend->cairo = NULL;
return redraw;
}
+
+GdkPixbuf *
+gog_renderer_cairo_get_pixbuf (GogRendererCairo *crend)
+{
+ g_return_val_if_fail (crend != NULL, NULL);
+
+ return crend->pixbuf;
+}
+
Index: goffice/graph/gog-renderer-cairo.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer-cairo.h,v
retrieving revision 1.2
diff -u -p -r1.2 gog-renderer-cairo.h
--- goffice/graph/gog-renderer-cairo.h 8 Aug 2005 08:56:59 -0000 1.2
+++ goffice/graph/gog-renderer-cairo.h 29 Nov 2005 15:24:10 -0000
@@ -22,6 +22,9 @@
#define GOG_RENDERER_CAIRO_H
#include <goffice/graph/goffice-graph.h>
+
+#include <gsf/gsf.h>
+
#include <glib-object.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -37,6 +40,8 @@ GType gog_renderer_cairo_get_type
GdkPixbuf *gog_renderer_cairo_get_pixbuf (GogRendererCairo *crend);
gboolean gog_renderer_cairo_update (GogRendererCairo *crend, int w, int h, double zoom);
+gboolean gog_renderer_cairo_export_to_pdf (GogRendererCairo *crend, GogGraph *graph, GsfOutput *output,
+ double width, double height, double scale);
G_END_DECLS
#endif /* GOG_RENDERER_CAIRO_H */
Index: goffice/graph/gog-renderer-impl.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer-impl.h,v
retrieving revision 1.27
diff -u -p -r1.27 gog-renderer-impl.h
--- goffice/graph/gog-renderer-impl.h 15 Nov 2005 15:56:23 -0000 1.27
+++ goffice/graph/gog-renderer-impl.h 29 Nov 2005 15:24:10 -0000
@@ -81,10 +81,13 @@ typedef struct {
GogViewAllocation const *pos, GtkAnchorType anchor,
GogViewAllocation *result);
void (*draw_marker) (GogRenderer *rend, double x, double y);
-
+
void (*get_text_OBR) (GogRenderer *rend, char const *text, GOGeometryOBR *obr);
-
- double (*line_size) (GogRenderer const *rend, double width);
+
+ double (*line_size) (GogRenderer const *rend, double width);
+
+ gboolean (*export_image) (GogRenderer *renderer, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi);
/* Signals */
void (*request_update) (GogRenderer *renderer);
Index: goffice/graph/gog-renderer-pixbuf.c
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer-pixbuf.c,v
retrieving revision 1.71
diff -u -p -r1.71 gog-renderer-pixbuf.c
--- goffice/graph/gog-renderer-pixbuf.c 25 Sep 2005 20:21:51 -0000 1.71
+++ goffice/graph/gog-renderer-pixbuf.c 29 Nov 2005 15:24:10 -0000
@@ -36,6 +36,7 @@
#include <libart_lgpl/art_render_mask.h>
#include <pango/pangoft2.h>
#include <gsf/gsf-impl-utils.h>
+#include <gsf/gsf-output-stdio.h>
#include <math.h>
@@ -943,6 +944,53 @@ gog_renderer_pixbuf_push_style (GogRende
}
}
+static gboolean
+gcp_gsf_gdk_pixbuf_save (const gchar *buf,
+ gsize count,
+ GError **error,
+ gpointer data)
+{
+ GsfOutput *output = GSF_OUTPUT (data);
+ gboolean ok = gsf_output_write (output, count, buf);
+
+ if (!ok && error)
+ *error = g_error_copy (gsf_output_error (output));
+
+ return ok;
+}
+
+static gboolean
+gog_renderer_pixbuf_export_image (GogRenderer *renderer, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi)
+{
+ GogRendererPixbuf *prend = GOG_RENDERER_PIXBUF (renderer);
+ GdkPixbuf *pixbuf;
+ GOImageFormatInfo const *format_info;
+ double width_in_pts, height_in_pts;
+
+ gog_graph_get_size (renderer->model, &width_in_pts, &height_in_pts);
+
+ switch (format) {
+ case GO_IMAGE_FORMAT_PNG:
+ case GO_IMAGE_FORMAT_JPG:
+ gog_renderer_pixbuf_update (prend,
+ width_in_pts * x_dpi / 72.0,
+ height_in_pts * y_dpi / 72.0, 1.0);
+ pixbuf = gog_renderer_pixbuf_get (prend);
+ if (pixbuf == NULL)
+ return FALSE;
+ format_info = go_image_get_format_info (format);
+ return gdk_pixbuf_save_to_callback (pixbuf,
+ gcp_gsf_gdk_pixbuf_save,
+ output, format_info->name,
+ NULL, NULL);
+ break;
+ default:
+ g_warning ("[GogRendererPixbuf:export_image] unsupported format");
+ return FALSE;
+ }
+}
+
static void
gog_renderer_pixbuf_class_init (GogRendererClass *rend_klass)
{
@@ -963,6 +1011,7 @@ gog_renderer_pixbuf_class_init (GogRende
rend_klass->draw_marker = gog_renderer_pixbuf_draw_marker;
rend_klass->get_text_OBR = gog_renderer_pixbuf_get_text_OBR;
rend_klass->line_size = gog_renderer_pixbuf_line_size;
+ rend_klass->export_image = gog_renderer_pixbuf_export_image;
}
static void
Index: goffice/graph/gog-renderer-svg.c
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer-svg.c,v
retrieving revision 1.32
diff -u -p -r1.32 gog-renderer-svg.c
--- goffice/graph/gog-renderer-svg.c 7 Oct 2005 14:36:42 -0000 1.32
+++ goffice/graph/gog-renderer-svg.c 29 Nov 2005 15:24:10 -0000
@@ -20,7 +20,7 @@
*/
#include <goffice/goffice-config.h>
-#include <goffice/graph/gog-graph-impl.h>
+#include <goffice/graph/gog-graph.h>
#include <goffice/graph/gog-renderer-svg.h>
#include <goffice/graph/gog-renderer-impl.h>
#include <goffice/graph/gog-style.h>
@@ -41,10 +41,6 @@
#define CC2XML(s) ((const xmlChar *)(s))
-#define GOG_RENDERER_SVG_TYPE (gog_renderer_svg_get_type ())
-#define GOG_RENDERER_SVG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_RENDERER_SVG_TYPE, GogRendererSvg))
-#define IS_GOG_RENDERER_SVG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_RENDERER_SVG_TYPE))
-
typedef struct _GogRendererSvg GogRendererSvg;
struct _GogRendererSvg {
@@ -64,8 +60,6 @@ typedef GogRendererClass GogRendererSvgC
static GObjectClass *parent_klass;
-static GType gog_renderer_svg_get_type (void);
-
static void
set_double_prop (xmlNodePtr node, const char *name, double value)
{
@@ -729,54 +723,22 @@ gog_renderer_svg_draw_text (GogRenderer
}
}
-static void
-gog_renderer_svg_class_init (GogRendererClass *rend_klass)
-{
- GObjectClass *gobject_klass = (GObjectClass *) rend_klass;
-
- parent_klass = g_type_class_peek_parent (rend_klass);
- gobject_klass->finalize = gog_renderer_svg_finalize;
- rend_klass->push_clip = gog_renderer_svg_push_clip;
- rend_klass->pop_clip = gog_renderer_svg_pop_clip;
- rend_klass->draw_path = gog_renderer_svg_draw_path;
- rend_klass->draw_polygon = gog_renderer_svg_draw_polygon;
- rend_klass->draw_bezier_path = gog_renderer_svg_draw_bezier_path;
- rend_klass->draw_bezier_polygon = gog_renderer_svg_draw_bezier_polygon;
- rend_klass->draw_text = gog_renderer_svg_draw_text;
- rend_klass->draw_marker = gog_renderer_svg_draw_marker;
- rend_klass->get_text_OBR = gog_renderer_svg_get_text_OBR;
-}
-
-static GSF_CLASS (GogRendererSvg, gog_renderer_svg,
- gog_renderer_svg_class_init, NULL,
- GOG_RENDERER_TYPE)
-
-/**
- * gog_graph_export_to_svg :
- * @graph : #GogGraph
- * @output : #GsfOutput
- * @width :
- * @height :
- *
- * Renders @graph as SVG and stores it in @output.
- *
- * Returns TRUE on success.
- **/
-gboolean
-gog_graph_export_to_svg (GogGraph *graph, GsfOutput *output,
- double width, double height, double scale)
+static gboolean
+gog_renderer_svg_export_image (GogRenderer *renderer, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi)
{
GogViewAllocation allocation;
- GogRendererSvg *prend;
+ GogRendererSvg *prend = GOG_RENDERER_SVG (renderer);
xmlNsPtr namespace;
+ double width_in_pts, height_in_pts;
gboolean success = TRUE;
- gog_graph_force_update (graph);
+ if (format != GO_IMAGE_FORMAT_SVG) {
+ g_warning ("[GogRendererSVG::export_image] Unsupported format");
+ return FALSE;
+ }
- prend = g_object_new (GOG_RENDERER_SVG_TYPE,
- "model", graph,
- NULL);
- prend->base.scale = scale;
+ prend->base.scale = 1.0;
prend->doc = xmlNewDoc (CC2XML ("1.0"));
xmlNewDtd (prend->doc,
@@ -795,14 +757,15 @@ gog_graph_export_to_svg (GogGraph *graph
namespace = xmlNewNs (prend->doc->children, CC2XML ("http://www.w3.org/1999/xlink"), CC2XML ("xlink"));
- set_double_prop (prend->doc->children, "width", width);
- set_double_prop (prend->doc->children, "height", height);
+ gog_graph_get_size (renderer->model, &width_in_pts, &height_in_pts);
+ set_double_prop (prend->doc->children, "width", width_in_pts);
+ set_double_prop (prend->doc->children, "height", height_in_pts);
prend->clip_counter = 0;
allocation.x = 0.;
allocation.y = 0.;
- allocation.w = width;
- allocation.h = height;
+ allocation.w = width_in_pts;
+ allocation.h = height_in_pts;
gog_view_size_allocate (prend->base.view, &allocation);
gog_view_render (prend->base.view, NULL);
@@ -816,8 +779,33 @@ gog_graph_export_to_svg (GogGraph *graph
success = FALSE;
xmlFreeDoc (prend->doc);
+ prend->doc = NULL;
g_hash_table_destroy (prend->table);
- g_object_unref (prend);
+ prend->table = NULL;
return success;
}
+
+static void
+gog_renderer_svg_class_init (GogRendererClass *rend_klass)
+{
+ GObjectClass *gobject_klass = (GObjectClass *) rend_klass;
+
+ parent_klass = g_type_class_peek_parent (rend_klass);
+ gobject_klass->finalize = gog_renderer_svg_finalize;
+ rend_klass->push_clip = gog_renderer_svg_push_clip;
+ rend_klass->pop_clip = gog_renderer_svg_pop_clip;
+ rend_klass->draw_path = gog_renderer_svg_draw_path;
+ rend_klass->draw_polygon = gog_renderer_svg_draw_polygon;
+ rend_klass->draw_bezier_path = gog_renderer_svg_draw_bezier_path;
+ rend_klass->draw_bezier_polygon = gog_renderer_svg_draw_bezier_polygon;
+ rend_klass->draw_text = gog_renderer_svg_draw_text;
+ rend_klass->draw_marker = gog_renderer_svg_draw_marker;
+ rend_klass->get_text_OBR = gog_renderer_svg_get_text_OBR;
+ rend_klass->export_image = gog_renderer_svg_export_image;
+}
+
+GSF_CLASS (GogRendererSvg, gog_renderer_svg,
+ gog_renderer_svg_class_init, NULL,
+ GOG_RENDERER_TYPE)
+
Index: goffice/graph/gog-renderer-svg.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer-svg.h,v
retrieving revision 1.4
diff -u -p -r1.4 gog-renderer-svg.h
--- goffice/graph/gog-renderer-svg.h 8 Aug 2005 08:56:59 -0000 1.4
+++ goffice/graph/gog-renderer-svg.h 29 Nov 2005 15:24:10 -0000
@@ -22,13 +22,18 @@
#define GOG_RENDERER_SVG_H
#include <goffice/graph/goffice-graph.h>
+
#include <gsf/gsf.h>
+#include <glib-object.h>
+
G_BEGIN_DECLS
-gboolean gog_graph_export_to_svg (GogGraph *graph,
- GsfOutput *output,
- double width, double height, double scale);
+#define GOG_RENDERER_SVG_TYPE (gog_renderer_svg_get_type ())
+#define GOG_RENDERER_SVG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOG_RENDERER_SVG_TYPE, GogRendererSvg))
+#define IS_GOG_RENDERER_SVG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOG_RENDERER_SVG_TYPE))
+
+GType gog_renderer_svg_get_type (void);
G_END_DECLS
Index: goffice/graph/gog-renderer.c
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer.c,v
retrieving revision 1.43
diff -u -p -r1.43 gog-renderer.c
--- goffice/graph/gog-renderer.c 18 Nov 2005 15:50:56 -0000 1.43
+++ goffice/graph/gog-renderer.c 29 Nov 2005 15:24:10 -0000
@@ -23,13 +23,16 @@
#include <goffice/graph/gog-renderer-impl.h>
#include <goffice/graph/gog-renderer-pixbuf.h>
#include <goffice/graph/gog-renderer-cairo.h>
+#include <goffice/graph/gog-renderer-svg.h>
#include <goffice/graph/gog-style.h>
#include <goffice/graph/gog-graph.h>
+#include <goffice/graph/gog-graph-impl.h>
#include <goffice/graph/gog-view.h>
#include <goffice/utils/go-units.h>
#include <goffice/utils/go-font.h>
#include <goffice/utils/go-math.h>
+#include <gsf/gsf.h>
#include <gsf/gsf-impl-utils.h>
/* We need to define an hair line width for the svg and gnome_print renderer.
@@ -671,6 +674,7 @@ gog_renderer_class_init (GogRendererClas
renderer_klass->sharp_path = NULL;
renderer_klass->line_size = NULL;
+ renderer_klass->export_image = NULL;
g_object_class_install_property (gobject_klass, RENDERER_PROP_MODEL,
g_param_spec_object ("model", "model",
@@ -895,4 +899,63 @@ gog_renderer_get_pixbuf (GogRenderer *re
g_return_val_if_fail (IS_GOG_RENDERER_PIXBUF (renderer), NULL);
return gog_renderer_pixbuf_get (GOG_RENDERER_PIXBUF (renderer));
#endif
+}
+
+GogRenderer *
+gog_renderer_new_for_format (GogGraph *graph, GOImageFormat format)
+{
+ GType type = G_TYPE_INVALID;
+
+ switch (format) {
+ case GO_IMAGE_FORMAT_PNG:
+ case GO_IMAGE_FORMAT_JPG:
+#ifdef WITH_CAIRO
+ type = GOG_RENDERER_CAIRO_TYPE;
+#else
+ type = GOG_RENDERER_PIXBUF_TYPE;
+#endif
+ break;
+ case GO_IMAGE_FORMAT_SVG:
+ type = GOG_RENDERER_SVG_TYPE;
+ break;
+ case GO_IMAGE_FORMAT_PDF:
+#ifdef CAIRO_HAS_PDF_SURFACE
+ type = GOG_RENDERER_CAIRO_TYPE;
+#else
+#warning MISSING PDF SUPPORT
+#endif
+ break;
+ case GO_IMAGE_FORMAT_PS:
+#ifdef CAIRO_HAS_PS_SURFACE
+ type = GOG_RENDERER_CAIRO_TYPE;
+#else
+#warning MISSING PS SUPPORT
+#endif
+ break;
+ default:
+ break;
+ }
+
+ if (type == G_TYPE_INVALID)
+ return NULL;
+
+ return g_object_new (type, "model", graph, NULL);
+}
+
+gboolean
+gog_renderer_export_image (GogRenderer *renderer, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi)
+{
+ GogRendererClass *klass;
+
+ g_return_val_if_fail (IS_GOG_RENDERER (renderer), FALSE);
+
+ gog_graph_force_update (renderer->model);
+
+ klass = GOG_RENDERER_GET_CLASS (renderer);
+
+ if (klass->export_image != NULL)
+ return (klass->export_image) (renderer, format, output, x_dpi, y_dpi);
+
+ return FALSE;
}
Index: goffice/graph/gog-renderer.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/graph/gog-renderer.h,v
retrieving revision 1.26
diff -u -p -r1.26 gog-renderer.h
--- goffice/graph/gog-renderer.h 18 Nov 2005 15:50:56 -0000 1.26
+++ goffice/graph/gog-renderer.h 29 Nov 2005 15:24:10 -0000
@@ -23,6 +23,10 @@
#include <goffice/graph/goffice-graph.h>
#include <goffice/utils/go-geometry.h>
+#include <goffice/gtk/goffice-gtk.h>
+
+#include <gsf/gsf.h>
+
#include <gtk/gtkenums.h>
#include <libart_lgpl/libart.h>
#include <gdk/gdk.h>
@@ -95,6 +99,10 @@ double gog_renderer_pt2r (GogRende
GogRenderer *gog_renderer_new_for_pixbuf (GogGraph *graph);
gboolean gog_renderer_update (GogRenderer *renderer, double w, double h, double zoom);
GdkPixbuf *gog_renderer_get_pixbuf (GogRenderer *renderer);
+
+GogRenderer *gog_renderer_new_for_format (GogGraph *graph, GOImageFormat format);
+gboolean gog_renderer_export_image (GogRenderer *renderer, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi);
G_END_DECLS
Index: goffice/gtk/goffice-gtk.c
===================================================================
RCS file: /cvs/gnome/goffice/goffice/gtk/goffice-gtk.c,v
retrieving revision 1.24
diff -u -p -r1.24 goffice-gtk.c
--- goffice/gtk/goffice-gtk.c 7 Oct 2005 16:15:01 -0000 1.24
+++ goffice/gtk/goffice-gtk.c 29 Nov 2005 15:24:10 -0000
@@ -554,10 +554,11 @@ go_gtk_select_image (GtkWindow *toplevel
}
char *
-gui_get_image_save_info (GtkWindow *toplevel, GSList *formats,
- GOImageType const **ret_format)
+gui_get_image_save_info (GtkWindow *toplevel, GSList *supported_formats,
+ GOImageFormat *ret_format)
{
- GOImageType const *sel_format = NULL;
+ GOImageFormat format;
+ GOImageFormatInfo const *format_info;
GtkComboBox *format_combo = NULL;
char *uri = NULL;
GtkFileChooser *fsel = gui_image_chooser_new (TRUE);
@@ -565,21 +566,18 @@ gui_get_image_save_info (GtkWindow *topl
g_object_set (G_OBJECT (fsel), "title", _("Save as"), NULL);
/* Make format chooser */
- if (formats && ret_format) {
+ if (supported_formats && ret_format) {
GtkWidget *label;
GtkWidget *box = gtk_hbox_new (FALSE, 5);
GSList *l;
int i;
format_combo = GTK_COMBO_BOX (gtk_combo_box_new_text ());
- if (*ret_format)
- sel_format = *ret_format;
- for (l = formats, i = 0; l != NULL; l = l->next, i++) {
-#warning we must find a better solution for translating strings not in goffice domain
- gtk_combo_box_append_text
- (format_combo,
- gettext (((GOImageType *) (l->data))->desc));
- if (l->data == (void *)sel_format)
+ for (l = supported_formats, i = 0; l != NULL; l = l->next, i++) {
+ format = GPOINTER_TO_UINT (l->data);
+ format_info = go_image_get_format_info (format);
+ gtk_combo_box_append_text (format_combo, _(format_info->desc));
+ if (format == *ret_format)
gtk_combo_box_set_active (format_combo, i);
}
if (gtk_combo_box_get_active (format_combo) < 0)
@@ -602,9 +600,11 @@ gui_get_image_save_info (GtkWindow *topl
if (format_combo) {
char *new_uri = NULL;
- sel_format = g_slist_nth_data (
- formats, gtk_combo_box_get_active (format_combo));
- if (!go_url_check_extension (uri, sel_format->ext, &new_uri) &&
+ format = GPOINTER_TO_UINT (g_slist_nth_data
+ (supported_formats,
+ gtk_combo_box_get_active (format_combo)));
+ format_info = go_image_get_format_info (format);
+ if (!go_url_check_extension (uri, format_info->ext, &new_uri) &&
!go_gtk_query_yes_no (GTK_WINDOW (fsel), TRUE,
_("The given file extension does not match the"
" chosen file type. Do you want to use this name"
@@ -617,7 +617,7 @@ gui_get_image_save_info (GtkWindow *topl
g_free (uri);
uri = new_uri;
}
- *ret_format = sel_format;
+ *ret_format = format;
}
if (!go_gtk_url_is_writeable (GTK_WINDOW (fsel), uri, TRUE)) {
g_free (uri);
@@ -691,6 +691,124 @@ go_image_format_to_mime (char const *for
g_slist_free (pixbuf_fmts);
return ret;
+}
+
+static GOImageFormatInfo const image_format_infos[GO_IMAGE_FORMAT_UNKNOWN] = {
+ {GO_IMAGE_FORMAT_SVG, (char *) "svg", (char *) N_("SVG (vector graphics)"),
+ (char *) "svg", FALSE, FALSE},
+ {GO_IMAGE_FORMAT_PNG, (char *) "png", (char *) N_("PNG (raster graphics)"),
+ (char *) "png", TRUE, TRUE},
+ {GO_IMAGE_FORMAT_JPG, (char *) "jpeg", (char *) N_("JPEG (photograph)"),
+ (char *) "jpg", TRUE, TRUE},
+ {GO_IMAGE_FORMAT_PDF, (char *) "pdf", (char *) N_("PDF (portable document format)"),
+ (char *) "pdf", FALSE, TRUE},
+ {GO_IMAGE_FORMAT_PS, (char *) "ps", (char *) N_("PS (postscript)"),
+ (char *) "ps", FALSE, TRUE},
+ {GO_IMAGE_FORMAT_EMF, (char *) "emf", (char *) N_("EMF (extended metafile)"),
+ (char *) "emf", FALSE, FALSE},
+ {GO_IMAGE_FORMAT_WMF, (char *) "wmf", (char *) N_("WMF (windows metafile)"),
+ (char *) "wmf", FALSE, FALSE}
+};
+
+static GOImageFormatInfo *pixbuf_image_format_infos = NULL;
+static unsigned pixbuf_format_nbr = 0;
+
+#define PIXBUF_IMAGE_FORMAT_OFFSET (1+GO_IMAGE_FORMAT_UNKNOWN)
+
+static void
+go_image_build_pixbuf_format_infos (void)
+{
+ GdkPixbufFormat *fmt;
+ GSList *l, *pixbuf_fmts;
+ GOImageFormatInfo *format_info;
+ gchar **exts;
+ unsigned i;
+
+ if (pixbuf_format_nbr > 0)
+ return;
+
+ pixbuf_fmts = gdk_pixbuf_get_formats ();
+ pixbuf_format_nbr = g_slist_length (pixbuf_fmts);
+ if (pixbuf_format_nbr == 0)
+ goto out;
+ pixbuf_image_format_infos = g_new (GOImageFormatInfo, pixbuf_format_nbr);
+
+ for (l = pixbuf_fmts, i = 1, format_info = pixbuf_image_format_infos;
+ l != NULL;
+ l = l->next, i++, format_info++) {
+ fmt = (GdkPixbufFormat *)l->data;
+
+ format_info->format = GO_IMAGE_FORMAT_UNKNOWN + i;
+ format_info->name = gdk_pixbuf_format_get_name (fmt);
+ format_info->desc = g_ascii_strup (format_info->name, -1);
+ exts = gdk_pixbuf_format_get_extensions (fmt);
+ format_info->ext = g_strdup (exts[0]);
+ if (format_info->ext == NULL)
+ format_info->ext = format_info->name;
+ g_strfreev (exts);
+ format_info->has_pixbuf_saver = gdk_pixbuf_format_is_writable (fmt);
+ format_info->is_dpi_useful = FALSE;
+ }
+
+out:
+ g_slist_free (pixbuf_fmts);
+}
+
+GOImageFormatInfo const *
+go_image_get_format_info (GOImageFormat format)
+{
+ if (format > GO_IMAGE_FORMAT_UNKNOWN)
+ go_image_build_pixbuf_format_infos ();
+
+ g_return_val_if_fail (format >= 0 &&
+ format != GO_IMAGE_FORMAT_UNKNOWN &&
+ format <= GO_IMAGE_FORMAT_UNKNOWN + pixbuf_format_nbr, NULL);
+ if (format < GO_IMAGE_FORMAT_UNKNOWN)
+ return &image_format_infos[format];
+
+ return &pixbuf_image_format_infos[format - PIXBUF_IMAGE_FORMAT_OFFSET];
+}
+
+GOImageFormat
+go_image_get_format_from_name (char const *name)
+{
+ unsigned i;
+
+ go_image_build_pixbuf_format_infos ();
+
+ for (i = 0; i < GO_IMAGE_FORMAT_UNKNOWN; i++) {
+ if (strcmp (name, image_format_infos[i].name) == 0)
+ return image_format_infos[i].format;
+ }
+
+ for (i = 0; i < pixbuf_format_nbr; i++) {
+ if (strcmp (name, pixbuf_image_format_infos[i].name) == 0)
+ return pixbuf_image_format_infos[i].format;
+ }
+
+ g_warning ("[GOImage::get_format_from_name] Unknown format name (%s)", name);
+ return GO_IMAGE_FORMAT_UNKNOWN;
+}
+
+GSList *
+go_image_get_formats_with_pixbuf_saver (void)
+{
+ GSList *list = NULL;
+ unsigned i;
+
+ for (i = 0; i < GO_IMAGE_FORMAT_UNKNOWN; i++)
+ if (image_format_infos[i].has_pixbuf_saver)
+ list = g_slist_prepend (list, GUINT_TO_POINTER (i));
+#if 0
+ /* TODO: before enabling this code, we must remove duplicate in pixbuf_image_format_infos */
+ go_image_build_pixbuf_format_infos ();
+
+ for (i = 0; i < pixbuf_format_nbr; i++) {
+ if (pixbuf_image_format_infos[i].has_pixbuf_saver)
+ list = g_slist_prepend (list, GUINT_TO_POINTER (i + PIXBUF_IMAGE_FORMAT_OFFSET));
+ }
+#endif
+ return list;
}
static void
Index: goffice/gtk/goffice-gtk.h
===================================================================
RCS file: /cvs/gnome/goffice/goffice/gtk/goffice-gtk.h,v
retrieving revision 1.8
diff -u -p -r1.8 goffice-gtk.h
--- goffice/gtk/goffice-gtk.h 8 Aug 2005 08:57:01 -0000 1.8
+++ goffice/gtk/goffice-gtk.h 29 Nov 2005 15:24:10 -0000
@@ -26,12 +26,25 @@
G_BEGIN_DECLS
+typedef enum {
+ GO_IMAGE_FORMAT_SVG,
+ GO_IMAGE_FORMAT_PNG,
+ GO_IMAGE_FORMAT_JPG,
+ GO_IMAGE_FORMAT_PDF,
+ GO_IMAGE_FORMAT_PS,
+ GO_IMAGE_FORMAT_EMF,
+ GO_IMAGE_FORMAT_WMF,
+ GO_IMAGE_FORMAT_UNKNOWN
+} GOImageFormat;
+
typedef struct {
+ GOImageFormat format;
char *name;
char *desc;
char *ext;
gboolean has_pixbuf_saver;
-} GOImageType;
+ gboolean is_dpi_useful;
+} GOImageFormatInfo;
void go_editable_enters (GtkWindow *window, GtkWidget *w);
@@ -65,10 +78,15 @@ void go_gtk_help_button_init (GtkWidg
void go_gtk_nonmodal_dialog (GtkWindow *toplevel, GtkWindow *dialog);
gboolean go_gtk_file_sel_dialog (GtkWindow *toplevel, GtkWidget *w);
char *go_gtk_select_image (GtkWindow *toplevel, const char *initial);
-char *gui_get_image_save_info (GtkWindow *toplevel, GSList *formats,
- GOImageType const **ret_format);
-char *go_mime_to_image_format (char const *mime_type);
-char *go_image_format_to_mime (char const *format);
+char *gui_get_image_save_info (GtkWindow *toplevel, GSList *supported_formats,
+ GOImageFormat *ret_format);
+char *go_mime_to_image_format (char const *mime_type);
+char *go_image_format_to_mime (char const *format);
+
+GOImageFormatInfo const *go_image_get_format_info (GOImageFormat format);
+GOImageFormat go_image_get_format_from_name (char const *name);
+GSList *go_image_get_formats_with_pixbuf_saver (void);
+
gboolean go_gtk_url_is_writeable (GtkWindow *parent, char const *url,
gboolean overwrite_by_default);
_______________________________________________
gnumeric-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gnumeric-list