CpmlPrimitive — Basic component of segments
#define CAIRO_PATH_ARC_TO CpmlPrimitive; enum CpmlPrimitiveType; size_t cpml_primitive_type_get_n_points (CpmlPrimitiveType type); void cpml_primitive_from_segment (CpmlPrimitive *primitive, CpmlSegment *segment); void cpml_primitive_copy (CpmlPrimitive *primitive, const CpmlPrimitive *src); void cpml_primitive_reset (CpmlPrimitive *primitive); cairo_bool_t cpml_primitive_next (CpmlPrimitive *primitive); size_t cpml_primitive_get_n_points (const CpmlPrimitive *primitive); cairo_path_data_t * cpml_primitive_get_point (const CpmlPrimitive *primitive, int n_point); double cpml_primitive_get_length (const CpmlPrimitive *primitive); void cpml_primitive_put_extents (const CpmlPrimitive *primitive, CpmlExtents *extents); void cpml_primitive_put_pair_at (const CpmlPrimitive *primitive, double pos, CpmlPair *pair); void cpml_primitive_put_vector_at (const CpmlPrimitive *primitive, double pos, CpmlVector *vector); double cpml_primitive_get_closest_pos (const CpmlPrimitive *primitive, const CpmlPair *pair); size_t cpml_primitive_put_intersections (const CpmlPrimitive *primitive, const CpmlPrimitive *primitive2, size_t n_dest, CpmlPair *dest); size_t cpml_primitive_put_intersections_with_segment (const CpmlPrimitive *primitive, const CpmlSegment *segment, size_t n_dest, CpmlPair *dest); void cpml_primitive_offset (CpmlPrimitive *primitive, double offset); cairo_bool_t cpml_primitive_join (CpmlPrimitive *primitive, CpmlPrimitive *primitive2); void cpml_primitive_to_cairo (const CpmlPrimitive *primitive, cairo_t *cr); void cpml_primitive_dump (const CpmlPrimitive *primitive, cairo_bool_t org_also);
A primitive is an atomic geometric element found inside CpmlSegment. The available primitives are the same defined by cairo_path_data_type_t with the additional CPML_ARC type (check CpmlPrimitiveType for further information) and without CPML_MOVE as it is not considered a primitive and it is managed in different way: the move-to primitives are only used to define the origin of a segment.
#define CAIRO_PATH_ARC_TO 100
Actually, at least up to version 1.9.6, the cairo library does not support arc primitives natively. Furthermore, there is no plan they will be ever supported.
Arcs are used extensively in many sectors and some operations are
trivials with arcs and a nightmare with cubic Bézier curves. The
CPML library provides native arc support, converting them to curves
when the CpmlSegment is returned to a cairo context, for instance
when using cpml_segment_to_cairo().
typedef struct {
CpmlSegment *segment;
cairo_path_data_t *org;
cairo_path_data_t *data;
} CpmlPrimitive;
As for CpmlSegment, also the primitive is unobtrusive. This means CpmlPrimitive does not include any coordinates but instead keeps pointers to the original segment (and, by transition, to the underlying CpmlPath struct).
|
CpmlSegment * |
the source CpmlSegment |
| a pointer to the first point of the primitive | |
| the array of the path data, prepended by the header |
typedef enum {
CPML_MOVE = CAIRO_PATH_MOVE_TO,
CPML_LINE = CAIRO_PATH_LINE_TO,
CPML_CURVE = CAIRO_PATH_CURVE_TO,
CPML_CLOSE = CAIRO_PATH_CLOSE_PATH,
CPML_ARC = CAIRO_PATH_ARC_TO
} CpmlPrimitiveType;
This is a type compatible with cairo_path_data_type_t type. It is basically the same enum but it embodies an important difference: it can be used to specify the special CPML_ARC primitive. This is not a native cairo primitive and having two different types is a good way to make clear when a function expect or not embedded CPML_ARC primitives.
size_t cpml_primitive_type_get_n_points (CpmlPrimitiveType type);
Gets the number of points required to identify the type primitive.
|
|
a primitive type |
|
Returns : |
the number of points or 0 on errors |
void cpml_primitive_from_segment (CpmlPrimitive *primitive, CpmlSegment *segment);
Initializes primitive to the first primitive of segment.
|
|
the destination CpmlPrimitive struct |
|
|
the source segment |
void cpml_primitive_copy (CpmlPrimitive *primitive, const CpmlPrimitive *src);
Copies src in primitive. This is a shallow copy: the internal fields
of primitive refer to the same memory as the original src primitive.
|
|
the destination CpmlPrimitive |
|
|
the source CpmlPrimitive |
void cpml_primitive_reset (CpmlPrimitive *primitive);
Resets primitive so it refers to the first primitive of the
source segment.
|
|
a CpmlPrimitive |
cairo_bool_t cpml_primitive_next (CpmlPrimitive *primitive);
Changes primitive so it refers to the next primitive on the
source segment. If there are no more primitives, primitive is
not changed and 0 is returned.
|
|
a CpmlPrimitive |
|
Returns : |
1 on success, 0 if no next primitive found or errors |
size_t cpml_primitive_get_n_points (const CpmlPrimitive *primitive);
Gets the number of points required to identify primitive.
It is similar to cpml_primitive_type_get_n_points() but using
a primitive instance instead of a type.
|
|
a CpmlPrimitive |
|
Returns : |
the number of points or 0 on errors |
cairo_path_data_t * cpml_primitive_get_point (const CpmlPrimitive *primitive, int n_point);
Gets the specified n_point from primitive. The index starts
at 0: if n_point is 0, the start point (the origin) is
returned, 1 for the second point and so on. If n_point is
negative, it is considered as a negative index from the end,
so that -1 is the end point, -2 the point before the end point
and so on.
CPML_CLOSE is managed in a special way: if n_point
is -1 or 1 and primitive is a close-path, this function cycles
the source CpmlSegment and returns the first point. This is
needed because requesting the end point (or the second point)
of a close path is a valid operation and must returns the start
of the segment.
|
|
a CpmlPrimitive |
|
|
the index of the point to retrieve |
|
Returns : |
a pointer to the requested point (in cairo format) or NULL if the point is outside the valid range |
double cpml_primitive_get_length (const CpmlPrimitive *primitive);
Abstracts the length() family functions by providing a common
way to access the underlying primitive-specific implementation.
The function returns the length of primitive.
|
|
a CpmlPrimitive |
|
Returns : |
the requested length or 0 on errors |
void cpml_primitive_put_extents (const CpmlPrimitive *primitive, CpmlExtents *extents);
Abstracts the extents() family functions by providing a common way to access the underlying primitive-specific implementation.
This function stores in extents the bounding box of primitive.
On errors, that is if the extents cannot be calculated for some reason, this function does nothing.
|
|
a CpmlPrimitive |
|
|
where to store the extents |
void cpml_primitive_put_pair_at (const CpmlPrimitive *primitive, double pos, CpmlPair *pair);
Abstracts the put_pair_at() family functions by providing a common way to access the underlying primitive-specific implementation.
It gets the coordinates of the point lying on primitive
at position pos. pos is an homogeneous factor where 0 is the
start point, 1 the end point, 0.5 the mid point and so on.
pos can be less than 0 or greater than 1, in which case the
coordinates of pair are interpolated.
On errors, that is if the coordinates cannot be calculated for some reason, this function does nothing.
|
|
a CpmlPrimitive |
|
|
the position value |
|
|
the destination CpmlPair |
void cpml_primitive_put_vector_at (const CpmlPrimitive *primitive, double pos, CpmlVector *vector);
Abstracts the put_vector_at() family functions by providing a common way to access the underlying primitive-specific implementation.
It gets the steepness of the point at position pos on primitive.
pos is an homogeneous factor where 0 is the start point, 1 the
end point, 0.5 the mid point and so on.
pos can be less than 0 or greater than 1, in which case the
coordinates of pair are interpolated.
On errors, that is if the steepness cannot be calculated for some reason, this function does nothing.
|
|
a CpmlPrimitive |
|
|
the position value |
|
|
the destination CpmlVector |
double cpml_primitive_get_closest_pos (const CpmlPrimitive *primitive, const CpmlPair *pair);
Returns the pos value of the point on primitive nearest to pair.
The returned value is always clamped between 0 and 1.
|
|
a CpmlPrimitive |
|
|
the coordinates of the subject point |
|
Returns : |
the requested pos value between 0 and 1, or -1 on errors |
size_t cpml_primitive_put_intersections (const CpmlPrimitive *primitive, const CpmlPrimitive *primitive2, size_t n_dest, CpmlPair *dest);
Finds the intersection points between the given primitives and
returns the result in dest. The size of dest should be enough
to store n_dest CpmlPair. The maximum number of intersections
is dependent on the type of the primitive involved in the
operation. If there are at least one Bézier curve involved, up to
4 intersections could be returned. Otherwise, if there is an arc
the intersections will be 2 at maximum. For line primitives, there
is only 1 point (or 0 if the lines are parallel).
The convention used by the CPML library is that a primitive should
implement only the intersection algorithms with lower degree
primitives. This is required to avoid code duplication: intersection
between arc and Bézier curves must be implemented by CPML_CURVE and
intersection between lines and arcs must be implemented by CPML_ARC.
cpml_primitive_put_intersections() will take care of swapping the
arguments if they are not properly ordered.
|
|
the first CpmlPrimitive |
|
|
the second CpmlPrimitive |
|
|
maximum number of intersections to return |
|
|
the destination buffer that can contain n_dest CpmlPair
|
|
Returns : |
the number of intersection points found or 0 if the primitives do not intersect or on errors |
size_t cpml_primitive_put_intersections_with_segment
(const CpmlPrimitive *primitive,
const CpmlSegment *segment,
size_t n_dest,
CpmlPair *dest);
Computes the intersections between segment and primitive by
sequentially scanning the primitives in segment and looking
for their intersections with primitive.
If the intersections are more than n_dest, only the first
n_dest pairs are stored.
|
|
a CpmlPrimitive |
|
|
a CpmlSegment |
|
|
maximum number of intersection pairs to return |
|
|
the destination buffer of CpmlPair |
|
Returns : |
the number of intersections found |
void cpml_primitive_offset (CpmlPrimitive *primitive, double offset);
Given a primitive, computes the same (or approximated) parallel
primitive distant offset from the original one and returns
the result by changing primitive.
On errors, that is if the offset primitive cannot be calculated for some reason, this function does nothing.
|
|
a CpmlPrimitive |
|
|
distance for the computed offset primitive |
cairo_bool_t cpml_primitive_join (CpmlPrimitive *primitive, CpmlPrimitive *primitive2);
Joins two primitive modifying the end point of primitive and the
start point of primitive2 so that the resulting points will overlap.
primitive and the start vector of primitive2 and
interpolating the intersection: this means no primitive
dependent code is needed. Anyway, it is likely to change
in the future because this approach is quite naive when
curves are involved.|
|
the first CpmlPrimitive |
|
|
the second CpmlPrimitive |
|
Returns : |
1 on success, 0 if the end vector of primitive
and the start vector of primitive2 are parallel
|
void cpml_primitive_to_cairo (const CpmlPrimitive *primitive, cairo_t *cr);
Renders a single primitive to the cr cairo context.
As a special case, if the primitive is a CPML_CLOSE, an
equivalent line is rendered, because a close path left alone
is not renderable.
Also a CPML_ARC primitive is treated specially, as it is not natively supported by cairo and has its own rendering API.
|
|
a CpmlPrimitive |
|
|
the destination cairo context |
void cpml_primitive_dump (const CpmlPrimitive *primitive, cairo_bool_t org_also);
Dumps info on the specified primitive to stdout: useful for
debugging purposes. If org_also is 1, a CPML_MOVE to the
origin is prepended to the data otherwise the
org field is not used.
|
|
a CpmlPrimitive |
|
|
whether to output also the origin coordinates |
CpmlPrimitivewas last modified by gtk-doc on Mon 05 Jul 2010 11:11:52 PM CEST