This is a high-level guide to how the ADG project is organized and how to get started hacking on it. The following statements should be considered recommendations, not rules.

Hints on how to submit patches

Any patch worth the inclusion in the mainstream could be submitted to the bug tracker or by using the mailing list. The former is preferred when the patch addresses some specific issue while the latter is a better choice for generic patches and proofs of concept.

The project uses git as version control system and the repositories could be found at different places. The following are all kept up to date:

The preferred way to create a patch is by using git format-patch to generate the file. A typical usage involves the following steps:

1
2
3
4
5
6
7
git clone git://repo.or.cz/adg.git
cd adg
# Modify and test...
git commit -a
# Write the commit message
git format-patch HEAD^
# You have just created a proper patch file: send it

Coding style

The easiest way to hack the core of the ADG project (plain C language) is by following the code close to the place you are hacking, but if you want a written down set of rules, the coding style is loosely based on the kernel normal form style using a 4 space indentation. The tabs should be expanded to spaces and there must not be any trailing spaces at the end of line or empty lines at the end of a file (they are a PITA in version control). A common way to deal with the latter problem is to enable the pre-commit hook in your own repository:

1
2
3
cd adg
cp nodist/pre-commit .git/hooks
chmod 0755 .git/hooks/pre-commit

API conventions

The rules used by the API are more rigid and they are strictly tied to the GObject API conventions. The prefixes must be ADG, Adg and adg for the ADG canvas and CPML, Cpml and cpml for the cairo path manipulation library. In addition, the following suggestions/rules also apply:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* Method emitting "signal-name" */
void            adg_object_signal_name          (AdgObject      *object,
                                                 /* Other parameters */);

/* Generic setter method */
void            adg_object_set_value            (AdgObject      *object,
                                                 const AdgValue *value);
/* Setter method for boolean values */
void            adg_object_switch_boolean_value (AdgObject      *object,
                                                 gboolean       *new_state);

/* Generic getter method */
const AdgValue *adg_object_get_value            (AdgObject      *object);

/* Getter method for boolean values */
gboolean        adg_object_has_boolean_value    (AdgObject      *object);

/* Getter method for reference counted values: an object could be
 * referenced and unreferenced also if read-only, so no const needed */
AdgObject *     adg_object_get_object           (AdgObject      *object);

/* Getter method returning scalar values must not be const:
 * they are passed by value */
ScalarType      adg_object_get_scalar_value     (AdgObject      *object);

/* Alternative getter method to use when the generic syntax is
 * not allowed, such as when the value is dynamically generated */
void            adg_object_put_value            (AdgObject      *object,
                                                 AdgValue       *value);

/* Different version of the same setter method for pair values */
void            adg_object_set_value            (AdgObject      *object,
                                                 const AdgPair  *value);
void            adg_object_set_value_explicit   (AdgObject      *object,
                                                 gdouble         value_x,
                                                 gdouble         value_y);
void            adg_object_set_value_from_model (AdgADim        *adim,
                                                 AdgModel       *model,
                                                 const gchar    *named_pair);

The method should be grouped by argument, that is methods working on the same subject should be adjacents. The constructors must be the first ones while the helper methods for signal emission should be the last ones. It is preferable to keep the setter before the getter in the list.

For any other non-C contribution (makefiles, translations, bindings, documentation, whatever) just follow the surronding text using a bit of common sense. When no surrounding text exists, use your preferred style and use it consistently.

How the API should be used

The getter methods must be considered read-only. Although in some circumstances some of them do not return a const value, this is done just to allow referencing and unreferencing an object, but still that object should be considered read-only. This means to change a property you should write something along these lines:

1
2
3
4
5
CpmlExtents extents;

cpml_extents_copy(&extents, adg_entity_get_extents(entity));
/* Modify extents... */
adg_entity_set_extents(entity, &extents);

The put version of a getter usually does not have the setter counterpart (because the returned value is typically computed) so the above will be reduced to:

1
2
3
4
CpmlExtents extents;

cpml_segment_put_extents(segment, &extents);
/* Use extents... */