Index
The following details could be outdated: to exactly know the current state you sould download the package and check the documentation (under the docs directory) or directly browse the sources online.
The project grew up around the GObject library: the ADG canvas is developed in plain C using the object-oriented approach supplied by GObject. This does not mean an ADG based application must be developed in C. The basic idea, when the API will be stable enough, is to have a set of language bindings for higher level languages (above all the garbage-collected ones). Then the application could be developed using those languages much in the same way as GTK+ applications are conceived. The first language supported will be probably LUA.
The rendering is based on the cairo engine, so the ADG project fully shares strong and weak points of the underlying cairo library.
For the optional database connectivity, my suggestion is to take a look to the libgda project, partly because it is an actively maintained project and partly because it uses the same technology (object-oriented C code using GObject and language bindings), so it can be easily integrated in a single application.
Basically, an application based on ADG must fulfill the following tasks:
The model is the abstract representation of the drawing subject (or part of it). The most common one is probably the AdgPath class, a model built around the cairo_path_t struct. A model can be rendered in the canvas more than once, with different styles and matrices.
The units used in the model definition are not relevant, as they will became signicative only while rendering it to the canvas (that is, when drawing a model into a view). It is common practice to use obvious units: for instance, in Italy you will use meters for plant projects and millimeters for mechanical parts. When adding the model to the canvas, you should set a proper local matrix to scale the drawing as needed and eventually get the proper ending scale.
You can have as many models as you need, depending on the application complexity. For instance, if the part you want to manage changes a lot only on some specific detail, you can consider to move this everchanging portion on its own model leaving the rest in another one, and join the models just before rendering them to the canvas.
With this operation the model is transposed to the view. Just instantiate an AdgCanvas and add entities inside it in the same way you construct a user interface in GTK+. Together with the model you will probably would like to add other decoration entities such as title block, quotes, hatches and whatever needed to get the final drawing.
Drawing by hand or with a CAD gives you full control: you must choose the best position for every quotes avoiding overlapping by hand. An automatic drawing system doesn't have the cognition of proper position and a collision detection system is beyond the scope of this project.
The ADG way to solve this issue is by providing everything needed to escape from (hopefully) any situation, allowing to customize almost everything. It is up to the application to put the quotes in a better place or to choose a proper scale.
One key concept of this approach is the use of two different matrices: the global matrix and the local matrix.
The global matrix is calculated by piling up (that is, multiplying) every global map defined by an AdgEntity and its ancestors. How the local matrix is calculated, instead, can be changed set by setting a specific property.
The big difference between these matrices is the global matrix is applied to everything while the local matrix only to some parts, usually the ones belonging in some way to a model. As a side note, the local matrix is always applied (when used) before the global matrix.
http://picasaweb.google.com/lh/photo/7w6AX3WoN7UHzoZhR1F81wTo grasp this concept, here it is a screenshot: applying a similar scale factor using a global map or a local map brings two really different results.
As you can see, when zooming in local space only the model shape is scaled and the start points of the dimensions follow this change (that is, they are scaled too). Other stuff, such as line thicknesses, text and arrow sizes, the distance from the extension lines to the shape and the spacing between the baselines, kept the original scale.
When zooming in global space, instead, you get the traditional zoom: everything is scaled.
By default global and local maps are initialized to the identity matrix, that is a matrix that, when used in multiplication, doesn't change the source.
The rendering customization is provided throught the interaction of the following ADG components:
The style is the brick over which all the customization is done. Being a huge task that could grow beyond any guess, the ADG approach is to implement the styles in an opened way, without knowing or guessing anything about them.
This means adding a new style is a matter of subclassing AdgStyle: the only requirement is to implement the apply() virtual method. You could put all the stuff you consider style stuff inside this new class: it is handled as an opaque object by the ADG library itsself. A new style will be likely used by a new entity, so you'd probably access the style instance only from the render() method of this new entity.
In the default implementation all the styles will be resolved by adg_dress_get_style(), but this implementation gives a good level of freedom, allowing the cascade overriding of a dress style with a single adg_entity_set_style() call. When required, new AdgDress values can be easily added with adg_dress_new(). Every dress always requires a default style, just to be sure to resolve any request as stated above.
To be useful, the canvas needs to be rendered somewhere. For convenience, the ADG library provides AdgWidget if the library has been built with GTK+ support enabled. This is a GtkWidget that can be embedded inside a GTK+ user interface but it is meant only as a demo widget.
In general you should use plain cairo to create the surface. The following example shows a quite basic way to render a canvas to a pdf file:
void
render_to_pdf(AdgCanvas *canvas)
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_pdf_surface_create("test.pdf", 841, 595);
cr = cairo_create(surface);
cairo_surface_destroy(surface);
adg_entity_render(ADG_ENTITY(canvas), cr);
cairo_show_page(cr);
cairo_destroy(cr);
}
You can check the demo/adg-demo.c source file for further examples.
Technical detailswas last modified by Nicola on Fri 07 May 2010 10:20:47 PM CEST