[CpmlSegment] Implemented a decent offseting curve algorithm
[adg.git] / demo / cpml-test.c
blobe9272626c3748d62f875f7db6f1c9604d3aa1125
1 #include <adg/adg.h>
2 #include <gtk/gtk.h>
5 static void path_constructor (AdgEntity *entity,
6 cairo_t *cr,
7 gpointer user_data);
8 static void path_expose (GtkWidget *widget,
9 GdkEventExpose *event,
10 AdgCanvas *canvas);
13 typedef struct {
14 AdgPair p1;
15 AdgPair p2;
16 AdgPair p3;
17 AdgPair p4;
18 } Bezier;
20 static Bezier bezier_samples[] = {
21 { { 0, 0 }, { 0, 40 }, { 120, 40 }, { 120, 0 } }, /* Simmetric low */
22 { { 40, 0 }, { 40, 160 }, { 80, 160 }, { 80, 0 } }, /* Simmetric high */
23 { { 0, 0 }, { 33.1371, 33.1371 }, { 86.8629, 33.1371 }, { 120, 0 } },
24 /* Arc approximation */
25 { { 0, 0 }, { 70, 120 }, { 50, 120 }, { 120, 0 } }, /* Twisted controls */
27 { { 0, 0 }, { 0, 120 }, { 60, 120 }, { 120, 0 } }, /* Vertical p1-p2 */
28 { { 0, 0 }, { 60, 120 }, { 120, 120 }, { 120, 0 } },/* Vertical p3-p4 */
29 { { 0, 120 }, { 120, 120 }, { 120, 60 }, { 0, 0 } },/* Horizontal p1-p2 */
30 { { 0, 120 }, { 120, 60 }, { 120, 0 }, { 0, 0 } }, /* Horizontal p3-p4 */
32 { { 0, 0 }, { 0, 120 }, { 120, 120 }, { 120, 0 } }, /* Down */
33 { { 0, 120 }, { 120, 120 }, { 120, 0 }, { 0, 0 } }, /* Right */
34 { { 0, 120 }, { 0, 0 }, { 120, 0 }, { 120, 120 } }, /* Up */
35 { { 120, 120 }, { 0, 120 }, { 0, 0 }, { 120, 0 } }, /* Left */
37 { { 0, 60 }, { 60, 120 }, { 120, 60 }, { 60, 0 } }, /* Down-right */
38 { { 60, 120 }, { 120, 60 }, { 60, 0 }, { 0, 60 } }, /* Up-right */
39 { { 120, 60 }, { 60, 0 }, { 0, 60 }, { 60, 120 } }, /* Up-left */
40 { { 60, 0 }, { 0, 60 }, { 60, 120 }, { 120, 60 } }, /* Down-left*/
42 { { 0, 0 }, { 60, 0 }, { 60, 120 }, { 120, 120 } }, /* Step left */
43 { { 120, 0 }, { 60, 0 }, { 60, 120 }, { 0, 120 } }, /* Step right */
44 { { 0, 0 }, { 60, 90 }, { 90, 120 }, { 120, 90 } }, /* Unbalanced opened */
45 { { 0, 0 }, { 40, 120 }, { 120, 120 }, { 60, 80 } } /* Unbalanced closed */
49 int
50 main(gint argc, gchar **argv)
52 GtkWidget *window;
53 GtkWidget *vbox;
54 GtkWidget *button_box;
55 GtkWidget *widget;
56 AdgCanvas *canvas;
57 AdgEntity *entity;
58 gint n;
60 gtk_init(&argc, &argv);
62 /* Create the canvas and populate it */
63 canvas = adg_canvas_new();
65 /* Add the Bézier curve samples */
66 for (n = 0; n < G_N_ELEMENTS(bezier_samples); ++n) {
67 entity = adg_path_new(path_constructor, GINT_TO_POINTER(n));
68 adg_container_add(ADG_CONTAINER(canvas), entity);
71 /* User interface stuff */
72 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
73 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
75 vbox = gtk_vbox_new(FALSE, 0);
77 widget = gtk_drawing_area_new();
78 gtk_widget_set_size_request(widget, 800, 800);
79 g_signal_connect(widget, "expose-event", G_CALLBACK(path_expose), canvas);
80 gtk_container_add(GTK_CONTAINER(vbox), widget);
82 button_box = gtk_hbutton_box_new();
83 gtk_container_set_border_width(GTK_CONTAINER(button_box), 5);
84 gtk_box_set_spacing(GTK_BOX(button_box), 5);
85 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
86 gtk_box_pack_end(GTK_BOX(vbox), button_box, FALSE, TRUE, 0);
88 widget = gtk_button_new_from_stock(GTK_STOCK_QUIT);
89 g_signal_connect(widget, "clicked", G_CALLBACK(gtk_main_quit), NULL);
90 gtk_container_add(GTK_CONTAINER(button_box), widget);
92 gtk_container_add(GTK_CONTAINER(window), vbox);
93 gtk_widget_show_all(window);
95 gtk_main();
97 return 0;
101 static void
102 path_constructor(AdgEntity *entity, cairo_t *cr, gpointer user_data)
104 gint n;
105 Bezier *bezier;
106 cairo_path_t *path;
107 CpmlSegment segment;
108 CpmlPair pair;
109 CpmlVector vector;
110 double t;
112 n = GPOINTER_TO_INT(user_data);
113 bezier = bezier_samples + n;
115 /* The samples are arranged in a 4x? matrix of 200x150 cells */
116 if (n == 0)
117 cairo_translate(cr, 25., 25.);
118 else if (n % 4 == 0)
119 cairo_translate(cr, -600., 150.);
120 else
121 cairo_translate(cr, 200., 0.);
123 /* Draw the Bézier curve */
124 cairo_move_to(cr, bezier->p1.x, bezier->p1.y);
125 cairo_curve_to(cr, bezier->p2.x, bezier->p2.y,
126 bezier->p3.x, bezier->p3.y, bezier->p4.x, bezier->p4.y);
128 /* Checking cpml_segment_offset */
129 path = cairo_copy_path(cr);
130 cpml_segment_init(&segment, path);
131 cpml_segment_offset(&segment, 20);
132 cairo_append_path(cr, path);
133 cairo_path_destroy(path);
135 /* Checking cpml_pair_at_curve and cpml_vector_at_curve */
136 for (t = 0; t < 1; t += 0.1) {
137 cpml_pair_at_curve(&pair, &bezier->p1, &bezier->p2,
138 &bezier->p3, &bezier->p4, t);
139 cpml_vector_at_curve(&vector, &bezier->p1, &bezier->p2,
140 &bezier->p3, &bezier->p4, t, 20);
141 cpml_vector_normal(&vector);
143 cairo_new_sub_path(cr);
144 cairo_arc(cr, pair.x, pair.y, 2.5, 0, M_PI*2);
145 cairo_move_to(cr, pair.x, pair.y);
146 cairo_line_to(cr, pair.x + vector.x, pair.y + vector.y);
150 static void
151 path_expose(GtkWidget *widget, GdkEventExpose *event, AdgCanvas *canvas)
153 cairo_t *cr = gdk_cairo_create(widget->window);
155 adg_entity_render(ADG_ENTITY(canvas), cr);
157 cairo_destroy(cr);