These API functions allow you to instantiate and manipulate
Affine transforms. An Affine transformation is a geometrical
transformation which is known to preserve the parallelism of
lines but not lengths and angles.
Figure 1. Affine transforms
Affine transforms are usually represented using Homogeneous
coordinates: given a point (x,y) in the traditional plane, its
canonical Homogenous coordinate is (x,y,1).
The Affine transforms are represented in Homogeneous coordinates
because the transformation of point A by any Affine transformation
can be expressed by the multiplication of a 3x3 Matrix and a 3x1
The above property is not trivial. For example, a translation in
normal cartesian space results in the addition of a Point vector
to the Point vector to transform while in Homogeneous space, the
same translation transformation results in a matrix/vector
multiplication. To convince you that I am telling you the truth,
the diagram below summarizes the different kinds of Affine matrixes
used and shows the scaling of point (x,y) by multiplication with a
scaling matrix in homogeneous space.
Figure 2. Affine transform Matrixes in Homogenous space
To compose two Affine transforms, all you need to do is to multiply
their matrices to get the matrix representing the resulting
Affine transform. Given Affines A and B represented the matrices
MA and MB, the Affine C = AoB is represented by the matrix MC = MA x MB.
Hopefully, all the above gory details (which are unfortunatly necessary
to understand the API) are more or less hidden by the API.
LibArt thus represents an Affine transform by an array of six doubles:
All non-degenerate affine transforms are invertible. If the original
affine is degenerate or nearly so, expect numerical instability and
very likely core dumps on Alpha and other fp-picky architectures.
Otherwise, dst multiplied with src, or src multiplied with dst
will be (to within roundoff error) the identity affine.
Where the resulting affine is stored.
The original affine transformation.
void art_affine_flip (double dst_affine,
const double src_affine,
Flips the affine transform. FALSE for both horiz and vert implements
a simple copy operation. TRUE for both horiz and vert is a
180 degree rotation. It is ok for src_affine and dst_affine to
be equal pointers.
Converts an affine transform into a bit of PostScript code that
implements the transform. Special cases of scaling, rotation, and
translation are detected, and the corresponding PostScript
operators used (this greatly aids understanding the output
generated). The identity transform is mapped to the null string.
Multiplies two affine transforms together, i.e. the resulting dst
is equivalent to doing first src1 then src2. Note that the
PostScript concat operator multiplies on the left, i.e. "M concat"
is equivalent to "CTM = multiply (M, CTM)";
It is safe to call this function with dst equal to src1 or src2.
Sets up a rotation matrix. In the standard libart coordinate
system, in which increasing y moves downward, this is a
counterclockwise rotation. In the standard PostScript coordinate
system, which is reversed in the y direction, it is a clockwise
Finds the expansion factor, i.e. the square root of the factor
by which the affine transform affects area. In an affine transform
composed of scaling, rotation, shearing, and translation, returns
the amount of scaling.
The affine transformation.
the expansion factor.
int art_affine_rectilinear (const double src);
Determines whether src is rectilinear, i.e. grid-aligned
rectangles are transformed to other grid-aligned rectangles. The
implementation has epsilon-tolerance for roundoff errors.
The original affine transformation.
TRUE if src is rectilinear.
int art_affine_equal (double matrix1,
Determines whether matrix1 and matrix2 are equal, with
epsilon-tolerance for roundoff errors.