diff options
Diffstat (limited to 'test/any2ppm.c')
-rw-r--r-- | test/any2ppm.c | 894 |
1 files changed, 0 insertions, 894 deletions
diff --git a/test/any2ppm.c b/test/any2ppm.c deleted file mode 100644 index b60b4d959..000000000 --- a/test/any2ppm.c +++ /dev/null @@ -1,894 +0,0 @@ -/* - * Copyright © 2008 Chris Wilson - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Chris Wilson not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Chris Wilson makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Chris Wilson <chris@chris-wilson.co.uk> - * - * Contributor(s): - * Carlos Garcia Campos <carlosgc@gnome.org> - * - * Adapted from pdf2png.c: - * Copyright © 2005 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Red Hat, Inc. not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Red Hat, Inc. makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Kristian Høgsberg <krh@redhat.com> - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#if HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <cairo.h> -#include <cairo-script-interpreter.h> - -#if CAIRO_CAN_TEST_PDF_SURFACE -#include <poppler.h> -#endif - -#if CAIRO_CAN_TEST_SVG_SURFACE -#include <librsvg/rsvg.h> -#ifndef RSVG_CAIRO_H -#include <librsvg/rsvg-cairo.h> -#endif -#endif - -#if CAIRO_HAS_SPECTRE -#include <libspectre/spectre.h> -#endif - -#include <errno.h> - -#if HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#if HAVE_UNISTD_H && HAVE_SIGNAL_H && HAVE_SYS_STAT_H && HAVE_SYS_SOCKET_H && HAVE_SYS_POLL_H && HAVE_SYS_UN_H -#include <signal.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/poll.h> -#include <sys/un.h> - -#define SOCKET_PATH "./.any2ppm" -#define TIMEOUT 60000 /* 60 seconds */ - -#if HAVE_FORK -#define CAN_RUN_AS_DAEMON 1 -#endif -#endif - -#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0]))) - -static int -_cairo_writen (int fd, char *buf, int len) -{ - while (len) { - int ret; - - ret = write (fd, buf, len); - if (ret == -1) { - int err = errno; - switch (err) { - case EINTR: - case EAGAIN: - continue; - default: - return 0; - } - } - len -= ret; - buf += ret; - } - - return 1; -} - -static int -_cairo_write (int fd, - char *buf, int maxlen, int buflen, - const unsigned char *src, int srclen) -{ - if (buflen < 0) - return buflen; - - while (srclen) { - int len; - - len = buflen + srclen; - if (len > maxlen) - len = maxlen; - len -= buflen; - - memcpy (buf + buflen, src, len); - buflen += len; - srclen -= len; - src += len; - - if (buflen == maxlen) { - if (! _cairo_writen (fd, buf, buflen)) - return -1; - - buflen = 0; - } - } - - return buflen; -} - -static const char * -write_ppm (cairo_surface_t *surface, int fd) -{ - char buf[4096]; - cairo_format_t format; - const char *format_str; - const unsigned char *data; - int len; - int width, height, stride; - int i, j; - - data = cairo_image_surface_get_data (surface); - height = cairo_image_surface_get_height (surface); - width = cairo_image_surface_get_width (surface); - stride = cairo_image_surface_get_stride (surface); - format = cairo_image_surface_get_format (surface); - if (format == CAIRO_FORMAT_ARGB32) { - /* see if we can convert to a standard ppm type and trim a few bytes */ - const unsigned char *alpha = data; - for (j = height; j--; alpha += stride) { - for (i = 0; i < width; i++) { - if ((*(unsigned int *) (alpha+4*i) & 0xff000000) != 0xff000000) - goto done; - } - } - format = CAIRO_FORMAT_RGB24; - done: ; - } - - switch (format) { - case CAIRO_FORMAT_ARGB32: - /* XXX need true alpha for svg */ - format_str = "P7"; - break; - case CAIRO_FORMAT_RGB24: - format_str = "P6"; - break; - case CAIRO_FORMAT_A8: - format_str = "P5"; - break; - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_INVALID: - default: - return "unhandled image format"; - } - - len = sprintf (buf, "%s %d %d 255\n", format_str, width, height); - for (j = 0; j < height; j++) { - const unsigned int *row = (unsigned int *) (data + stride * j); - - switch ((int) format) { - case CAIRO_FORMAT_ARGB32: - len = _cairo_write (fd, - buf, sizeof (buf), len, - (unsigned char *) row, 4 * width); - break; - case CAIRO_FORMAT_RGB24: - for (i = 0; i < width; i++) { - unsigned char rgb[3]; - unsigned int p = *row++; - rgb[0] = (p & 0xff0000) >> 16; - rgb[1] = (p & 0x00ff00) >> 8; - rgb[2] = (p & 0x0000ff) >> 0; - len = _cairo_write (fd, - buf, sizeof (buf), len, - rgb, 3); - } - break; - case CAIRO_FORMAT_A8: - len = _cairo_write (fd, - buf, sizeof (buf), len, - (unsigned char *) row, width); - break; - } - if (len < 0) - return "write failed"; - } - - if (len && ! _cairo_writen (fd, buf, len)) - return "write failed"; - - return NULL; -} - -static cairo_surface_t * -_create_image (void *closure, - cairo_content_t content, - double width, double height, - long uid) -{ - cairo_surface_t **out = closure; - cairo_format_t format; - switch (content) { - case CAIRO_CONTENT_ALPHA: - format = CAIRO_FORMAT_A8; - break; - case CAIRO_CONTENT_COLOR: - format = CAIRO_FORMAT_RGB24; - break; - default: - case CAIRO_CONTENT_COLOR_ALPHA: - format = CAIRO_FORMAT_ARGB32; - break; - } - *out = cairo_image_surface_create (format, width, height); - return cairo_surface_reference (*out); -} - -#if CAIRO_HAS_INTERPRETER -static const char * -_cairo_script_render_page (const char *filename, - cairo_surface_t **surface_out) -{ - cairo_script_interpreter_t *csi; - cairo_surface_t *surface = NULL; - cairo_status_t status; - const cairo_script_interpreter_hooks_t hooks = { - &surface, - _create_image, - NULL, /* surface_destroy */ - NULL, /* context_create */ - NULL, /* context_destroy */ - NULL, /* show_page */ - NULL /* copy_page */ - }; - - csi = cairo_script_interpreter_create (); - cairo_script_interpreter_install_hooks (csi, &hooks); - status = cairo_script_interpreter_run (csi, filename); - if (status) { - cairo_surface_destroy (surface); - surface = NULL; - } - status = cairo_script_interpreter_destroy (csi); - if (surface == NULL) - return "cairo-script interpreter failed"; - - if (status == CAIRO_STATUS_SUCCESS) - status = cairo_surface_status (surface); - if (status) { - cairo_surface_destroy (surface); - return cairo_status_to_string (status); - } - - *surface_out = surface; - return NULL; -} - -static const char * -cs_convert (char **argv, int fd) -{ - const char *err; - cairo_surface_t *surface = NULL; /* silence compiler warning */ - - err = _cairo_script_render_page (argv[0], &surface); - if (err != NULL) - return err; - - err = write_ppm (surface, fd); - cairo_surface_destroy (surface); - - return err; -} -#else -static const char * -cs_convert (char **argv, int fd) -{ - return "compiled without CairoScript support."; -} -#endif - -#if CAIRO_CAN_TEST_PDF_SURFACE -/* adapted from pdf2png.c */ -static const char * -_poppler_render_page (const char *filename, - const char *page_label, - cairo_surface_t **surface_out) -{ - PopplerDocument *document; - PopplerPage *page; - double width, height; - GError *error = NULL; - gchar *absolute, *uri; - cairo_surface_t *surface; - cairo_t *cr; - cairo_status_t status; - - if (g_path_is_absolute (filename)) { - absolute = g_strdup (filename); - } else { - gchar *dir = g_get_current_dir (); - absolute = g_build_filename (dir, filename, (gchar *) 0); - g_free (dir); - } - - uri = g_filename_to_uri (absolute, NULL, &error); - g_free (absolute); - if (uri == NULL) - return error->message; /* XXX g_error_free (error) */ - - document = poppler_document_new_from_file (uri, NULL, &error); - g_free (uri); - if (document == NULL) - return error->message; /* XXX g_error_free (error) */ - - page = poppler_document_get_page_by_label (document, page_label); - g_object_unref (document); - if (page == NULL) - return "page not found"; - - poppler_page_get_size (page, &width, &height); - - surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); - cr = cairo_create (surface); - - cairo_set_source_rgb (cr, 1., 1., 1.); - cairo_paint (cr); - cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA); - - poppler_page_render (page, cr); - g_object_unref (page); - - cairo_pop_group_to_source (cr); - cairo_paint (cr); - - status = cairo_status (cr); - cairo_destroy (cr); - - if (status) { - cairo_surface_destroy (surface); - return cairo_status_to_string (status); - } - - *surface_out = surface; - return NULL; -} - -static const char * -pdf_convert (char **argv, int fd) -{ - const char *err; - cairo_surface_t *surface = NULL; /* silence compiler warning */ - - err = _poppler_render_page (argv[0], argv[1], &surface); - if (err != NULL) - return err; - - err = write_ppm (surface, fd); - cairo_surface_destroy (surface); - - return err; -} -#else -static const char * -pdf_convert (char **argv, int fd) -{ - return "compiled without PDF support."; -} -#endif - -#if CAIRO_CAN_TEST_SVG_SURFACE -static const char * -_rsvg_render_page (const char *filename, - cairo_surface_t **surface_out) -{ - RsvgHandle *handle; - RsvgDimensionData dimensions; - GError *error = NULL; - cairo_surface_t *surface; - cairo_t *cr; - cairo_status_t status; - - handle = rsvg_handle_new_from_file (filename, &error); - if (handle == NULL) - return error->message; /* XXX g_error_free */ - - rsvg_handle_get_dimensions (handle, &dimensions); - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - dimensions.width, - dimensions.height); - cr = cairo_create (surface); - - rsvg_handle_render_cairo (handle, cr); - g_object_unref (handle); - - status = cairo_status (cr); - cairo_destroy (cr); - - if (status) { - cairo_surface_destroy (surface); - return cairo_status_to_string (status); - } - - *surface_out = surface; - return NULL; -} - -static const char * -svg_convert (char **argv, int fd) -{ - const char *err; - cairo_surface_t *surface = NULL; /* silence compiler warning */ - - err = _rsvg_render_page (argv[0], &surface); - if (err != NULL) - return err; - - err = write_ppm (surface, fd); - cairo_surface_destroy (surface); - - return err; -} -#else -static const char * -svg_convert (char **argv, int fd) -{ - return "compiled without SVG support."; -} -#endif - -#if CAIRO_HAS_SPECTRE -static const char * -_spectre_render_page (const char *filename, - const char *page_label, - cairo_surface_t **surface_out) -{ - static const cairo_user_data_key_t key; - - SpectreDocument *document; - SpectreStatus status; - int width, height, stride; - unsigned char *pixels; - cairo_surface_t *surface; - - document = spectre_document_new (); - spectre_document_load (document, filename); - status = spectre_document_status (document); - if (status) { - spectre_document_free (document); - return spectre_status_to_string (status); - } - - if (page_label) { - SpectrePage *page; - SpectreRenderContext *rc; - - page = spectre_document_get_page_by_label (document, page_label); - spectre_document_free (document); - if (page == NULL) - return "page not found"; - - spectre_page_get_size (page, &width, &height); - rc = spectre_render_context_new (); - spectre_render_context_set_page_size (rc, width, height); - spectre_page_render (page, rc, &pixels, &stride); - spectre_render_context_free (rc); - status = spectre_page_status (page); - spectre_page_free (page); - if (status) { - free (pixels); - return spectre_status_to_string (status); - } - } else { - spectre_document_get_page_size (document, &width, &height); - spectre_document_render (document, &pixels, &stride); - spectre_document_free (document); - } - - surface = cairo_image_surface_create_for_data (pixels, - CAIRO_FORMAT_RGB24, - width, height, - stride); - cairo_surface_set_user_data (surface, &key, - pixels, (cairo_destroy_func_t) free); - *surface_out = surface; - return NULL; -} - -static const char * -ps_convert (char **argv, int fd) -{ - const char *err; - cairo_surface_t *surface = NULL; /* silence compiler warning */ - - err = _spectre_render_page (argv[0], argv[1], &surface); - if (err != NULL) - return err; - - err = write_ppm (surface, fd); - cairo_surface_destroy (surface); - - return err; -} -#else -static const char * -ps_convert (char **argv, int fd) -{ - return "compiled without PostScript support."; -} -#endif - -static const char * -convert (char **argv, int fd) -{ - static const struct converter { - const char *type; - const char *(*func) (char **, int); - } converters[] = { - { "cs", cs_convert }, - { "pdf", pdf_convert }, - { "ps", ps_convert }, - { "svg", svg_convert }, - { NULL, NULL } - }; - const struct converter *converter = converters; - char *type; - - type = strrchr (argv[0], '.'); - if (type == NULL) - return "no file extension"; - type++; - - while (converter->type) { - if (strcmp (type, converter->type) == 0) - return converter->func (argv, fd); - converter++; - } - return "no converter"; -} - -#if CAN_RUN_AS_DAEMON -static int -_getline (int fd, char **linep, size_t *lenp) -{ - char *line; - size_t len, i; - ssize_t ret; - - line = *linep; - if (line == NULL) { - line = malloc (1024); - if (line == NULL) - return -1; - line[0] = '\0'; - len = 1024; - } else - len = *lenp; - - /* XXX simple, but ugly! */ - i = 0; - do { - if (i == len - 1) { - char *nline; - - nline = realloc (line, len + 1024); - if (nline == NULL) - goto out; - - line = nline; - len += 1024; - } - - ret = read (fd, line + i, 1); - if (ret == -1 || ret == 0) - goto out; - } while (line[i++] != '\n'); - -out: - line[i] = '\0'; - *linep = line; - *lenp = len; - return i-1; -} - -static int -split_line (char *line, char *argv[], int max_argc) -{ - int i = 0; - - max_argc--; /* leave one spare for the trailing NULL */ - - argv[i++] = line; - while (i < max_argc && (line = strchr (line, ' ')) != NULL) { - *line++ = '\0'; - argv[i++] = line; - } - - /* chomp the newline */ - line = strchr (argv[i-1], '\n'); - if (line != NULL) - *line = '\0'; - - argv[i] = NULL; - - return i; -} - -static int -any2ppm_daemon_exists (void) -{ - struct stat st; - int fd; - char buf[80]; - int pid; - int ret; - - if (stat (SOCKET_PATH, &st) < 0) - return 0; - - fd = open (SOCKET_PATH ".pid", O_RDONLY); - if (fd < 0) - return 0; - - pid = 0; - ret = read (fd, buf, sizeof (buf) - 1); - if (ret > 0) { - buf[ret] = '\0'; - pid = atoi (buf); - } - close (fd); - - return pid > 0 && kill (pid, 0) == 0; -} - -static int -write_pid_file (void) -{ - int fd; - char buf[80]; - int ret; - - fd = open (SOCKET_PATH ".pid", O_CREAT | O_TRUNC | O_WRONLY, 0666); - if (fd < 0) - return 0; - - ret = sprintf (buf, "%d\n", getpid ()); - ret = write (fd, buf, ret) == ret; - close (fd); - - return ret; -} - -static int -open_devnull_to_fd (int want_fd, int flags) -{ - int error; - int got_fd; - - close (want_fd); - - got_fd = open("/dev/null", flags | O_CREAT, 0700); - if (got_fd == -1) - return -1; - - error = dup2 (got_fd, want_fd); - close (got_fd); - - return error; -} - -static int -daemonize (void) -{ - void (*oldhup) (int); - - /* Let the parent go. */ - switch (fork ()) { - case -1: return -1; - case 0: break; - default: _exit (0); - } - - /* Become session leader. */ - if (setsid () == -1) - return -1; - - /* Refork to yield session leadership. */ - oldhup = signal (SIGHUP, SIG_IGN); - - switch (fork ()) { /* refork to yield session leadership. */ - case -1: return -1; - case 0: break; - default: _exit (0); - } - - signal (SIGHUP, oldhup); - - /* Establish stdio. */ - if (open_devnull_to_fd (0, O_RDONLY) == -1) - return -1; - if (open_devnull_to_fd (1, O_WRONLY | O_APPEND) == -1) - return -1; - if (dup2 (1, 2) == -1) - return -1; - - return 0; -} - -static const char * -any2ppm_daemon (void) -{ - int timeout = TIMEOUT; - struct pollfd pfd; - int sk, fd; - long flags; - struct sockaddr_un addr; - char *line = NULL; - size_t len = 0; - -#ifdef SIGPIPE - signal (SIGPIPE, SIG_IGN); -#endif - - /* XXX racy! */ - if (getenv ("ANY2PPM_FORCE") == NULL && any2ppm_daemon_exists ()) - return "any2ppm daemon already running"; - - unlink (SOCKET_PATH); - - sk = socket (PF_UNIX, SOCK_STREAM, 0); - if (sk == -1) - return "unable to create socket"; - - memset (&addr, 0, sizeof (addr)); - addr.sun_family = AF_UNIX; - strcpy (addr.sun_path, SOCKET_PATH); - if (bind (sk, (struct sockaddr *) &addr, sizeof (addr)) == -1) { - close (sk); - return "unable to bind socket"; - } - - flags = fcntl (sk, F_GETFL); - if (flags == -1 || fcntl (sk, F_SETFL, flags | O_NONBLOCK) == -1) { - close (sk); - return "unable to set socket to non-blocking"; - } - - if (listen (sk, 5) == -1) { - close (sk); - return "unable to listen on socket"; - } - - /* ready for client connection - detach from parent/terminal */ - if (getenv ("ANY2PPM_NODAEMON") == NULL && daemonize () == -1) { - close (sk); - return "unable to detach from parent"; - } - - if (! write_pid_file ()) { - close (sk); - return "unable to write pid file"; - } - - if (getenv ("ANY2PPM_TIMEOUT") != NULL) { - timeout = atoi (getenv ("ANY2PPM_TIMEOUT")); - if (timeout == 0) - timeout = -1; - if (timeout > 0) - timeout *= 1000; /* convert env (in seconds) to milliseconds */ - } - - pfd.fd = sk; - pfd.events = POLLIN; - pfd.revents = 0; /* valgrind */ - while (poll (&pfd, 1, timeout) > 0) { - while ((fd = accept (sk, NULL, NULL)) != -1) { - if (_getline (fd, &line, &len) != -1) { - char *argv[10]; - - if (split_line (line, argv, ARRAY_LENGTH (argv)) > 0) { - const char *err; - - err = convert (argv, fd); - if (err != NULL) { - FILE *file = fopen (".any2ppm.errors", "a"); - if (file != NULL) { - fprintf (file, - "Failed to convert '%s': %s\n", - argv[0], err); - fclose (file); - } - } - } - } - close (fd); - } - } - close (sk); - unlink (SOCKET_PATH); - unlink (SOCKET_PATH ".pid"); - - free (line); - return NULL; -} -#else -static const char * -any2ppm_daemon (void) -{ - return "daemon not compiled in."; -} -#endif - -int -main (int argc, char **argv) -{ - const char *err; - -#if CAIRO_CAN_TEST_PDF_SURFACE || CAIRO_CAN_TEST_SVG_SURFACE -#if GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION <= 34 - g_type_init (); -#endif -#endif - -#if CAIRO_CAN_TEST_SVG_SURFACE - rsvg_set_default_dpi (72.0); -#endif - -#if defined(_WIN32) && !defined (__CYGWIN__) - _setmode (1, _O_BINARY); -#endif - - if (argc == 1) - err = any2ppm_daemon (); - else - err = convert (argv + 1, 1); - if (err != NULL) { - fprintf (stderr, "Failed to run converter: %s\n", err); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} |