cairo-boilerplate-pdf.c [plain text]
#include "cairo-boilerplate.h"
#include "cairo-boilerplate-pdf-private.h"
#include <cairo-pdf.h>
#include <cairo-pdf-surface-private.h>
#include <cairo-paginated-surface-private.h>
#if HAVE_SIGNAL_H
#include <stdlib.h>
#include <signal.h>
#endif
cairo_user_data_key_t pdf_closure_key;
typedef struct _pdf_target_closure
{
char *filename;
int width;
int height;
cairo_surface_t *target;
} pdf_target_closure_t;
#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
cairo_surface_t *
_cairo_boilerplate_pdf_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)
{
pdf_target_closure_t *ptc;
cairo_surface_t *surface;
cairo_status_t status;
if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
content = CAIRO_CONTENT_COLOR_ALPHA;
*closure = ptc = xmalloc (sizeof (pdf_target_closure_t));
ptc->width = width;
ptc->height = height;
xasprintf (&ptc->filename, "%s-out.pdf", name);
xunlink (ptc->filename);
surface = cairo_pdf_surface_create (ptc->filename, width, height);
if (cairo_surface_status (surface))
goto CLEANUP_FILENAME;
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, &pdf_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_status_t
_cairo_boilerplate_pdf_finish_surface (cairo_surface_t *surface)
{
pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface,
&pdf_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_pdf_surface_write_to_png (cairo_surface_t *surface, const char *filename)
{
pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface, &pdf_closure_key);
char command[4096];
int exitstatus;
sprintf (command, "./pdf2png %s %s 1",
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_pdf_convert_to_image (cairo_surface_t *surface, int page)
{
pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface,
&pdf_closure_key);
return cairo_boilerplate_convert_to_image (ptc->filename, page+1);
}
cairo_surface_t *
_cairo_boilerplate_pdf_get_image_surface (cairo_surface_t *surface,
int page,
int width,
int height)
{
cairo_surface_t *image;
image = _cairo_boilerplate_pdf_convert_to_image (surface, page);
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_pdf_cleanup (void *closure)
{
pdf_target_closure_t *ptc = closure;
if (ptc->target)
cairo_surface_destroy (ptc->target);
free (ptc->filename);
free (ptc);
}
void
_cairo_boilerplate_pdf_force_fallbacks (cairo_surface_t *abstract_surface,
unsigned int flags)
{
pdf_target_closure_t *ptc = cairo_surface_get_user_data (abstract_surface,
&pdf_closure_key);
cairo_paginated_surface_t *paginated;
cairo_pdf_surface_t *surface;
if (ptc->target)
abstract_surface = ptc->target;
paginated = (cairo_paginated_surface_t*) abstract_surface;
surface = (cairo_pdf_surface_t*) paginated->target;
surface->force_fallbacks = TRUE;
}