Reset platonic code.
[voro++.git] / branches / 2d_boundary / Tests / svgfig / _viewer.c
bloba250511720a1f449d7948128ecdac0ddac98de21
1 #include <Python.h>
2 #include <gtk/gtk.h>
3 #include <gdk/gdkdrawable.h>
4 #include <gdk/gdkcairo.h>
5 #include <librsvg-2/librsvg/rsvg.h>
6 #include <librsvg-2/librsvg/rsvg-cairo.h>
7 #include <time.h>
9 #ifndef PyMODINIT_FUNC
10 #define PyMODINIT_FUNC void
11 #endif
13 static GtkWidget *window;
14 static GtkWidget *drawing_area;
15 static char ready = 0;
16 static char done = 1;
17 static RsvgHandle *rsvg = NULL;
19 static void draw(GtkWidget *widget, cairo_t *cr) {
20 if (rsvg == NULL) return;
22 double window_width, window_height;
23 window_width = widget->allocation.width;
24 window_height = widget->allocation.height;
26 RsvgDimensionData dimensions;
27 rsvg_handle_get_dimensions(rsvg, &dimensions);
28 unsigned int w, h;
29 w = dimensions.width;
30 h = dimensions.height;
31 double aspect_ratio;
32 aspect_ratio = 1.0 * w / h;
34 double page_width, page_height;
35 page_height = window_height - 8;
36 page_width = page_height * aspect_ratio;
37 if (page_width > window_width - 8) {
38 page_width = window_width - 8;
39 page_height = page_width / aspect_ratio;
41 double x = (window_width - page_width + 4.) / 2.;
42 double y = (window_height - page_height + 4.) / 2.;
44 cairo_rectangle(cr, x, y, page_width, page_height);
45 cairo_set_source_rgb(cr, 1, 1, 1);
46 cairo_fill(cr);
48 cairo_translate(cr, x, y);
49 cairo_scale(cr, page_width/w, page_height/h);
50 rsvg_handle_render_cairo(rsvg, cr);
53 static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event) {
54 ready = 0;
56 cairo_t *cr;
57 cr = gdk_cairo_create(widget->window);
58 cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height);
59 cairo_clip(cr);
60 draw(widget, cr);
61 cairo_destroy(cr);
63 ready = 1;
64 return FALSE;
67 static void *thread() {
68 done = 0;
70 gtk_init(0, NULL);
71 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
72 gtk_window_set_title(GTK_WINDOW(window), "SVGFig");
73 drawing_area = gtk_drawing_area_new();
74 gtk_container_add(GTK_CONTAINER(window), drawing_area);
76 g_signal_connect(GTK_OBJECT(window), "delete_event", (GtkSignalFunc)(gtk_main_quit), NULL);
77 g_signal_connect(GTK_OBJECT(drawing_area), "expose_event", (GtkSignalFunc)(expose_event), NULL);
78 gtk_widget_set_events(drawing_area, GDK_EXPOSURE_MASK);
80 gtk_widget_show(drawing_area);
81 gtk_widget_show(window);
83 ready = 1;
84 gtk_main();
85 done = 1;
86 return NULL;
89 static PyObject *_viewer_str(PyObject *self, PyObject *args) {
90 char *str_source = NULL;
91 int str_size;
92 if (!PyArg_ParseTuple(args, "es#", "utf-16", &str_source, &str_size)) {
93 PyErr_SetString(PyExc_TypeError, "source must be an SVG string or Unicode object.");
94 return NULL;
97 if (done) {
98 GError *error = NULL;
99 if (!g_thread_create(thread, NULL, FALSE, &error)) {
100 PyErr_Format(PyExc_RuntimeError, "Could not create GDK thread: %s", error->message);
101 PyMem_Free(str_source);
102 return NULL;
106 if (rsvg != NULL) {
107 g_object_unref(rsvg);
108 rsvg = NULL;
111 GError* error = NULL;
112 rsvg = rsvg_handle_new_from_data((guint8*)(str_source), (gsize)(str_size), &error);
113 if (rsvg == NULL) {
114 PyErr_Format(PyExc_RuntimeError, "Couldn't parse SVG: %s", error->message);
115 PyMem_Free(str_source);
116 return NULL;
119 /* wait for the window to appear, and don't wait forever */
120 /* if 5 seconds are reached, don't explicitly throw an error, let */
121 /* GDK do that if it needs to */
122 g_thread_yield();
123 time_t start = time(NULL);
124 while (!ready) {
125 time_t now = time(NULL);
126 if (difftime(now, start) > 5) break;
129 gdk_threads_enter();
130 gtk_widget_queue_draw(drawing_area);
131 gdk_threads_leave();
133 PyMem_Free(str_source);
134 return Py_BuildValue("O", Py_None);
137 static PyMethodDef _viewer_methods[] = {
138 {"str", ((PyCFunction)(_viewer_str)), METH_VARARGS, ""},
139 {NULL}
142 PyMODINIT_FUNC init_viewer() {
143 Py_InitModule3("_viewer", _viewer_methods, "");
144 rsvg_init();
145 g_thread_init(NULL);
146 gdk_threads_init();