[AdgPath] Added _explicit version of adg_path_arc()
[adg.git] / demo / adg-demo.c
blob03cb0f0d70ea190d6a35eb83e1a2a7ed4179508b
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");
48 sample = (GtkWidget *) gtk_builder_get_object(builder, "areaSample");
49 adg_widget_set_canvas(ADG_WIDGET(sample), sample_canvas());
51 operations = (GtkWidget *) gtk_builder_get_object(builder, "areaOperations");
52 adg_widget_set_canvas(ADG_WIDGET(operations), operations_canvas());
54 mapping = (GtkWidget *) gtk_builder_get_object(builder, "areaMapping");
55 adg_widget_set_canvas(ADG_WIDGET(mapping), mapping_canvas());
57 /* Connect signals */
58 g_signal_connect(window, "delete-event",
59 G_CALLBACK(gtk_main_quit), NULL);
60 g_signal_connect(gtk_builder_get_object(builder, "btnQuit"),
61 "clicked", G_CALLBACK(gtk_main_quit), NULL);
62 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPng"),
63 "clicked", G_CALLBACK(to_png), sample);
64 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPdf"),
65 "clicked", G_CALLBACK(to_pdf), sample);
66 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPs"),
67 "clicked", G_CALLBACK(to_ps), sample);
69 g_object_unref(builder);
71 gtk_widget_show_all(window);
72 gtk_main();
74 return 0;
78 static AdgPath * non_trivial_model (void);
81 /**********************************************
82 * A sample mechanical part example
83 **********************************************/
85 #define SQRT3 1.732050808
86 #define CHAMFER 0.3
88 typedef struct _SampleData SampleData;
90 struct _SampleData {
91 gdouble A, B, C;
92 gdouble D1, D2, D3, D4, D5, D6, D7;
93 gdouble RD34, RD56;
94 gdouble LD2, LD3, LD5, LD6, LD7;
97 static void sample_get (SampleData *data);
98 static AdgPath *sample_path (const SampleData *data);
99 static void sample_add_dimensions (AdgCanvas *canvas,
100 AdgModel *model,
101 const SampleData *data);
102 static void sample_add_stuff (AdgCanvas *canvas,
103 const SampleData *data);
104 static void reverse_pair (const gchar *name,
105 AdgPair *pair,
106 AdgModel *model);
109 static AdgCanvas *
110 sample_canvas(void)
112 SampleData data;
113 AdgCanvas *canvas;
114 AdgContainer *container;
115 AdgTrail *shape, *edges;
116 AdgEntity *entity;
117 AdgMatrix map;
119 sample_get(&data);
120 canvas = adg_canvas_new();
121 container = (AdgContainer *) canvas;
122 shape = ADG_TRAIL(sample_path(&data));
123 edges = ADG_TRAIL(adg_edges_new_with_source(shape));
125 entity = ADG_ENTITY(adg_stroke_new(shape));
126 adg_container_add(container, entity);
128 entity = ADG_ENTITY(adg_hatch_new(shape));
129 adg_container_add(container, entity);
131 entity = ADG_ENTITY(adg_stroke_new(edges));
132 adg_container_add(container, entity);
134 sample_add_dimensions(canvas, ADG_MODEL(shape), &data);
135 sample_add_stuff(canvas, &data);
137 cairo_matrix_init_translate(&map, 100, 70);
138 cairo_matrix_scale(&map, 6.883, 6.883);
139 cairo_matrix_translate(&map, 0, 10);
140 adg_entity_set_local_map(ADG_ENTITY(container), &map);
142 return canvas;
145 static void
146 sample_get(SampleData *data)
148 data->A = 52.3;
149 data->B = 20.6;
150 data->C = 2;
151 data->D1 = 9.3;
152 data->D2 = 6.5;
153 data->D3 = 11.9;
154 data->D4 = 6.5;
155 data->D5 = 4.5;
156 data->D6 = 7.2;
157 data->D7 = 3;
158 data->RD34 = 1;
159 data->LD2 = 7;
160 data->LD3 = 3.5;
161 data->LD5 = 5;
162 data->LD6 = 1;
163 data->LD7 = 0.5;
166 static AdgPath *
167 sample_path(const SampleData *data)
169 AdgPath *path;
170 AdgModel *model;
171 AdgPair pair, tmp;
172 AdgSegment segment;
173 AdgSegment *dup_segment;
174 const AdgPrimitive *primitive;
175 cairo_matrix_t matrix;
177 path = adg_path_new();
178 model = ADG_MODEL(path);
180 pair.x = 0;
181 pair.y = data->D1 / 2;
182 adg_path_move_to(path, &pair);
183 adg_model_set_named_pair(model, "D1I", &pair);
185 pair.x = data->A - data->B - data->LD2;
186 adg_path_line_to(path, &pair);
187 adg_model_set_named_pair(model, "D1F", &pair);
189 pair.x += (data->D1 - data->D2) * SQRT3 / 2;
190 pair.y -= (data->D1 - data->D2) / 2;
191 adg_path_line_to(path, &pair);
192 adg_model_set_named_pair(model, "D2I", &pair);
194 pair.x = data->A - data->B;
195 adg_path_line_to(path, &pair);
196 adg_path_fillet(path, 0.4);
198 pair.x = data->A - data->B;
199 pair.y = data->D3 / 2;
200 adg_path_line_to(path, &pair);
201 adg_model_set_named_pair(model, "D3I", &pair);
203 adg_path_chamfer(path, CHAMFER, CHAMFER);
205 pair.x = data->A - data->B + data->LD3;
206 pair.y = data->D3 / 2;
207 adg_path_line_to(path, &pair);
209 primitive = adg_path_over_primitive(path);
210 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
211 adg_model_set_named_pair(model, "D3I_X", &tmp);
213 adg_path_chamfer(path, CHAMFER, CHAMFER);
215 pair.y = data->D4 / 2;
216 adg_path_line_to(path, &pair);
218 primitive = adg_path_over_primitive(path);
219 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
220 adg_model_set_named_pair(model, "D3F_Y", &tmp);
221 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
222 adg_model_set_named_pair(model, "D3F_X", &tmp);
224 adg_path_fillet(path, data->RD34);
226 pair.x = data->A - data->C - data->LD5;
227 adg_path_line_to(path, &pair);
228 adg_model_set_named_pair(model, "D4F", &pair);
230 primitive = adg_path_over_primitive(path);
231 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
232 tmp.x += data->RD34;
233 adg_model_set_named_pair(model, "RD34", &tmp);
235 tmp.x -= cos(G_PI_4) * data->RD34,
236 tmp.y -= sin(G_PI_4) * data->RD34,
237 adg_model_set_named_pair(model, "RD34_R", &tmp);
239 tmp.x += data->RD34,
240 tmp.y += data->RD34,
241 adg_model_set_named_pair(model, "RD34_XY", &tmp);
243 pair.x += (data->D4 - data->D5) / 2;
244 pair.y = data->D5 / 2;
245 adg_path_line_to(path, &pair);
247 pair.x = data->A - data->C;
248 adg_path_line_to(path, &pair);
250 adg_path_fillet(path, 0.2);
252 pair.y = data->D6 / 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, "D5F", &tmp);
259 adg_path_fillet(path, 0.1);
261 pair.x += data->LD6;
262 adg_path_line_to(path, &pair);
263 adg_model_set_named_pair(model, "D6F", &pair);
265 primitive = adg_path_over_primitive(path);
266 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
267 adg_model_set_named_pair(model, "D6I_Y", &tmp);
269 pair.x = data->A - data->LD7;
270 pair.y -= (data->C - data->LD7 - data->LD6) / SQRT3;
271 adg_path_line_to(path, &pair);
272 adg_model_set_named_pair(model, "D67", &pair);
274 pair.y = data->D7 / 2;
275 adg_path_line_to(path, &pair);
277 pair.x = data->A;
278 adg_path_line_to(path, &pair);
279 adg_model_set_named_pair(model, "D7F", &pair);
281 /* Reflect the shape by duplicating the first segment of
282 * the current path, applying a -1 y scale (that is
283 * mirroring it on the y=0 axis), reversing the resulting
284 * path and appending it to the original one */
285 adg_trail_get_segment(ADG_TRAIL(path), &segment, 1);
286 dup_segment = adg_segment_deep_dup(&segment);
287 cpml_segment_reverse(dup_segment);
288 cairo_matrix_init(&matrix, 1, 0, 0, -1, 0, 0);
289 cpml_segment_transform(dup_segment, &matrix);
290 dup_segment->data[0].header.type = CAIRO_PATH_LINE_TO;
292 adg_path_append_segment(path, dup_segment);
294 g_free(dup_segment);
296 adg_model_foreach_named_pair(model, (AdgNamedPairCallback) reverse_pair,
297 model);
299 adg_path_close(path);
300 return path;
303 static void
304 sample_add_dimensions(AdgCanvas *canvas, AdgModel *model,
305 const SampleData *data)
307 AdgLDim *ldim;
308 AdgADim *adim;
309 AdgRDim *rdim;
311 /* NORTH */
313 ldim = adg_ldim_new_full_from_model(model, "-D1F", "-D3I_X", "-D3F_Y",
314 ADG_DIR_UP);
315 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
317 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
318 ADG_DIR_UP);
319 adg_ldim_switch_extension1(ldim, FALSE);
320 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
322 /* SOUTH */
324 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "D3F_Y",
325 ADG_DIR_DOWN);
326 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
327 adg_ldim_switch_extension2(ldim, FALSE);
328 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
330 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
331 ADG_DIR_DOWN);
332 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
333 adg_dim_set_level(ADG_DIM(ldim), 2);
334 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
336 adim = adg_adim_new_full_from_model(model, "D6F", "D6I_Y", "D67",
337 "D6F", "D6F");
338 adg_dim_set_level(ADG_DIM(adim), 2);
339 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
341 rdim = adg_rdim_new_full_from_model(model, "RD34", "RD34_R", "RD34_XY");
342 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
344 /* EAST */
346 ldim = adg_ldim_new_full_from_model(model, "D3F_Y", "-D3F_Y", "D7F",
347 ADG_DIR_RIGHT);
348 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
349 adg_dim_set_level(ADG_DIM(ldim), 5);
350 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
352 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "D7F",
353 ADG_DIR_RIGHT);
354 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
355 adg_dim_set_level(ADG_DIM(ldim), 4);
356 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
358 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "D7F",
359 ADG_DIR_RIGHT);
360 adg_dim_set_level(ADG_DIM(ldim), 3);
361 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
363 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "D7F",
364 ADG_DIR_RIGHT);
365 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
366 adg_dim_set_level(ADG_DIM(ldim), 2);
367 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
369 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "D7F",
370 ADG_DIR_RIGHT);
371 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
373 /* WEST */
375 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "D1I",
376 ADG_DIR_LEFT);
377 adg_dim_set_limits(ADG_DIM(ldim), "+0.05", "-0.05");
378 adg_dim_set_level(ADG_DIM(ldim), 2);
379 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
381 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "D1I",
382 ADG_DIR_LEFT);
383 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
384 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
387 static void
388 sample_add_stuff(AdgCanvas *canvas, const SampleData *data)
390 AdgToyText *toy_text;
391 AdgMatrix map;
393 toy_text = adg_toy_text_new("Rotate the mouse wheel to zoom in and out");
394 cairo_matrix_init_translate(&map, 0, data->D3 / 2);
395 adg_entity_set_local_map(ADG_ENTITY(toy_text), &map);
396 cairo_matrix_translate(&map, 10, 30 + 30 * 2);
397 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
398 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
400 toy_text = adg_toy_text_new("Keep the wheel pressed while dragging the mouse to translate");
401 cairo_matrix_init_translate(&map, 0, data->D3 / 2);
402 adg_entity_set_local_map(ADG_ENTITY(toy_text), &map);
403 cairo_matrix_init_translate(&map, 10, 50 + 30 * 2);
404 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
405 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
409 #if defined(CAIRO_HAS_PNG_FUNCTIONS) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_PS_SURFACE)
411 /* Only needed if there is at least one supported surface */
412 static void
413 file_generated(GtkWidget *caller, const gchar *file)
415 GtkWindow *window;
416 GtkWidget *dialog;
418 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
419 dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_MODAL,
420 GTK_MESSAGE_INFO,
421 GTK_BUTTONS_CLOSE,
422 "The requested operation generated\n"
423 "<b>%s</b> in the current directory.",
424 file);
425 gtk_window_set_title(GTK_WINDOW(dialog), "Operation completed");
426 gtk_dialog_run(GTK_DIALOG(dialog));
427 gtk_widget_destroy(dialog);
430 #endif
432 #if !defined(CAIRO_HAS_PNG_FUNCTIONS) || !defined(CAIRO_HAS_PDF_SURFACE) || !defined(CAIRO_HAS_PS_SURFACE)
434 /* Only needed if there is a missing surface */
435 static void
436 missing_feature(GtkWidget *caller, const gchar *feature)
438 GtkWindow *window;
439 GtkWidget *dialog;
441 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
442 dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL,
443 GTK_MESSAGE_WARNING,
444 GTK_BUTTONS_OK,
445 "The provided cairo library\n"
446 "was compiled with no %s support!",
447 feature);
448 gtk_window_set_title(GTK_WINDOW(dialog), "Missing feature");
449 gtk_dialog_run(GTK_DIALOG(dialog));
450 gtk_widget_destroy(dialog);
453 #endif
456 #ifdef CAIRO_HAS_PNG_FUNCTIONS
458 static void
459 to_png(AdgWidget *widget, GtkWidget *caller)
461 cairo_surface_t *surface;
462 cairo_t *cr;
464 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
465 cr = cairo_create(surface);
466 cairo_surface_destroy(surface);
468 /* Rendering process */
469 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
471 cairo_show_page(cr);
472 cairo_surface_write_to_png(surface, "test.png");
473 cairo_destroy(cr);
475 file_generated(caller, "test.png");
478 #else
480 static void
481 to_png(AdgWidget *widget, GtkWidget *caller)
483 missing_feature(caller, "PNG");
486 #endif
488 #ifdef CAIRO_HAS_PDF_SURFACE
490 #include <cairo-pdf.h>
492 static void
493 to_pdf(AdgWidget *widget, GtkWidget *caller)
495 cairo_surface_t *surface;
496 cairo_t *cr;
498 surface = cairo_pdf_surface_create("test.pdf", 841, 595);
499 cr = cairo_create(surface);
500 cairo_surface_destroy(surface);
502 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
504 cairo_show_page(cr);
505 cairo_destroy(cr);
507 file_generated(caller, "test.pdf");
510 #else
512 static void
513 to_pdf(AdgWidget *widget, GtkWidget *caller)
515 missing_feature(caller, "PDF");
518 #endif
520 #ifdef CAIRO_HAS_PS_SURFACE
522 #include <cairo-ps.h>
524 static void
525 to_ps(AdgWidget *widget, GtkWidget *caller)
527 cairo_surface_t *surface;
528 cairo_t *cr;
530 /* Surface creation: A4 size */
531 surface = cairo_ps_surface_create("test.ps", 841, 595);
532 cairo_ps_surface_dsc_comment(surface,
533 "%%Title: Automatic Drawing Generation (ADG) demo");
534 cairo_ps_surface_dsc_comment(surface,
535 "%%Copyright: Copyright (C) 2006-2009 Fontana Nicola");
536 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Portrait");
538 cairo_ps_surface_dsc_begin_setup(surface);
540 cairo_ps_surface_dsc_begin_page_setup(surface);
541 cairo_ps_surface_dsc_comment(surface,
542 "%%IncludeFeature: *PageSize A4");
544 cr = cairo_create(surface);
545 cairo_surface_destroy(surface);
547 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
549 cairo_show_page(cr);
550 cairo_destroy(cr);
552 file_generated(caller, "test.ps");
555 #else
557 static void
558 to_ps(AdgWidget *widget, GtkWidget *caller)
560 missing_feature(caller, "PostScript");
563 #endif
566 /**********************************************
567 * Test case for basic operations,
568 * such as chamfer and fillet
569 **********************************************/
571 static AdgPath * operations_chamfer (const AdgPath *path,
572 gdouble delta1,
573 gdouble delta2);
574 static AdgPath * operations_fillet (const AdgPath *path,
575 gdouble radius);
577 static AdgCanvas *
578 operations_canvas(void)
580 AdgPath *path, *chamfer_path, *fillet_path;
581 AdgCanvas *canvas;
582 AdgContainer *container;
583 AdgEntity *entity;
584 AdgMatrix map;
586 path = non_trivial_model();
587 chamfer_path = operations_chamfer(path, 0.25, 0.25);
588 fillet_path = operations_fillet(path, 0.20);
589 canvas = adg_canvas_new();
591 /* Add the original shape */
592 container = adg_container_new();
593 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
595 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
596 adg_container_add(container, entity);
598 entity = ADG_ENTITY(adg_toy_text_new("Original shape"));
599 cairo_matrix_init_translate(&map, 5, 10);
600 adg_entity_set_local_map(entity, &map);
601 cairo_matrix_init_translate(&map, -50, 20);
602 adg_entity_set_global_map(entity, &map);
603 adg_container_add(ADG_CONTAINER(canvas), entity);
605 /* Add the shape with 0.25x0.25 chamfer */
606 container = adg_container_new();
607 cairo_matrix_init_translate(&map, 15, 0);
608 adg_entity_set_local_map(ADG_ENTITY(container), &map);
609 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
611 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(chamfer_path)));
612 adg_container_add(container, entity);
614 entity = ADG_ENTITY(adg_toy_text_new("Shape with 0.25x0.25 chamfer"));
615 cairo_matrix_init_translate(&map, 5, 10);
616 adg_entity_set_local_map(entity, &map);
617 cairo_matrix_init_translate(&map, -120, 20);
618 adg_entity_set_global_map(entity, &map);
619 adg_container_add(container, entity);
621 /* Add the shape with fillets with 0.20 of radius */
622 container = adg_container_new();
623 cairo_matrix_init_translate(&map, 30, 0);
624 adg_entity_set_local_map(ADG_ENTITY(container), &map);
625 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
627 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(fillet_path)));
628 adg_container_add(container, entity);
630 entity = ADG_ENTITY(adg_toy_text_new("Shape with R=20 fillet"));
631 cairo_matrix_init_translate(&map, 5, 10);
632 adg_entity_set_local_map(entity, &map);
633 cairo_matrix_init_translate(&map, -90, 20);
634 adg_entity_set_global_map(entity, &map);
635 adg_container_add(container, entity);
637 /* Set a decent start position and zoom */
638 cairo_matrix_init_translate(&map, 10, -140);
639 cairo_matrix_scale(&map, 15, 15);
640 cairo_matrix_translate(&map, 0, 10);
641 adg_entity_set_local_map(ADG_ENTITY(canvas), &map);
643 return canvas;
646 static AdgPath *
647 operations_chamfer(const AdgPath *model, gdouble delta1, gdouble delta2)
649 AdgPath *path;
650 CpmlSegment segment;
651 CpmlPrimitive primitive;
652 CpmlPair org;
654 path = adg_path_new();
655 adg_trail_get_segment(ADG_TRAIL(model), &segment, 1);
656 cpml_primitive_from_segment(&primitive, &segment);
657 cpml_pair_from_cairo(&org, primitive.org);
659 adg_path_move_to(path, &org);
661 do {
662 adg_path_append_primitive(path, &primitive);
663 if (primitive.data[0].header.type == CAIRO_PATH_LINE_TO)
664 adg_path_chamfer(path, delta1, delta2);
665 } while (cpml_primitive_next(&primitive));
667 return path;
670 static AdgPath *
671 operations_fillet(const AdgPath *model, gdouble radius)
673 AdgPath *path;
674 CpmlSegment segment;
675 CpmlPrimitive primitive;
676 CpmlPair org;
678 path = adg_path_new();
679 adg_trail_get_segment(ADG_TRAIL(model), &segment, 1);
680 cpml_primitive_from_segment(&primitive, &segment);
681 cpml_pair_from_cairo(&org, primitive.org);
683 adg_path_move_to(path, &org);
685 do {
686 adg_path_append_primitive(path, &primitive);
687 if (primitive.data[0].header.type == CAIRO_PATH_LINE_TO)
688 adg_path_fillet(path, radius);
689 } while (cpml_primitive_next(&primitive));
691 return path;
695 /**********************************************
696 * Test case for mapping transformations,
697 * either on the local and global map
698 **********************************************/
700 static AdgCanvas *
701 mapping_canvas(void)
703 AdgPath *path;
704 AdgCanvas *canvas;
705 AdgContainer *container;
706 AdgEntity *entity;
707 AdgMatrix map;
709 path = non_trivial_model();
710 canvas = adg_canvas_new();
712 /* Add the original shape */
713 container = adg_container_new();
714 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
716 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
717 adg_container_add(container, entity);
719 entity = ADG_ENTITY(adg_toy_text_new("Original shape"));
720 cairo_matrix_init_translate(&map, -50, 20);
721 adg_entity_set_global_map(entity, &map);
722 cairo_matrix_init_translate(&map, 5, 10);
723 adg_entity_set_local_map(entity, &map);
724 adg_container_add(ADG_CONTAINER(canvas), entity);
726 /* Original shape with global rotated by 90 and local translated x+=10 */
727 container = adg_container_new();
728 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
729 cairo_matrix_init_translate(&map, 15, 0);
730 adg_entity_set_local_map(ADG_ENTITY(container), &map);
732 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
733 cairo_matrix_init_rotate(&map, M_PI_2);
734 adg_entity_set_global_map(entity, &map);
735 cairo_matrix_init_translate(&map, 10, 0);
736 adg_entity_set_local_map(entity, &map);
737 adg_container_add(container, entity);
739 entity = ADG_ENTITY(adg_toy_text_new("Global map rotated by 90"));
740 cairo_matrix_init_translate(&map, -120, 20);
741 adg_entity_set_global_map(entity, &map);
742 cairo_matrix_init_translate(&map, 5, 10);
743 adg_entity_set_local_map(entity, &map);
744 adg_container_add(container, entity);
746 /* Original shape with local translated x+=10 and rotated by 90 */
747 container = adg_container_new();
748 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
749 cairo_matrix_init_translate(&map, 30, 0);
750 adg_entity_set_local_map(ADG_ENTITY(container), &map);
752 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
753 cairo_matrix_init_translate(&map, 10, 0);
754 cairo_matrix_rotate(&map, M_PI_2);
755 adg_entity_set_local_map(entity, &map);
756 adg_container_add(container, entity);
758 entity = ADG_ENTITY(adg_toy_text_new("Local map rotated by 90"));
759 cairo_matrix_init_translate(&map, -120, 20);
760 adg_entity_set_global_map(entity, &map);
761 cairo_matrix_init_translate(&map, 5, 10);
762 adg_entity_set_local_map(entity, &map);
763 adg_container_add(container, entity);
765 /* Original shape with global map scaled by 0.5 */
766 container = adg_container_new();
767 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
768 cairo_matrix_init_translate(&map, 3.5, 15);
769 adg_entity_set_local_map(ADG_ENTITY(container), &map);
771 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
772 cairo_matrix_init_scale(&map, 0.5, 0.5);
773 adg_entity_set_global_map(entity, &map);
774 adg_container_add(container, entity);
776 entity = ADG_ENTITY(adg_toy_text_new("Global map scaled by 0.5"));
777 cairo_matrix_init_translate(&map, -100, 20);
778 adg_entity_set_global_map(entity, &map);
779 cairo_matrix_init_translate(&map, 2.5, 5);
780 adg_entity_set_local_map(entity, &map);
781 adg_container_add(container, entity);
783 /* Original shape with local map scaled by 0.5 */
784 container = adg_container_new();
785 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
786 cairo_matrix_init_translate(&map, 18, 15);
787 adg_entity_set_local_map(ADG_ENTITY(container), &map);
789 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
790 cairo_matrix_init_scale(&map, 0.5, 0.5);
791 adg_entity_set_local_map(entity, &map);
792 adg_container_add(container, entity);
794 entity = ADG_ENTITY(adg_toy_text_new("Local map scaled by 0.5"));
795 cairo_matrix_init_translate(&map, -100, 20);
796 adg_entity_set_global_map(entity, &map);
797 cairo_matrix_init_translate(&map, 2.5, 5);
798 adg_entity_set_local_map(entity, &map);
799 adg_container_add(container, entity);
801 /* Original shape with global and local maps scaled by 0.5 */
802 container = adg_container_new();
803 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
804 cairo_matrix_init_translate(&map, 33, 15);
805 adg_entity_set_local_map(ADG_ENTITY(container), &map);
807 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
808 cairo_matrix_init_scale(&map, 0.5, 0.5);
809 adg_entity_set_global_map(entity, &map);
810 adg_entity_set_local_map(entity, &map);
811 adg_container_add(container, entity);
813 entity = ADG_ENTITY(adg_toy_text_new("Local&global scaled by 0.5"));
814 cairo_matrix_init_translate(&map, -130, 20);
815 adg_entity_set_global_map(entity, &map);
816 cairo_matrix_init_translate(&map, 2.5, 5);
817 adg_entity_set_local_map(entity, &map);
818 adg_container_add(container, entity);
820 /* Set a decent start position and zoom */
821 cairo_matrix_init_translate(&map, 10, -140);
822 cairo_matrix_scale(&map, 15, 15);
823 cairo_matrix_translate(&map, 0, 10);
824 adg_entity_set_local_map(ADG_ENTITY(canvas), &map);
826 return canvas;
830 /**********************************************
831 * Non specific test related stuff
832 **********************************************/
834 static AdgPath *
835 non_trivial_model()
837 AdgPath *path = adg_path_new();
839 adg_path_move_to_explicit(path, 2, 0);
840 adg_path_line_to_explicit(path, 0, 5);
841 adg_path_line_to_explicit(path, 2, 2);
842 adg_path_line_to_explicit(path, 0, 8);
843 adg_path_line_to_explicit(path, 2, 8);
844 adg_path_line_to_explicit(path, 2, 10);
845 adg_path_line_to_explicit(path, 3, 10);
846 adg_path_line_to_explicit(path, 10, 9);
847 adg_path_line_to_explicit(path, 5, 5);
848 adg_path_line_to_explicit(path, 3, 0);
849 adg_path_close(path);
851 return path;
854 static void
855 reverse_pair(const gchar *name, AdgPair *pair, AdgModel *model)
857 gchar *new_name;
858 AdgPair new_pair;
860 new_name = g_strdup_printf("-%s", name);
861 cpml_pair_copy(&new_pair, pair);
862 new_pair.y = -new_pair.y;
864 adg_model_set_named_pair(model, new_name, &new_pair);
866 g_free(new_name);