7 static AdgCanvas
* sample_canvas (void);
8 static AdgCanvas
* operations_canvas (void);
9 static void to_pdf (AdgWidget
*widget
,
11 static void to_png (AdgWidget
*widget
,
13 static void to_ps (AdgWidget
*widget
,
18 main(gint argc
, gchar
**argv
)
23 GtkWidget
*window
, *sample
, *operations
;
25 gtk_init(&argc
, &argv
);
27 path
= demo_find_data_file("adg-demo.ui");
29 g_print("adg-demo.ui not found!\n");
33 builder
= gtk_builder_new();
36 gtk_builder_add_from_file(builder
, path
, &error
);
38 g_print("%s\n", error
->message
);
42 window
= (GtkWidget
*) gtk_builder_get_object(builder
, "wndMain");
44 sample
= (GtkWidget
*) gtk_builder_get_object(builder
, "areaSample");
45 adg_widget_set_canvas(ADG_WIDGET(sample
), sample_canvas());
47 operations
= (GtkWidget
*) gtk_builder_get_object(builder
, "areaOperations");
48 adg_widget_set_canvas(ADG_WIDGET(operations
), operations_canvas());
51 g_signal_connect(window
, "delete-event",
52 G_CALLBACK(gtk_main_quit
), NULL
);
53 g_signal_connect(gtk_builder_get_object(builder
, "btnQuit"),
54 "clicked", G_CALLBACK(gtk_main_quit
), NULL
);
55 g_signal_connect_swapped(gtk_builder_get_object(builder
, "btnPng"),
56 "clicked", G_CALLBACK(to_png
), sample
);
57 g_signal_connect_swapped(gtk_builder_get_object(builder
, "btnPdf"),
58 "clicked", G_CALLBACK(to_pdf
), sample
);
59 g_signal_connect_swapped(gtk_builder_get_object(builder
, "btnPs"),
60 "clicked", G_CALLBACK(to_ps
), sample
);
62 g_object_unref(builder
);
64 gtk_widget_show_all(window
);
71 /**********************************************
72 * A sample mechanical part example
73 **********************************************/
75 #define SQRT3 1.732050808
78 typedef struct _SampleData SampleData
;
82 gdouble D1
, D2
, D3
, D4
, D5
, D6
, D7
;
84 gdouble LD2
, LD3
, LD5
, LD6
, LD7
;
87 static void sample_get (SampleData
*data
);
88 static AdgPath
*sample_path (const SampleData
*data
);
89 static void sample_add_dimensions (AdgCanvas
*canvas
,
90 const SampleData
*data
);
91 static void sample_add_stuff (AdgCanvas
*canvas
,
92 const SampleData
*data
);
101 AdgContainer
*container
;
106 path
= sample_path(&data
);
107 canvas
= adg_canvas_new();
108 container
= (AdgContainer
*) canvas
;
110 entity
= adg_stroke_new(path
);
111 adg_container_add(container
, entity
);
113 sample_add_dimensions(canvas
, &data
);
114 sample_add_stuff(canvas
, &data
);
116 cairo_matrix_init_translate(&map
, 100, 70);
117 cairo_matrix_scale(&map
, 6.883, 6.883);
118 cairo_matrix_translate(&map
, 0, 10);
119 adg_entity_set_local_map(ADG_ENTITY(container
), &map
);
125 sample_get(SampleData
*data
)
146 sample_path(const SampleData
*data
)
150 AdgSegment segment_org
;
152 cairo_matrix_t matrix
;
154 path
= (AdgPath
*) adg_path_new();
156 adg_path_move_to(path
, 0, data
->D1
/ 2);
157 adg_path_line_to(path
, data
->A
- data
->B
- data
->LD2
, data
->D1
/ 2);
158 y
= (data
->D1
- data
->D2
) / 2;
159 adg_path_line_to(path
, data
->A
- data
->B
- data
->LD2
+ y
* SQRT3
, data
->D1
/ 2 - y
);
160 adg_path_line_to(path
, data
->A
- data
->B
, data
->D2
/ 2);
161 adg_path_fillet(path
, 0.4);
162 adg_path_line_to(path
, data
->A
- data
->B
, data
->D3
/ 2);
163 adg_path_chamfer(path
, CHAMFER
, CHAMFER
);
164 adg_path_line_to(path
, data
->A
- data
->B
+ data
->LD3
, data
->D3
/ 2);
165 adg_path_chamfer(path
, CHAMFER
, CHAMFER
);
166 adg_path_line_to(path
, data
->A
- data
->B
+ data
->LD3
, data
->D4
/ 2);
167 adg_path_fillet(path
, data
->RD34
);
168 adg_path_line_to(path
, data
->A
- data
->C
- data
->LD5
, data
->D4
/ 2);
169 y
= (data
->D4
- data
->D5
) / 2;
170 adg_path_line_to(path
, data
->A
- data
->C
- data
->LD5
+ y
, data
->D4
/ 2 - y
);
171 adg_path_line_to(path
, data
->A
- data
->C
, data
->D5
/ 2);
172 adg_path_fillet(path
, 0.2);
173 adg_path_line_to(path
, data
->A
- data
->C
, data
->D6
/ 2);
174 adg_path_fillet(path
, 0.1);
175 adg_path_line_to(path
, data
->A
- data
->C
+ data
->LD6
, data
->D6
/ 2);
176 x
= data
->C
- data
->LD7
- data
->LD6
;
178 adg_path_line_to(path
, data
->A
- data
->C
+ data
->LD6
+ x
, data
->D6
/ 2 - y
);
179 adg_path_line_to(path
, data
->A
- data
->LD7
, data
->D7
/ 2);
180 adg_path_line_to(path
, data
->A
, data
->D7
/ 2);
182 /* Build the rounded shape by duplicating the first segment of
183 * the current path, reflecting it on the y=0 axis, reversing and
184 * joining it the result to the original path */
185 cpml_segment_from_cairo(&segment_org
, adg_path_get_cpml_path(path
));
186 segment
= adg_segment_deep_dup(&segment_org
);
187 cpml_segment_reverse(segment
);
188 adg_matrix_init_reflection(&matrix
, 0);
189 cpml_segment_transform(segment
, &matrix
);
190 segment
->data
[0].header
.type
= CAIRO_PATH_LINE_TO
;
192 adg_path_append_segment(path
, segment
);
196 adg_path_close(path
);
201 sample_add_dimensions(AdgCanvas
*canvas
, const SampleData
*data
)
209 entity
= adg_ldim_new_full_explicit(data
->A
- data
->B
- data
->LD2
, -data
->D1
/ 2, data
->A
- data
->B
,
210 -data
->D3
/ 2 + CHAMFER
, ADG_DIR_UP
, 0,
212 adg_container_add(ADG_CONTAINER(canvas
), entity
);
215 entity
= adg_ldim_new_full_explicit(data
->A
- data
->B
, -data
->D3
/ 2 + CHAMFER
, data
->A
- data
->B
+ data
->LD3
,
216 -data
->D3
/ 2 + CHAMFER
, ADG_DIR_UP
, 0,
218 adg_container_add(ADG_CONTAINER(canvas
), entity
);
223 entity
= adg_ldim_new_full_explicit(data
->A
- data
->B
, data
->D3
/ 2 - CHAMFER
, data
->A
, data
->D7
/ 2,
224 ADG_DIR_DOWN
, 0, data
->D3
/ 2);
225 adg_dim_set_tolerances(ADG_DIM(entity
), "+0.1", NULL
);
226 adg_container_add(ADG_CONTAINER(canvas
), entity
);
229 entity
= adg_ldim_new_full_explicit(0, data
->D1
/ 2, data
->A
, data
->D7
/ 2,
230 ADG_DIR_DOWN
, 0, data
->D3
/ 2);
231 adg_dim_set_tolerances(ADG_DIM(entity
), "+0.05", "-0.05");
232 adg_dim_set_level(ADG_DIM(entity
), 2);
233 adg_container_add(ADG_CONTAINER(canvas
), entity
);
238 x
= data
->A
- data
->B
+ data
->LD3
- CHAMFER
;
239 entity
= adg_ldim_new_full_explicit(x
, -data
->D3
/ 2, x
, data
->D3
/ 2,
240 ADG_DIR_RIGHT
, data
->A
, 0);
241 adg_dim_set_tolerances(ADG_DIM(entity
), "-0.25", NULL
);
242 adg_dim_set_level(ADG_DIM(entity
), 5);
243 adg_container_add(ADG_CONTAINER(canvas
), entity
);
246 x
= data
->A
- data
->C
+ data
->LD6
;
247 entity
= adg_ldim_new_full_explicit(x
, -data
->D6
/ 2, x
, data
->D6
/ 2,
248 ADG_DIR_RIGHT
, data
->A
, 0);
249 adg_dim_set_tolerances(ADG_DIM(entity
), "-0.1", NULL
);
250 adg_dim_set_level(ADG_DIM(entity
), 4);
251 adg_container_add(ADG_CONTAINER(canvas
), entity
);
254 x
= data
->A
- data
->C
- data
->LD5
;
255 entity
= adg_ldim_new_full_explicit(x
, -data
->D4
/ 2, x
, data
->D4
/ 2,
256 ADG_DIR_RIGHT
, data
->A
, 0);
257 adg_dim_set_level(ADG_DIM(entity
), 3);
258 adg_container_add(ADG_CONTAINER(canvas
), entity
);
261 x
= data
->A
- data
->C
;
262 entity
= adg_ldim_new_full_explicit(x
, -data
->D5
/ 2, x
, data
->D5
/ 2,
263 ADG_DIR_RIGHT
, data
->A
, 0);
264 adg_dim_set_tolerances(ADG_DIM(entity
), "-0.1", NULL
);
265 adg_dim_set_level(ADG_DIM(entity
), 2);
266 adg_container_add(ADG_CONTAINER(canvas
), entity
);
269 entity
= adg_ldim_new_full_explicit(data
->A
, -data
->D7
/ 2, data
->A
, data
->D7
/ 2,
270 ADG_DIR_RIGHT
, data
->A
, 0);
271 adg_container_add(ADG_CONTAINER(canvas
), entity
);
276 entity
= adg_ldim_new_full_explicit(0, -data
->D1
/ 2, 0, data
->D1
/ 2,
278 adg_dim_set_tolerances(ADG_DIM(entity
), "+0.05", "-0.05");
279 adg_dim_set_level(ADG_DIM(entity
), 2);
280 adg_container_add(ADG_CONTAINER(canvas
), entity
);
283 y
= (data
->D1
- data
->D2
) / 2;
284 x
= data
->A
- data
->B
- data
->LD2
+ y
* SQRT3
;
285 entity
= adg_ldim_new_full_explicit(x
, -data
->D2
/ 2, x
, data
->D2
/ 2,
287 adg_dim_set_tolerances(ADG_DIM(entity
), "-0.1", NULL
);
288 adg_container_add(ADG_CONTAINER(canvas
), entity
);
292 sample_add_stuff(AdgCanvas
*canvas
, const SampleData
*data
)
297 toy_text
= adg_toy_text_new("Rotate the mouse wheel to zoom in and out");
298 cairo_matrix_init_translate(&map
, 0., data
->D3
/ 2);
299 adg_entity_set_local_map(toy_text
, &map
);
300 cairo_matrix_init_translate(&map
, 10., 30. + 30. * 2);
301 adg_entity_set_global_map(toy_text
, &map
);
302 adg_container_add(ADG_CONTAINER(canvas
), toy_text
);
304 toy_text
= adg_toy_text_new("Keep the wheel pressed while dragging the mouse to translate");
305 cairo_matrix_init_translate(&map
, 0., data
->D3
/ 2);
306 adg_entity_set_local_map(toy_text
, &map
);
307 cairo_matrix_init_translate(&map
, 10., 45. + 30. * 2);
308 adg_entity_set_global_map(toy_text
, &map
);
309 adg_container_add(ADG_CONTAINER(canvas
), toy_text
);
313 #if defined(CAIRO_HAS_PNG_FUNCTIONS) || defined(CAIRO_HAS_PDF_SURFACE) || defined(CAIRO_HAS_PS_SURFACE)
315 /* Only needed if there is at least one supported surface */
317 file_generated(GtkWidget
*caller
, const gchar
*file
)
322 window
= (GtkWindow
*) gtk_widget_get_toplevel(caller
);
323 dialog
= gtk_message_dialog_new_with_markup(window
, GTK_DIALOG_MODAL
,
326 "The requested operation generated\n"
327 "<b>%s</b> in the current directory.",
329 gtk_window_set_title(GTK_WINDOW(dialog
), "Operation completed");
330 gtk_dialog_run(GTK_DIALOG(dialog
));
331 gtk_widget_destroy(dialog
);
336 #if !defined(CAIRO_HAS_PNG_FUNCTIONS) || !defined(CAIRO_HAS_PDF_SURFACE) || !defined(CAIRO_HAS_PS_SURFACE)
338 /* Only needed if there is a missing surface */
340 missing_feature(GtkWidget
*caller
, const gchar
*feature
)
345 window
= (GtkWindow
*) gtk_widget_get_toplevel(caller
);
346 dialog
= gtk_message_dialog_new(window
, GTK_DIALOG_MODAL
,
349 "The provided cairo library\n"
350 "was compiled with no %s support!",
352 gtk_window_set_title(GTK_WINDOW(dialog
), "Missing feature");
353 gtk_dialog_run(GTK_DIALOG(dialog
));
354 gtk_widget_destroy(dialog
);
360 #ifdef CAIRO_HAS_PNG_FUNCTIONS
363 to_png(AdgWidget
*widget
, GtkWidget
*caller
)
365 cairo_surface_t
*surface
;
368 surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, 800, 600);
369 cr
= cairo_create(surface
);
370 cairo_surface_destroy(surface
);
372 /* Rendering process */
373 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget
)), cr
);
376 cairo_surface_write_to_png(surface
, "test.png");
379 file_generated(caller
, "test.png");
385 to_png(AdgWidget
*widget
, GtkWidget
*caller
)
387 missing_feature(caller
, "PNG");
392 #ifdef CAIRO_HAS_PDF_SURFACE
394 #include <cairo-pdf.h>
397 to_pdf(AdgWidget
*widget
, GtkWidget
*caller
)
399 cairo_surface_t
*surface
;
402 surface
= cairo_pdf_surface_create("test.pdf", 841, 595);
403 cr
= cairo_create(surface
);
404 cairo_surface_destroy(surface
);
406 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget
)), cr
);
411 file_generated(caller
, "test.pdf");
417 to_pdf(AdgWidget
*widget
, GtkWidget
*caller
)
419 missing_feature(caller
, "PDF");
424 #ifdef CAIRO_HAS_PS_SURFACE
426 #include <cairo-ps.h>
429 to_ps(AdgWidget
*widget
, GtkWidget
*caller
)
431 cairo_surface_t
*surface
;
434 /* Surface creation: A4 size */
435 surface
= cairo_ps_surface_create("test.ps", 841, 595);
436 cairo_ps_surface_dsc_comment(surface
,
437 "%%Title: Automatic Drawing Generation (ADG) demo");
438 cairo_ps_surface_dsc_comment(surface
,
439 "%%Copyright: Copyright (C) 2006-2009 Fontana Nicola");
440 cairo_ps_surface_dsc_comment(surface
, "%%Orientation: Portrait");
442 cairo_ps_surface_dsc_begin_setup(surface
);
444 cairo_ps_surface_dsc_begin_page_setup(surface
);
445 cairo_ps_surface_dsc_comment(surface
,
446 "%%IncludeFeature: *PageSize A4");
448 cr
= cairo_create(surface
);
449 cairo_surface_destroy(surface
);
451 adg_entity_render(ADG_ENTITY(adg_widget_get_canvas(widget
)), cr
);
456 file_generated(caller
, "test.ps");
462 to_ps(AdgWidget
*widget
, GtkWidget
*caller
)
464 missing_feature(caller
, "PostScript");
470 /**********************************************
471 * Test case for basic operations,
472 * such as chamfer and fillet
473 **********************************************/
475 static AdgPath
* operations_chamfer (const AdgPath
*path
,
478 static AdgPath
* operations_fillet (const AdgPath
*path
,
482 operations_canvas(void)
484 AdgPath
*path
, *chamfer_path
, *fillet_path
;
486 AdgContainer
*container
;
490 /* Build the base model */
491 path
= (AdgPath
*) adg_path_new();
493 adg_path_move_to(path
, 2, 0);
494 adg_path_line_to(path
, 0, 5);
495 adg_path_line_to(path
, 2, 2);
496 adg_path_line_to(path
, 0, 8);
497 adg_path_line_to(path
, 2, 8);
498 adg_path_line_to(path
, 2, 10);
499 adg_path_line_to(path
, 3, 10);
500 adg_path_line_to(path
, 10, 9);
501 adg_path_line_to(path
, 5, 5);
502 adg_path_line_to(path
, 3, 0);
503 adg_path_close(path
);
505 /* Build the chamfer model */
506 chamfer_path
= operations_chamfer(path
, 0.25, 0.25);
508 /* Build the fillet model */
509 fillet_path
= operations_fillet(path
, 0.20);
511 /* Create the canvas */
512 canvas
= adg_canvas_new();
514 /* Add the original shape */
515 container
= (AdgContainer
*) adg_container_new();
516 adg_container_add(ADG_CONTAINER(canvas
), ADG_ENTITY(container
));
517 adg_container_add(container
, adg_stroke_new(path
));
518 entity
= adg_toy_text_new("Original shape");
519 cairo_matrix_init_translate(&map
, 5, 10);
520 adg_entity_set_local_map(entity
, &map
);
521 cairo_matrix_init_translate(&map
, -50, 20);
522 adg_entity_set_global_map(entity
, &map
);
523 adg_container_add(ADG_CONTAINER(canvas
), entity
);
525 /* Add the shape with 0.25x0.25 chamfer */
526 container
= (AdgContainer
*) adg_container_new();
527 cairo_matrix_init_translate(&map
, 15., 0.);
528 adg_entity_set_local_map(ADG_ENTITY(container
), &map
);
529 adg_container_add(ADG_CONTAINER(canvas
), ADG_ENTITY(container
));
530 adg_container_add(container
, adg_stroke_new(chamfer_path
));
531 entity
= adg_toy_text_new("Shape with 0.25x0.25 chamfer");
532 cairo_matrix_init_translate(&map
, 5, 10);
533 adg_entity_set_local_map(entity
, &map
);
534 cairo_matrix_init_translate(&map
, -120, 20);
535 adg_entity_set_global_map(entity
, &map
);
536 adg_container_add(container
, entity
);
538 /* Add the shape with fillets with 0.20 of radius */
539 container
= (AdgContainer
*) adg_container_new();
540 cairo_matrix_init_translate(&map
, 30., 0.);
541 adg_entity_set_local_map(ADG_ENTITY(container
), &map
);
542 adg_container_add(ADG_CONTAINER(canvas
), ADG_ENTITY(container
));
543 adg_container_add(container
, adg_stroke_new(fillet_path
));
544 entity
= adg_toy_text_new("Shape with R=20 fillet");
545 cairo_matrix_init_translate(&map
, 5, 10);
546 adg_entity_set_local_map(entity
, &map
);
547 cairo_matrix_init_translate(&map
, -90, 20);
548 adg_entity_set_global_map(entity
, &map
);
549 adg_container_add(container
, entity
);
551 /* Set a decent start position and zoom */
552 cairo_matrix_init_translate(&map
, 10, -140);
553 cairo_matrix_scale(&map
, 15, 15);
554 cairo_matrix_translate(&map
, 0, 10);
555 adg_entity_set_local_map(ADG_ENTITY(canvas
), &map
);
561 operations_chamfer(const AdgPath
*model
, gdouble delta1
, gdouble delta2
)
565 CpmlPrimitive primitive
;
567 path
= (AdgPath
*) adg_path_new();
568 cpml_segment_from_cairo(&segment
, adg_path_get_cpml_path((AdgPath
*) model
));
569 cpml_primitive_from_segment(&primitive
, &segment
);
571 adg_path_move_to(path
, (primitive
.org
)->point
.x
, (primitive
.org
)->point
.y
);
574 adg_path_append_primitive(path
, &primitive
);
575 if (primitive
.data
[0].header
.type
== CAIRO_PATH_LINE_TO
)
576 adg_path_chamfer(path
, delta1
, delta2
);
577 } while (cpml_primitive_next(&primitive
));
583 operations_fillet(const AdgPath
*model
, gdouble radius
)
587 CpmlPrimitive primitive
;
589 path
= (AdgPath
*) adg_path_new();
590 cpml_segment_from_cairo(&segment
, adg_path_get_cpml_path((AdgPath
*) model
));
591 cpml_primitive_from_segment(&primitive
, &segment
);
593 adg_path_move_to(path
, (primitive
.org
)->point
.x
, (primitive
.org
)->point
.y
);
596 adg_path_append_primitive(path
, &primitive
);
597 if (primitive
.data
[0].header
.type
== CAIRO_PATH_LINE_TO
)
598 adg_path_fillet(path
, radius
);
599 } while (cpml_primitive_next(&primitive
));