[AdgTable] Propagate signals to the internal children
[adg.git] / demo / adg-demo.c
blobf12a268dccbde565b3649b035875df623790e635
1 #include <adg/adg.h>
2 #include <math.h>
4 #include "demo.h"
7 static AdgCanvas * sample_canvas (void);
8 static AdgCanvas * operations_canvas (void);
9 static AdgCanvas * mapping_canvas (void);
10 static void to_pdf (AdgWidget *widget,
11 GtkWidget *caller);
12 static void to_png (AdgWidget *widget,
13 GtkWidget *caller);
14 static void to_ps (AdgWidget *widget,
15 GtkWidget *caller);
18 int
19 main(gint argc, gchar **argv)
21 gchar *path;
22 GtkBuilder *builder;
23 GError *error;
24 GtkWidget *window;
25 GtkWidget *sample;
26 GtkWidget *operations;
27 GtkWidget *mapping;
29 gtk_init(&argc, &argv);
31 path = demo_find_data_file("adg-demo.ui");
32 if (path == NULL) {
33 g_print("adg-demo.ui not found!\n");
34 return 1;
37 builder = gtk_builder_new();
38 error = NULL;
40 gtk_builder_add_from_file(builder, path, &error);
41 if (error != NULL) {
42 g_print("%s\n", error->message);
43 return 2;
46 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
47 gtk_window_maximize(GTK_WINDOW(window));
49 sample = (GtkWidget *) gtk_builder_get_object(builder, "areaSample");
50 adg_widget_set_canvas(ADG_WIDGET(sample), sample_canvas());
52 operations = (GtkWidget *) gtk_builder_get_object(builder, "areaOperations");
53 adg_widget_set_canvas(ADG_WIDGET(operations), operations_canvas());
55 mapping = (GtkWidget *) gtk_builder_get_object(builder, "areaMapping");
56 adg_widget_set_canvas(ADG_WIDGET(mapping), mapping_canvas());
58 /* Connect signals */
59 g_signal_connect(window, "delete-event",
60 G_CALLBACK(gtk_main_quit), NULL);
61 g_signal_connect(gtk_builder_get_object(builder, "btnQuit"),
62 "clicked", G_CALLBACK(gtk_main_quit), NULL);
63 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPng"),
64 "clicked", G_CALLBACK(to_png), sample);
65 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPdf"),
66 "clicked", G_CALLBACK(to_pdf), sample);
67 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPs"),
68 "clicked", G_CALLBACK(to_ps), sample);
70 g_object_unref(builder);
72 gtk_widget_show_all(window);
73 gtk_main();
75 return 0;
79 static AdgPath * non_trivial_model (void);
82 /**********************************************
83 * A sample mechanical part example
84 **********************************************/
86 #define SQRT3 1.732050808
87 #define CHAMFER 0.3
89 typedef struct _SampleData SampleData;
91 struct _SampleData {
92 gdouble A, B, C;
93 gdouble DHOLE, LHOLE;
94 gdouble D1, D2, D3, D4, D5, D6, D7;
95 gdouble RD34, RD56;
96 gdouble LD2, LD3, LD5, LD6, LD7;
99 static void sample_get (SampleData *data);
100 static AdgPath *sample_bottom_path (const SampleData *data,
101 gdouble height);
102 static AdgPath *sample_path (const SampleData *data);
103 static void sample_add_dimensions (AdgCanvas *canvas,
104 AdgModel *model,
105 const SampleData *data);
106 static void sample_add_stuff (AdgCanvas *canvas,
107 const SampleData *data);
110 static AdgCanvas *
111 sample_canvas(void)
113 SampleData data;
114 AdgCanvas *canvas;
115 AdgContainer *container;
116 AdgPath *bottom, *shape;
117 AdgEdges *edges;
118 AdgEntity *entity;
119 AdgMatrix map;
121 sample_get(&data);
122 canvas = adg_canvas_new();
123 container = (AdgContainer *) canvas;
125 bottom = sample_bottom_path(&data, data.LHOLE + 2);
126 adg_path_reflect(bottom, NULL);
127 adg_path_close(bottom);
129 shape = sample_path(&data);
130 adg_path_reflect(shape, NULL);
131 adg_path_close(shape);
132 adg_path_move_to_explicit(shape, data.LHOLE + 2, data.D1 / 2);
133 adg_path_line_to_explicit(shape, data.LHOLE + 2, -data.D1 / 2);
135 edges = adg_edges_new_with_source(ADG_TRAIL(shape));
137 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(shape)));
138 adg_container_add(container, entity);
140 entity = ADG_ENTITY(adg_hatch_new(ADG_TRAIL(bottom)));
141 adg_container_add(container, entity);
143 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(edges)));
144 adg_container_add(container, entity);
146 sample_add_dimensions(canvas, ADG_MODEL(shape), &data);
147 sample_add_stuff(canvas, &data);
149 cairo_matrix_init_translate(&map, 110, 70);
150 cairo_matrix_scale(&map, 6.883, 6.883);
151 cairo_matrix_translate(&map, 0, 10);
152 adg_entity_set_local_map(ADG_ENTITY(container), &map);
154 return canvas;
157 static void
158 sample_get(SampleData *data)
160 data->A = 52.3;
161 data->B = 20.6;
162 data->C = 2;
163 data->DHOLE = 2;
164 data->LHOLE = 3;
165 data->D1 = 9.3;
166 data->D2 = 6.5;
167 data->D3 = 11.9;
168 data->D4 = 6.5;
169 data->D5 = 4.5;
170 data->D6 = 7.2;
171 data->D7 = 3;
172 data->RD34 = 1;
173 data->LD2 = 7;
174 data->LD3 = 3.5;
175 data->LD5 = 5;
176 data->LD6 = 1;
177 data->LD7 = 0.5;
180 static AdgPath *
181 sample_bottom_path(const SampleData *data, gdouble height)
183 AdgPath *path;
184 AdgModel *model;
185 AdgPair pair;
187 path = adg_path_new();
188 model = ADG_MODEL(path);
190 pair.x = data->LHOLE;
191 pair.y = 0;
192 adg_path_move_to(path, &pair);
193 adg_model_set_named_pair(model, "LHOLE", &pair);
195 pair.y = data->DHOLE / 2;
196 pair.x -= pair.y / SQRT3;
197 adg_path_line_to(path, &pair);
199 pair.x = 0;
200 adg_path_line_to(path, &pair);
201 adg_model_set_named_pair(model, "DHOLE", &pair);
203 pair.y = data->D1 / 2;
204 adg_path_line_to(path, &pair);
205 adg_model_set_named_pair(model, "D1I", &pair);
207 pair.x = height;
208 adg_path_line_to(path, &pair);
209 adg_model_set_named_pair(model, "D1F", &pair);
211 return path;
214 static AdgPath *
215 sample_path(const SampleData *data)
217 AdgPath *path;
218 AdgModel *model;
219 AdgPair pair, tmp;
220 const AdgPrimitive *primitive;
222 pair.x = data->A - data->B - data->LD2;
223 path = sample_bottom_path(data, pair.x);
224 model = ADG_MODEL(path);
226 pair.x += (data->D1 - data->D2) * SQRT3 / 2;
227 pair.y = data->D2 / 2;
228 adg_path_line_to(path, &pair);
229 adg_model_set_named_pair(model, "D2I", &pair);
231 pair.x = data->A - data->B;
232 adg_path_line_to(path, &pair);
233 adg_path_fillet(path, 0.4);
235 pair.x = data->A - data->B;
236 pair.y = data->D3 / 2;
237 adg_path_line_to(path, &pair);
238 adg_model_set_named_pair(model, "D3I", &pair);
240 adg_path_chamfer(path, CHAMFER, CHAMFER);
242 pair.x = data->A - data->B + data->LD3;
243 pair.y = data->D3 / 2;
244 adg_path_line_to(path, &pair);
246 primitive = adg_path_over_primitive(path);
247 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
248 adg_model_set_named_pair(model, "D3I_X", &tmp);
250 adg_path_chamfer(path, CHAMFER, CHAMFER);
252 pair.y = data->D4 / 2;
253 adg_path_line_to(path, &pair);
255 primitive = adg_path_over_primitive(path);
256 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
257 adg_model_set_named_pair(model, "D3F_Y", &tmp);
258 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
259 adg_model_set_named_pair(model, "D3F_X", &tmp);
261 adg_path_fillet(path, data->RD34);
263 pair.x = data->A - data->C - data->LD5;
264 adg_path_line_to(path, &pair);
265 adg_model_set_named_pair(model, "D4F", &pair);
267 primitive = adg_path_over_primitive(path);
268 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
269 tmp.x += data->RD34;
270 adg_model_set_named_pair(model, "RD34", &tmp);
272 tmp.x -= cos(G_PI_4) * data->RD34,
273 tmp.y -= sin(G_PI_4) * data->RD34,
274 adg_model_set_named_pair(model, "RD34_R", &tmp);
276 tmp.x += data->RD34,
277 tmp.y += data->RD34,
278 adg_model_set_named_pair(model, "RD34_XY", &tmp);
280 pair.x += (data->D4 - data->D5) / 2;
281 pair.y = data->D5 / 2;
282 adg_path_line_to(path, &pair);
284 pair.x = data->A - data->C;
285 adg_path_line_to(path, &pair);
287 adg_path_fillet(path, 0.2);
289 pair.y = data->D6 / 2;
290 adg_path_line_to(path, &pair);
292 primitive = adg_path_over_primitive(path);
293 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
294 adg_model_set_named_pair(model, "D5F", &tmp);
296 adg_path_fillet(path, 0.1);
298 pair.x += data->LD6;
299 adg_path_line_to(path, &pair);
300 adg_model_set_named_pair(model, "D6F", &pair);
302 primitive = adg_path_over_primitive(path);
303 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
304 adg_model_set_named_pair(model, "D6I_Y", &tmp);
306 pair.x = data->A - data->LD7;
307 pair.y -= (data->C - data->LD7 - data->LD6) / SQRT3;
308 adg_path_line_to(path, &pair);
309 adg_model_set_named_pair(model, "D67", &pair);
311 pair.y = data->D7 / 2;
312 adg_path_line_to(path, &pair);
314 pair.x = data->A;
315 adg_path_line_to(path, &pair);
316 adg_model_set_named_pair(model, "D7F", &pair);
318 return path;
321 static void
322 sample_add_dimensions(AdgCanvas *canvas, AdgModel *model,
323 const SampleData *data)
325 AdgLDim *ldim;
326 AdgADim *adim;
327 AdgRDim *rdim;
329 /* NORTH */
331 ldim = adg_ldim_new_full_from_model(model, "-D1F", "-D3I_X", "-D3F_Y",
332 ADG_DIR_UP);
333 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
334 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
336 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
337 ADG_DIR_UP);
338 adg_ldim_switch_extension1(ldim, FALSE);
339 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
340 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
342 /* SOUTH */
344 ldim = adg_ldim_new_full_from_model(model, "D1I", "LHOLE", "D3F_Y",
345 ADG_DIR_DOWN);
346 adg_ldim_switch_extension1(ldim, FALSE);
347 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
349 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "D3F_Y",
350 ADG_DIR_DOWN);
351 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
352 adg_ldim_switch_extension2(ldim, FALSE);
353 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
355 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
356 ADG_DIR_DOWN);
357 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
358 adg_dim_set_level(ADG_DIM(ldim), 2);
359 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
361 adim = adg_adim_new_full_from_model(model, "D6F", "D6I_Y", "D67",
362 "D6F", "D6F");
363 adg_dim_set_level(ADG_DIM(adim), 2);
364 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
366 rdim = adg_rdim_new_full_from_model(model, "RD34", "RD34_R", "RD34_XY");
367 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
369 /* EAST */
371 ldim = adg_ldim_new_full_from_model(model, "D3F_Y", "-D3F_Y", "D7F",
372 ADG_DIR_RIGHT);
373 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
374 adg_dim_set_level(ADG_DIM(ldim), 5);
375 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
377 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "D7F",
378 ADG_DIR_RIGHT);
379 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
380 adg_dim_set_level(ADG_DIM(ldim), 4);
381 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
383 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "D7F",
384 ADG_DIR_RIGHT);
385 adg_dim_set_level(ADG_DIM(ldim), 3);
386 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
388 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "D7F",
389 ADG_DIR_RIGHT);
390 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
391 adg_dim_set_level(ADG_DIM(ldim), 2);
392 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
394 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "D7F",
395 ADG_DIR_RIGHT);
396 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
398 /* WEST */
400 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "D1I",
401 ADG_DIR_LEFT);
402 adg_dim_set_limits(ADG_DIM(ldim), "+0.05", "-0.05");
403 adg_dim_set_level(ADG_DIM(ldim), 3);
404 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
406 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "D1I",
407 ADG_DIR_LEFT);
408 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
409 adg_dim_set_level(ADG_DIM(ldim), 2);
410 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
412 ldim = adg_ldim_new_full_from_model(model, "DHOLE", "-DHOLE", "D1I",
413 ADG_DIR_LEFT);
414 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
417 static void
418 sample_add_stuff(AdgCanvas *canvas, const SampleData *data)
420 AdgToyText *toy_text;
421 AdgMatrix map;
422 AdgTable *table;
423 AdgTableRow *row;
425 toy_text = adg_toy_text_new("Rotate the mouse wheel to zoom in and out");
426 cairo_matrix_init_translate(&map, 0, data->D3 / 2);
427 adg_entity_set_local_map(ADG_ENTITY(toy_text), &map);
428 cairo_matrix_translate(&map, 10, 30 + 30 * 2);
429 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
430 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
432 toy_text = adg_toy_text_new("Keep the wheel pressed while dragging the mouse to translate");
433 cairo_matrix_init_translate(&map, 0, data->D3 / 2);
434 adg_entity_set_local_map(ADG_ENTITY(toy_text), &map);
435 cairo_matrix_init_translate(&map, 10, 50 + 30 * 2);
436 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
437 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
439 table = adg_table_new();
440 cairo_matrix_init_translate(&map, 500, 500);
441 adg_entity_set_global_map(ADG_ENTITY(table), &map);
442 row = adg_table_row_new(table);
443 adg_table_cell_new(row, 40);
444 adg_table_cell_new_full(row, 200, "title", "TITLE", "Title of the drawing");
445 row = adg_table_row_new(table);
446 adg_table_cell_new(row, 40);
447 adg_table_cell_new_full(row, 100, "file", "FILE", "File name");
448 adg_table_cell_new_full(row, 100, "author", "AUTHOR", "Author");
449 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(table));
453 #if defined(CAIRO_HAS_PNG_FUNCTIONS) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_PS_SURFACE)
455 /* Only needed if there is at least one supported surface */
456 static void
457 file_generated(GtkWidget *caller, const gchar *file)
459 GtkWindow *window;
460 GtkWidget *dialog;
462 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
463 dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_MODAL,
464 GTK_MESSAGE_INFO,
465 GTK_BUTTONS_CLOSE,
466 "The requested operation generated\n"
467 "<b>%s</b> in the current directory.",
468 file);
469 gtk_window_set_title(GTK_WINDOW(dialog), "Operation completed");
470 gtk_dialog_run(GTK_DIALOG(dialog));
471 gtk_widget_destroy(dialog);
474 #endif
476 #if !defined(CAIRO_HAS_PNG_FUNCTIONS) || !defined(CAIRO_HAS_PDF_SURFACE) || !defined(CAIRO_HAS_PS_SURFACE)
478 /* Only needed if there is a missing surface */
479 static void
480 missing_feature(GtkWidget *caller, const gchar *feature)
482 GtkWindow *window;
483 GtkWidget *dialog;
485 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
486 dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL,
487 GTK_MESSAGE_WARNING,
488 GTK_BUTTONS_OK,
489 "The provided cairo library\n"
490 "was compiled with no %s support!",
491 feature);
492 gtk_window_set_title(GTK_WINDOW(dialog), "Missing feature");
493 gtk_dialog_run(GTK_DIALOG(dialog));
494 gtk_widget_destroy(dialog);
497 #endif
500 #ifdef CAIRO_HAS_PNG_FUNCTIONS
502 static void
503 to_png(AdgWidget *widget, GtkWidget *caller)
505 cairo_surface_t *surface;
506 cairo_t *cr;
508 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
509 cr = cairo_create(surface);
510 cairo_surface_destroy(surface);
512 /* Rendering process */
513 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
515 cairo_show_page(cr);
516 cairo_surface_write_to_png(surface, "test.png");
517 cairo_destroy(cr);
519 file_generated(caller, "test.png");
522 #else
524 static void
525 to_png(AdgWidget *widget, GtkWidget *caller)
527 missing_feature(caller, "PNG");
530 #endif
532 #ifdef CAIRO_HAS_PDF_SURFACE
534 #include <cairo-pdf.h>
536 static void
537 to_pdf(AdgWidget *widget, GtkWidget *caller)
539 cairo_surface_t *surface;
540 cairo_t *cr;
542 surface = cairo_pdf_surface_create("test.pdf", 841, 595);
543 cr = cairo_create(surface);
544 cairo_surface_destroy(surface);
546 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
548 cairo_show_page(cr);
549 cairo_destroy(cr);
551 file_generated(caller, "test.pdf");
554 #else
556 static void
557 to_pdf(AdgWidget *widget, GtkWidget *caller)
559 missing_feature(caller, "PDF");
562 #endif
564 #ifdef CAIRO_HAS_PS_SURFACE
566 #include <cairo-ps.h>
568 static void
569 to_ps(AdgWidget *widget, GtkWidget *caller)
571 cairo_surface_t *surface;
572 cairo_t *cr;
574 /* Surface creation: A4 size */
575 surface = cairo_ps_surface_create("test.ps", 841, 595);
576 cairo_ps_surface_dsc_comment(surface,
577 "%%Title: Automatic Drawing Generation (ADG) demo");
578 cairo_ps_surface_dsc_comment(surface,
579 "%%Copyright: Copyright (C) 2006-2009 Fontana Nicola");
580 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Portrait");
582 cairo_ps_surface_dsc_begin_setup(surface);
584 cairo_ps_surface_dsc_begin_page_setup(surface);
585 cairo_ps_surface_dsc_comment(surface,
586 "%%IncludeFeature: *PageSize A4");
588 cr = cairo_create(surface);
589 cairo_surface_destroy(surface);
591 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
593 cairo_show_page(cr);
594 cairo_destroy(cr);
596 file_generated(caller, "test.ps");
599 #else
601 static void
602 to_ps(AdgWidget *widget, GtkWidget *caller)
604 missing_feature(caller, "PostScript");
607 #endif
610 /**********************************************
611 * Test case for basic operations,
612 * such as chamfer and fillet
613 **********************************************/
615 static AdgPath * operations_chamfer (const AdgPath *path,
616 gdouble delta1,
617 gdouble delta2);
618 static AdgPath * operations_fillet (const AdgPath *path,
619 gdouble radius);
621 static AdgCanvas *
622 operations_canvas(void)
624 AdgPath *path, *chamfer_path, *fillet_path;
625 AdgCanvas *canvas;
626 AdgContainer *container;
627 AdgEntity *entity;
628 AdgMatrix map;
630 path = non_trivial_model();
631 chamfer_path = operations_chamfer(path, 0.25, 0.25);
632 fillet_path = operations_fillet(path, 0.20);
633 canvas = adg_canvas_new();
635 /* Add the original shape */
636 container = adg_container_new();
637 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
639 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
640 adg_container_add(container, entity);
642 entity = ADG_ENTITY(adg_toy_text_new("Original shape"));
643 cairo_matrix_init_translate(&map, 5, 10);
644 adg_entity_set_local_map(entity, &map);
645 cairo_matrix_init_translate(&map, -50, 20);
646 adg_entity_set_global_map(entity, &map);
647 adg_container_add(ADG_CONTAINER(canvas), entity);
649 /* Add the shape with 0.25x0.25 chamfer */
650 container = adg_container_new();
651 cairo_matrix_init_translate(&map, 15, 0);
652 adg_entity_set_local_map(ADG_ENTITY(container), &map);
653 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
655 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(chamfer_path)));
656 adg_container_add(container, entity);
658 entity = ADG_ENTITY(adg_toy_text_new("Shape with 0.25x0.25 chamfer"));
659 cairo_matrix_init_translate(&map, 5, 10);
660 adg_entity_set_local_map(entity, &map);
661 cairo_matrix_init_translate(&map, -120, 20);
662 adg_entity_set_global_map(entity, &map);
663 adg_container_add(container, entity);
665 /* Add the shape with fillets with 0.20 of radius */
666 container = adg_container_new();
667 cairo_matrix_init_translate(&map, 30, 0);
668 adg_entity_set_local_map(ADG_ENTITY(container), &map);
669 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
671 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(fillet_path)));
672 adg_container_add(container, entity);
674 entity = ADG_ENTITY(adg_toy_text_new("Shape with R=20 fillet"));
675 cairo_matrix_init_translate(&map, 5, 10);
676 adg_entity_set_local_map(entity, &map);
677 cairo_matrix_init_translate(&map, -90, 20);
678 adg_entity_set_global_map(entity, &map);
679 adg_container_add(container, entity);
681 /* Set a decent start position and zoom */
682 cairo_matrix_init_translate(&map, 10, -140);
683 cairo_matrix_scale(&map, 15, 15);
684 cairo_matrix_translate(&map, 0, 10);
685 adg_entity_set_local_map(ADG_ENTITY(canvas), &map);
687 return canvas;
690 static AdgPath *
691 operations_chamfer(const AdgPath *model, gdouble delta1, gdouble delta2)
693 AdgPath *path;
694 CpmlSegment segment;
695 CpmlPrimitive primitive;
696 CpmlPair org;
698 path = adg_path_new();
699 adg_trail_get_segment(ADG_TRAIL(model), &segment, 1);
700 cpml_primitive_from_segment(&primitive, &segment);
701 cpml_pair_from_cairo(&org, primitive.org);
703 adg_path_move_to(path, &org);
705 do {
706 adg_path_append_primitive(path, &primitive);
707 if (primitive.data[0].header.type == CAIRO_PATH_LINE_TO)
708 adg_path_chamfer(path, delta1, delta2);
709 } while (cpml_primitive_next(&primitive));
711 return path;
714 static AdgPath *
715 operations_fillet(const AdgPath *model, gdouble radius)
717 AdgPath *path;
718 CpmlSegment segment;
719 CpmlPrimitive primitive;
720 CpmlPair org;
722 path = adg_path_new();
723 adg_trail_get_segment(ADG_TRAIL(model), &segment, 1);
724 cpml_primitive_from_segment(&primitive, &segment);
725 cpml_pair_from_cairo(&org, primitive.org);
727 adg_path_move_to(path, &org);
729 do {
730 adg_path_append_primitive(path, &primitive);
731 if (primitive.data[0].header.type == CAIRO_PATH_LINE_TO)
732 adg_path_fillet(path, radius);
733 } while (cpml_primitive_next(&primitive));
735 return path;
739 /**********************************************
740 * Test case for mapping transformations,
741 * either on the local and global map
742 **********************************************/
744 static AdgCanvas *
745 mapping_canvas(void)
747 AdgPath *path;
748 AdgCanvas *canvas;
749 AdgContainer *container;
750 AdgEntity *entity;
751 AdgMatrix map;
753 path = non_trivial_model();
754 canvas = adg_canvas_new();
756 /* Add the original shape */
757 container = adg_container_new();
758 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
760 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
761 adg_container_add(container, entity);
763 entity = ADG_ENTITY(adg_toy_text_new("Original shape"));
764 cairo_matrix_init_translate(&map, -50, 20);
765 adg_entity_set_global_map(entity, &map);
766 cairo_matrix_init_translate(&map, 5, 10);
767 adg_entity_set_local_map(entity, &map);
768 adg_container_add(ADG_CONTAINER(canvas), entity);
770 /* Original shape with global rotated by 90 and local translated x+=10 */
771 container = adg_container_new();
772 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
773 cairo_matrix_init_translate(&map, 15, 0);
774 adg_entity_set_local_map(ADG_ENTITY(container), &map);
776 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
777 cairo_matrix_init_rotate(&map, M_PI_2);
778 adg_entity_set_global_map(entity, &map);
779 cairo_matrix_init_translate(&map, 10, 0);
780 adg_entity_set_local_map(entity, &map);
781 adg_container_add(container, entity);
783 entity = ADG_ENTITY(adg_toy_text_new("Global map rotated by 90"));
784 cairo_matrix_init_translate(&map, -120, 20);
785 adg_entity_set_global_map(entity, &map);
786 cairo_matrix_init_translate(&map, 5, 10);
787 adg_entity_set_local_map(entity, &map);
788 adg_container_add(container, entity);
790 /* Original shape with local translated x+=10 and rotated by 90 */
791 container = adg_container_new();
792 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
793 cairo_matrix_init_translate(&map, 30, 0);
794 adg_entity_set_local_map(ADG_ENTITY(container), &map);
796 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
797 cairo_matrix_init_translate(&map, 10, 0);
798 cairo_matrix_rotate(&map, M_PI_2);
799 adg_entity_set_local_map(entity, &map);
800 adg_container_add(container, entity);
802 entity = ADG_ENTITY(adg_toy_text_new("Local map rotated by 90"));
803 cairo_matrix_init_translate(&map, -120, 20);
804 adg_entity_set_global_map(entity, &map);
805 cairo_matrix_init_translate(&map, 5, 10);
806 adg_entity_set_local_map(entity, &map);
807 adg_container_add(container, entity);
809 /* Original shape with global map scaled by 0.5 */
810 container = adg_container_new();
811 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
812 cairo_matrix_init_translate(&map, 3.5, 15);
813 adg_entity_set_local_map(ADG_ENTITY(container), &map);
815 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
816 cairo_matrix_init_scale(&map, 0.5, 0.5);
817 adg_entity_set_global_map(entity, &map);
818 adg_container_add(container, entity);
820 entity = ADG_ENTITY(adg_toy_text_new("Global map scaled by 0.5"));
821 cairo_matrix_init_translate(&map, -100, 20);
822 adg_entity_set_global_map(entity, &map);
823 cairo_matrix_init_translate(&map, 2.5, 5);
824 adg_entity_set_local_map(entity, &map);
825 adg_container_add(container, entity);
827 /* Original shape with local map scaled by 0.5 */
828 container = adg_container_new();
829 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
830 cairo_matrix_init_translate(&map, 18, 15);
831 adg_entity_set_local_map(ADG_ENTITY(container), &map);
833 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
834 cairo_matrix_init_scale(&map, 0.5, 0.5);
835 adg_entity_set_local_map(entity, &map);
836 adg_container_add(container, entity);
838 entity = ADG_ENTITY(adg_toy_text_new("Local map scaled by 0.5"));
839 cairo_matrix_init_translate(&map, -100, 20);
840 adg_entity_set_global_map(entity, &map);
841 cairo_matrix_init_translate(&map, 2.5, 5);
842 adg_entity_set_local_map(entity, &map);
843 adg_container_add(container, entity);
845 /* Original shape with global and local maps scaled by 0.5 */
846 container = adg_container_new();
847 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
848 cairo_matrix_init_translate(&map, 33, 15);
849 adg_entity_set_local_map(ADG_ENTITY(container), &map);
851 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
852 cairo_matrix_init_scale(&map, 0.5, 0.5);
853 adg_entity_set_global_map(entity, &map);
854 adg_entity_set_local_map(entity, &map);
855 adg_container_add(container, entity);
857 entity = ADG_ENTITY(adg_toy_text_new("Local&global scaled by 0.5"));
858 cairo_matrix_init_translate(&map, -130, 20);
859 adg_entity_set_global_map(entity, &map);
860 cairo_matrix_init_translate(&map, 2.5, 5);
861 adg_entity_set_local_map(entity, &map);
862 adg_container_add(container, entity);
864 /* Set a decent start position and zoom */
865 cairo_matrix_init_translate(&map, 10, -140);
866 cairo_matrix_scale(&map, 15, 15);
867 cairo_matrix_translate(&map, 0, 10);
868 adg_entity_set_local_map(ADG_ENTITY(canvas), &map);
870 return canvas;
874 /**********************************************
875 * Non specific test related stuff
876 **********************************************/
878 static AdgPath *
879 non_trivial_model()
881 AdgPath *path = adg_path_new();
883 adg_path_move_to_explicit(path, 2, 0);
884 adg_path_line_to_explicit(path, 0, 5);
885 adg_path_line_to_explicit(path, 2, 2);
886 adg_path_line_to_explicit(path, 0, 8);
887 adg_path_line_to_explicit(path, 2, 8);
888 adg_path_line_to_explicit(path, 2, 10);
889 adg_path_line_to_explicit(path, 3, 10);
890 adg_path_line_to_explicit(path, 10, 9);
891 adg_path_line_to_explicit(path, 5, 5);
892 adg_path_line_to_explicit(path, 3, 0);
893 adg_path_close(path);
895 return path;