[docs] Updated italian localization
[adg.git] / demo / cpml-demo.c
blobf54440a2e5125037fb39567a3dccc7ec087909bb
1 /* Needed for localization support */
2 #include <adg/adg-internal.h>
4 /* Force the reinclusion of adg.h */
5 #undef __ADG_H__
7 #include "demo.h"
8 #include <cpml.h>
9 #include <math.h>
12 static void parse_args (gint *p_argc,
13 gchar **p_argv[]);
14 static cairo_path_t *
15 duplicate_and_stroke (cairo_t *cr);
16 static void stroke_and_destroy (cairo_t *cr,
17 cairo_path_t *path);
19 static void browsing (GtkWidget *widget,
20 GdkEventExpose *event,
21 gpointer user_data);
22 static void browsing_segment (GtkToggleButton*togglebutton,
23 gpointer user_data);
24 static void browsing_primitive (GtkToggleButton*togglebutton,
25 gpointer user_data);
26 static void browsing_reset (GtkButton *button,
27 gpointer user_data);
28 static void browsing_next (GtkButton *button,
29 gpointer user_data);
31 static void arcs (GtkWidget *widget,
32 GdkEventExpose *event,
33 gpointer user_data);
34 static void arc3p (cairo_t *cr,
35 double x1,
36 double y1,
37 double x2,
38 double y2,
39 double x3,
40 double y3);
42 static void intersections (GtkWidget *widget,
43 GdkEventExpose *event,
44 gpointer user_data);
46 static void offset_curves (GtkWidget *widget,
47 GdkEventExpose *event,
48 gpointer user_data);
50 static void offset_segments (GtkWidget *widget,
51 GdkEventExpose *event,
52 gpointer user_data);
54 static void circle_callback (cairo_t *cr);
55 static void piston_callback (cairo_t *cr);
56 static void curve1_callback (cairo_t *cr);
57 static void line1_callback (cairo_t *cr);
59 static struct {
60 GtkWidget *area;
61 cairo_path_t *cairo_path;
62 gboolean use_segment;
63 CpmlSegment segment;
64 CpmlPrimitive primitive;
65 } browsing_data = {
66 NULL,
69 static CpmlPair bezier_samples[][4] = {
70 { { 0, 0 }, { 0, 40 }, { 120, 40 }, { 120, 0 } }, /* Simmetric low */
71 { { 40, 0 }, { 40, 160 }, { 80, 160 }, { 80, 0 } }, /* Simmetric high */
72 { { 0, 0 }, { 33.1371, 33.1371 }, { 86.8629, 33.1371 }, { 120, 0 } },
73 /* Arc approximation */
74 { { 0, 0 }, { 70, 120 }, { 50, 120 }, { 120, 0 } }, /* Twisted controls */
76 { { 0, 0 }, { 0, 120 }, { 60, 120 }, { 120, 0 } }, /* Vertical p1-p2 */
77 { { 0, 0 }, { 60, 120 }, { 120, 120 }, { 120, 0 } },/* Vertical p3-p4 */
78 { { 0, 120 }, { 120, 120 }, { 120, 60 }, { 0, 0 } },/* Horizontal p1-p2 */
79 { { 0, 120 }, { 120, 60 }, { 120, 0 }, { 0, 0 } }, /* Horizontal p3-p4 */
81 { { 0, 0 }, { 0, 120 }, { 120, 120 }, { 120, 0 } }, /* Down */
82 { { 0, 120 }, { 120, 120 }, { 120, 0 }, { 0, 0 } }, /* Right */
83 { { 0, 120 }, { 0, 0 }, { 120, 0 }, { 120, 120 } }, /* Up */
84 { { 120, 120 }, { 0, 120 }, { 0, 0 }, { 120, 0 } }, /* Left */
86 { { 0, 60 }, { 60, 120 }, { 120, 60 }, { 60, 0 } }, /* Down-right */
87 { { 60, 120 }, { 120, 60 }, { 60, 0 }, { 0, 60 } }, /* Up-right */
88 { { 120, 60 }, { 60, 0 }, { 0, 60 }, { 60, 120 } }, /* Up-left */
89 { { 60, 0 }, { 0, 60 }, { 60, 120 }, { 120, 60 } }, /* Down-left*/
91 { { 0, 0 }, { 60, 0 }, { 60, 120 }, { 120, 120 } }, /* Step left */
92 { { 120, 0 }, { 60, 0 }, { 60, 120 }, { 0, 120 } }, /* Step right */
93 { { 0, 0 }, { 60, 90 }, { 90, 120 }, { 120, 90 } }, /* Unbalanced opened */
94 { { 0, 0 }, { 40, 120 }, { 120, 120 }, { 60, 80 } } /* Unbalanced closed */
97 static void (*path_samples[]) (cairo_t *cr) = {
98 circle_callback,
99 piston_callback,
100 curve1_callback,
101 line1_callback,
106 main(gint argc, gchar **argv)
108 gchar *path;
109 GtkBuilder *builder;
110 GError *error;
111 GtkWidget *window;
113 parse_args(&argc, &argv);
115 path = demo_find_data_file("cpml-demo.ui", argv[0]);
116 if (path == NULL) {
117 g_warning(_("cpml-demo.ui not found!\n"));
118 return 1;
121 builder = gtk_builder_new();
122 error = NULL;
124 gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
125 gtk_builder_add_from_file(builder, path, &error);
126 if (error != NULL) {
127 g_print("%s\n", error->message);
128 return 2;
131 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
133 /* Connect signals */
134 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
135 g_signal_connect(gtk_builder_get_object(builder, "areaBrowsing"),
136 "expose-event", G_CALLBACK(browsing), NULL);
137 g_signal_connect(gtk_builder_get_object(builder, "optBrowsingSegment"),
138 "toggled", G_CALLBACK(browsing_segment), NULL);
139 g_signal_connect(gtk_builder_get_object(builder, "optBrowsingPrimitive"),
140 "toggled", G_CALLBACK(browsing_primitive), NULL);
141 g_signal_connect(gtk_builder_get_object(builder, "btnBrowsingReset"),
142 "clicked", G_CALLBACK(browsing_reset), NULL);
143 g_signal_connect(gtk_builder_get_object(builder, "btnBrowsingNext"),
144 "clicked", G_CALLBACK(browsing_next), NULL);
145 g_signal_connect(gtk_builder_get_object(builder, "areaArcs"),
146 "expose-event", G_CALLBACK(arcs), NULL);
147 g_signal_connect(gtk_builder_get_object(builder, "areaIntersections"),
148 "expose-event", G_CALLBACK(intersections), NULL);
149 g_signal_connect(gtk_builder_get_object(builder, "areaOffsetCurves"),
150 "expose-event", G_CALLBACK(offset_curves), NULL);
151 g_signal_connect(gtk_builder_get_object(builder, "areaOffsetSegments"),
152 "expose-event", G_CALLBACK(offset_segments), NULL);
153 g_signal_connect(gtk_builder_get_object(builder, "btnQuit"),
154 "clicked", G_CALLBACK(gtk_main_quit), NULL);
156 g_object_unref(builder);
158 gtk_widget_show_all(window);
159 gtk_main();
161 return 0;
165 /**********************************************
166 * Command line options parser
167 **********************************************/
169 static void
170 version(void)
172 g_print("cpml-demo " PACKAGE_VERSION "\n");
173 exit(0);
176 static void
177 parse_args(gint *p_argc, gchar **p_argv[])
179 GError *error = NULL;
180 GOptionEntry entries[] = {
181 {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, version,
182 _("Display version information"), NULL},
183 {NULL}
186 gtk_init_with_args(p_argc, p_argv, _("- CPML demonstration program"),
187 entries, GETTEXT_PACKAGE, &error);
189 if (error != NULL) {
190 gint error_code = error->code;
192 g_printerr("%s\n", error->message);
194 g_error_free(error);
195 exit(error_code);
200 static cairo_path_t *
201 duplicate_and_stroke(cairo_t *cr)
203 cairo_path_t *path = cairo_copy_path(cr);
205 cairo_set_line_width(cr, 2.);
206 cairo_stroke(cr);
208 return path;
211 static void
212 stroke_and_destroy(cairo_t *cr, cairo_path_t *path)
214 cairo_append_path(cr, path);
215 cairo_path_destroy(path);
217 cairo_set_line_width(cr, 1.);
218 cairo_stroke(cr);
222 static void
223 browsing(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
225 cairo_t *cr;
226 int n;
228 cr = gdk_cairo_create(widget->window);
230 if (browsing_data.area == NULL) {
231 /* Initialize browsing_data */
232 browsing_data.area = widget;
233 browsing_data.use_segment = TRUE;
235 /* Append all the path samples to the cairo context */
236 cairo_save(cr);
237 cairo_translate(cr, 270.5, -120.5);
238 for (n = 0; n < G_N_ELEMENTS(path_samples); ++n) {
239 if ((n & 1) == 0) {
240 cairo_translate(cr, -270., 240.);
241 } else {
242 cairo_translate(cr, 270., 0.);
245 (path_samples[n]) (cr);
248 cairo_restore(cr);
249 browsing_data.cairo_path = cairo_copy_path(cr);
250 cpml_segment_from_cairo(&browsing_data.segment,
251 browsing_data.cairo_path);
252 cpml_primitive_from_segment(&browsing_data.primitive,
253 &browsing_data.segment);
254 } else {
255 cairo_append_path(cr, browsing_data.cairo_path);
258 cairo_set_line_width(cr, 2.);
259 cairo_stroke(cr);
261 cairo_set_source_rgb(cr, 1., 0.4, 0.);
262 cairo_set_line_width(cr, 5.);
264 if (browsing_data.use_segment)
265 cpml_segment_to_cairo(&browsing_data.segment, cr);
266 else
267 cpml_primitive_to_cairo(&browsing_data.primitive, cr);
269 cairo_stroke(cr);
270 cairo_destroy(cr);
273 static void
274 browsing_segment(GtkToggleButton *togglebutton, gpointer user_data)
276 if (!gtk_toggle_button_get_active(togglebutton))
277 return;
279 browsing_data.use_segment = TRUE;
280 gtk_widget_queue_draw(browsing_data.area);
283 static void
284 browsing_primitive(GtkToggleButton*togglebutton, gpointer user_data)
286 if (!gtk_toggle_button_get_active(togglebutton))
287 return;
289 browsing_data.use_segment = FALSE;
290 gtk_widget_queue_draw(browsing_data.area);
293 static void
294 browsing_reset(GtkButton *button, gpointer user_data)
296 if (browsing_data.use_segment) {
297 cpml_segment_reset(&browsing_data.segment);
298 cpml_primitive_from_segment(&browsing_data.primitive,
299 &browsing_data.segment);
300 } else {
301 cpml_primitive_reset(&browsing_data.primitive);
304 gtk_widget_queue_draw(browsing_data.area);
307 static void
308 browsing_next(GtkButton *button, gpointer user_data)
310 if (browsing_data.use_segment) {
311 cpml_segment_next(&browsing_data.segment);
312 cpml_primitive_from_segment(&browsing_data.primitive,
313 &browsing_data.segment);
314 } else {
315 cpml_primitive_next(&browsing_data.primitive);
318 gtk_widget_queue_draw(browsing_data.area);
322 static void
323 arcs(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
325 cairo_t *cr = gdk_cairo_create(widget->window);
327 cairo_translate(cr, 100.5, 100.5);
328 arc3p(cr, 0, 0, 0, 120, 120, 120);
330 cairo_translate(cr, 200, 0.);
331 arc3p(cr, 0, 0, 120, 0, 120, 120);
333 cairo_translate(cr, 200, 0.);
334 arc3p(cr, 60, 0, 0, 120, 120, 120);
336 cairo_translate(cr, -400, 200);
337 arc3p(cr, 0, 50, -2, 85, 120, 0);
339 cairo_translate(cr, 200, 0);
340 arc3p(cr, -2, 85, 0, 50, 120, 0);
342 cairo_destroy(cr);
345 static void
346 arc3p(cairo_t *cr, double x1, double y1,
347 double x2, double y2, double x3, double y3)
349 CpmlPrimitive arc;
350 cairo_path_data_t p[4];
351 CpmlPair center;
352 double r, start, end;
354 arc.segment = NULL;
355 arc.org = &p[0];
356 arc.data = &p[1];
358 p[1].header.type = CPML_ARC;
359 p[1].header.length = 3;
361 p[0].point.x = x1;
362 p[0].point.y = y1;
363 p[2].point.x = x2;
364 p[2].point.y = y2;
365 p[3].point.x = x3;
366 p[3].point.y = y3;
368 cpml_primitive_to_cairo(&arc, cr);
370 cairo_set_line_width(cr, 1.);
371 cairo_stroke(cr);
373 /* Add an arc generated by cairo, just for reference */
374 if (!cpml_arc_info(&arc, &center, &r, &start, &end)) {
375 g_warning(_("Unable to get arc info (%lf, %lf) (%lf, %lf) (%lf, %lf)\n"),
376 x1, y1, x2, y2, x3, y3);
377 return;
380 if (start < end)
381 cairo_arc(cr, center.x, center.y, r-5., start, end);
382 else
383 cairo_arc_negative(cr, center.x, center.y, r-5., start, end);
385 /* Show the inscribed triangle */
386 cairo_move_to(cr, x1, y1);
387 cairo_line_to(cr, x2, y2);
388 cairo_line_to(cr, x3, y3);
390 cairo_set_line_width(cr, 0.5);
391 cairo_stroke(cr);
395 static void
396 intersections(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
398 cairo_t *cr;
399 cairo_path_t *path;
400 CpmlSegment segment1, segment2;
401 CpmlPair intersection;
403 cr = gdk_cairo_create(widget->window);
404 cairo_translate(cr, 10.5, 120.5);
406 line1_callback(cr);
408 path = cairo_copy_path(cr);
410 cairo_set_line_width(cr, 1.);
411 cairo_stroke(cr);
413 cpml_segment_from_cairo(&segment1, path);
414 cpml_segment_from_cairo(&segment2, path);
416 while (cpml_segment_next(&segment2)) {
417 cpml_segment_put_intersections(&segment1, &segment2, 1, &intersection);
419 cairo_arc(cr, intersection.x, intersection.y, 2.5, 0, 2 * M_PI);
420 cairo_fill(cr);
422 cpml_segment_next(&segment1);
425 cairo_path_destroy(path);
426 cairo_destroy(cr);
430 static void
431 offset_curves(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
433 cairo_t *cr;
434 gint n;
435 CpmlPair *bezier;
436 cairo_path_t *path, *path_copy;
437 CpmlSegment segment;
438 CpmlPrimitive primitive;
439 CpmlPair pair;
440 CpmlVector vector;
441 double t;
443 cr = gdk_cairo_create(widget->window);
445 /* Add the Bézier curve samples */
446 for (n = 0; n < G_N_ELEMENTS(bezier_samples); ++n) {
447 bezier = &bezier_samples[n][0];
449 /* The samples are arranged in a 4x? matrix of 200x150 cells */
450 if (n == 0)
451 cairo_translate(cr, 25., 25.);
452 else if (n % 4 == 0)
453 cairo_translate(cr, -600., 150.);
454 else
455 cairo_translate(cr, 200., 0.);
457 /* Draw the Bézier curve */
458 cairo_move_to(cr, bezier[0].x, bezier[0].y);
459 cairo_curve_to(cr, bezier[1].x, bezier[1].y,
460 bezier[2].x, bezier[2].y, bezier[3].x, bezier[3].y);
462 /* Create a copy, to be used after */
463 path_copy = cairo_copy_path(cr);
465 path = duplicate_and_stroke(cr);
466 cpml_segment_from_cairo(&segment, path);
467 cpml_segment_offset(&segment, 20.);
468 stroke_and_destroy(cr, path);
470 cpml_segment_from_cairo(&segment, path_copy);
471 cpml_primitive_from_segment(&primitive, &segment);
473 /* Checking cpml_curve_put_pair_at_time and cpml_curve_put_vector_at_time */
474 cairo_set_line_width(cr, 1.);
475 for (t = 0; t < 1; t += 0.1) {
476 cpml_curve_put_pair_at_time(&primitive, t, &pair);
477 cpml_curve_put_vector_at_time(&primitive, t, &vector);
478 cpml_vector_set_length(&vector, 20.);
479 cpml_vector_normal(&vector);
481 cairo_new_sub_path(cr);
482 cairo_arc(cr, pair.x, pair.y, 2.5, 0, M_PI*2);
483 cairo_fill(cr);
485 cairo_move_to(cr, pair.x, pair.y);
486 cairo_line_to(cr, pair.x + vector.x, pair.y + vector.y);
487 cairo_stroke(cr);
490 cairo_path_destroy(path_copy);
493 cairo_destroy(cr);
497 static void
498 offset_segments(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
500 cairo_t *cr;
501 cairo_path_t *path;
502 CpmlSegment segment;
503 int n;
505 cr = gdk_cairo_create(widget->window);
506 cairo_translate(cr, 270.5, -120.5);
508 /* Offset the path samples */
509 for (n = 0; n < G_N_ELEMENTS(path_samples); ++n) {
510 if ((n & 1) == 0) {
511 cairo_translate(cr, -270., 240.);
512 } else {
513 cairo_translate(cr, 270., 0.);
516 /* Call the path callback */
517 (path_samples[n]) (cr);
519 path = duplicate_and_stroke(cr);
520 cpml_segment_from_cairo(&segment, path);
521 cpml_segment_offset(&segment, 15.);
522 stroke_and_destroy(cr, path);
525 cairo_destroy(cr);
529 static void
530 circle_callback(cairo_t *cr)
532 cairo_new_sub_path(cr);
533 cairo_arc(cr, 120., 0., 100., 0., M_PI*2);
536 static void
537 piston_callback(cairo_t *cr)
539 cairo_path_t *old_path, *path;
540 cairo_matrix_t matrix;
541 CpmlSegment segment;
543 /* Save the previous path, if any */
544 old_path = cairo_copy_path(cr);
546 cairo_new_path(cr);
547 cairo_move_to(cr, 0., 46.5);
548 cairo_line_to(cr, 210., 46.5);
549 cairo_line_to(cr, 222.5, 35.);
550 cairo_line_to(cr, 270., 35.);
551 cairo_line_to(cr, 270., 56.);
552 cairo_line_to(cr, 273., 59.);
553 cairo_line_to(cr, 302., 59.);
554 cairo_line_to(cr, 305., 56.);
555 cairo_arc(cr, 325., 52.5, 20., G_PI, 3. * G_PI_2);
556 cairo_line_to(cr, 400., 32.5);
557 cairo_line_to(cr, 410., 22.5);
558 cairo_line_to(cr, 450., 22.5);
559 cairo_arc_negative(cr,
560 452., 34., 2., G_PI, G_PI_2);
561 cairo_line_to(cr, 460., 36.);
562 cairo_line_to(cr, 470., 30.);
563 cairo_line_to(cr, 472., 12.5);
565 /* Mirror a reversed copy of the current path on the y = 0 axis */
566 path = cairo_copy_path(cr);
567 cpml_segment_from_cairo(&segment, path);
569 cpml_segment_reverse(&segment);
570 cairo_matrix_init_scale(&matrix, 1., -1.);
571 cpml_segment_transform(&segment, &matrix);
573 /* Join the mirrored path to the old path... */
574 path->data[0].header.type = CPML_LINE;
575 cairo_append_path(cr, path);
576 cairo_path_destroy(path);
578 /* ...and close the shape */
579 cairo_close_path(cr);
581 /* Save the resulting path and clear the path memory */
582 path = cairo_copy_path(cr);
583 cairo_new_path(cr);
585 /* Restore the previous path and reappend the new path */
586 cairo_append_path(cr, old_path);
587 cairo_path_destroy(old_path);
588 cairo_append_path(cr, path);
589 cairo_path_destroy(path);
592 static void
593 curve1_callback(cairo_t *cr)
595 cairo_move_to(cr, 30., 0.);
596 cairo_curve_to(cr, 120., 120., 180., 100., 180., 20.);
597 cairo_curve_to(cr, 180., -20., 50., 40., 150., 40.);
598 cairo_curve_to(cr, 220., 40., 190., -60., 150., -60.);
599 cairo_curve_to(cr, 100., -60., 80., -40., 60., -60.);
602 static void
603 line1_callback(cairo_t *cr)
605 cairo_move_to(cr, 0, -50);
606 cairo_line_to(cr, 100, 50);
608 cairo_move_to(cr, 100, -50);
609 cairo_line_to(cr, 0, 50);
611 cairo_move_to(cr, 120, -50);
612 cairo_line_to(cr, 200, -10);
614 cairo_move_to(cr, 120, 50);
615 cairo_line_to(cr, 200, 10);
617 cairo_move_to(cr, 220, 0);
618 cairo_line_to(cr, 280, 0);
620 cairo_move_to(cr, 270, -40);
621 cairo_line_to(cr, 270, 20);
623 cairo_move_to(cr, 320, 60);
624 cairo_line_to(cr, 380, 60);
626 cairo_move_to(cr, 300, -40);
627 cairo_line_to(cr, 340, 0);
629 cairo_move_to(cr, 480, 10);
630 cairo_line_to(cr, 400, 40);
632 cairo_move_to(cr, 400, 40);
633 cairo_line_to(cr, 450, -40);