? 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 #include #include +#include #include #include #include @@ -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 #include - #include +#include + +#include #include @@ -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 #include #include + #include +#include -#include +#include +#include +#include #include @@ -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 + +#include + #include #include @@ -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 #include #include +#include #include @@ -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 -#include +#include #include #include #include @@ -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 + #include +#include + 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 #include #include +#include #include #include +#include #include #include #include #include +#include #include /* 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 #include +#include + +#include + #include #include #include @@ -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);