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