From a3e3ba07b6da4bacb85ae6874cab10286d239903 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 15 Mar 2009 14:31:28 -0400 Subject: [pango-view] Add ability to save to PS, EPS, PDF, and SVG --- pango-view/viewer-cairo.c | 192 ++++++++++++++++++++++++++++++++++++++--- pango-view/viewer-cairo.h | 2 +- pango-view/viewer-pangocairo.c | 3 +- 3 files changed, 183 insertions(+), 14 deletions(-) diff --git a/pango-view/viewer-cairo.c b/pango-view/viewer-cairo.c index 0f3cd5ca..f50ddb57 100644 --- a/pango-view/viewer-cairo.c +++ b/pango-view/viewer-cairo.c @@ -25,6 +25,8 @@ #include +#include + #ifdef HAVE_CAIRO_XLIB @@ -53,6 +55,18 @@ static CairoViewerIface cairo_x_viewer_iface = { + +static cairo_surface_t * +cairo_view_iface_create_surface (gpointer instance, + gpointer surface, + int width, + int height) +{ + return cairo_surface_reference (surface); +} + + + static gpointer cairo_image_view_create (const PangoViewer *klass G_GNUC_UNUSED) { @@ -96,27 +110,183 @@ const PangoViewer cairo_image_viewer = { NULL }; +static CairoViewerIface cairo_image_viewer_iface = { + &cairo_image_viewer, + cairo_view_iface_create_surface +}; + + + + +#ifdef CAIRO_HAS_SVG_SURFACE +# include +#endif +#ifdef CAIRO_HAS_PDF_SURFACE +# include +#endif +#ifdef CAIRO_HAS_PS_SURFACE +# include +# if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0) +# define HAS_EPS 1 + static cairo_surface_t * -cairo_image_view_iface_create_surface (gpointer instance, - gpointer surface, - int width, - int height) +_cairo_eps_surface_create (const char *filename, + double width, + double height) { + cairo_surface_t *surface; + + surface = cairo_ps_surface_create (filename, width, height); + cairo_ps_surface_set_eps (surface, TRUE); + return surface; } -static CairoViewerIface cairo_image_viewer_iface = { - &cairo_image_viewer, - cairo_image_view_iface_create_surface +# else +# undef HAS_EPS +# endif +#endif + +typedef cairo_surface_t *(*CairoVectorFileCreateFunc) (const char *filename, + double width, + double height); + +typedef struct +{ + const char *filename; + CairoVectorFileCreateFunc constructor; +} CairoVectorViewer; + +static gpointer +cairo_vector_view_create (const PangoViewer *klass G_GNUC_UNUSED) +{ + const char *extension = NULL; + CairoVectorFileCreateFunc constructor = NULL; + + if (opt_output) + { + extension = strrchr (opt_output, '.'); + if (extension) + extension++; /* skip the dot */ + } + + if (!extension) + return NULL; + + if (0) + ; + #ifdef CAIRO_HAS_SVG_SURFACE + else if (0 == strcasecmp (extension, "svg")) + constructor = cairo_svg_surface_create; + #endif + #ifdef CAIRO_HAS_PDF_SURFACE + else if (0 == strcasecmp (extension, "pdf")) + constructor = cairo_pdf_surface_create; + #endif + #ifdef CAIRO_HAS_PS_SURFACE + else if (0 == strcasecmp (extension, "ps")) + constructor = cairo_ps_surface_create; + #ifdef HAS_EPS + else if (0 == strcasecmp (extension, "eps")) + constructor = _cairo_eps_surface_create; + #endif + #endif + + if (constructor) + { + CairoVectorViewer *instance; + + instance = g_slice_new (CairoVectorViewer); + + /* save output filename and unset it such that the viewer layer + * doesn't try to save to file. + */ + instance->filename = opt_output; + opt_output = NULL; + + instance->constructor = constructor; + + /* Fix dpi on 72. That's what cairo vector surfaces are. */ + opt_dpi = 72; + + return instance; + } + + return NULL; +} + +static void +cairo_vector_view_destroy (gpointer instance G_GNUC_UNUSED) +{ + CairoVectorViewer *c = (CairoVectorViewer *) instance; + + g_slice_free (CairoVectorViewer, c); +} + +static gpointer +cairo_vector_view_create_surface (gpointer instance, + int width, + int height) +{ + CairoVectorViewer *c = (CairoVectorViewer *) instance; + cairo_surface_t *surface; + + surface = c->constructor (c->filename, width, height); + + /*cairo_surface_set_fallback_resolution (surface, fallback_resolution_x, fallback_resolution_y);*/ + + return surface; +} + +static void +cairo_vector_view_destroy_surface (gpointer instance, + gpointer surface) +{ + /* TODO: check for errors */ + cairo_surface_destroy (surface); +} + +const PangoViewer cairo_vector_viewer = { + "CairoFile", + NULL, + NULL, + cairo_vector_view_create, + cairo_vector_view_destroy, + NULL, + cairo_vector_view_create_surface, + cairo_vector_view_destroy_surface, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static CairoViewerIface cairo_vector_viewer_iface = { + &cairo_vector_viewer, + cairo_view_iface_create_surface }; -const CairoViewerIface * -get_cairo_viewer_iface (void) + + +gpointer +cairo_viewer_iface_create (const CairoViewerIface **iface) { + gpointer ret; + + *iface = &cairo_vector_viewer_iface; + ret = (*iface)->backend_class->create ((*iface)->backend_class); + if (ret) + return ret; + #ifdef HAVE_CAIRO_XLIB if (opt_display) - return &cairo_x_viewer_iface; + { + *iface = &cairo_x_viewer_iface; + return (*iface)->backend_class->create ((*iface)->backend_class); + } #endif /* HAVE_CAIRO_XLIB */ - return &cairo_image_viewer_iface; + *iface = &cairo_image_viewer_iface; + return (*iface)->backend_class->create ((*iface)->backend_class); } diff --git a/pango-view/viewer-cairo.h b/pango-view/viewer-cairo.h index 7e6d9ae3..ecd06760 100644 --- a/pango-view/viewer-cairo.h +++ b/pango-view/viewer-cairo.h @@ -37,6 +37,6 @@ struct _CairoViewerIface int height); }; -const CairoViewerIface *get_cairo_viewer_iface (void); +gpointer cairo_viewer_iface_create (const CairoViewerIface **iface_out); #endif /* VIEWER_CAIRO_H */ diff --git a/pango-view/viewer-pangocairo.c b/pango-view/viewer-pangocairo.c index f8145f7c..a4770741 100644 --- a/pango-view/viewer-pangocairo.c +++ b/pango-view/viewer-pangocairo.c @@ -43,8 +43,7 @@ pangocairo_view_create (const PangoViewer *klass G_GNUC_UNUSED) instance = g_slice_new (CairoViewer); - instance->iface = get_cairo_viewer_iface (); - instance->backend = instance->iface->backend_class->create (instance->iface->backend_class); + instance->backend = cairo_viewer_iface_create (&instance->iface); instance->fontmap = pango_cairo_font_map_new (); pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (instance->fontmap), opt_dpi); -- cgit v1.2.1