/util/cairo-script/csi-replay.c

https://github.com/miyabe/cairo · C · 360 lines · 312 code · 48 blank · 0 comment · 28 complexity · a68973246f79375ad96d35235883ea68 MD5 · raw file

  1. #include <cairo.h>
  2. #include <cairo-script-interpreter.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. static const cairo_user_data_key_t _key;
  7. #define SINGLE_SURFACE 1
  8. #if SINGLE_SURFACE
  9. static cairo_surface_t *
  10. _similar_surface_create (void *closure,
  11. cairo_content_t content,
  12. double width, double height,
  13. long uid)
  14. {
  15. return cairo_surface_create_similar (closure, content, width, height);
  16. }
  17. static struct list {
  18. struct list *next;
  19. cairo_t *context;
  20. cairo_surface_t *surface;
  21. } *list;
  22. static cairo_t *
  23. _context_create (void *closure, cairo_surface_t *surface)
  24. {
  25. cairo_t *cr = cairo_create (surface);
  26. struct list *l = malloc (sizeof (*l));
  27. l->next = list;
  28. l->context = cr;
  29. l->surface = cairo_surface_reference (surface);
  30. list = l;
  31. return cr;
  32. }
  33. static void
  34. _context_destroy (void *closure, void *ptr)
  35. {
  36. struct list *l, **prev = &list;
  37. while ((l = *prev) != NULL) {
  38. if (l->context == ptr) {
  39. if (cairo_surface_status (l->surface) == CAIRO_STATUS_SUCCESS) {
  40. cairo_t *cr = cairo_create (closure);
  41. cairo_set_source_surface (cr, l->surface, 0, 0);
  42. cairo_paint (cr);
  43. cairo_destroy (cr);
  44. }
  45. cairo_surface_destroy (l->surface);
  46. *prev = l->next;
  47. free (l);
  48. return;
  49. }
  50. prev = &l->next;
  51. }
  52. }
  53. #endif
  54. #if CAIRO_HAS_XLIB_SURFACE
  55. #include <cairo-xlib.h>
  56. static Display *
  57. _get_display (void)
  58. {
  59. static Display *dpy;
  60. if (dpy != NULL)
  61. return dpy;
  62. dpy = XOpenDisplay (NULL);
  63. if (dpy == NULL) {
  64. fprintf (stderr, "Failed to open display.\n");
  65. exit (1);
  66. }
  67. return dpy;
  68. }
  69. static void
  70. _destroy_window (void *closure)
  71. {
  72. XFlush (_get_display ());
  73. XDestroyWindow (_get_display(), (Window) closure);
  74. }
  75. static cairo_surface_t *
  76. _xlib_surface_create (void *closure,
  77. cairo_content_t content,
  78. double width, double height,
  79. long uid)
  80. {
  81. Display *dpy;
  82. XSetWindowAttributes attr;
  83. Visual *visual;
  84. int depth;
  85. Window w;
  86. cairo_surface_t *surface;
  87. dpy = _get_display ();
  88. visual = DefaultVisual (dpy, DefaultScreen (dpy));
  89. depth = DefaultDepth (dpy, DefaultScreen (dpy));
  90. attr.override_redirect = True;
  91. w = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
  92. width <= 0 ? 1 : width,
  93. height <= 0 ? 1 : height,
  94. 0, depth,
  95. InputOutput, visual, CWOverrideRedirect, &attr);
  96. XMapWindow (dpy, w);
  97. surface = cairo_xlib_surface_create (dpy, w, visual, width, height);
  98. cairo_surface_set_user_data (surface, &_key, (void *) w, _destroy_window);
  99. return surface;
  100. }
  101. #if CAIRO_HAS_XLIB_XRENDER_SURFACE
  102. #include <cairo-xlib-xrender.h>
  103. static void
  104. _destroy_pixmap (void *closure)
  105. {
  106. XFreePixmap (_get_display(), (Pixmap) closure);
  107. }
  108. static cairo_surface_t *
  109. _xrender_surface_create (void *closure,
  110. cairo_content_t content,
  111. double width, double height,
  112. long uid)
  113. {
  114. Display *dpy;
  115. Pixmap pixmap;
  116. XRenderPictFormat *xrender_format;
  117. cairo_surface_t *surface;
  118. dpy = _get_display ();
  119. content = CAIRO_CONTENT_COLOR_ALPHA;
  120. switch (content) {
  121. case CAIRO_CONTENT_COLOR_ALPHA:
  122. xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
  123. break;
  124. case CAIRO_CONTENT_COLOR:
  125. xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
  126. break;
  127. case CAIRO_CONTENT_ALPHA:
  128. default:
  129. xrender_format = XRenderFindStandardFormat (dpy, PictStandardA8);
  130. }
  131. pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
  132. width, height, xrender_format->depth);
  133. surface = cairo_xlib_surface_create_with_xrender_format (dpy, pixmap,
  134. DefaultScreenOfDisplay (dpy),
  135. xrender_format,
  136. width, height);
  137. cairo_surface_set_user_data (surface, &_key,
  138. (void *) pixmap, _destroy_pixmap);
  139. return surface;
  140. }
  141. #endif
  142. #endif
  143. #if CAIRO_HAS_GL_GLX_SURFACE
  144. #include <cairo-gl.h>
  145. static cairo_gl_context_t *
  146. _glx_get_context (cairo_content_t content)
  147. {
  148. static cairo_gl_context_t *context;
  149. if (context == NULL) {
  150. int rgba_attribs[] = {
  151. GLX_RGBA,
  152. GLX_RED_SIZE, 1,
  153. GLX_GREEN_SIZE, 1,
  154. GLX_BLUE_SIZE, 1,
  155. GLX_ALPHA_SIZE, 1,
  156. GLX_DOUBLEBUFFER,
  157. None
  158. };
  159. XVisualInfo *visinfo;
  160. GLXContext gl_ctx;
  161. Display *dpy;
  162. dpy = XOpenDisplay (NULL);
  163. if (dpy == NULL) {
  164. fprintf (stderr, "Failed to open display.\n");
  165. exit (1);
  166. }
  167. visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
  168. if (visinfo == NULL) {
  169. fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
  170. exit (1);
  171. }
  172. gl_ctx = glXCreateContext (dpy, visinfo, NULL, True);
  173. XFree (visinfo);
  174. context = cairo_glx_context_create (dpy, gl_ctx);
  175. }
  176. return context;
  177. }
  178. static cairo_surface_t *
  179. _glx_surface_create (void *closure,
  180. cairo_content_t content,
  181. double width, double height,
  182. long uid)
  183. {
  184. if (width == 0)
  185. width = 1;
  186. if (height == 0)
  187. height = 1;
  188. return cairo_gl_surface_create (_glx_get_context (content),
  189. content, width, height);
  190. }
  191. #endif
  192. #if CAIRO_HAS_PDF_SURFACE
  193. #include <cairo-pdf.h>
  194. static cairo_surface_t *
  195. _pdf_surface_create (void *closure,
  196. cairo_content_t content,
  197. double width, double height,
  198. long uid)
  199. {
  200. return cairo_pdf_surface_create_for_stream (NULL, NULL, width, height);
  201. }
  202. #endif
  203. #if CAIRO_HAS_PS_SURFACE
  204. #include <cairo-ps.h>
  205. static cairo_surface_t *
  206. _ps_surface_create (void *closure,
  207. cairo_content_t content,
  208. double width, double height,
  209. long uid)
  210. {
  211. return cairo_ps_surface_create_for_stream (NULL, NULL, width, height);
  212. }
  213. #endif
  214. #if CAIRO_HAS_SVG_SURFACE
  215. #include <cairo-svg.h>
  216. static cairo_surface_t *
  217. _svg_surface_create (void *closure,
  218. cairo_content_t content,
  219. double width, double height,
  220. long uid)
  221. {
  222. return cairo_svg_surface_create_for_stream (NULL, NULL, width, height);
  223. }
  224. #endif
  225. static cairo_surface_t *
  226. _image_surface_create (void *closure,
  227. cairo_content_t content,
  228. double width, double height,
  229. long uid)
  230. {
  231. return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
  232. }
  233. int
  234. main (int argc, char **argv)
  235. {
  236. cairo_script_interpreter_t *csi;
  237. cairo_script_interpreter_hooks_t hooks = {
  238. #if SINGLE_SURFACE
  239. .surface_create = _similar_surface_create,
  240. .context_create = _context_create,
  241. .context_destroy = _context_destroy
  242. #elif CAIRO_HAS_XLIB_XRENDER_SURFACE
  243. .surface_create = _xrender_surface_create
  244. #elif CAIRO_HAS_XLIB_SURFACE
  245. .surface_create = _xlib_surface_create
  246. #elif CAIRO_PDF_SURFACE
  247. .surface_create = _pdf_surface_create
  248. #elif CAIRO_PS_SURFACE
  249. .surface_create = _ps_surface_create
  250. #elif CAIRO_SVG_SURFACE
  251. .surface_create = _svg_surface_create
  252. #else
  253. .surface_create = _image_surface_create
  254. #endif
  255. };
  256. int i;
  257. const struct backends {
  258. const char *name;
  259. csi_surface_create_func_t create;
  260. } backends[] = {
  261. { "--image", _image_surface_create },
  262. #if CAIRO_HAS_XLIB_XRENDER_SURFACE
  263. { "--xrender", _xrender_surface_create },
  264. #endif
  265. #if CAIRO_HAS_GL_GLX_SURFACE
  266. { "--glx", _glx_surface_create },
  267. #endif
  268. #if CAIRO_HAS_XLIB_SURFACE
  269. { "--xlib", _xlib_surface_create },
  270. #endif
  271. #if CAIRO_HAS_PDF_SURFACE
  272. { "--pdf", _pdf_surface_create },
  273. #endif
  274. #if CAIRO_HAS_PS_SURFACE
  275. { "--ps", _ps_surface_create },
  276. #endif
  277. #if CAIRO_HAS_SVG_SURFACE
  278. { "--svg", _svg_surface_create },
  279. #endif
  280. { NULL, NULL }
  281. };
  282. #if SINGLE_SURFACE
  283. hooks.closure = backends[0].create (NULL,
  284. CAIRO_CONTENT_COLOR_ALPHA,
  285. 512, 512,
  286. 0);
  287. #endif
  288. csi = cairo_script_interpreter_create ();
  289. cairo_script_interpreter_install_hooks (csi, &hooks);
  290. for (i = 1; i < argc; i++) {
  291. const struct backends *b;
  292. for (b = backends; b->name != NULL; b++) {
  293. if (strcmp (b->name, argv[i]) == 0) {
  294. #if SINGLE_SURFACE
  295. cairo_surface_destroy (hooks.closure);
  296. hooks.closure = b->create (NULL,
  297. CAIRO_CONTENT_COLOR_ALPHA,
  298. 512, 512,
  299. 0);
  300. #else
  301. hooks.surface_create = b->create;
  302. #endif
  303. cairo_script_interpreter_install_hooks (csi, &hooks);
  304. break;
  305. }
  306. }
  307. if (b->name == NULL)
  308. cairo_script_interpreter_run (csi, argv[i]);
  309. }
  310. cairo_surface_destroy (hooks.closure);
  311. return cairo_script_interpreter_destroy (csi);
  312. }