[AdgADim] Added construction with named pairs
[adg.git] / demo / adg-demo.c
blob69fddcee3cd11bed151278043cbc87a99a612f76
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;
172 double x, y;
173 AdgSegment segment;
174 AdgSegment *dup_segment;
175 const AdgPrimitive *primitive;
176 cairo_matrix_t matrix;
178 path = adg_path_new();
179 model = ADG_MODEL(path);
181 pair.x = 0;
182 pair.y = data->D1 / 2;
183 adg_path_move_to(path, pair.x, pair.y);
184 adg_model_set_named_pair(model, "D1I", &pair);
186 pair.x = data->A - data->B - data->LD2;
187 adg_path_line_to(path, pair.x, pair.y);
188 adg_model_set_named_pair(model, "D1F", &pair);
190 y = (data->D1 - data->D2) / 2;
191 pair.x += (data->D1 - data->D2) * SQRT3 / 2;
192 pair.y -= (data->D1 - data->D2) / 2;
193 adg_path_line_to(path, pair.x, pair.y);
194 adg_model_set_named_pair(model, "D2I", &pair);
196 adg_path_line_to(path, data->A - data->B, data->D2 / 2);
197 adg_path_fillet(path, 0.4);
199 pair.x = data->A - data->B;
200 pair.y = data->D3 / 2;
201 adg_path_line_to(path, pair.x, pair.y);
202 adg_model_set_named_pair(model, "D3I", &pair);
204 adg_path_chamfer(path, CHAMFER, CHAMFER);
206 pair.x = data->A - data->B + data->LD3;
207 pair.y = data->D3 / 2;
208 adg_path_line_to(path, pair.x, pair.y);
210 primitive = adg_path_over_primitive(path);
211 cpml_pair_from_cairo(&pair, cpml_primitive_get_point(primitive, 0));
212 adg_model_set_named_pair(model, "D3I_X", &pair);
214 adg_path_chamfer(path, CHAMFER, CHAMFER);
215 adg_path_line_to(path, data->A - data->B + data->LD3, data->D4 / 2);
217 primitive = adg_path_over_primitive(path);
218 cpml_pair_from_cairo(&pair, cpml_primitive_get_point(primitive, 0));
219 adg_model_set_named_pair(model, "D3F_Y", &pair);
220 cpml_pair_from_cairo(&pair, cpml_primitive_get_point(primitive, -1));
221 adg_model_set_named_pair(model, "D3F_X", &pair);
223 adg_path_fillet(path, data->RD34);
225 pair.x = data->A - data->C - data->LD5;
226 pair.y = data->D4 / 2;
227 adg_path_line_to(path, pair.x, pair.y);
228 adg_model_set_named_pair(model, "D4F", &pair);
230 y = (data->D4 - data->D5) / 2;
231 adg_path_line_to(path, data->A - data->C - data->LD5 + y, data->D4 / 2 - y);
232 adg_path_line_to(path, data->A - data->C, data->D5 / 2);
234 adg_path_fillet(path, 0.2);
236 adg_path_line_to(path, data->A - data->C, data->D6 / 2);
238 primitive = adg_path_over_primitive(path);
239 cpml_pair_from_cairo(&pair, cpml_primitive_get_point(primitive, 0));
240 adg_model_set_named_pair(model, "D5F", &pair);
242 adg_path_fillet(path, 0.1);
244 pair.x = data->A - data->C + data->LD6;
245 pair.y = data->D6 / 2;
246 adg_path_line_to(path, pair.x, pair.y);
247 adg_model_set_named_pair(model, "D6F", &pair);
249 x = data->C - data->LD7 - data->LD6;
250 y = x / SQRT3;
251 adg_path_line_to(path, data->A - data->C + data->LD6 + x, data->D6 / 2 - y);
252 adg_path_line_to(path, data->A - data->LD7, data->D7 / 2);
254 pair.x = data->A;
255 pair.y = data->D7 / 2;
256 adg_path_line_to(path, pair.x, pair.y);
257 adg_model_set_named_pair(model, "D7F", &pair);
259 /* Reflect the shape by duplicating the first segment of
260 * the current path, applying a -1 y scale (that is
261 * mirroring it on the y=0 axis), reversing the resulting
262 * path and appending it to the original one */
263 adg_trail_get_segment(ADG_TRAIL(path), &segment, 1);
264 dup_segment = adg_segment_deep_dup(&segment);
265 cpml_segment_reverse(dup_segment);
266 cairo_matrix_init(&matrix, 1, 0, 0, -1, 0, 0);
267 cpml_segment_transform(dup_segment, &matrix);
268 dup_segment->data[0].header.type = CAIRO_PATH_LINE_TO;
270 adg_path_append_segment(path, dup_segment);
272 g_free(dup_segment);
274 adg_model_foreach_named_pair(model, (AdgNamedPairCallback) reverse_pair,
275 model);
277 adg_path_close(path);
278 return path;
281 static void
282 sample_add_dimensions(AdgCanvas *canvas, AdgModel *model,
283 const SampleData *data)
285 AdgLDim *ldim;
286 AdgADim *adim;
287 AdgRDim *rdim;
288 double x, y;
290 /* NORTH */
292 ldim = adg_ldim_new_full_from_model(model, "-D1F", "-D3I_X", "-D3F_Y",
293 ADG_DIR_UP);
294 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
296 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
297 ADG_DIR_UP);
298 adg_ldim_switch_extension1(ldim, FALSE);
299 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
301 /* SOUTH */
303 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "D3F_Y",
304 ADG_DIR_DOWN);
305 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
306 adg_ldim_switch_extension2(ldim, FALSE);
307 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
309 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
310 ADG_DIR_DOWN);
311 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
312 adg_dim_set_level(ADG_DIM(ldim), 2);
313 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
315 /* Angular D6+ */
316 x = data->A - data->C;
317 y = data->D6 / 2 - (data->C - data->LD6 - data->LD7) / SQRT3;
318 adim = adg_adim_new_full_explicit(x + data->LD6, data->D6 / 2,
319 x + 0.1, data->D6 / 2,
320 data->A - data->LD7, y,
321 x + data->LD6, data->D6 / 2,
322 x + data->LD6, data->D6 / 2);
323 adg_dim_set_level(ADG_DIM(adim), 2);
324 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
326 /* Radial RD34 */
327 x = data->A - data->B + data->LD3 + data->RD34;
328 y = data->D4 / 2 + data->RD34;
329 rdim = adg_rdim_new_full_explicit(x, y,
330 x - cos(G_PI_4) * data->RD34,
331 y - sin(G_PI_4) * data->RD34,
332 x + cos(G_PI_4) * data->RD34,
333 y + sin(G_PI_4) * data->RD34);
334 adg_dim_set_level(ADG_DIM(rdim), 1);
335 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
337 /* EAST */
339 ldim = adg_ldim_new_full_from_model(model, "D3F_Y", "-D3F_Y", "D7F",
340 ADG_DIR_RIGHT);
341 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
342 adg_dim_set_level(ADG_DIM(ldim), 5);
343 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
345 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "D7F",
346 ADG_DIR_RIGHT);
347 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
348 adg_dim_set_level(ADG_DIM(ldim), 4);
349 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
351 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "D7F",
352 ADG_DIR_RIGHT);
353 adg_dim_set_level(ADG_DIM(ldim), 3);
354 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
356 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "D7F",
357 ADG_DIR_RIGHT);
358 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
359 adg_dim_set_level(ADG_DIM(ldim), 2);
360 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
362 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "D7F",
363 ADG_DIR_RIGHT);
364 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
366 /* WEST */
368 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "D1I",
369 ADG_DIR_LEFT);
370 adg_dim_set_limits(ADG_DIM(ldim), "+0.05", "-0.05");
371 adg_dim_set_level(ADG_DIM(ldim), 2);
372 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
374 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "D1I",
375 ADG_DIR_LEFT);
376 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
377 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
380 static void
381 sample_add_stuff(AdgCanvas *canvas, const SampleData *data)
383 AdgToyText *toy_text;
384 AdgMatrix map;
386 toy_text = adg_toy_text_new("Rotate the mouse wheel to zoom in and out");
387 cairo_matrix_init_translate(&map, 0, data->D3 / 2);
388 adg_entity_set_local_map(ADG_ENTITY(toy_text), &map);
389 cairo_matrix_translate(&map, 10, 30 + 30 * 2);
390 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
391 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
393 toy_text = adg_toy_text_new("Keep the wheel pressed while dragging the mouse to translate");
394 cairo_matrix_init_translate(&map, 0, data->D3 / 2);
395 adg_entity_set_local_map(ADG_ENTITY(toy_text), &map);
396 cairo_matrix_init_translate(&map, 10, 50 + 30 * 2);
397 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
398 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
402 #if defined(CAIRO_HAS_PNG_FUNCTIONS) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_PS_SURFACE)
404 /* Only needed if there is at least one supported surface */
405 static void
406 file_generated(GtkWidget *caller, const gchar *file)
408 GtkWindow *window;
409 GtkWidget *dialog;
411 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
412 dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_MODAL,
413 GTK_MESSAGE_INFO,
414 GTK_BUTTONS_CLOSE,
415 "The requested operation generated\n"
416 "<b>%s</b> in the current directory.",
417 file);
418 gtk_window_set_title(GTK_WINDOW(dialog), "Operation completed");
419 gtk_dialog_run(GTK_DIALOG(dialog));
420 gtk_widget_destroy(dialog);
423 #endif
425 #if !defined(CAIRO_HAS_PNG_FUNCTIONS) || !defined(CAIRO_HAS_PDF_SURFACE) || !defined(CAIRO_HAS_PS_SURFACE)
427 /* Only needed if there is a missing surface */
428 static void
429 missing_feature(GtkWidget *caller, const gchar *feature)
431 GtkWindow *window;
432 GtkWidget *dialog;
434 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
435 dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL,
436 GTK_MESSAGE_WARNING,
437 GTK_BUTTONS_OK,
438 "The provided cairo library\n"
439 "was compiled with no %s support!",
440 feature);
441 gtk_window_set_title(GTK_WINDOW(dialog), "Missing feature");
442 gtk_dialog_run(GTK_DIALOG(dialog));
443 gtk_widget_destroy(dialog);
446 #endif
449 #ifdef CAIRO_HAS_PNG_FUNCTIONS
451 static void
452 to_png(AdgWidget *widget, GtkWidget *caller)
454 cairo_surface_t *surface;
455 cairo_t *cr;
457 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
458 cr = cairo_create(surface);
459 cairo_surface_destroy(surface);
461 /* Rendering process */
462 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
464 cairo_show_page(cr);
465 cairo_surface_write_to_png(surface, "test.png");
466 cairo_destroy(cr);
468 file_generated(caller, "test.png");
471 #else
473 static void
474 to_png(AdgWidget *widget, GtkWidget *caller)
476 missing_feature(caller, "PNG");
479 #endif
481 #ifdef CAIRO_HAS_PDF_SURFACE
483 #include <cairo-pdf.h>
485 static void
486 to_pdf(AdgWidget *widget, GtkWidget *caller)
488 cairo_surface_t *surface;
489 cairo_t *cr;
491 surface = cairo_pdf_surface_create("test.pdf", 841, 595);
492 cr = cairo_create(surface);
493 cairo_surface_destroy(surface);
495 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
497 cairo_show_page(cr);
498 cairo_destroy(cr);
500 file_generated(caller, "test.pdf");
503 #else
505 static void
506 to_pdf(AdgWidget *widget, GtkWidget *caller)
508 missing_feature(caller, "PDF");
511 #endif
513 #ifdef CAIRO_HAS_PS_SURFACE
515 #include <cairo-ps.h>
517 static void
518 to_ps(AdgWidget *widget, GtkWidget *caller)
520 cairo_surface_t *surface;
521 cairo_t *cr;
523 /* Surface creation: A4 size */
524 surface = cairo_ps_surface_create("test.ps", 841, 595);
525 cairo_ps_surface_dsc_comment(surface,
526 "%%Title: Automatic Drawing Generation (ADG) demo");
527 cairo_ps_surface_dsc_comment(surface,
528 "%%Copyright: Copyright (C) 2006-2009 Fontana Nicola");
529 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Portrait");
531 cairo_ps_surface_dsc_begin_setup(surface);
533 cairo_ps_surface_dsc_begin_page_setup(surface);
534 cairo_ps_surface_dsc_comment(surface,
535 "%%IncludeFeature: *PageSize A4");
537 cr = cairo_create(surface);
538 cairo_surface_destroy(surface);
540 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget)), cr);
542 cairo_show_page(cr);
543 cairo_destroy(cr);
545 file_generated(caller, "test.ps");
548 #else
550 static void
551 to_ps(AdgWidget *widget, GtkWidget *caller)
553 missing_feature(caller, "PostScript");
556 #endif
559 /**********************************************
560 * Test case for basic operations,
561 * such as chamfer and fillet
562 **********************************************/
564 static AdgPath * operations_chamfer (const AdgPath *path,
565 gdouble delta1,
566 gdouble delta2);
567 static AdgPath * operations_fillet (const AdgPath *path,
568 gdouble radius);
570 static AdgCanvas *
571 operations_canvas(void)
573 AdgPath *path, *chamfer_path, *fillet_path;
574 AdgCanvas *canvas;
575 AdgContainer *container;
576 AdgEntity *entity;
577 AdgMatrix map;
579 path = non_trivial_model();
580 chamfer_path = operations_chamfer(path, 0.25, 0.25);
581 fillet_path = operations_fillet(path, 0.20);
582 canvas = adg_canvas_new();
584 /* Add the original shape */
585 container = adg_container_new();
586 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
588 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
589 adg_container_add(container, entity);
591 entity = ADG_ENTITY(adg_toy_text_new("Original shape"));
592 cairo_matrix_init_translate(&map, 5, 10);
593 adg_entity_set_local_map(entity, &map);
594 cairo_matrix_init_translate(&map, -50, 20);
595 adg_entity_set_global_map(entity, &map);
596 adg_container_add(ADG_CONTAINER(canvas), entity);
598 /* Add the shape with 0.25x0.25 chamfer */
599 container = adg_container_new();
600 cairo_matrix_init_translate(&map, 15, 0);
601 adg_entity_set_local_map(ADG_ENTITY(container), &map);
602 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
604 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(chamfer_path)));
605 adg_container_add(container, entity);
607 entity = ADG_ENTITY(adg_toy_text_new("Shape with 0.25x0.25 chamfer"));
608 cairo_matrix_init_translate(&map, 5, 10);
609 adg_entity_set_local_map(entity, &map);
610 cairo_matrix_init_translate(&map, -120, 20);
611 adg_entity_set_global_map(entity, &map);
612 adg_container_add(container, entity);
614 /* Add the shape with fillets with 0.20 of radius */
615 container = adg_container_new();
616 cairo_matrix_init_translate(&map, 30, 0);
617 adg_entity_set_local_map(ADG_ENTITY(container), &map);
618 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
620 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(fillet_path)));
621 adg_container_add(container, entity);
623 entity = ADG_ENTITY(adg_toy_text_new("Shape with R=20 fillet"));
624 cairo_matrix_init_translate(&map, 5, 10);
625 adg_entity_set_local_map(entity, &map);
626 cairo_matrix_init_translate(&map, -90, 20);
627 adg_entity_set_global_map(entity, &map);
628 adg_container_add(container, entity);
630 /* Set a decent start position and zoom */
631 cairo_matrix_init_translate(&map, 10, -140);
632 cairo_matrix_scale(&map, 15, 15);
633 cairo_matrix_translate(&map, 0, 10);
634 adg_entity_set_local_map(ADG_ENTITY(canvas), &map);
636 return canvas;
639 static AdgPath *
640 operations_chamfer(const AdgPath *model, gdouble delta1, gdouble delta2)
642 AdgPath *path;
643 CpmlSegment segment;
644 CpmlPrimitive primitive;
646 path = adg_path_new();
647 adg_trail_get_segment(ADG_TRAIL(model), &segment, 1);
648 cpml_primitive_from_segment(&primitive, &segment);
650 adg_path_move_to(path, (primitive.org)->point.x, (primitive.org)->point.y);
652 do {
653 adg_path_append_primitive(path, &primitive);
654 if (primitive.data[0].header.type == CAIRO_PATH_LINE_TO)
655 adg_path_chamfer(path, delta1, delta2);
656 } while (cpml_primitive_next(&primitive));
658 return path;
661 static AdgPath *
662 operations_fillet(const AdgPath *model, gdouble radius)
664 AdgPath *path;
665 CpmlSegment segment;
666 CpmlPrimitive primitive;
668 path = adg_path_new();
669 adg_trail_get_segment(ADG_TRAIL(model), &segment, 1);
670 cpml_primitive_from_segment(&primitive, &segment);
672 adg_path_move_to(path, (primitive.org)->point.x, (primitive.org)->point.y);
674 do {
675 adg_path_append_primitive(path, &primitive);
676 if (primitive.data[0].header.type == CAIRO_PATH_LINE_TO)
677 adg_path_fillet(path, radius);
678 } while (cpml_primitive_next(&primitive));
680 return path;
684 /**********************************************
685 * Test case for mapping transformations,
686 * either on the local and global map
687 **********************************************/
689 static AdgCanvas *
690 mapping_canvas(void)
692 AdgPath *path;
693 AdgCanvas *canvas;
694 AdgContainer *container;
695 AdgEntity *entity;
696 AdgMatrix map;
698 path = non_trivial_model();
699 canvas = adg_canvas_new();
701 /* Add the original shape */
702 container = adg_container_new();
703 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
705 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
706 adg_container_add(container, entity);
708 entity = ADG_ENTITY(adg_toy_text_new("Original shape"));
709 cairo_matrix_init_translate(&map, -50, 20);
710 adg_entity_set_global_map(entity, &map);
711 cairo_matrix_init_translate(&map, 5, 10);
712 adg_entity_set_local_map(entity, &map);
713 adg_container_add(ADG_CONTAINER(canvas), entity);
715 /* Original shape with global rotated by 90 and local translated x+=10 */
716 container = adg_container_new();
717 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
718 cairo_matrix_init_translate(&map, 15, 0);
719 adg_entity_set_local_map(ADG_ENTITY(container), &map);
721 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
722 cairo_matrix_init_rotate(&map, M_PI_2);
723 adg_entity_set_global_map(entity, &map);
724 cairo_matrix_init_translate(&map, 10, 0);
725 adg_entity_set_local_map(entity, &map);
726 adg_container_add(container, entity);
728 entity = ADG_ENTITY(adg_toy_text_new("Global map rotated by 90"));
729 cairo_matrix_init_translate(&map, -120, 20);
730 adg_entity_set_global_map(entity, &map);
731 cairo_matrix_init_translate(&map, 5, 10);
732 adg_entity_set_local_map(entity, &map);
733 adg_container_add(container, entity);
735 /* Original shape with local translated x+=10 and rotated by 90 */
736 container = adg_container_new();
737 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
738 cairo_matrix_init_translate(&map, 30, 0);
739 adg_entity_set_local_map(ADG_ENTITY(container), &map);
741 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
742 cairo_matrix_init_translate(&map, 10, 0);
743 cairo_matrix_rotate(&map, M_PI_2);
744 adg_entity_set_local_map(entity, &map);
745 adg_container_add(container, entity);
747 entity = ADG_ENTITY(adg_toy_text_new("Local map rotated by 90"));
748 cairo_matrix_init_translate(&map, -120, 20);
749 adg_entity_set_global_map(entity, &map);
750 cairo_matrix_init_translate(&map, 5, 10);
751 adg_entity_set_local_map(entity, &map);
752 adg_container_add(container, entity);
754 /* Original shape with global map scaled by 0.5 */
755 container = adg_container_new();
756 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
757 cairo_matrix_init_translate(&map, 3.5, 15);
758 adg_entity_set_local_map(ADG_ENTITY(container), &map);
760 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
761 cairo_matrix_init_scale(&map, 0.5, 0.5);
762 adg_entity_set_global_map(entity, &map);
763 adg_container_add(container, entity);
765 entity = ADG_ENTITY(adg_toy_text_new("Global map scaled by 0.5"));
766 cairo_matrix_init_translate(&map, -100, 20);
767 adg_entity_set_global_map(entity, &map);
768 cairo_matrix_init_translate(&map, 2.5, 5);
769 adg_entity_set_local_map(entity, &map);
770 adg_container_add(container, entity);
772 /* Original shape with local map scaled by 0.5 */
773 container = adg_container_new();
774 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
775 cairo_matrix_init_translate(&map, 18, 15);
776 adg_entity_set_local_map(ADG_ENTITY(container), &map);
778 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
779 cairo_matrix_init_scale(&map, 0.5, 0.5);
780 adg_entity_set_local_map(entity, &map);
781 adg_container_add(container, entity);
783 entity = ADG_ENTITY(adg_toy_text_new("Local map scaled by 0.5"));
784 cairo_matrix_init_translate(&map, -100, 20);
785 adg_entity_set_global_map(entity, &map);
786 cairo_matrix_init_translate(&map, 2.5, 5);
787 adg_entity_set_local_map(entity, &map);
788 adg_container_add(container, entity);
790 /* Original shape with global and local maps scaled by 0.5 */
791 container = adg_container_new();
792 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(container));
793 cairo_matrix_init_translate(&map, 33, 15);
794 adg_entity_set_local_map(ADG_ENTITY(container), &map);
796 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(path)));
797 cairo_matrix_init_scale(&map, 0.5, 0.5);
798 adg_entity_set_global_map(entity, &map);
799 adg_entity_set_local_map(entity, &map);
800 adg_container_add(container, entity);
802 entity = ADG_ENTITY(adg_toy_text_new("Local&global scaled by 0.5"));
803 cairo_matrix_init_translate(&map, -130, 20);
804 adg_entity_set_global_map(entity, &map);
805 cairo_matrix_init_translate(&map, 2.5, 5);
806 adg_entity_set_local_map(entity, &map);
807 adg_container_add(container, entity);
809 /* Set a decent start position and zoom */
810 cairo_matrix_init_translate(&map, 10, -140);
811 cairo_matrix_scale(&map, 15, 15);
812 cairo_matrix_translate(&map, 0, 10);
813 adg_entity_set_local_map(ADG_ENTITY(canvas), &map);
815 return canvas;
819 /**********************************************
820 * Non specific test related stuff
821 **********************************************/
823 static AdgPath *
824 non_trivial_model()
826 AdgPath *path = adg_path_new();
828 adg_path_move_to(path, 2, 0);
829 adg_path_line_to(path, 0, 5);
830 adg_path_line_to(path, 2, 2);
831 adg_path_line_to(path, 0, 8);
832 adg_path_line_to(path, 2, 8);
833 adg_path_line_to(path, 2, 10);
834 adg_path_line_to(path, 3, 10);
835 adg_path_line_to(path, 10, 9);
836 adg_path_line_to(path, 5, 5);
837 adg_path_line_to(path, 3, 0);
838 adg_path_close(path);
840 return path;
843 static void
844 reverse_pair(const gchar *name, AdgPair *pair, AdgModel *model)
846 gchar *new_name;
847 AdgPair new_pair;
849 new_name = g_strdup_printf("-%s", name);
850 cpml_pair_copy(&new_pair, pair);
851 new_pair.y = -new_pair.y;
853 adg_model_set_named_pair(model, new_name, &new_pair);
855 g_free(new_name);