[demo] Set the translation domain on GtkBuilder
[adg.git] / demo / cpml-demo.c
blob4e9288599668bd2f51be60cec859cf5a7a9035f2
1 #include <config.h>
2 #include "demo.h"
3 #include <cpml.h>
4 #include <math.h>
7 static void parse_args (gint *p_argc,
8 gchar **p_argv[]);
9 static cairo_path_t *
10 duplicate_and_stroke (cairo_t *cr);
11 static void stroke_and_destroy (cairo_t *cr,
12 cairo_path_t *path);
14 static void browsing (GtkWidget *widget,
15 GdkEventExpose *event,
16 gpointer user_data);
17 static void browsing_segment (GtkToggleButton*togglebutton,
18 gpointer user_data);
19 static void browsing_primitive (GtkToggleButton*togglebutton,
20 gpointer user_data);
21 static void browsing_reset (GtkButton *button,
22 gpointer user_data);
23 static void browsing_next (GtkButton *button,
24 gpointer user_data);
26 static void arcs (GtkWidget *widget,
27 GdkEventExpose *event,
28 gpointer user_data);
29 static void arc3p (cairo_t *cr,
30 double x1,
31 double y1,
32 double x2,
33 double y2,
34 double x3,
35 double y3);
37 static void intersections (GtkWidget *widget,
38 GdkEventExpose *event,
39 gpointer user_data);
41 static void offset_curves (GtkWidget *widget,
42 GdkEventExpose *event,
43 gpointer user_data);
45 static void offset_segments (GtkWidget *widget,
46 GdkEventExpose *event,
47 gpointer user_data);
49 static void circle_callback (cairo_t *cr);
50 static void piston_callback (cairo_t *cr);
51 static void curve1_callback (cairo_t *cr);
52 static void line1_callback (cairo_t *cr);
54 static struct {
55 GtkWidget *area;
56 cairo_path_t *cairo_path;
57 gboolean use_segment;
58 CpmlSegment segment;
59 CpmlPrimitive primitive;
60 } browsing_data = {
61 NULL,
64 static CpmlPair bezier_samples[][4] = {
65 { { 0, 0 }, { 0, 40 }, { 120, 40 }, { 120, 0 } }, /* Simmetric low */
66 { { 40, 0 }, { 40, 160 }, { 80, 160 }, { 80, 0 } }, /* Simmetric high */
67 { { 0, 0 }, { 33.1371, 33.1371 }, { 86.8629, 33.1371 }, { 120, 0 } },
68 /* Arc approximation */
69 { { 0, 0 }, { 70, 120 }, { 50, 120 }, { 120, 0 } }, /* Twisted controls */
71 { { 0, 0 }, { 0, 120 }, { 60, 120 }, { 120, 0 } }, /* Vertical p1-p2 */
72 { { 0, 0 }, { 60, 120 }, { 120, 120 }, { 120, 0 } },/* Vertical p3-p4 */
73 { { 0, 120 }, { 120, 120 }, { 120, 60 }, { 0, 0 } },/* Horizontal p1-p2 */
74 { { 0, 120 }, { 120, 60 }, { 120, 0 }, { 0, 0 } }, /* Horizontal p3-p4 */
76 { { 0, 0 }, { 0, 120 }, { 120, 120 }, { 120, 0 } }, /* Down */
77 { { 0, 120 }, { 120, 120 }, { 120, 0 }, { 0, 0 } }, /* Right */
78 { { 0, 120 }, { 0, 0 }, { 120, 0 }, { 120, 120 } }, /* Up */
79 { { 120, 120 }, { 0, 120 }, { 0, 0 }, { 120, 0 } }, /* Left */
81 { { 0, 60 }, { 60, 120 }, { 120, 60 }, { 60, 0 } }, /* Down-right */
82 { { 60, 120 }, { 120, 60 }, { 60, 0 }, { 0, 60 } }, /* Up-right */
83 { { 120, 60 }, { 60, 0 }, { 0, 60 }, { 60, 120 } }, /* Up-left */
84 { { 60, 0 }, { 0, 60 }, { 60, 120 }, { 120, 60 } }, /* Down-left*/
86 { { 0, 0 }, { 60, 0 }, { 60, 120 }, { 120, 120 } }, /* Step left */
87 { { 120, 0 }, { 60, 0 }, { 60, 120 }, { 0, 120 } }, /* Step right */
88 { { 0, 0 }, { 60, 90 }, { 90, 120 }, { 120, 90 } }, /* Unbalanced opened */
89 { { 0, 0 }, { 40, 120 }, { 120, 120 }, { 60, 80 } } /* Unbalanced closed */
92 static void (*path_samples[]) (cairo_t *cr) = {
93 circle_callback,
94 piston_callback,
95 curve1_callback,
96 line1_callback,
101 main(gint argc, gchar **argv)
103 gchar *path;
104 GtkBuilder *builder;
105 GError *error;
106 GtkWidget *window;
108 parse_args(&argc, &argv);
110 path = demo_find_data_file("cpml-demo.ui", argv[0]);
111 if (path == NULL) {
112 g_print("cpml-demo.ui not found!\n");
113 return 1;
116 builder = gtk_builder_new();
117 error = NULL;
119 gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
120 gtk_builder_add_from_file(builder, path, &error);
121 if (error != NULL) {
122 g_print("%s\n", error->message);
123 return 2;
126 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
128 /* Connect signals */
129 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
130 g_signal_connect(gtk_builder_get_object(builder, "areaBrowsing"),
131 "expose-event", G_CALLBACK(browsing), NULL);
132 g_signal_connect(gtk_builder_get_object(builder, "optBrowsingSegment"),
133 "toggled", G_CALLBACK(browsing_segment), NULL);
134 g_signal_connect(gtk_builder_get_object(builder, "optBrowsingPrimitive"),
135 "toggled", G_CALLBACK(browsing_primitive), NULL);
136 g_signal_connect(gtk_builder_get_object(builder, "btnBrowsingReset"),
137 "clicked", G_CALLBACK(browsing_reset), NULL);
138 g_signal_connect(gtk_builder_get_object(builder, "btnBrowsingNext"),
139 "clicked", G_CALLBACK(browsing_next), NULL);
140 g_signal_connect(gtk_builder_get_object(builder, "areaArcs"),
141 "expose-event", G_CALLBACK(arcs), NULL);
142 g_signal_connect(gtk_builder_get_object(builder, "areaIntersections"),
143 "expose-event", G_CALLBACK(intersections), NULL);
144 g_signal_connect(gtk_builder_get_object(builder, "areaOffsetCurves"),
145 "expose-event", G_CALLBACK(offset_curves), NULL);
146 g_signal_connect(gtk_builder_get_object(builder, "areaOffsetSegments"),
147 "expose-event", G_CALLBACK(offset_segments), NULL);
148 g_signal_connect(gtk_builder_get_object(builder, "btnQuit"),
149 "clicked", G_CALLBACK(gtk_main_quit), NULL);
151 g_object_unref(builder);
153 gtk_widget_show_all(window);
154 gtk_main();
156 return 0;
160 /**********************************************
161 * Command line options parser
162 **********************************************/
164 static void
165 version(void)
167 g_print("cpml-demo " PACKAGE_VERSION "\n");
168 exit(0);
171 static void
172 parse_args(gint *p_argc, gchar **p_argv[])
174 GError *error = NULL;
175 GOptionEntry entries[] = {
176 {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, version,
177 "Display version information", NULL},
178 {NULL}
181 gtk_init_with_args(p_argc, p_argv, "- CPML demonstration program",
182 entries, NULL, &error);
184 if (error != NULL) {
185 gint error_code = error->code;
187 g_printerr("%s\n", error->message);
189 g_error_free(error);
190 exit(error_code);
195 static cairo_path_t *
196 duplicate_and_stroke(cairo_t *cr)
198 cairo_path_t *path = cairo_copy_path(cr);
200 cairo_set_line_width(cr, 2.);
201 cairo_stroke(cr);
203 return path;
206 static void
207 stroke_and_destroy(cairo_t *cr, cairo_path_t *path)
209 cairo_append_path(cr, path);
210 cairo_path_destroy(path);
212 cairo_set_line_width(cr, 1.);
213 cairo_stroke(cr);
217 static void
218 browsing(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
220 cairo_t *cr;
221 int n;
223 cr = gdk_cairo_create(widget->window);
225 if (browsing_data.area == NULL) {
226 /* Initialize browsing_data */
227 browsing_data.area = widget;
228 browsing_data.use_segment = TRUE;
230 /* Append all the path samples to the cairo context */
231 cairo_save(cr);
232 cairo_translate(cr, 270.5, -120.5);
233 for (n = 0; n < G_N_ELEMENTS(path_samples); ++n) {
234 if ((n & 1) == 0) {
235 cairo_translate(cr, -270., 240.);
236 } else {
237 cairo_translate(cr, 270., 0.);
240 (path_samples[n]) (cr);
243 cairo_restore(cr);
244 browsing_data.cairo_path = cairo_copy_path(cr);
245 cpml_segment_from_cairo(&browsing_data.segment,
246 browsing_data.cairo_path);
247 cpml_primitive_from_segment(&browsing_data.primitive,
248 &browsing_data.segment);
249 } else {
250 cairo_append_path(cr, browsing_data.cairo_path);
253 cairo_set_line_width(cr, 2.);
254 cairo_stroke(cr);
256 cairo_set_source_rgb(cr, 1., 0.4, 0.);
257 cairo_set_line_width(cr, 5.);
259 if (browsing_data.use_segment)
260 cpml_segment_to_cairo(&browsing_data.segment, cr);
261 else
262 cpml_primitive_to_cairo(&browsing_data.primitive, cr);
264 cairo_stroke(cr);
265 cairo_destroy(cr);
268 static void
269 browsing_segment(GtkToggleButton *togglebutton, gpointer user_data)
271 if (!gtk_toggle_button_get_active(togglebutton))
272 return;
274 browsing_data.use_segment = TRUE;
275 gtk_widget_queue_draw(browsing_data.area);
278 static void
279 browsing_primitive(GtkToggleButton*togglebutton, gpointer user_data)
281 if (!gtk_toggle_button_get_active(togglebutton))
282 return;
284 browsing_data.use_segment = FALSE;
285 gtk_widget_queue_draw(browsing_data.area);
288 static void
289 browsing_reset(GtkButton *button, gpointer user_data)
291 if (browsing_data.use_segment) {
292 cpml_segment_reset(&browsing_data.segment);
293 cpml_primitive_from_segment(&browsing_data.primitive,
294 &browsing_data.segment);
295 } else {
296 cpml_primitive_reset(&browsing_data.primitive);
299 gtk_widget_queue_draw(browsing_data.area);
302 static void
303 browsing_next(GtkButton *button, gpointer user_data)
305 if (browsing_data.use_segment) {
306 cpml_segment_next(&browsing_data.segment);
307 cpml_primitive_from_segment(&browsing_data.primitive,
308 &browsing_data.segment);
309 } else {
310 cpml_primitive_next(&browsing_data.primitive);
313 gtk_widget_queue_draw(browsing_data.area);
317 static void
318 arcs(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
320 cairo_t *cr = gdk_cairo_create(widget->window);
322 cairo_translate(cr, 100.5, 100.5);
323 arc3p(cr, 0, 0, 0, 120, 120, 120);
325 cairo_translate(cr, 200, 0.);
326 arc3p(cr, 0, 0, 120, 0, 120, 120);
328 cairo_translate(cr, 200, 0.);
329 arc3p(cr, 60, 0, 0, 120, 120, 120);
331 cairo_translate(cr, -400, 200);
332 arc3p(cr, 0, 50, -2, 85, 120, 0);
334 cairo_translate(cr, 200, 0);
335 arc3p(cr, -2, 85, 0, 50, 120, 0);
337 cairo_destroy(cr);
340 static void
341 arc3p(cairo_t *cr, double x1, double y1,
342 double x2, double y2, double x3, double y3)
344 CpmlPrimitive arc;
345 cairo_path_data_t p[4];
346 CpmlPair center;
347 double r, start, end;
349 arc.segment = NULL;
350 arc.org = &p[0];
351 arc.data = &p[1];
353 p[1].header.type = CPML_ARC;
354 p[1].header.length = 3;
356 p[0].point.x = x1;
357 p[0].point.y = y1;
358 p[2].point.x = x2;
359 p[2].point.y = y2;
360 p[3].point.x = x3;
361 p[3].point.y = y3;
363 cpml_primitive_to_cairo(&arc, cr);
365 cairo_set_line_width(cr, 1.);
366 cairo_stroke(cr);
368 /* Add an arc generated by cairo, just for reference */
369 if (!cpml_arc_info(&arc, &center, &r, &start, &end)) {
370 g_print("Unable to get arc info (%lf, %lf) (%lf, %lf) (%lf, %lf)\n",
371 x1, y1, x2, y2, x3, y3);
372 return;
375 if (start < end)
376 cairo_arc(cr, center.x, center.y, r-5., start, end);
377 else
378 cairo_arc_negative(cr, center.x, center.y, r-5., start, end);
380 /* Show the inscribed triangle */
381 cairo_move_to(cr, x1, y1);
382 cairo_line_to(cr, x2, y2);
383 cairo_line_to(cr, x3, y3);
385 cairo_set_line_width(cr, 0.5);
386 cairo_stroke(cr);
390 static void
391 intersections(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
393 cairo_t *cr;
394 cairo_path_t *path;
395 CpmlSegment segment1, segment2;
396 CpmlPair intersection;
398 cr = gdk_cairo_create(widget->window);
399 cairo_translate(cr, 10.5, 120.5);
401 line1_callback(cr);
403 path = cairo_copy_path(cr);
405 cairo_set_line_width(cr, 1.);
406 cairo_stroke(cr);
408 cpml_segment_from_cairo(&segment1, path);
409 cpml_segment_from_cairo(&segment2, path);
411 while (cpml_segment_next(&segment2)) {
412 cpml_segment_put_intersections(&segment1, &segment2, 1, &intersection);
414 cairo_arc(cr, intersection.x, intersection.y, 2.5, 0, 2 * M_PI);
415 cairo_fill(cr);
417 cpml_segment_next(&segment1);
420 cairo_path_destroy(path);
421 cairo_destroy(cr);
425 static void
426 offset_curves(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
428 cairo_t *cr;
429 gint n;
430 CpmlPair *bezier;
431 cairo_path_t *path, *path_copy;
432 CpmlSegment segment;
433 CpmlPrimitive primitive;
434 CpmlPair pair;
435 CpmlVector vector;
436 double t;
438 cr = gdk_cairo_create(widget->window);
440 /* Add the Bézier curve samples */
441 for (n = 0; n < G_N_ELEMENTS(bezier_samples); ++n) {
442 bezier = &bezier_samples[n][0];
444 /* The samples are arranged in a 4x? matrix of 200x150 cells */
445 if (n == 0)
446 cairo_translate(cr, 25., 25.);
447 else if (n % 4 == 0)
448 cairo_translate(cr, -600., 150.);
449 else
450 cairo_translate(cr, 200., 0.);
452 /* Draw the Bézier curve */
453 cairo_move_to(cr, bezier[0].x, bezier[0].y);
454 cairo_curve_to(cr, bezier[1].x, bezier[1].y,
455 bezier[2].x, bezier[2].y, bezier[3].x, bezier[3].y);
457 /* Create a copy, to be used after */
458 path_copy = cairo_copy_path(cr);
460 path = duplicate_and_stroke(cr);
461 cpml_segment_from_cairo(&segment, path);
462 cpml_segment_offset(&segment, 20.);
463 stroke_and_destroy(cr, path);
465 cpml_segment_from_cairo(&segment, path_copy);
466 cpml_primitive_from_segment(&primitive, &segment);
468 /* Checking cpml_curve_put_pair_at_time and cpml_curve_put_vector_at_time */
469 cairo_set_line_width(cr, 1.);
470 for (t = 0; t < 1; t += 0.1) {
471 cpml_curve_put_pair_at_time(&primitive, t, &pair);
472 cpml_curve_put_vector_at_time(&primitive, t, &vector);
473 cpml_vector_set_length(&vector, 20.);
474 cpml_vector_normal(&vector);
476 cairo_new_sub_path(cr);
477 cairo_arc(cr, pair.x, pair.y, 2.5, 0, M_PI*2);
478 cairo_fill(cr);
480 cairo_move_to(cr, pair.x, pair.y);
481 cairo_line_to(cr, pair.x + vector.x, pair.y + vector.y);
482 cairo_stroke(cr);
485 cairo_path_destroy(path_copy);
488 cairo_destroy(cr);
492 static void
493 offset_segments(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
495 cairo_t *cr;
496 cairo_path_t *path;
497 CpmlSegment segment;
498 int n;
500 cr = gdk_cairo_create(widget->window);
501 cairo_translate(cr, 270.5, -120.5);
503 /* Offset the path samples */
504 for (n = 0; n < G_N_ELEMENTS(path_samples); ++n) {
505 if ((n & 1) == 0) {
506 cairo_translate(cr, -270., 240.);
507 } else {
508 cairo_translate(cr, 270., 0.);
511 /* Call the path callback */
512 (path_samples[n]) (cr);
514 path = duplicate_and_stroke(cr);
515 cpml_segment_from_cairo(&segment, path);
516 cpml_segment_offset(&segment, 15.);
517 stroke_and_destroy(cr, path);
520 cairo_destroy(cr);
524 static void
525 circle_callback(cairo_t *cr)
527 cairo_new_sub_path(cr);
528 cairo_arc(cr, 120., 0., 100., 0., M_PI*2);
531 static void
532 piston_callback(cairo_t *cr)
534 cairo_path_t *old_path, *path;
535 cairo_matrix_t matrix;
536 CpmlSegment segment;
538 /* Save the previous path, if any */
539 old_path = cairo_copy_path(cr);
541 cairo_new_path(cr);
542 cairo_move_to(cr, 0., 46.5);
543 cairo_line_to(cr, 210., 46.5);
544 cairo_line_to(cr, 222.5, 35.);
545 cairo_line_to(cr, 270., 35.);
546 cairo_line_to(cr, 270., 56.);
547 cairo_line_to(cr, 273., 59.);
548 cairo_line_to(cr, 302., 59.);
549 cairo_line_to(cr, 305., 56.);
550 cairo_arc(cr, 325., 52.5, 20., G_PI, 3. * G_PI_2);
551 cairo_line_to(cr, 400., 32.5);
552 cairo_line_to(cr, 410., 22.5);
553 cairo_line_to(cr, 450., 22.5);
554 cairo_arc_negative(cr,
555 452., 34., 2., G_PI, G_PI_2);
556 cairo_line_to(cr, 460., 36.);
557 cairo_line_to(cr, 470., 30.);
558 cairo_line_to(cr, 472., 12.5);
560 /* Mirror a reversed copy of the current path on the y = 0 axis */
561 path = cairo_copy_path(cr);
562 cpml_segment_from_cairo(&segment, path);
564 cpml_segment_reverse(&segment);
565 cairo_matrix_init_scale(&matrix, 1., -1.);
566 cpml_segment_transform(&segment, &matrix);
568 /* Join the mirrored path to the old path... */
569 path->data[0].header.type = CPML_LINE;
570 cairo_append_path(cr, path);
571 cairo_path_destroy(path);
573 /* ...and close the shape */
574 cairo_close_path(cr);
576 /* Save the resulting path and clear the path memory */
577 path = cairo_copy_path(cr);
578 cairo_new_path(cr);
580 /* Restore the previous path and reappend the new path */
581 cairo_append_path(cr, old_path);
582 cairo_path_destroy(old_path);
583 cairo_append_path(cr, path);
584 cairo_path_destroy(path);
587 static void
588 curve1_callback(cairo_t *cr)
590 cairo_move_to(cr, 30., 0.);
591 cairo_curve_to(cr, 120., 120., 180., 100., 180., 20.);
592 cairo_curve_to(cr, 180., -20., 50., 40., 150., 40.);
593 cairo_curve_to(cr, 220., 40., 190., -60., 150., -60.);
594 cairo_curve_to(cr, 100., -60., 80., -40., 60., -60.);
597 static void
598 line1_callback(cairo_t *cr)
600 cairo_move_to(cr, 0, -50);
601 cairo_line_to(cr, 100, 50);
603 cairo_move_to(cr, 100, -50);
604 cairo_line_to(cr, 0, 50);
606 cairo_move_to(cr, 120, -50);
607 cairo_line_to(cr, 200, -10);
609 cairo_move_to(cr, 120, 50);
610 cairo_line_to(cr, 200, 10);
612 cairo_move_to(cr, 220, 0);
613 cairo_line_to(cr, 280, 0);
615 cairo_move_to(cr, 270, -40);
616 cairo_line_to(cr, 270, 20);
618 cairo_move_to(cr, 320, 60);
619 cairo_line_to(cr, 380, 60);
621 cairo_move_to(cr, 300, -40);
622 cairo_line_to(cr, 340, 0);
624 cairo_move_to(cr, 480, 10);
625 cairo_line_to(cr, 400, 40);
627 cairo_move_to(cr, 400, 40);
628 cairo_line_to(cr, 450, -40);