[cairo-commit] 2 commits - util/cairo-sphinx util/meson.build

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Sep 23 11:11:19 UTC 2023


 util/cairo-sphinx/.gitignore  |    1 
 util/cairo-sphinx/fdr.c       |  257 ------
 util/cairo-sphinx/meson.build |   26 
 util/cairo-sphinx/sphinx.c    | 1559 ------------------------------------------
 util/meson.build              |   10 
 5 files changed, 1853 deletions(-)

New commits:
commit 6f9dbdad8139cb4722b45634cdf69566c6252963
Merge: 6d2d6f312 e6b0c5842
Author: Emmanuele Bassi <ebassi at gmail.com>
Date:   Sat Sep 23 11:11:17 2023 +0000

    Merge branch 'remove-sphinx' into 'master'
    
    Remove cairo-sphinx
    
    See merge request cairo/cairo!510

commit e6b0c58424b9c0b214953d916dc04a8890cd0f03
Author: Uli Schlachter <psychon at znc.in>
Date:   Mon Sep 4 18:10:03 2023 +0200

    Remove cairo-sphinx
    
    I tried to use cairo-sphinx do to something useful. I failed.
    
    The cairo-sphinx binary was added in commit 6e0b3be903 in 2009 by ickle
    with the explanation:
    
        Add cairo-sphinx utility for regression analysis
    
        sphinx is an alternate version of the current cairo-test-trace. It's
        purpose is to replay a live application (which may just be a replay of a
        trace) against a backend and its reference. The improvement over the
        original cairo-test-trace is that the reference backend may be from an
        older version of cairo.
    
    Ever since this commit, there were only build fixes to this code (for
    example to fix compilation on AIX or to fix compilation after
    cairo-tee.h became optional). So, either this code was perfect from the
    beginning or it was not much used.
    
    Next, I tried to reverse-engineer a bit how to actually use this. The
    non-existing documentation didn't help much. The result? Well...
    something happened, but I am not quite sure what. Then the server
    process just exited.
    
    So, in this commit I am removing cairo-sphinx. The hope is that someone
    speaks up and complains. That person then hopefully can provide some
    explanation on how to use this. Alternatively, no one speaks up and we
    no longer have to maintain this piece of code.
    
    Signed-off-by: Uli Schlachter <psychon at znc.in>

diff --git a/util/cairo-sphinx/.gitignore b/util/cairo-sphinx/.gitignore
deleted file mode 100644
index 56ecd5de8..000000000
--- a/util/cairo-sphinx/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-cairo-sphinx
diff --git a/util/cairo-sphinx/fdr.c b/util/cairo-sphinx/fdr.c
deleted file mode 100644
index a28251650..000000000
--- a/util/cairo-sphinx/fdr.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* cairo-fdr - a 'flight data recorder', a black box, for cairo
- *
- * Copyright © 2009 Chris Wilson
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <cairo.h>
-#include <cairo-script.h>
-#include <cairo-tee.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <dlfcn.h>
-
-static void *_dlhandle = RTLD_NEXT;
-#define DLCALL(name, args...) ({ \
-    static typeof (&name) name##_real; \
-    if (name##_real == NULL) { \
-	name##_real = dlsym (_dlhandle, #name); \
-	if (name##_real == NULL && _dlhandle == RTLD_NEXT) { \
-	    _dlhandle = dlopen ("libcairo.so", RTLD_LAZY); \
-	    name##_real = dlsym (_dlhandle, #name); \
-	    assert (name##_real != NULL); \
-	} \
-    } \
-    (*name##_real) (args);  \
-})
-
-static cairo_device_t *fdr_context;
-static const cairo_user_data_key_t fdr_key;
-
-static void
-fdr_get_extents (cairo_surface_t *surface,
-		 cairo_rectangle_t *extents)
-{
-    cairo_t *cr;
-
-    cr = DLCALL (cairo_create, surface);
-    DLCALL (cairo_clip_extents, cr,
-	    &extents->x, &extents->y, &extents->width, &extents->height);
-    DLCALL (cairo_destroy, cr);
-
-    extents->width -= extents->x;
-    extents->height -= extents->y;
-}
-
-static void
-fdr_surface_destroy (void *surface)
-{
-    DLCALL (cairo_surface_destroy, surface);
-}
-
-static void
-fdr_surface_reference (void *surface)
-{
-    DLCALL (cairo_surface_reference, surface);
-}
-
-static cairo_surface_t *
-fdr_surface_get_tee (cairo_surface_t *surface)
-{
-    return DLCALL (cairo_surface_get_user_data, surface, &fdr_key);
-}
-
-static cairo_surface_t *
-fdr_tee_surface_index (cairo_surface_t *surface, int index)
-{
-    return DLCALL (cairo_tee_surface_index, surface, index);
-}
-
-static cairo_status_t
-fdr_write (void *closure, const unsigned char *data, unsigned int len)
-{
-    int fd = (int) (intptr_t) closure;
-    while (len) {
-	int ret = write (fd, data, len);
-	if (ret < 0) {
-	    switch (errno) {
-	    case EAGAIN:
-	    case EINTR:
-		continue;
-	    default:
-		return CAIRO_STATUS_WRITE_ERROR;
-	    }
-	} else if (ret == 0) {
-	    return CAIRO_STATUS_WRITE_ERROR;
-	} else {
-	    data += ret;
-	    len -= ret;
-	}
-    }
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_t *
-cairo_create (cairo_surface_t *surface)
-{
-    cairo_surface_t *tee;
-
-    tee = fdr_surface_get_tee (surface);
-    if (tee == NULL) {
-	cairo_surface_t *script;
-	cairo_rectangle_t extents;
-	cairo_content_t content;
-
-	if (fdr_context == NULL) {
-	    const char *env = getenv ("CAIRO_SPHINX_FD");
-	    int fd = env ? atoi (env) : 1;
-	    fdr_context = DLCALL (cairo_script_create_for_stream,
-				  fdr_write, (void *) (intptr_t) fd);
-	}
-
-	fdr_get_extents (surface, &extents);
-	content = DLCALL (cairo_surface_get_content, surface);
-
-	tee = DLCALL (cairo_tee_surface_create, surface);
-	script = DLCALL (cairo_script_surface_create,
-			 fdr_context, content, extents.width, extents.height);
-	DLCALL (cairo_tee_surface_add, tee, script);
-
-	DLCALL (cairo_surface_set_user_data, surface,
-		&fdr_key, tee, fdr_surface_destroy);
-    }
-
-    return DLCALL (cairo_create, tee);
-}
-
-static void
-fdr_remove_tee (cairo_surface_t *surface)
-{
-    fdr_surface_reference (surface);
-    DLCALL (cairo_surface_set_user_data, surface, &fdr_key, NULL, NULL);
-    fdr_surface_destroy (surface);
-}
-
-void
-cairo_destroy (cairo_t *cr)
-{
-    cairo_surface_t *tee;
-
-    tee = DLCALL (cairo_get_target, cr);
-    DLCALL (cairo_destroy, cr);
-
-    if (DLCALL (cairo_surface_get_reference_count, tee) == 1)
-	fdr_remove_tee (fdr_tee_surface_index (tee, 0));
-}
-
-void
-cairo_pattern_destroy (cairo_pattern_t *pattern)
-{
-    if (DLCALL (cairo_pattern_get_type, pattern) == CAIRO_PATTERN_TYPE_SURFACE) {
-	cairo_surface_t *surface;
-
-	if (DLCALL (cairo_pattern_get_surface, pattern, &surface) == CAIRO_STATUS_SUCCESS &&
-	    DLCALL (cairo_surface_get_type, surface) == CAIRO_SURFACE_TYPE_TEE &&
-	    DLCALL (cairo_surface_get_reference_count, surface) == 2)
-	{
-	    fdr_remove_tee (fdr_tee_surface_index (surface, 0));
-	}
-    }
-
-    DLCALL (cairo_pattern_destroy, pattern);
-}
-
-cairo_surface_t *
-cairo_get_target (cairo_t *cr)
-{
-    cairo_surface_t *tee;
-
-    tee = DLCALL (cairo_get_target, cr);
-    return fdr_tee_surface_index (tee, 0);
-}
-
-cairo_surface_t *
-cairo_get_group_target (cairo_t *cr)
-{
-    cairo_surface_t *tee;
-
-    tee = DLCALL (cairo_get_group_target, cr);
-    return fdr_tee_surface_index (tee, 0);
-}
-
-cairo_pattern_t *
-cairo_pattern_create_for_surface (cairo_surface_t *surface)
-{
-    cairo_surface_t *tee;
-
-    tee = fdr_surface_get_tee (surface);
-    if (tee != NULL)
-	surface = tee;
-
-    return DLCALL (cairo_pattern_create_for_surface, surface);
-}
-
-cairo_status_t
-cairo_pattern_get_surface (cairo_pattern_t *pattern,
-			   cairo_surface_t **surface)
-{
-    cairo_status_t status;
-    cairo_surface_t *tee;
-
-    status = DLCALL (cairo_pattern_get_surface, pattern, surface);
-    if (status != CAIRO_STATUS_SUCCESS)
-	return status;
-
-    tee = fdr_surface_get_tee (*surface);
-    if (tee != NULL)
-	*surface = tee;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-void
-cairo_set_source_surface (cairo_t *cr,
-			  cairo_surface_t *surface,
-			  double x, double y)
-{
-    cairo_surface_t *tee;
-
-    tee = fdr_surface_get_tee (surface);
-    if (tee != NULL)
-	surface = tee;
-
-    DLCALL (cairo_set_source_surface, cr, surface, x, y);
-}
-
-cairo_surface_t *
-cairo_surface_create_similar (cairo_surface_t *surface,
-			      cairo_content_t content,
-			      int width, int height)
-{
-    cairo_surface_t *tee;
-
-    tee = fdr_surface_get_tee (surface);
-    if (tee != NULL)
-	surface = tee;
-
-    return DLCALL (cairo_surface_create_similar,
-		   surface, content, width, height);
-}
diff --git a/util/cairo-sphinx/meson.build b/util/cairo-sphinx/meson.build
deleted file mode 100644
index 01ef64bec..000000000
--- a/util/cairo-sphinx/meson.build
+++ /dev/null
@@ -1,26 +0,0 @@
-libcairo_sphinx_sources = [
-  'fdr.c',
-]
-
-cairo_sphinx_sources = [
-  'sphinx.c',
-]
-
-libcairosphinx = shared_library('cairo-sphinx', libcairo_sphinx_sources,
-  include_directories: [incbase, incsrc],
-  dependencies: deps,
-  install: true,
-  install_dir: get_option('libdir') / 'cairo',
-)
-
-libdir = join_paths(get_option('prefix'), get_option('libdir'))
-
-cairosphinx_exe = executable('cairo-sphinx', cairo_sphinx_sources,
-  include_directories: [incbase],
-  c_args: ['-DLIBDIR="@0@"'.format(libdir)] + pthread_c_args,
-  dependencies: deps + [glib_dep, rt_dep, libcairo_dep, cairoboilerplate_dep, libcairoscript_dep],
-  link_with: [libcairosphinx],
-  link_args: extra_link_args,
-  gnu_symbol_visibility: 'hidden',
-  install: true,
-)
diff --git a/util/cairo-sphinx/sphinx.c b/util/cairo-sphinx/sphinx.c
deleted file mode 100644
index 467f26cab..000000000
--- a/util/cairo-sphinx/sphinx.c
+++ /dev/null
@@ -1,1559 +0,0 @@
-/*
- * The intention for sphinx is for detection of rendering errors inside
- * applications by simultaneously rendering on to the target device and on
- * an image surface and comparing the two. If it found a discrepancy, it
- * would then dump the trace that reproduces the error. (Then apply
- * delta-debugging to reduce that down to a minimal trace.)
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-#include <assert.h>
-#include <pthread.h>
-
-#if defined(HAVE_POLL_H)
-#include <poll.h>
-#elif defined(HAVE_SYS_POLL_H)
-#include <sys/poll.h>
-#else
-#error No poll.h equivalent found
-#endif
-
-#include <cairo.h>
-#include <cairo-script.h>
-#include <cairo-script-interpreter.h>
-#include <cairo-boilerplate.h>
-
-#include <glib.h> /* for checksumming */
-
-#ifndef CAIRO_HAS_REAL_PTHREAD
-# error "cairo-sphinx needs real pthreads"
-#endif
-
-#ifndef MAP_NORESERVE
-#define MAP_NORESERVE 0
-#endif
-
-#define DATA_SIZE (256 << 20)
-#define SHM_PATH_XXX "/shmem-cairo-sphinx"
-
-struct client {
-    int sk;
-    const cairo_boilerplate_target_t *target;
-    cairo_surface_t *surface;
-    void *base;
-
-    cairo_script_interpreter_t *csi;
-    struct context_closure {
-	struct context_closure *next;
-	unsigned long id;
-	cairo_t *context;
-	cairo_surface_t *surface;
-	cairo_surface_t *original;
-    } *contexts;
-
-    unsigned long context_id;
-};
-
-struct surface_tag {
-    long width, height;
-};
-static const cairo_user_data_key_t surface_tag;
-
-static int
-client_socket (const char *socket_path);
-
-static int
-writen (int fd, const void *ptr, int len)
-{
-#if 1
-    const uint8_t *data = ptr;
-    while (len) {
-	int ret = write (fd, data, len);
-	if (ret < 0) {
-	    switch (errno) {
-	    case EAGAIN:
-	    case EINTR:
-		continue;
-	    default:
-		return FALSE;
-	    }
-	} else if (ret == 0) {
-	    return FALSE;
-	} else {
-	    data += ret;
-	    len -= ret;
-	}
-    }
-    return TRUE;
-#else
-    int ret = send (fd, ptr, len, 0);
-    return ret == len;
-#endif
-}
-
-static int
-readn (int fd, void *ptr, int len)
-{
-#if 0
-    uint8_t *data = ptr;
-    while (len) {
-	int ret = read (fd, data, len);
-	if (ret < 0) {
-	    switch (errno) {
-	    case EAGAIN:
-	    case EINTR:
-		continue;
-	    default:
-		return FALSE;
-	    }
-	} else if (ret == 0) {
-	    return FALSE;
-	} else {
-	    data += ret;
-	    len -= ret;
-	}
-    }
-    return TRUE;
-#else
-    int ret = recv (fd, ptr, len, MSG_WAITALL);
-    return ret == len;
-#endif
-}
-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 ()) {
-    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 int
-server_socket (const char *socket_path)
-{
-    long flags;
-    struct sockaddr_un addr;
-    int sk;
-
-    unlink (socket_path);
-
-    sk = socket (PF_UNIX, SOCK_STREAM, 0);
-    if (sk == -1)
-	return -1;
-
-    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 -1;
-    }
-
-    flags = fcntl (sk, F_GETFL);
-    if (flags == -1 || fcntl (sk, F_SETFL, flags | O_NONBLOCK) == -1) {
-	close (sk);
-	return -1;
-    }
-
-    if (listen (sk, 5) == -1) {
-	close (sk);
-	return -1;
-    }
-
-    return sk;
-}
-
-static int
-readline (int fd, char *line, int max)
-{
-    int len = 0;
-    do {
-	int ret = read (fd, &line[len], 1);
-	if (ret <= 0)
-	    return -1;
-    } while (line[len] != '\n' && ++len < max);
-    line[len] = '\0';
-    return len;
-}
-
-struct clients {
-    int count, size;
-    int complete;
-
-    cairo_surface_t *recording;
-    unsigned long serial;
-
-    struct client_info {
-	int sk;
-	int trace;
-	unsigned long image_serial;
-	cairo_surface_t *image;
-	char *name;
-	char *target;
-	char *reference;
-
-	uint8_t *out_buf;
-	int out_len;
-	int out_size;
-    } *clients;
-    const char *shm_path;
-    unsigned long offset;
-    uint8_t *base;
-};
-
-static void *
-clients_shm (const char *shm_path)
-{
-    void *base;
-    int fd;
-
-    shm_unlink (shm_path);
-    fd = shm_open (shm_path, O_RDWR | O_EXCL | O_CREAT, 0777);
-    if (fd == -1)
-	return MAP_FAILED;
-
-    if (ftruncate (fd, DATA_SIZE) == -1) {
-	close (fd);
-	return MAP_FAILED;
-    }
-
-    base = mmap (NULL, DATA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-    close (fd);
-
-    return base;
-}
-
-static int
-clients_init (struct clients *clients)
-{
-    clients->count = 0;
-    clients->complete = 0;
-    clients->size = 4;
-    clients->clients = xmalloc (clients->size * sizeof (struct client_info));
-
-    clients->shm_path = SHM_PATH_XXX;
-    clients->base = clients_shm (clients->shm_path);
-    if (clients->base == MAP_FAILED)
-	return -1;
-    clients->offset = 0;
-
-    clients->recording = NULL;
-    clients->serial = 0;
-
-    return 0;
-}
-
-static void
-clients_add_command (struct clients *clients, int fd, char *info)
-{
-    struct client_info *c;
-    char buf[1024];
-    int len;
-    char *str;
-
-    if (clients->count == clients->size) {
-	clients->size *= 2;
-	clients->clients = xrealloc (clients->clients,
-				     clients->size * sizeof (struct client_info));
-    }
-
-    c = &clients->clients[clients->count++];
-    c->sk = fd;
-    c->trace = -1;
-    c->image_serial = 0;
-    c->image = NULL;
-    c->name = c->target = c->reference = NULL;
-
-    c->out_size = 8192;
-    c->out_buf = xmalloc (c->out_size);
-    c->out_len = 0;
-
-    str = strstr (info, "name=");
-    if (str != NULL) {
-	char *sp = strchr (str + 5, ' ');
-	int len;
-	if (sp)
-	    len = sp - str - 5;
-	else
-	    len = strlen (str + 5);
-	c->name = xmalloc (len + 1);
-	memcpy (c->name, str + 5, len);
-	c->name[len] = '\0';
-    }
-
-    str = strstr (info, "target=");
-    if (str != NULL) {
-	char *sp = strchr (str + 7, ' ');
-	int len;
-	if (sp)
-	    len = sp - str - 7;
-	else
-	    len = strlen (str + 7);
-	c->target = xmalloc (len + 1);
-	memcpy (c->target, str + 7, len);
-	c->target[len] = '\0';
-    }
-
-    str = strstr (info, "reference=");
-    if (str != NULL) {
-	char *sp = strchr (str + 10, ' ');
-	int len;
-	if (sp)
-	    len = sp - str - 10;
-	else
-	    len = strlen (str + 10);
-	c->reference = xmalloc (len + 1);
-	memcpy (c->reference, str + 10, len);
-	c->reference[len] = '\0';
-    }
-
-    len = sprintf (buf, "%s\n", clients->shm_path);
-    writen (fd, buf, len);
-}
-
-static void
-clients_add_trace (struct clients *clients, int fd, char *info)
-{
-    char *str, *sp;
-    char *name;
-    int i;
-
-    str = strstr (info, "name=");
-    assert (str != NULL);
-    sp = strchr (str + 5, ' ');
-    if (sp)
-	i = sp - str - 5;
-    else
-	i = strlen (str + 5);
-
-    name = xmalloc (i + 1);
-    memcpy (name, str + 5, i);
-    name[i] = '\0';
-
-    for (i = 0; i < clients->count; i++) {
-	struct client_info *c = &clients->clients[i];
-	if (strcmp (name, c->name) == 0) {
-	    c->trace = fd;
-	    break;
-	}
-    }
-
-    free (name);
-}
-
-static int
-clients_image (struct clients *clients, int fd, char *info)
-{
-    struct client_info *c = NULL;
-    int format, width, height, stride, size;
-    int i;
-
-    for (i = 0; i < clients->count; i++) {
-	if (clients->clients[i].sk == fd) {
-	    c = &clients->clients[i];
-	    break;
-	}
-    }
-
-    if (c == NULL)
-	return 0;
-
-    if (sscanf (info, "%lu %d %d %d %d",
-		&c->image_serial, &format, &width, &height, &stride) != 5)
-    {
-	return 0;
-    }
-
-    size = height * stride;
-    size = (size + 4095) & -4096;
-    assert (clients->offset + size <= DATA_SIZE);
-
-    c->image =
-	cairo_image_surface_create_for_data (clients->base + clients->offset,
-					     format, width, height, stride);
-
-    if (! writen (fd, &clients->offset, sizeof (clients->offset)))
-	return 0;
-
-    clients->offset += size;
-
-    return 1;
-}
-
-static int
-u8_cmp (const void *A, const void *B)
-{
-    const uint8_t *a = A, *b = B;
-    return (int) *a - (int) *b;
-}
-
-static uint8_t
-median (uint8_t *values, int count)
-{
-    /* XXX could use a fast median here if we cared */
-    qsort (values, count, 1, u8_cmp);
-    return values[count/2];
-}
-
-static uint32_t
-get_pixel32 (int x, int y, const uint8_t *data, int stride)
-{
-    return ((uint32_t *)(data + y * stride))[x];
-}
-
-static uint8_t
-get_median_32 (int x, int y, int channel,
-	       const uint8_t *data, int width, int height, int stride)
-{
-    uint8_t neighbourhood[25];
-    int cnt = 0;
-    int xx, yy;
-
-    for (yy = y - 2; yy <= y + 2; yy++) {
-	if (yy < 0)
-	    continue;
-	if (yy >= height)
-	    continue;
-
-	for (xx = x - 2; xx <= x + 2; xx++) {
-	    if (xx < 0)
-		continue;
-	    if (xx >= width)
-		continue;
-
-	    neighbourhood[cnt++] = (get_pixel32 (xx, yy, data, stride) >> (channel*8)) & 0xff;
-	}
-    }
-
-    return median (neighbourhood, cnt);
-}
-
-static uint8_t
-get_pixel8 (int x, int y, const uint8_t *data, int stride)
-{
-    return data[y * stride + x];
-}
-
-static uint8_t
-get_median_8 (int x, int y, const uint8_t *data, int width, int height, int stride)
-{
-    uint8_t neighbourhood[25];
-    int cnt = 0;
-    int xx, yy;
-
-    for (yy = y - 2; yy <= y + 2; yy++) {
-	if (yy < 0)
-	    continue;
-	if (yy >= height)
-	    continue;
-
-	for (xx = x - 2; xx <= x + 2; xx++) {
-	    if (xx < 0)
-		continue;
-	    if (xx >= width)
-		continue;
-
-	    neighbourhood[cnt++] = get_pixel8 (xx, yy, data, stride);
-	}
-    }
-
-    return median (neighbourhood, cnt);
-}
-
-static cairo_bool_t
-compare_images (cairo_surface_t *a,
-		cairo_surface_t *b)
-{
-    int width, height, stride;
-    const uint8_t *aa, *bb;
-    int x, y;
-
-    if (cairo_surface_status (a) || cairo_surface_status (b))
-	return FALSE;
-
-    if (cairo_surface_get_type (a) != cairo_surface_get_type (b))
-	return FALSE;
-
-    if (cairo_image_surface_get_format (a) != cairo_image_surface_get_format (b))
-	return FALSE;
-
-    if (cairo_image_surface_get_width (a) != cairo_image_surface_get_width (b))
-	return FALSE;
-
-    if (cairo_image_surface_get_height (a) != cairo_image_surface_get_height (b))
-	return FALSE;
-
-    if (cairo_image_surface_get_stride (a) != cairo_image_surface_get_stride (b))
-	return FALSE;
-
-
-    width = cairo_image_surface_get_width (a);
-    height = cairo_image_surface_get_height (a);
-    stride = cairo_image_surface_get_stride (a);
-
-    aa = cairo_image_surface_get_data (a);
-    bb = cairo_image_surface_get_data (b);
-    switch (cairo_image_surface_get_format (a)) {
-    case CAIRO_FORMAT_ARGB32:
-	for (y = 0; y < height; y++) {
-	    const uint32_t *ua = (uint32_t *) aa;
-	    const uint32_t *ub = (uint32_t *) bb;
-	    for (x = 0; x < width; x++) {
-		if (ua[x] != ub[x]) {
-		    int channel;
-
-		    for (channel = 0; channel < 4; channel++) {
-			int va, vb;
-                        unsigned diff;
-
-			va = (ua[x] >> (channel*8)) & 0xff;
-			vb = (ub[x] >> (channel*8)) & 0xff;
-			diff = abs (va - vb);
-			if (diff > 1) {
-			    va = get_median_32 (x, y, channel, aa, width, height, stride);
-			    vb = get_median_32 (x, y, channel, bb, width, height, stride);
-			    diff = abs (va - vb);
-			    if (diff > 1)
-				return FALSE;
-			}
-		    }
-		}
-	    }
-	    aa += stride;
-	    bb += stride;
-	}
-	break;
-
-    case CAIRO_FORMAT_RGB24:
-	for (y = 0; y < height; y++) {
-	    const uint32_t *ua = (uint32_t *) aa;
-	    const uint32_t *ub = (uint32_t *) bb;
-	    for (x = 0; x < width; x++) {
-		if ((ua[x] & 0x00ffffff) != (ub[x] & 0x00ffffff)) {
-		    int channel;
-
-		    for (channel = 0; channel < 3; channel++) {
-			int va, vb;
-                        unsigned diff;
-
-			va = (ua[x] >> (channel*8)) & 0xff;
-			vb = (ub[x] >> (channel*8)) & 0xff;
-			diff = abs (va - vb);
-			if (diff > 1) {
-			    va = get_median_32 (x, y, channel, aa, width, height, stride);
-			    vb = get_median_32 (x, y, channel, bb, width, height, stride);
-			    diff = abs (va - vb);
-			    if (diff > 1)
-				return FALSE;
-			}
-		    }
-		}
-	    }
-	    aa += stride;
-	    bb += stride;
-	}
-	break;
-
-    case CAIRO_FORMAT_A8:
-	for (y = 0; y < height; y++) {
-	    for (x = 0; x < width; x++) {
-		if (aa[x] != bb[x]) {
-		    unsigned diff = abs (aa[x] - bb[x]);
-		    if (diff > 1) {
-			int8_t va, vb;
-
-			va = get_median_8 (x, y, aa, width, height, stride);
-			vb = get_median_8 (x, y, bb, width, height, stride);
-			diff = abs (va - vb);
-			if (diff > 1)
-			    return FALSE;
-		    }
-
-		}
-	    }
-	    aa += stride;
-	    bb += stride;
-	}
-	break;
-
-    case CAIRO_FORMAT_A1:
-	width /= 8;
-	for (y = 0; y < height; y++) {
-	    if (memcmp (aa, bb, width))
-		return FALSE;
-	    aa += stride;
-	    bb += stride;
-	}
-	break;
-
-    case CAIRO_FORMAT_INVALID:
-    case CAIRO_FORMAT_RGB16_565: /* XXX */
-    case CAIRO_FORMAT_RGB30:
-    case CAIRO_FORMAT_RGB96F:
-    case CAIRO_FORMAT_RGBA128F:
-	break;
-    }
-
-    return TRUE;
-}
-
-static int
-check_images (struct clients *clients)
-{
-    int i, j;
-
-    for (i = 0; i < clients->count; i++) {
-	struct client_info *c = &clients->clients[i];
-
-	if (c->reference == NULL)
-	    continue;
-
-	for (j = 0; j < clients->count; j++) {
-	    struct client_info *ref = &clients->clients[j];
-
-	    if (strcmp (c->reference, ref->name))
-		continue;
-
-	    if (! compare_images (c->image, ref->image))
-		return 0;
-	}
-    }
-
-    return 1;
-}
-
-static gchar *
-checksum (const char *filename)
-{
-    gchar *str = NULL;
-    gchar *data;
-    gsize len;
-
-    if (g_file_get_contents (filename, &data, &len, NULL)) {
-	str = g_compute_checksum_for_data (G_CHECKSUM_SHA1, (guchar *) data, len);
-	g_free (data);
-    }
-
-    return str;
-}
-
-static void
-write_trace (struct clients *clients)
-{
-    cairo_device_t *ctx;
-    gchar *csum;
-    char buf[4096];
-    int i;
-
-    mkdir ("output", 0777);
-
-    ctx = cairo_script_create ("output/cairo-sphinx.trace");
-    cairo_script_from_recording_surface (ctx, clients->recording);
-    cairo_device_destroy (ctx);
-
-    csum = checksum ("output/cairo-sphinx.trace");
-
-    sprintf (buf, "output/%s.trace", csum);
-    if (! g_file_test (buf, G_FILE_TEST_EXISTS)) {
-	rename ("output/cairo-sphinx.trace", buf);
-
-	sprintf (buf, "output/%s.recording.png", csum);
-	cairo_surface_write_to_png (clients->recording, buf);
-
-	for (i = 0; i < clients->count; i++) {
-	    struct client_info *c = &clients->clients[i];
-	    if (c->image != NULL) {
-		sprintf (buf, "output/%s.%s.png", csum, c->name);
-		cairo_surface_write_to_png (c->image, buf);
-	    }
-	}
-    }
-}
-
-static void
-clients_complete (struct clients *clients, int fd)
-{
-    int i;
-
-    for (i = 0; i < clients->count; i++) {
-	if (clients->clients[i].sk == fd) {
-	    break;
-	}
-    }
-    if (i == clients->count)
-	return;
-
-    if (++clients->complete != clients->count)
-	return;
-
-    clients->offset = 0;
-    clients->complete = 0;
-
-    if (! check_images (clients))
-	write_trace (clients);
-
-    /* ack */
-    for (i = 0; i < clients->count; i++) {
-	struct client_info *c = &clients->clients[i];
-
-	cairo_surface_destroy (c->image);
-	c->image = NULL;
-
-	if (! writen (c->sk, &clients->serial, sizeof (clients->serial)))
-	    continue;
-
-	c->image_serial = 0;
-    }
-
-    clients->recording = NULL;
-    clients->serial = 0;
-}
-
-static void
-clients_recording (struct clients *clients, int fd, char *info)
-{
-    sscanf (info, "%p %lu", &clients->recording, &clients->serial);
-    clients_complete (clients, fd);
-}
-
-static void
-clients_remove (struct clients *clients, int fd)
-{
-    int i, j;
-
-    for (i = 0; i < clients->count; i++) {
-	struct client_info *c = &clients->clients[i];
-	if (c->sk == fd) {
-	    free (c->out_buf);
-	    break;
-	}
-    }
-
-    for (j = i++; i < clients->count; i++)
-	clients->clients[j] = clients->clients[i];
-
-    clients->count = j;
-}
-
-static void
-clients_send_trace (struct clients *clients,
-		    const char * const line, const int len)
-{
-    int i;
-
-    for (i = 0; i < clients->count; i++) {
-	struct client_info *c = &clients->clients[i];
-	int ret, rem = len;
-
-	if (c->trace == -1)
-	    continue;
-
-	if (c->out_len) {
-	    ret = write (c->trace, c->out_buf, c->out_len);
-	    if (ret > 0) {
-		c->out_len -= ret;
-		if (c->out_len)
-		    memmove (c->out_buf, c->out_buf + ret, c->out_len);
-	    }
-	}
-
-	if (! c->out_len) {
-	    ret = write (c->trace, line, rem);
-	    if (ret > 0)
-		rem -= ret;
-	}
-
-	if (rem) {
-	    if (c->out_len + rem > c->out_size) {
-		c->out_size *= 2;
-		c->out_buf = xrealloc (c->out_buf, c->out_size);
-	    }
-
-	    memcpy (c->out_buf + c->out_len, line, rem);
-	    c->out_len += rem;
-	}
-    }
-}
-
-static void
-clients_fini (struct clients *clients)
-{
-    shm_unlink (clients->shm_path);
-    munmap (clients->base, DATA_SIZE);
-    free (clients->clients);
-}
-
-static int
-nonblocking (int fd)
-{
-    long flags;
-
-    flags = fcntl (fd, F_GETFL);
-    if (flags == -1)
-	return -1;
-
-    return fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-}
-
-static void *
-request_image (struct client *c,
-	       struct context_closure *closure,
-	       cairo_format_t format,
-	       int width, int height, int stride)
-{
-    char buf[1024];
-    unsigned long offset = -1;
-    int len;
-
-    assert (format != CAIRO_FORMAT_INVALID);
-
-    len = sprintf (buf, ".image %lu %d %d %d %d\n",
-		   closure->id, format, width, height, stride);
-    writen (c->sk, buf, len);
-
-    readn (c->sk, &offset, sizeof (offset));
-    if (offset == (unsigned long) -1)
-	return NULL;
-
-    return (uint8_t *) c->base + offset;
-}
-
-static cairo_format_t
-format_for_content (cairo_content_t content)
-{
-    switch (content) {
-    case CAIRO_CONTENT_ALPHA:
-	return CAIRO_FORMAT_A8;
-    case CAIRO_CONTENT_COLOR:
-	return CAIRO_FORMAT_RGB24;
-    default:
-    case CAIRO_CONTENT_COLOR_ALPHA:
-	return CAIRO_FORMAT_ARGB32;
-    }
-}
-
-static void
-get_surface_size (cairo_surface_t *surface,
-		  int *width, int *height,
-		  cairo_format_t *format)
-{
-    if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE) {
-	*width = cairo_image_surface_get_width (surface);
-	*height = cairo_image_surface_get_height (surface);
-	*format = cairo_image_surface_get_format (surface);
-    } else {
-	struct surface_tag *tag;
-
-	tag = cairo_surface_get_user_data (surface, &surface_tag);
-	if (tag != NULL) {
-	    *width = tag->width;
-	    *height = tag->height;
-	} else {
-	    double x0, x1, y0, y1;
-	    cairo_t *cr;
-
-	    /* presumably created using cairo_surface_create_similar() */
-	    cr = cairo_create (surface);
-	    cairo_clip_extents (cr, &x0, &y0, &x1, &y1);
-	    cairo_destroy (cr);
-
-	    tag = xmalloc (sizeof (*tag));
-	    *width = tag->width = ceil (x1 - x0);
-	    *height = tag->height = ceil (y1 - y0);
-
-	    if (cairo_surface_set_user_data (surface, &surface_tag, tag, free))
-		exit (-1);
-	}
-    }
-}
-
-
-static void
-send_surface (struct client *c,
-	      struct context_closure *closure)
-{
-    cairo_surface_t *source = closure->surface;
-    cairo_surface_t *image;
-    cairo_format_t format = CAIRO_FORMAT_INVALID;
-    cairo_t *cr;
-    int width, height, stride;
-    void *data;
-    unsigned long serial;
-
-    get_surface_size (source, &width, &height, &format);
-    if (format == CAIRO_FORMAT_INVALID)
-	format = format_for_content (cairo_surface_get_content (source));
-
-    stride = cairo_format_stride_for_width (format, width);
-
-    data = request_image (c, closure, format, width, height, stride);
-    if (data == NULL)
-	exit (-1);
-
-    image = cairo_image_surface_create_for_data (data,
-						 format,
-						 width, height,
-						 stride);
-    cr = cairo_create (image);
-    cairo_surface_destroy (image);
-
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_surface (cr, source, 0, 0);
-    cairo_paint (cr);
-    cairo_destroy (cr);
-
-    /* signal completion */
-    writen (c->sk, ".complete\n", strlen (".complete\n"));
-
-    /* wait for image check */
-    serial = 0;
-    readn (c->sk, &serial, sizeof (serial));
-    if (serial != closure->id)
-	exit (-1);
-}
-
-static void
-send_recording (struct client *c,
-		struct context_closure *closure)
-{
-    cairo_surface_t *source = closure->surface;
-    char buf[1024];
-    int len;
-    unsigned long serial;
-
-    assert (cairo_surface_get_type (source) == CAIRO_SURFACE_TYPE_RECORDING);
-    len = sprintf (buf, ".recording %p %lu\n", source, closure->id);
-    writen (c->sk, buf, len);
-
-    /* wait for image check */
-
-    serial = 0;
-    readn (c->sk, &serial, sizeof (serial));
-    if (serial != closure->id)
-	exit (-1);
-}
-
-static cairo_surface_t *
-_surface_create (void *closure,
-		 cairo_content_t content,
-		 double width, double height,
-		 long uid)
-{
-    struct client *c = closure;
-    cairo_surface_t *surface;
-
-    surface = cairo_surface_create_similar (c->surface,
-					    content, width, height);
-    if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE) {
-	struct surface_tag *tag;
-
-	tag = xmalloc (sizeof (*tag));
-	tag->width = width;
-	tag->height = height;
-	if (cairo_surface_set_user_data (surface, &surface_tag, tag, free))
-	    exit (-1);
-    }
-
-    return surface;
-}
-
-static cairo_t *
-_context_create (void *closure, cairo_surface_t *surface)
-{
-    struct client *c = closure;
-    struct context_closure *l;
-    cairo_bool_t foreign = FALSE;
-
-    l = xmalloc (sizeof (*l));
-    l->next = c->contexts;
-    l->surface = surface;
-    l->original = cairo_surface_reference (surface);
-    l->id = ++c->context_id;
-    if (l->id == 0)
-	l->id = ++c->context_id;
-    c->contexts = l;
-
-    /* record everything, including writes to images */
-    if (c->target == NULL) {
-	if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_RECORDING) {
-	    cairo_format_t format;
-	    int width, height;
-
-	    get_surface_size (surface, &width, &height, &format);
-	    l->surface = cairo_surface_create_similar (c->surface,
-						       cairo_surface_get_content (surface),
-						       width, height);
-	    foreign = TRUE;
-	}
-    }
-
-    l->context = cairo_create (l->surface);
-    if (foreign) {
-	cairo_set_source_surface (l->context, surface, 0, 0);
-	cairo_paint (l->context);
-    }
-
-    return l->context;
-}
-
-static void
-_context_destroy (void *closure, void *ptr)
-{
-    struct client *c = closure;
-    struct context_closure *l, **prev = &c->contexts;
-
-    while ((l = *prev) != NULL) {
-	if (l->context == ptr) {
-	    if (cairo_surface_status (l->surface) == CAIRO_STATUS_SUCCESS) {
-		if (c->target == NULL)
-		    send_recording (c, l);
-		else
-		    send_surface (c, l);
-            } else {
-		exit (-1);
-	    }
-
-            cairo_surface_destroy (l->original);
-            *prev = l->next;
-            free (l);
-            return;
-        }
-        prev = &l->next;
-    }
-}
-
-static void *
-recorder (void *arg)
-{
-    struct client client;
-    const cairo_script_interpreter_hooks_t hooks = {
-	.closure = &client,
-	.surface_create = _surface_create,
-	.context_create = _context_create,
-	.context_destroy = _context_destroy,
-    };
-    char *buf;
-    int buf_size;
-    int len = 0, ret;
-    struct pollfd pfd;
-
-    client.target = NULL;
-    client.sk = client_socket ("/tmp/cairo-sphinx");
-    if (client.sk < 0)
-	return NULL;
-
-    buf_size = 65536;
-    buf = xmalloc (buf_size);
-
-    len = sprintf (buf, "client-command target=recording name=.recorder\n");
-    if (! writen (client.sk, buf, len))
-	return NULL;
-
-    /* drain the shm_path */
-    len = readline (client.sk, buf, buf_size);
-
-    pfd.fd = client_socket ("/tmp/cairo-sphinx");
-    if (pfd.fd < 0)
-	return NULL;
-
-    len = sprintf (buf, "client-trace name=.recorder\n");
-    if (! writen (pfd.fd, buf, len))
-	return NULL;
-
-    client.surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA,
-						     NULL);
-
-    client.context_id = 0;
-    client.csi = cairo_script_interpreter_create ();
-    cairo_script_interpreter_install_hooks (client.csi, &hooks);
-
-    nonblocking (pfd.fd);
-    pfd.events = POLLIN;
-    len = 0;
-    while (poll (&pfd, 1, -1) > 0) {
-	while ((ret = read (pfd.fd, buf + len, buf_size - len)) > 0) {
-	    int end;
-
-	    if (ret == buf_size - len) {
-		buf_size *= 2;
-		buf = xrealloc (buf, buf_size);
-	    }
-	    len += ret;
-
-	    for (end = len; end > 0 && buf[--end] != '\n'; )
-		;
-	    if (end > 0) {
-		buf[end] = '\0';
-		cairo_script_interpreter_feed_string (client.csi, buf, end);
-
-		len -= end + 1;
-		if (len)
-		    memmove (buf, buf + end + 1, len);
-	    }
-	}
-	if (ret == 0)
-	    break;
-	if (! (errno == EAGAIN || errno == EINTR))
-	    break;
-    }
-
-    cairo_script_interpreter_finish (client.csi);
-    cairo_script_interpreter_destroy (client.csi);
-
-    cairo_surface_destroy (client.surface);
-    return NULL;
-}
-
-static int
-do_server (const char *path)
-{
-    pthread_t thread;
-    struct clients clients;
-    char line[4096];
-    struct pollfd *pfd;
-    int num_pfd, size_pfd;
-    int n, cnt, ret = 1;
-    int sk, source = -1;
-    int waiter = -1, waiter_count = 0;
-    int len;
-
-    signal (SIGPIPE, SIG_IGN);
-
-    if (clients_init (&clients) < 0) {
-	fprintf (stderr, "Failed to initialise clients structure\n");
-	return -1;
-    }
-
-    sk = server_socket (path);
-    if (sk < 0) {
-	fprintf (stderr, "Failed to create server socket\n");
-	return 1;
-    }
-
-    if (daemonize () < 0)
-	return 1;
-
-    if (pthread_create (&thread, NULL, recorder, NULL) < 0) {
-	fprintf (stderr, "Failed to create spawn recording thread\n");
-	return 1;
-    }
-
-    size_pfd = 4;
-    pfd = xmalloc (sizeof (*pfd) * size_pfd);
-    pfd[0].fd = sk;
-    pfd[0].events = POLLIN;
-    num_pfd = 1;
-
-    while ((cnt = poll (pfd, num_pfd, -1)) > 0) {
-	int have_source;
-
-	if (pfd[0].revents) {
-	    while ((sk = accept (pfd[0].fd, NULL, NULL)) != -1) {
-		len = readline (sk, line, sizeof (line));
-		if (strcmp (line, "source") == 0) {
-
-		    if (source != -1)
-			exit (1);
-
-		    source = sk;
-		    if (nonblocking (sk) < 0) {
-			close (sk);
-			continue;
-		    }
-		} else if (strncmp (line, "client-command", 14) == 0) {
-		    if (source == -1)
-			clients_add_command (&clients, sk, line);
-		} else if (strncmp (line, "client-trace", 12) == 0) {
-		    if (source == -1) {
-			clients_add_trace (&clients, sk, line);
-			if (nonblocking (sk) < 0) {
-			    close (sk);
-			    continue;
-			}
-
-			if (clients.count == waiter_count) {
-			    for (n = 1; n < num_pfd; n++) {
-				if (pfd[n].fd == waiter) {
-				    pfd[n].fd = -1;
-				    break;
-				}
-			    }
-			    close (waiter);
-			    waiter_count = -1;
-			}
-		    }
-		} else if (strncmp (line, "wait", 4) == 0) {
-		    int count = atoi (line + 5) + 1;
-		    if (clients.count == count) {
-			close (sk);
-			continue;
-		    } else {
-			waiter = sk;
-			waiter_count = count;
-		    }
-		}
-
-		if (num_pfd == size_pfd) {
-		    size_pfd *= 2;
-		    pfd = xrealloc (pfd, sizeof (*pfd) * size_pfd);
-		}
-
-		pfd[num_pfd].fd = sk;
-		pfd[num_pfd].events = POLLIN;
-		pfd[num_pfd].revents = 0;
-		num_pfd++;
-	    }
-	    cnt--;
-	}
-
-	have_source = 0;
-	for (n = 1; cnt && n < num_pfd; n++) {
-	    if (! pfd[n].revents)
-		continue;
-	    cnt--;
-
-	    if (pfd[n].fd == -1)
-		continue;
-
-	    if (source == pfd[n].fd) {
-		have_source = n;
-	    } else {
-		len = readline (pfd[n].fd, line, sizeof (line));
-		if (len < 0) {
-		    clients_remove (&clients, pfd[n].fd);
-		    close (pfd[n].fd);
-		    pfd[n].fd = -1;
-		    continue;
-		}
-
-		 if (strncmp (line, ".image", 6) == 0) {
-		    if (! clients_image (&clients, pfd[n].fd, line + 7)) {
-			clients_remove (&clients, pfd[n].fd);
-			close (pfd[n].fd);
-			pfd[n].fd = -1;
-			continue;
-		    }
-		} else if (strncmp (line, ".complete", 9) == 0) {
-		    clients_complete (&clients, pfd[n].fd);
-		} else if (strncmp (line, ".recording", 10) == 0) {
-		    clients_recording (&clients, pfd[n].fd, line + 6);
-		} else {
-		    printf ("do_command (%s)\n", line);
-		}
-	    }
-	}
-
-	if (have_source) {
-	    do {
-		len = read (source, line, sizeof (line));
-		if (len > 0) {
-		    clients_send_trace (&clients, line, len);
-		} else if (len == 0) {
-		    close (source);
-		    pfd[have_source].fd = source = -1;
-		    goto done;
-		} else
-		    break;
-	    } while (1);
-	}
-
-	for (n = cnt = 1; n < num_pfd; n++) {
-	    if (pfd[n].fd != -1) {
-		if (cnt != n)
-		    pfd[cnt] = pfd[n];
-		cnt++;
-	    }
-	}
-	num_pfd = cnt;
-    }
-
-done:
-    ret = 0;
-    for (n = 0; n < num_pfd; n++) {
-	if (pfd[n].fd != -1)
-	    close (pfd[n].fd);
-    }
-    free (pfd);
-    clients_fini (&clients);
-
-    return ret;
-}
-
-static void *
-client_shm (const char *shm_path)
-{
-    void *base;
-    int fd;
-
-    fd = shm_open (shm_path, O_RDWR, 0);
-    if (fd == -1)
-	return MAP_FAILED;
-
-    base = mmap (NULL, DATA_SIZE,
-		 PROT_READ | PROT_WRITE,
-#ifdef MAP_NORESERVE
-		 MAP_SHARED | MAP_NORESERVE,
-#else
-		 MAP_SHARED,
-#endif
-		 fd, 0);
-    close (fd);
-
-    return base;
-}
-
-static int
-client_socket (const char *socket_path)
-{
-    struct sockaddr_un addr;
-    int sk;
-
-    sk = socket (PF_UNIX, SOCK_STREAM, 0);
-    if (sk == -1)
-	return -1;
-
-    memset (&addr, 0, sizeof (addr));
-    addr.sun_family = AF_UNIX;
-    strcpy (addr.sun_path, socket_path);
-
-    if (connect (sk, (struct sockaddr *) &addr, sizeof (addr)) == -1)
-	return -1;
-
-    return sk;
-}
-
-static int
-do_client (int fd,
-	   const char *target,
-	   const char *name,
-	   const char *reference,
-	   cairo_content_t content)
-{
-    struct client client;
-    const cairo_script_interpreter_hooks_t hooks = {
-	.closure = &client,
-	.surface_create = _surface_create,
-	.context_create = _context_create,
-	.context_destroy = _context_destroy,
-    };
-    void *closure;
-    char *buf;
-    int buf_size;
-    int len = 0, ret;
-    struct pollfd pfd;
-
-    client.sk = fd;
-    client.target = cairo_boilerplate_get_target_by_name (target, content);
-    client.context_id = 0;
-
-    client.surface = client.target->create_surface (NULL, content, 1, 1, 1, 1,
-						    CAIRO_BOILERPLATE_MODE_TEST,
-						    &closure);
-    if (client.surface == NULL) {
-	fprintf (stderr, "Failed to create target surface: %s.\n",
-		 client.target->name);
-	return 1;
-    }
-
-    buf_size = 65536;
-    buf = xmalloc (buf_size);
-
-    if (reference != NULL) {
-	len = sprintf (buf,
-		       "client-command name=%s target=%s reference=%s\n",
-		       name, target, reference);
-    } else {
-	len = sprintf (buf,
-		       "client-command name=%s target=%s\n",
-		       name, target);
-    }
-    if (! writen (fd, buf, len))
-	return 1;
-
-    len = readline (fd, buf, buf_size);
-    client.base = client_shm (buf);
-    if (client.base == MAP_FAILED) {
-	fprintf (stderr, "Failed to map shared memory segment '%s'.\n", buf);
-	return 1;
-    }
-
-    if (daemonize () < 0)
-	return 1;
-
-    pfd.fd = client_socket ("/tmp/cairo-sphinx");
-    if (pfd.fd < 0)
-	return 1;
-
-    len = sprintf (buf, "client-trace name=%s\n", name);
-    if (! writen (pfd.fd, buf, len))
-	return 1;
-
-    client.csi = cairo_script_interpreter_create ();
-    cairo_script_interpreter_install_hooks (client.csi, &hooks);
-
-    nonblocking (pfd.fd);
-    pfd.events = POLLIN;
-    len = 0;
-    while (poll (&pfd, 1, -1) > 0) {
-	while ((ret = read (pfd.fd, buf + len, buf_size - len)) > 0) {
-	    int end;
-
-	    if (ret == buf_size - len) {
-		buf_size *= 2;
-		buf = xrealloc (buf, buf_size);
-	    }
-	    len += ret;
-
-	    for (end = len; end > 0 && buf[--end] != '\n'; )
-		;
-	    if (end > 0) {
-		buf[end] = '\0';
-		cairo_script_interpreter_feed_string (client.csi, buf, end);
-
-		len -= end + 1;
-		if (len)
-		    memmove (buf, buf + end + 1, len);
-	    }
-	}
-	if (ret == 0)
-	    break;
-	if (! (errno == EAGAIN || errno == EINTR))
-	    break;
-    }
-
-    cairo_script_interpreter_finish (client.csi);
-    cairo_script_interpreter_destroy (client.csi);
-
-    cairo_surface_destroy (client.surface);
-    close (fd);
-
-    return 0;
-}
-
-static int
-do_exec (int fd, char **argv)
-{
-    char buf[4096];
-
-    if (*argv == NULL)
-	return 0;
-
-    snprintf (buf, sizeof (buf), "%s/cairo-trace.so", LIBDIR);
-    setenv ("LD_PRELOAD", buf, 1);
-
-    snprintf (buf, sizeof (buf), "0");
-    setenv ("CAIRO_TRACE_LINE_INFO", buf, 1);
-
-    snprintf (buf, sizeof (buf), "%d", fd);
-    setenv ("CAIRO_TRACE_FD", buf, 1);
-    putenv (buf);
-
-    return execvp (argv[0], argv);
-}
-
-static int
-do_wait (int fd)
-{
-    char buf;
-    int ret = read (fd, &buf, 1);
-    return ret != 0;
-}
-
-int
-main (int argc, char **argv)
-{
-    char buf[4096];
-    int len;
-    int fd;
-
-    if (argc == 1)
-	return do_server ("/tmp/cairo-sphinx");
-
-    fd = client_socket ("/tmp/cairo-sphinx");
-    if (fd < 0)
-	return 1;
-
-    if (strcmp (argv[1], "client") == 0) {
-	return do_client (fd, argv[2], argv[3], argv[4],
-			  CAIRO_CONTENT_COLOR_ALPHA);
-    }
-
-    if (strcmp (argv[1], "wait") == 0) {
-	len = snprintf (buf, sizeof (buf), "wait %s\n", argv[2]);
-	if (! writen (fd, buf, len))
-	    return 1;
-
-	return do_wait (fd);
-    }
-
-    if (strcmp (argv[1], "exec") == 0) {
-	len = snprintf (buf, sizeof (buf), "source\n");
-	if (! writen (fd, buf, len))
-	    return 1;
-
-	return do_exec (fd, argv+2);
-    }
-
-    if (strcmp (argv[1], "replay") == 0) {
-	len = snprintf (buf, sizeof (buf), "replay %s\n", argv[2]);
-	return ! writen (fd, buf, len);
-    }
-
-    return 0;
-}
diff --git a/util/meson.build b/util/meson.build
index a598d9daf..d64dbad0b 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -22,16 +22,6 @@ if conf.get('CAIRO_HAS_TRACE', 0) == 1
   endif
 endif
 
-if (glib_dep.found() and
-    png_dep.found() and
-    have_shm and
-    host_machine.system() != 'windows' and
-    conf.get('CAIRO_HAS_DLSYM', 0) == 1 and
-    feature_conf.get('CAIRO_HAS_SCRIPT_SURFACE', 0) == 1 and
-    feature_conf.get('CAIRO_HAS_TEE_SURFACE', 0) == 1)
-  subdir('cairo-sphinx')
-endif
-
 if gtk_dep.found()
   cairo_utils += [
     ['show-contour.c', {'deps': [gtk_dep]}],


More information about the cairo-commit mailing list