diff options
Diffstat (limited to 'util/cairo-script/csi-replay.c')
-rwxr-xr-x | util/cairo-script/csi-replay.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c new file mode 100755 index 000000000..67fed3b33 --- /dev/null +++ b/util/cairo-script/csi-replay.c @@ -0,0 +1,360 @@ +#include <cairo.h> +#include <cairo-script-interpreter.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const cairo_user_data_key_t _key; + +#define SINGLE_SURFACE 1 + +#if SINGLE_SURFACE +static cairo_surface_t * +_similar_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + return cairo_surface_create_similar (closure, content, width, height); +} + +static struct list { + struct list *next; + cairo_t *context; + cairo_surface_t *surface; +} *list; + +static cairo_t * +_context_create (void *closure, cairo_surface_t *surface) +{ + cairo_t *cr = cairo_create (surface); + struct list *l = malloc (sizeof (*l)); + l->next = list; + l->context = cr; + l->surface = cairo_surface_reference (surface); + list = l; + return cr; +} + +static void +_context_destroy (void *closure, void *ptr) +{ + struct list *l, **prev = &list; + while ((l = *prev) != NULL) { + if (l->context == ptr) { + if (cairo_surface_status (l->surface) == CAIRO_STATUS_SUCCESS) { + cairo_t *cr = cairo_create (closure); + cairo_set_source_surface (cr, l->surface, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + } + + cairo_surface_destroy (l->surface); + *prev = l->next; + free (l); + return; + } + prev = &l->next; + } +} +#endif + +#if CAIRO_HAS_XLIB_SURFACE +#include <cairo-xlib.h> +static Display * +_get_display (void) +{ + static Display *dpy; + + if (dpy != NULL) + return dpy; + + dpy = XOpenDisplay (NULL); + if (dpy == NULL) { + fprintf (stderr, "Failed to open display.\n"); + exit (1); + } + + return dpy; +} + +static void +_destroy_window (void *closure) +{ + XFlush (_get_display ()); + XDestroyWindow (_get_display(), (Window) closure); +} + +static cairo_surface_t * +_xlib_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + Display *dpy; + XSetWindowAttributes attr; + Visual *visual; + int depth; + Window w; + cairo_surface_t *surface; + + dpy = _get_display (); + + visual = DefaultVisual (dpy, DefaultScreen (dpy)); + depth = DefaultDepth (dpy, DefaultScreen (dpy)); + attr.override_redirect = True; + w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, + width <= 0 ? 1 : width, + height <= 0 ? 1 : height, + 0, depth, + InputOutput, visual, CWOverrideRedirect, &attr); + XMapWindow (dpy, w); + + surface = cairo_xlib_surface_create (dpy, w, visual, width, height); + cairo_surface_set_user_data (surface, &_key, (void *) w, _destroy_window); + + return surface; +} + +#if CAIRO_HAS_XLIB_XRENDER_SURFACE +#include <cairo-xlib-xrender.h> + +static void +_destroy_pixmap (void *closure) +{ + XFreePixmap (_get_display(), (Pixmap) closure); +} + +static cairo_surface_t * +_xrender_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + Display *dpy; + Pixmap pixmap; + XRenderPictFormat *xrender_format; + cairo_surface_t *surface; + + dpy = _get_display (); + + content = CAIRO_CONTENT_COLOR_ALPHA; + + switch (content) { + case CAIRO_CONTENT_COLOR_ALPHA: + xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32); + break; + case CAIRO_CONTENT_COLOR: + xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24); + break; + case CAIRO_CONTENT_ALPHA: + default: + xrender_format = XRenderFindStandardFormat (dpy, PictStandardA8); + } + + pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy), + width, height, xrender_format->depth); + + surface = cairo_xlib_surface_create_with_xrender_format (dpy, pixmap, + DefaultScreenOfDisplay (dpy), + xrender_format, + width, height); + cairo_surface_set_user_data (surface, &_key, + (void *) pixmap, _destroy_pixmap); + + return surface; +} +#endif +#endif + +#if CAIRO_HAS_GL_GLX_SURFACE +#include <cairo-gl.h> +static cairo_gl_context_t * +_glx_get_context (cairo_content_t content) +{ + static cairo_gl_context_t *context; + + if (context == NULL) { + int rgba_attribs[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_ALPHA_SIZE, 1, + GLX_DOUBLEBUFFER, + None + }; + XVisualInfo *visinfo; + GLXContext gl_ctx; + Display *dpy; + + dpy = XOpenDisplay (NULL); + if (dpy == NULL) { + fprintf (stderr, "Failed to open display.\n"); + exit (1); + } + + visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); + if (visinfo == NULL) { + fprintf (stderr, "Failed to create RGBA, double-buffered visual\n"); + exit (1); + } + + gl_ctx = glXCreateContext (dpy, visinfo, NULL, True); + XFree (visinfo); + + context = cairo_glx_context_create (dpy, gl_ctx); + } + + return context; +} + +static cairo_surface_t * +_glx_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + if (width == 0) + width = 1; + if (height == 0) + height = 1; + + return cairo_gl_surface_create (_glx_get_context (content), + content, width, height); +} +#endif + +#if CAIRO_HAS_PDF_SURFACE +#include <cairo-pdf.h> +static cairo_surface_t * +_pdf_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + return cairo_pdf_surface_create_for_stream (NULL, NULL, width, height); +} +#endif + +#if CAIRO_HAS_PS_SURFACE +#include <cairo-ps.h> +static cairo_surface_t * +_ps_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + return cairo_ps_surface_create_for_stream (NULL, NULL, width, height); +} +#endif + +#if CAIRO_HAS_SVG_SURFACE +#include <cairo-svg.h> +static cairo_surface_t * +_svg_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + return cairo_svg_surface_create_for_stream (NULL, NULL, width, height); +} +#endif + +static cairo_surface_t * +_image_surface_create (void *closure, + cairo_content_t content, + double width, double height, + long uid) +{ + return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); +} + +int +main (int argc, char **argv) +{ + cairo_script_interpreter_t *csi; + cairo_script_interpreter_hooks_t hooks = { +#if SINGLE_SURFACE + .surface_create = _similar_surface_create, + .context_create = _context_create, + .context_destroy = _context_destroy +#elif CAIRO_HAS_XLIB_XRENDER_SURFACE + .surface_create = _xrender_surface_create +#elif CAIRO_HAS_XLIB_SURFACE + .surface_create = _xlib_surface_create +#elif CAIRO_PDF_SURFACE + .surface_create = _pdf_surface_create +#elif CAIRO_PS_SURFACE + .surface_create = _ps_surface_create +#elif CAIRO_SVG_SURFACE + .surface_create = _svg_surface_create +#else + .surface_create = _image_surface_create +#endif + }; + int i; + const struct backends { + const char *name; + csi_surface_create_func_t create; + } backends[] = { + { "--image", _image_surface_create }, +#if CAIRO_HAS_XLIB_XRENDER_SURFACE + { "--xrender", _xrender_surface_create }, +#endif +#if CAIRO_HAS_GL_GLX_SURFACE + { "--glx", _glx_surface_create }, +#endif +#if CAIRO_HAS_XLIB_SURFACE + { "--xlib", _xlib_surface_create }, +#endif +#if CAIRO_HAS_PDF_SURFACE + { "--pdf", _pdf_surface_create }, +#endif +#if CAIRO_HAS_PS_SURFACE + { "--ps", _ps_surface_create }, +#endif +#if CAIRO_HAS_SVG_SURFACE + { "--svg", _svg_surface_create }, +#endif + { NULL, NULL } + }; + +#if SINGLE_SURFACE + hooks.closure = backends[0].create (NULL, + CAIRO_CONTENT_COLOR_ALPHA, + 512, 512, + 0); +#endif + + + csi = cairo_script_interpreter_create (); + cairo_script_interpreter_install_hooks (csi, &hooks); + + for (i = 1; i < argc; i++) { + const struct backends *b; + + for (b = backends; b->name != NULL; b++) { + if (strcmp (b->name, argv[i]) == 0) { +#if SINGLE_SURFACE + cairo_surface_destroy (hooks.closure); + hooks.closure = b->create (NULL, + CAIRO_CONTENT_COLOR_ALPHA, + 512, 512, + 0); +#else + hooks.surface_create = b->create; +#endif + cairo_script_interpreter_install_hooks (csi, &hooks); + break; + } + } + + if (b->name == NULL) + cairo_script_interpreter_run (csi, argv[i]); + } + cairo_surface_destroy (hooks.closure); + + return cairo_script_interpreter_destroy (csi); +} |