cairo-boilerplate-svg.c [plain text]
#include "cairo-boilerplate.h"
#include "cairo-boilerplate-svg-private.h"
#include <cairo-svg.h>
#include <cairo-svg-surface-private.h>
#include <cairo-paginated-surface-private.h>
#if HAVE_SIGNAL_H
#include <stdlib.h>
#include <signal.h>
#endif
static const cairo_user_data_key_t svg_closure_key;
typedef struct _svg_target_closure {
char *filename;
int width, height;
cairo_surface_t *target;
} svg_target_closure_t;
static cairo_surface_t *
_cairo_boilerplate_svg_create_surface (const char *name,
cairo_content_t content,
cairo_svg_version_t version,
int width,
int height,
int max_width,
int max_height,
cairo_boilerplate_mode_t mode,
int id,
void **closure)
{
svg_target_closure_t *ptc;
cairo_surface_t *surface;
cairo_status_t status;
*closure = ptc = xmalloc (sizeof (svg_target_closure_t));
ptc->width = width;
ptc->height = height;
xasprintf (&ptc->filename, "%s-out.svg", name);
xunlink (ptc->filename);
surface = cairo_svg_surface_create (ptc->filename, width, height);
if (cairo_surface_status (surface))
goto CLEANUP_FILENAME;
cairo_svg_surface_restrict_to_version (surface, version);
cairo_surface_set_fallback_resolution (surface, 72., 72.);
if (content == CAIRO_CONTENT_COLOR) {
ptc->target = surface;
surface = cairo_surface_create_similar (ptc->target,
CAIRO_CONTENT_COLOR,
width, height);
if (cairo_surface_status (surface))
goto CLEANUP_TARGET;
} else
ptc->target = NULL;
status = cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
if (status == CAIRO_STATUS_SUCCESS)
return surface;
cairo_surface_destroy (surface);
surface = cairo_boilerplate_surface_create_in_error (status);
CLEANUP_TARGET:
cairo_surface_destroy (ptc->target);
CLEANUP_FILENAME:
free (ptc->filename);
free (ptc);
return surface;
}
cairo_surface_t *
_cairo_boilerplate_svg11_create_surface (const char *name,
cairo_content_t content,
int width,
int height,
int max_width,
int max_height,
cairo_boilerplate_mode_t mode,
int id,
void **closure)
{
return _cairo_boilerplate_svg_create_surface (name, content,
CAIRO_SVG_VERSION_1_1,
width, height,
max_width, max_height,
mode, id,
closure);
}
cairo_surface_t *
_cairo_boilerplate_svg12_create_surface (const char *name,
cairo_content_t content,
int width,
int height,
int max_width,
int max_height,
cairo_boilerplate_mode_t mode,
int id,
void **closure)
{
return _cairo_boilerplate_svg_create_surface (name, content,
CAIRO_SVG_VERSION_1_2,
width, height,
max_width, max_height,
mode, id,
closure);
}
cairo_status_t
_cairo_boilerplate_svg_finish_surface (cairo_surface_t *surface)
{
svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
&svg_closure_key);
cairo_status_t status;
cairo_surface_set_device_offset (surface, 0, 0);
if (ptc->target) {
cairo_t *cr;
cr = cairo_create (ptc->target);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
cairo_show_page (cr);
status = cairo_status (cr);
cairo_destroy (cr);
if (status)
return status;
cairo_surface_finish (surface);
status = cairo_surface_status (surface);
if (status)
return status;
surface = ptc->target;
}
cairo_surface_finish (surface);
status = cairo_surface_status (surface);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_boilerplate_svg_surface_write_to_png (cairo_surface_t *surface, const char *filename)
{
svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
&svg_closure_key);
char command[4096];
int exitstatus;
sprintf (command, "./svg2png %s %s",
ptc->filename, filename);
exitstatus = system (command);
#if _XOPEN_SOURCE && HAVE_SIGNAL_H
if (WIFSIGNALED (exitstatus))
raise (WTERMSIG (exitstatus));
#endif
if (exitstatus)
return CAIRO_STATUS_WRITE_ERROR;
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_boilerplate_svg_convert_to_image (cairo_surface_t *surface)
{
svg_target_closure_t *ptc = cairo_surface_get_user_data (surface,
&svg_closure_key);
return cairo_boilerplate_convert_to_image (ptc->filename, 0);
}
cairo_surface_t *
_cairo_boilerplate_svg_get_image_surface (cairo_surface_t *surface,
int page,
int width,
int height)
{
cairo_surface_t *image;
if (page != 0)
return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
image = _cairo_boilerplate_svg_convert_to_image (surface);
cairo_surface_set_device_offset (image,
cairo_image_surface_get_width (image) - width,
cairo_image_surface_get_height (image) - height);
surface = _cairo_boilerplate_get_image_surface (image, 0, width, height);
cairo_surface_destroy (image);
return surface;
}
void
_cairo_boilerplate_svg_cleanup (void *closure)
{
svg_target_closure_t *ptc = closure;
if (ptc->target)
cairo_surface_destroy (ptc->target);
free (ptc->filename);
free (ptc);
}
void
_cairo_boilerplate_svg_force_fallbacks (cairo_surface_t *abstract_surface,
unsigned int flags)
{
svg_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
&svg_closure_key);
cairo_paginated_surface_t *paginated;
cairo_svg_surface_t *surface;
if (ptc->target)
abstract_surface = ptc->target;
paginated = (cairo_paginated_surface_t*) abstract_surface;
surface = (cairo_svg_surface_t*) paginated->target;
surface->force_fallbacks = TRUE;
}