Sie sind auf Seite 1von 37

CPML reference manual

CPML reference manual

CPML reference manual


ii

COLLABORATORS TITLE : CPML reference manual ACTION NAME DATE SIGNATURE

WRITTEN BY

October 31, 2012

REVISION HISTORY NUMBER DATE DESCRIPTION NAME

CPML reference manual


iii

Contents

I
1 2 3

Core reference
Utilities CpmlPair CpmlExtents

1
2 3 8

II
4 5 6

Path constructs
CpmlSegment CpmlPrimitive Special primitives 6.1 6.2

12
13 20 28

CpmlArc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 CpmlCurve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Index

34

CPML reference manual


1 / 34

Part I

Core reference

CPML reference manual


2 / 34

Chapter 1

Utilities
Utilities Assorted macros and functions

Synopsis
#define double CPML_GNUC_CONST cpml_angle (double angle);

Description
Collection of macros and functions that do not t inside any other topic.

Details
CPML_GNUC_CONST
#define CPML_GNUC_CONST __attribute__((__const__))

To be appended at the end of a function to notice the compiler (gcc) that the return value is constant. The coded is an adaptation of the G_GNUC_CONST macro dened by glib-2.18.3 in glib/gmacros.h. Since 1.0

cpml_angle ()
double cpml_angle (double angle);

Normalizes angle, that is returns the equivalent radians value between the range M_PI (inclusive) and -M_PI (exclusive).
angle : an angle in radians

Returns : an equivalent value in radians Since 1.0

CPML reference manual


3 / 34

Chapter 2

CpmlPair
CpmlPair Basic struct holding a couple of values

Synopsis
struct typedef void double int void double void void double void void void void CpmlPair; CpmlVector; cpml_pair_copy cpml_pair_distance cpml_pair_equal cpml_pair_from_cairo cpml_pair_squared_distance cpml_pair_to_cairo cpml_pair_transform cpml_vector_angle cpml_vector_from_angle cpml_vector_normal cpml_vector_set_length cpml_vector_transform

(CpmlPair *pair, const CpmlPair *src); (const CpmlPair *from, const CpmlPair *to); (const CpmlPair *pair, const CpmlPair *src); (CpmlPair *pair, const cairo_path_data_t *path_data (const CpmlPair *from, const CpmlPair *to); (const CpmlPair *pair, cairo_path_data_t *path_data); (CpmlPair *pair, const cairo_matrix_t *matrix); (const CpmlVector *vector); (CpmlVector *vector, double angle); (CpmlVector *vector); (CpmlVector *vector, double length); (CpmlVector *vector, const cairo_matrix_t *matrix);

Description
The CpmlPair is a generic 2D structure. It can be used to represent coordinates, sizes, offsets or whatever have two components. The name comes from MetaFont.

CPML reference manual


4 / 34

Details
struct CpmlPair
struct CpmlPair { double x, y; };

A generic 2D structure. double x ; the x component of the pair double y ; the y component of the pair Since 1.0

CpmlVector
typedef struct _CpmlPair CpmlVector;

Another name for CpmlPair. It is used to clarify when a function expects a generic pair (usually coordinates) or a vector. A vector represents a line starting from the origin (0,0) and ending to the given coordinates pair. Vectors are useful to dene direction and length at once. Keep in mind the cairo default coordinates system is not problably what you expect: the x axis increases at right (as usual) but the y axis increases at down (the reverse of a usual cartesian plan). An angle of 0 is at V=(1; 0) (middle right). Since 1.0

cpml_pair_copy ()
void cpml_pair_copy (CpmlPair *pair, const CpmlPair *src);

Copies src in pair .


pair : the destination CpmlPair. [out] src : the source CpmlPair. [in]

Since 1.0

cpml_pair_distance ()
double cpml_pair_distance (const CpmlPair *from, const CpmlPair *to);

Gets the distance between from and to. If you need this value only for comparation purpose, you could use cpm_pair_squared_distance() instead.
from or to could be NULL, in which case the fallback (0, 0) pair will be used.

The algorithm used is adapted from: "Replacing Square Roots by Pythagorean Sums" by Clave Moler and Donald Morrison (1983) IBM Journal of Research and Development 27 (6): 577581 http://www.research.ibm.com/journal/rd/276/ibmrd2706P.pdf
from : the rst CpmlPair struct to : the second CpmlPair struct

Returns : the distance Since 1.0

CPML reference manual


5 / 34

cpml_pair_equal ()
int cpml_pair_equal (const CpmlPair *pair, const CpmlPair *src);

Compares pair to src and returns 1 if the pairs are equals. Two NULL pairs are considered equal.
pair : the rst pair to compare src : the second pair to compare

Returns : 1 if pair is equal to src, 0 otherwise. [type gboolean] Since 1.0

cpml_pair_from_cairo ()
void cpml_pair_from_cairo (CpmlPair *pair, const cairo_path_data_t *path_data );

Sets pair from a cairo_path_data_t struct. path_data should contains a point data: it is up to the caller to be sure path_data is valid.
pair : the destination CpmlPair. [out] path_data : the original path data point. [in][type gpointer]

Since 1.0

cpml_pair_squared_distance ()
double cpml_pair_squared_distance (const CpmlPair *from, const CpmlPair *to);

Gets the squared distance between from and to. This value is useful for comparation purpose: if you need to get the real distance, use cpml_pair_distance().
from or to could be NULL, in which case the fallback (0, 0) pair will be used. from : the rst CpmlPair struct to : the second CpmlPair struct

Returns : the squared distance Since 1.0

cpml_pair_to_cairo ()
void cpml_pair_to_cairo (const CpmlPair *pair, cairo_path_data_t *path_data);

Sets a cairo_path_data_t struct to pair . This is exactly the reverse operation of cpml_pair_from_cairo().
pair : the source CpmlPair. [in] path_data : the path data point to modify. [out][type gpointer]

Since 1.0

CPML reference manual


6 / 34

cpml_pair_transform ()
void cpml_pair_transform (CpmlPair *pair, const cairo_matrix_t *matrix);

Shortcut to apply a specic transformation matrix to pair .


pair : the destination CpmlPair struct. [inout] matrix : the transformation matrix. [in]

Since 1.0

cpml_vector_angle ()
double cpml_vector_angle (const CpmlVector *vector);

Gets the angle of vector , in radians. If vector is (0, 0), 0 is returned.


vector : the source CpmlVector

Returns : the angle in radians, a value between -M_PI and M_PI Since 1.0

cpml_vector_from_angle ()
void cpml_vector_from_angle (CpmlVector *vector, double angle);

Calculates the coordinates of the point far 1 from the origin in the angle direction. The result is stored in vector .
vector : the destination CpmlVector. [out] angle : angle of direction, in radians. [in]

Since 1.0

cpml_vector_normal ()
void cpml_vector_normal (CpmlVector *vector);

Stores in vector a vector normal to the original vector . The length is retained. The algorithm is really quick because no trigonometry is involved.
vector : the subject CpmlVector. [inout]

Since 1.0

CPML reference manual


7 / 34

cpml_vector_set_length ()
void cpml_vector_set_length (CpmlVector *vector, double length);

Imposes the specied length to vector . If the old length is 0 (and so the direction is not known), nothing happens. If length is 0, vector is set to (0, 0). The length parameter can be negative, in which case the vector is inverted.
vector : a CpmlVector. [inout] length : the new length. [in]

Since 1.0

cpml_vector_transform ()
void cpml_vector_transform (CpmlVector *vector, const cairo_matrix_t *matrix);

Shortcut to apply a specic transformation matrix to vector . It works in a similar way of cpml_pair_transform() but uses cairo_matrix_transform_distance() instead of cairo_matrix_transform_point().
vector : the destination CpmlPair struct. [inout] matrix : the transformation matrix. [in]

Since 1.0

CPML reference manual


8 / 34

Chapter 3

CpmlExtents
CpmlExtents A rectangular area representing a bounding box

Synopsis
struct void void int void int void int void CpmlExtents; cpml_extents_add cpml_extents_copy cpml_extents_equal cpml_extents_from_cairo_text cpml_extents_is_inside cpml_extents_pair_add cpml_extents_pair_is_inside cpml_extents_transform

(CpmlExtents *extents, const CpmlExtents *src); (CpmlExtents *extents, const CpmlExtents *src); (const CpmlExtents *extents, const CpmlExtents *src); (CpmlExtents *extents, const cairo_text_extents_t *cairo_ (const CpmlExtents *extents, const CpmlExtents *src); (CpmlExtents *extents, const CpmlPair *src); (const CpmlExtents *extents, const CpmlPair *src); (CpmlExtents *extents, const cairo_matrix_t *matrix);

Description
The CpmlExtents struct groups two pairs representing the rectangular area of a bounding box.

Details
struct CpmlExtents
struct CpmlExtents { int is_defined; CpmlPair org; CpmlVector size; };

CPML reference manual


9 / 34

A structure dening a bounding box area. These APIs expect the size of the extents to be always positives, so be careful while directly accessing the size eld. int is_defined ; set to 0 when these extents are undened CpmlPair org ; the lowest x,y coordinates CpmlVector size; the width (x) and height (y) of the extents Since 1.0

cpml_extents_add ()
void cpml_extents_add (CpmlExtents *extents, const CpmlExtents *src);

Merges extents and src and store the result in extents.


extents : the destination CpmlExtents. [inout] src : the extents to add. [in]

Since 1.0

cpml_extents_copy ()
void cpml_extents_copy (CpmlExtents *extents, const CpmlExtents *src);

Copies src in extents.


extents : the destination CpmlExtents. [out] src : the source CpmlExtents. [in]

Since 1.0

cpml_extents_equal ()
int cpml_extents_equal (const CpmlExtents *extents, const CpmlExtents *src);

Compares extents to src and returns 1 if the extents are equals. Two NULL or two undened extents are considered equal, athough NULL extents are not equal to undened extents.
extents : the rst extents to compare src : the second extents to compare

Returns : 1 if extents is equal to src, 0 otherwise. [type gboolean] Since 1.0

CPML reference manual


10 / 34

cpml_extents_from_cairo_text ()
void cpml_extents_from_cairo_text (CpmlExtents *extents, const cairo_text_extents_t * cairo_extents);

Converts cairo_extents in a CpmlExtents format and stores the result in extents.


extents : the destination CpmlExtents. [out] cairo_extents : the source cairo_text_extents_t. [in][type gpointer]

Since 1.0

cpml_extents_is_inside ()
int cpml_extents_is_inside (const CpmlExtents *extents, const CpmlExtents *src);

Checks wheter src is enterely contained by extents. If extents is undened, 0 will be returned. If src is undened, 1 will be returned. The border of extents is considered inside.
extents : the container CpmlExtents src : the subject CpmlExtents

Returns : 1 if src is totally inside extents, 0 otherwise. [type gboolean] Since 1.0

cpml_extents_pair_add ()
void cpml_extents_pair_add (CpmlExtents *extents, const CpmlPair *src);

Extends extents, if required, to include src. If extents is undened, the origin of extents is set to src and its size will be (0,0).
extents : the source and destination CpmlExtents. [inout] src : the AdgPair to add. [in]

Since 1.0

cpml_extents_pair_is_inside ()
int cpml_extents_pair_is_inside (const CpmlExtents *extents, const CpmlPair *src);

Checks wheter src is inside extents. If extents is undened, 0 will be returned. The border of extents is considered inside.
extents : the container CpmlExtents src : the subject CpmlPair

Returns : 1 if src is inside extents, 0 otherwise. [type gboolean] Since 1.0

CPML reference manual


11 / 34

cpml_extents_transform ()
void cpml_extents_transform (CpmlExtents *extents, const cairo_matrix_t *matrix);

Transforms the four corners of extents with matrix and recomputes extents. This will logically equivalent to transform an extents box and gets the extents of the resulting shape.
extents : the container CpmlExtents. [inout] matrix : the transformation matrix. [in]

Since 1.0

CPML reference manual


12 / 34

Part II

Path constructs

CPML reference manual


13 / 34

Chapter 4

CpmlSegment
CpmlSegment Contiguous segment that can be a fragment or a whole cairo path

Synopsis
typedef struct int void void int double int void void size_t CpmlPath; CpmlSegment; cpml_path_is_empty cpml_segment_copy cpml_segment_dump cpml_segment_from_cairo cpml_segment_get_length cpml_segment_next cpml_segment_offset cpml_segment_put_extents cpml_segment_put_intersections

void

cpml_segment_put_pair_at

void

cpml_segment_put_vector_at

void void void void

cpml_segment_reset cpml_segment_reverse cpml_segment_to_cairo cpml_segment_transform

(const CpmlPath *path); (CpmlSegment *segment, const CpmlSegment *src); (const CpmlSegment *segment); (CpmlSegment *segment, CpmlPath *path); (const CpmlSegment *segment); (CpmlSegment *segment); (CpmlSegment *segment, double offset); (const CpmlSegment *segment, CpmlExtents *extents); (const CpmlSegment *segment, const CpmlSegment *segment2, size_t n_dest, CpmlPair *dest); (const CpmlSegment *segment, double pos, CpmlPair *pair); (const CpmlSegment *segment, double pos, CpmlVector *vector); (CpmlSegment *segment); (CpmlSegment *segment); (const CpmlSegment *segment, cairo_t *cr); (CpmlSegment *segment, const cairo_matrix_t *matrix);

CPML reference manual


14 / 34

Description
A segment is a single contiguous line got from a cairo path. The CPML library relies on one assumption to let the data be independent from the current point (and thus from the cairo context): any segment MUST be preceded by at least one CPML_MOVE primitive. This means a valid segment in cairo could be rejected by CPML. CpmlSegment provides an unobtrusive way to access a cairo path. This means CpmlSegment itsself does not hold any coordinates but instead a bunch of pointers to the original cairo_path_t struct: modifying data throught this struct also changes the original path. Every CpmlPath struct can contain more than one segment: the CPML library provides iteration APIs to browse the segments of a path. Use cpml_segment_reset() to reset the iterator at the start of the cairo path (will point the rst segment) and cpml_segment_next() to get the next segment. Getting the previous segment is not provided as the underlying cairo struct is not accessible in reverse order. When initialized, CpmlSegment yet refers to the rst segment so the initial reset is not required.

Details
CpmlPath
typedef cairo_path_t CpmlPath;

This is another name for the cairo_path_t type. Although phisically they are the same struct, CpmlPath conceptually embodies an important difference: it is a cairo path that can embed CPML_ARC primitives. This is not a native cairo primitive and having two different data types is a good way to make clear when a function expect or not embedded arc-to primitives. Since 1.0

struct CpmlSegment
struct CpmlSegment { CpmlPath *path; cairo_path_data_t *data; int num_data; };

This is an unobtrusive struct to identify a segment inside a cairo path. Unobtrusive means that the real coordinates are still stored in path: CpmlSegment only provides a way to access them. CpmlPath *path; the source CpmlPath struct cairo_path_data_t *data; the data points of the segment; the rst primitive will always be a CPML_MOVE int num_data; size of data Since 1.0

cpml_path_is_empty ()
int cpml_path_is_empty (const CpmlPath *path);

Checks if path is empty. An invalid path is considered empty.


path : a CpmlPath (or a cairo_path_t) pointer

Returns : 1 if the path is empty or invalid, 0 otherwise. [type gboolean] Since 1.0

CPML reference manual


15 / 34

cpml_segment_copy ()
void cpml_segment_copy (CpmlSegment *segment, const CpmlSegment *src);

Makes a shallow copy of src into segment.


segment : a CpmlSegment src : the source segment to copy

Since 1.0

cpml_segment_dump ()
void cpml_segment_dump (const CpmlSegment *segment);

Dumps the specied segment to stdout. Useful for debugging purposes.


segment : a CpmlSegment

Since 1.0

cpml_segment_from_cairo ()
int cpml_segment_from_cairo (CpmlSegment *segment, CpmlPath *path);

Builds a CpmlSegment from a CpmlPath structure. This operation involves stripping the duplicate CPML_MOVE primitives at the start of the path and setting num_data eld to the end of the contiguous line, that is when another CPML_MOVE primitive is found or at the end of the path. A pointer to the source cairo path is kept though. This function will fail if path is null, empty or if its status member is not CAIRO_STATUS_SUCCESS. Also, the rst primitive must be a CPML_MOVE, so no dependency on the cairo context is needed.
segment : a CpmlSegment. [out] path : the source CpmlPath. [in]

Returns : 1 if segment has been succesfully computed, 0 on errors. [type gboolean] Since 1.0

cpml_segment_get_length ()
double cpml_segment_get_length (const CpmlSegment *segment);

Gets the whole length of segment.


segment : a CpmlSegment

Returns : the requested length Since 1.0

CPML reference manual


16 / 34

cpml_segment_next ()
int cpml_segment_next (CpmlSegment *segment);

Modies segment to point to the next segment of the source cairo path.
segment : a CpmlSegment

Returns : 1 on success, 0 if no next segment found or errors. [type gboolean] Since 1.0

cpml_segment_offset ()
void cpml_segment_offset (CpmlSegment *segment, double offset);

Offsets a segment of the specied amount, that is builds a "parallel" segment at the offset distance from the original one and returns the result by replacing the original segment.
TODO Closed path are not yet managed: an elegant solution is not so obvious: use cpml_close_offset() when available. Degenerated primitives, such as lines of length 0, are not managed properly.

segment : a CpmlSegment offset : the offset distance

Since 1.0

cpml_segment_put_extents ()
void cpml_segment_put_extents (const CpmlSegment *segment, CpmlExtents *extents);

Gets the whole extents of segment.


segment : a CpmlSegment extents : where to store the extents

Since 1.0

CPML reference manual


17 / 34

cpml_segment_put_intersections ()
size_t cpml_segment_put_intersections (const CpmlSegment *segment, const CpmlSegment *segment2, size_t n_dest, CpmlPair *dest);

Computes the intersections between segment and segment2 and returns the found points in dest. If the intersections are more than n_dest, only the rst n_dest pairs are stored in dest. To get the job done, the primitives of segment are sequentially scanned for intersections with any primitive in segment2. This means segment has a higher precedence over segment2.
segment : the rst CpmlSegment segment2 : the second CpmlSegment n_dest : maximum number of intersections to return dest : the destination vector of CpmlPair

Returns : the number of intersections found Since 1.0

cpml_segment_put_pair_at ()
void cpml_segment_put_pair_at (const CpmlSegment *segment, double pos, CpmlPair *pair);

Gets the coordinates of the point lying on segment 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. The relation 0 < pos < 1 should be satised, although some cases accept value outside this range.

TODO The actual implementation returns only the start and end points, that is only when pos is 0 or 1.

segment : a CpmlSegment pos : the position value pair : the destination CpmlPair

Since 1.0

cpml_segment_put_vector_at ()
void cpml_segment_put_vector_at (const CpmlSegment *segment, double pos, CpmlVector *vector);

CPML reference manual


18 / 34

Gets the steepness of the point lying on segment 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. The relation 0 < pos < 1 should be satised, although some cases accept value outside this range.

TODO The actual implementation returns only the start and end steepness, that is only when pos is 0 or 1.

segment : a CpmlSegment pos : the position value vector : the destination CpmlVector

Since 1.0

cpml_segment_reset ()
void cpml_segment_reset (CpmlSegment *segment);

Modies segment to point to the rst segment of the source cairo path.
segment : a CpmlSegment

Since 1.0

cpml_segment_reverse ()
void cpml_segment_reverse (CpmlSegment *segment);

Reverses segment in-place. The resulting rendering will be the same, but with the primitives generated in reverse order. It is assumed that segment has yet been sanitized, that is returned by some CPML API function or it is a path yet conforming to the segment rules described by the cpml_segment_from_cairo() function.
segment : a CpmlSegment

Since 1.0

cpml_segment_to_cairo ()
void cpml_segment_to_cairo (const CpmlSegment *segment, cairo_t *cr);

Appends the path of segment to cr . The segment is "attened", that is CPML_ARC primitives are approximated by one or more CPML_CURVE using cpml_arc_to_cairo(). Check its documentation for further details.
segment : a CpmlSegment cr : the destination cairo context

Since 1.0

CPML reference manual


19 / 34

cpml_segment_transform ()
void cpml_segment_transform (CpmlSegment *segment, const cairo_matrix_t *matrix);

Applies matrix on all the points of segment.


segment : a CpmlSegment matrix : the matrix to be applied

Since 1.0

CPML reference manual


20 / 34

Chapter 5

CpmlPrimitive
CpmlPrimitive Basic component of segments

Synopsis
struct enum void void void double double size_t int int void void size_t CpmlPrimitive; CpmlPrimitiveType; cpml_primitive_copy

size_t

void

void

void

(CpmlPrimitive *primitive, const CpmlPrimitive *src); cpml_primitive_dump (const CpmlPrimitive *primitive, int org_also); cpml_primitive_from_segment (CpmlPrimitive *primitive, CpmlSegment *segment); cpml_primitive_get_closest_pos (const CpmlPrimitive *primitive, const CpmlPair *pair); cpml_primitive_get_length (const CpmlPrimitive *primitive); cpml_primitive_get_n_points (const CpmlPrimitive *primitive); cpml_primitive_join (CpmlPrimitive *primitive, CpmlPrimitive *primitive2); cpml_primitive_next (CpmlPrimitive *primitive); cpml_primitive_offset (CpmlPrimitive *primitive, double offset); cpml_primitive_put_extents (const CpmlPrimitive *primitive, CpmlExtents *extents); cpml_primitive_put_intersections (const CpmlPrimitive *primitive, const CpmlPrimitive *primitive2, size_t n_dest, CpmlPair *dest); cpml_primitive_put_intersections_with_segment (const CpmlPrimitive *primitive, const CpmlSegment *segment, size_t n_dest, CpmlPair *dest); cpml_primitive_put_pair_at (const CpmlPrimitive *primitive, double pos, CpmlPair *pair); cpml_primitive_put_point (const CpmlPrimitive *primitive, int n_point, CpmlPair *pair); cpml_primitive_put_vector_at (const CpmlPrimitive *primitive,

CPML reference manual


21 / 34

void void

cpml_primitive_reset cpml_primitive_set_point

void size_t

cpml_primitive_to_cairo cpml_primitive_type_get_n_points

double pos, CpmlVector *vector); (CpmlPrimitive *primitive); (CpmlPrimitive *primitive, int n_point, const CpmlPair *pair); (const CpmlPrimitive *primitive, cairo_t *cr); (CpmlPrimitiveType type);

Description
A primitive is an atomic geometric element found inside CpmlSegment. The available primitives are the same dened 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 dene the origin of a segment.

Details
struct CpmlPrimitive
struct CpmlPrimitive { CpmlSegment *segment; cairo_path_data_t *org; cairo_path_data_t *data; };

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 *segment; the source CpmlSegment cairo_path_data_t *org ; a pointer to the rst point of the primitive cairo_path_data_t *data; the array of the path data, prepended by the header Since 1.0

enum CpmlPrimitiveType
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 = 88 } 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. Having two different types is a good way to make clear when a function expect or not embedded CPML_ARC primitives. Arcs are used extensively in technical drawing: some operations are trivials with arcs and a nightmare with cubic Bzier curves. Actually, at least up to version 1.10.2, the cairo library does not support arc primitives natively and there is no plan they will be ever supported.

CPML reference manual


22 / 34

The CPML library supports arc natively, converting them to curves when the CpmlSegment is returned to the cairo context, for instance when using cpml_segment_to_cairo(). CPML_MOVE equivalent to CAIRO_PATH_MOVE_TO CPML_LINE equivalent to CAIRO_PATH_LINE_TO CPML_CURVE equivalent to CAIRO_PATH_CURVE_TO CPML_CLOSE equivalent to CAIRO_PATH_CLOSE_PATH CPML_ARC an arc representation at CPML level Since 1.0

cpml_primitive_copy ()
void cpml_primitive_copy (CpmlPrimitive *primitive, const CpmlPrimitive *src);

Copies src in primitive. This is a shallow copy: the internal elds of primitive refer to the same memory as the original src primitive.
primitive : the destination CpmlPrimitive. [out] src : the source CpmlPrimitive. [in]

Since 1.0

cpml_primitive_dump ()
void cpml_primitive_dump (const CpmlPrimitive *primitive, int org_also);

Dumps info on the specied 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 eld is not used.
primitive : a CpmlPrimitive org_also : whether to output also the origin coordinates

Since 1.0

cpml_primitive_from_segment ()
void cpml_primitive_from_segment (CpmlPrimitive *primitive, CpmlSegment *segment);

Initializes primitive to the rst primitive of segment.


primitive : the destination CpmlPrimitive struct. [out] segment : the source segment. [in]

Since 1.0

CPML reference manual


23 / 34

cpml_primitive_get_closest_pos ()
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.
primitive : a CpmlPrimitive pair : the coordinates of the subject point

Returns : the requested pos value between 0 and 1, or -1 on errors Since 1.0

cpml_primitive_get_length ()
double cpml_primitive_get_length (const CpmlPrimitive *primitive);

Abstracts the length() family functions by providing a common way to access the underlying primitive-specic implementation. The function returns the length of primitive.
primitive : a CpmlPrimitive

Returns : the requested length or 0 on errors Since 1.0

cpml_primitive_get_n_points ()
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.
primitive : a CpmlPrimitive

Returns : the number of points or 0 on errors Since 1.0

cpml_primitive_join ()
int 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.
TODO Actually, the join is done by extending the end vector of 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.

CPML reference manual


24 / 34

primitive : the rst CpmlPrimitive. [inout] primitive2 : the second CpmlPrimitive. [inout]

Returns : 1 on success, 0 if the primitives cannot be joint . [type boolean] Since 1.0

cpml_primitive_next ()
int 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.
primitive : a CpmlPrimitive. [inout]

Returns : 1 on success, 0 if no next primitive found or errors. [type boolean] Since 1.0

cpml_primitive_offset ()
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.
primitive : a CpmlPrimitive. [inout] offset : distance for the computed offset primitive. [in]

Since 1.0

cpml_primitive_put_extents ()
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-specic 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.
primitive : a CpmlPrimitive. [in] extents : where to store the extents. [out]

Since 1.0

CPML reference manual


25 / 34

cpml_primitive_put_intersections ()
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 Bzier 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).
Note 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 Bzier 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.

primitive : the rst CpmlPrimitive. [in] primitive2 : the second CpmlPrimitive. [in] n_dest : maximum number of intersections to return. [in] dest : the destination buffer that can contain n_dest CpmlPair. [out]

Returns : the number of intersection points found or 0 if the primitives do not intersect or on errors Since 1.0

cpml_primitive_put_intersections_with_segment ()
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 rst n_dest pairs are stored.
primitive : a CpmlPrimitive. [in] segment : a CpmlSegment. [in] n_dest : maximum number of intersection pairs to return. [in] dest : the destination buffer of CpmlPair. [out]

Returns : the number of intersections found Since 1.0

CPML reference manual


26 / 34

cpml_primitive_put_pair_at ()
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-specic 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.
primitive : a CpmlPrimitive. [in] pos : the position value. [in] pair : the destination CpmlPair. [out]

Since 1.0

cpml_primitive_put_point ()
void cpml_primitive_put_point (const CpmlPrimitive *primitive, int n_point, CpmlPair *pair);

Gets the specied n_point from primitive and stores it into pair . The n_point index is subject to the same rules explained in the cpml_primitive_set_point() function.
primitive : a CpmlPrimitive. [in] n_point : the index of the point to retrieve. [in] pair : the destination CpmlPair. [out]

Since 1.0

cpml_primitive_put_vector_at ()
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-specic 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.
primitive : a CpmlPrimitive. [in] pos : the position value. [in] vector : the destination CpmlVector. [out]

Since 1.0

CPML reference manual


27 / 34

cpml_primitive_reset ()
void cpml_primitive_reset (CpmlPrimitive *primitive);

Resets primitive so it refers to the rst primitive of the source segment.


primitive : a CpmlPrimitive. [inout]

Since 1.0

cpml_primitive_set_point ()
void cpml_primitive_set_point (CpmlPrimitive *primitive, int n_point, const CpmlPair *pair);

Sets the specied n_point of primitive to pair . The n_point index starts from 0: if n_point is 0, the start point (the origin) is changed, 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 rst 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 origin of the segment.
primitive : a CpmlPrimitive n_point : the index of the point to retrieve pair : the source CpmlPair

Since 1.0

cpml_primitive_to_cairo ()
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.
primitive : a CpmlPrimitive. [in] cr : the destination cairo context. [inout]

Since 1.0

cpml_primitive_type_get_n_points ()
size_t cpml_primitive_type_get_n_points (CpmlPrimitiveType type);

Gets the number of points required to identify the type primitive.


type : a primitive type

Returns : the number of points or 0 on errors Since 1.0

CPML reference manual


28 / 34

Chapter 6

Special primitives
6.1 CpmlArc

CpmlArc Manipulation of circular arcs

Synopsis
int cpml_arc_info (const CpmlPrimitive *arc, CpmlPair *center, double *r, double *start, double *end); (const CpmlPrimitive *arc, cairo_t *cr); (const CpmlPrimitive *arc, CpmlSegment *segment, size_t n_curves);

void void

cpml_arc_to_cairo cpml_arc_to_curves

Description
The following functions manipulate CPML_ARC CpmlPrimitive. No validation is made on the input so use the following methods only when you are sure the primitive argument is effectively an arc-to. The arc primitive is dened by 3 points: the rst one is the usual implicit point got from the previous primitive, the second point is an arbitrary intermediate point laying on the arc and the third point is the end of the arc. These points identify univocally an arc: furthermore, the intermediate point also gives the side of the arc. As a special case, when the rst point is coincident with the end point the primitive is considered a circle with diameter dened by the segment between the rst and the intermediate point.

Important An arc is not a native cairo primitive and should be treated specially.

Using these CPML APIs you are free to use CPML_ARC whenever you want but, if you are directly accessing the struct elds, you are responsible of converting arcs to curves before passing them to cairo. In other words, do not directly feed CpmlPath struct to cairo (throught cairo_append_path() for example) or at least do not expect it will work.

CPML reference manual


29 / 34

The conversion is provided by two APIs: cpml_arc_to_cairo() and cpml_arc_to_curves(). The former directly renders to a cairo context and is internally used by all the ..._to_cairo() functions when an arc is met. The latter provided a more powerful (and more complex) approach as it allows to specify the number of curves to use and do not need a cairo context.
TODO the get_closest_pos() method must be implemented; the put_intersections() method must be implemented;

Details
cpml_arc_info ()

int

cpml_arc_info

(const CpmlPrimitive *arc, CpmlPair *center, double *r, double *start, double *end);

Given an arc, this function calculates and returns its basic data. Any pointer can be NULL, in which case the requested info is not returned. This function can fail (when the three points lay on a straight line, for example) in which case 0 is returned and no data can be considered valid. The radius r can be 0 when the three points are coincidents: a circle with radius 0 is considered a valid path. When the start and end angle are returned, together with their values these angles implicitely gives another important information: the arc direction. If start < end the arc must be rendered with increasing angle value (clockwise direction using the ordinary cairo coordinate system) while if start > end the arc must be rendered in reverse order (that is counterclockwise in the cairo world). This is the reason the angle values are returned in the range { -M_PI < value < 3*M_PI } inclusive instead of the usual { -M_PI < value < M_PI } range.
arc : the CpmlPrimitive arc data. [in] center : where to store the center coordinates. [out][allow-none] r : where to store the radius. [out][allow-none] start : where to store the starting angle. [out][allow-none] end : where to store the ending angle. [out][allow-none]

Returns : 1 if the function worked succesfully, 0 on errors. [type boolean] Since 1.0
cpml_arc_to_cairo ()

void

cpml_arc_to_cairo

(const CpmlPrimitive *arc, cairo_t *cr);

Renders arc to the cr cairo context. As cairo does not support arcs natively, it is approximated using one or more Bzier curves. The number of curves used is dependent from the angle of the arc. Anyway, this function uses internally the hardcoded M_PI_2 value as threshold value. This means the maximum arc approximated by a single curve will be a quarter of a circle and, consequently, a whole circle will be approximated by 4 Bzier curves.

CPML reference manual


30 / 34

arc : the CpmlPrimitive arc data. [in] cr : the destination cairo context. [inout]

Since 1.0
cpml_arc_to_curves ()

void

cpml_arc_to_curves

(const CpmlPrimitive *arc, CpmlSegment *segment, size_t n_curves);

Converts arc to a serie of n_curves Bzier curves and puts them inside segment. Obviously, segment must have enough space to contain at least n_curves curves. This function works in a similar way as cpml_arc_to_cairo() but has two important differences: it does not need a cairo context and the number of curves to be generated is explicitely dened. The latter difference allows a more specic error control from the application: in the le src/cairo-arc.c, found in the cairo tarball (at least in cairo-1.9.1), there is a table showing the magnitude of error of this curve approximation algorithm.
arc : the CpmlPrimitive arc data. [in] segment : the destination CpmlSegment. [out] n_curves : number of Bzier to use. [in]

Since 1.0

6.2

CpmlCurve

CpmlCurve Bzier cubic curve primitive management

Synopsis
void cpml_curve_put_pair_at_time (const CpmlPrimitive *curve, double t, CpmlPair *pair); (const CpmlPrimitive *curve, double t, CpmlVector *vector);

void

cpml_curve_put_vector_at_time

Description
The following functions manipulate CPML_CURVE CpmlPrimitive. No validation is made on the input so use the following methods only when you are sure the primitive argument is effectively a cubic Bzier curve.

CPML reference manual


31 / 34

TODO the get_length() method must be implemented; actually the put_extents() method is implemented by computing the bounding box of the control polygon and this will likely include some empty space: there is room for improvements; the put_pair_at() method must be implemented; the put_vector_at() method must be implemented; the get_closest_pos() method must be implemented; the put_intersections() method must be implemented; by default, the offset curve is calculated by using the point at t=0.5 as reference: use a better candidate; in the offset() implementation, when the equations are inconsistent, the alternative approach performs very bad if v0 and v3 are opposite or staggered.

Offseting algorithm

Given a cubic Bzier primitive, it must be found the approximated Bzier curve parallel to the original one at a specic distance (the so called "offset curve"). The four points needed to build the new curve must be returned. To solve the offset problem, a custom algorithm is used. First, the resulting curve MUST have the same slope at the start and end point. These constraints are not sufcient to resolve the system, so I let the curve pass thought a given point (pm, known and got from the original curve) at a given time (m, now hardcoded to 0.5). Firstly, some useful variables are dened:
v0 v3 p0 p3 = = = = unitvector(p[1] - p[0]) $\times$ offset; unitvector(p[3] - p[2]) $\times$ offset; p[0] + normal v0; p[3] + normal v3.

The resulting curve must have the same slopes than the original one at the start and end points. Forcing the same slopes means:
p1 = p0 + k0 v0.

where k0 is an arbitrary factor. Decomposing for x and y:


p1.x = p0.x + k0 v0.x; p1.y = p0.y + k0 v0.y.

and doing the same for the end point:


p2.x = p3.x + k3 v3.x; p2.y = p3.y + k3 v3.y.

This does not give a resolvable system, though. The curve will be interpolated by forcing its path to pass throught pm when time is m, where 0 m 1. Knowing the function of the cubic Bzier:
C(t) = (1 - t)$^3$p0 + 3t(1 - t)$^2$p1 + 3t$^2$(1 - t)p2 + t$^3$p3.

and forcing t = m and C(t) = pm:


pm = (1 - m)$^3$p0 + 3m(1 - m)$^2$p1 + 3m$^2$(1 - m)p2 + m$^3$p3. (1 - m) p1 + m p2 = (pm - (1 - m)$^3$p0 - m$^3$p3) / (3m (1 - m)).

CPML reference manual


32 / 34

gives this nal system:


p1.x p1.y p2.x p2.y (1 (1 = p0.x + k0 = p0.y + k0 = p3.x + k3 = p3.y + k3 m) p1.x + m m) p1.y + m v0.x; v0.y; v3.x; v3.y; p2.x = (pm.x - (1 - m)$^3$p0.x - m$^3$p3.x) / (3m (1 - m)); p2.y = (pm.y - (1 - m)$^3$p0.y - m$^3$p3.y) / (3m (1 - m)).

Substituting and resolving for k0 and k3:


(1 - m) k0 v0.x + m k3 v3.x = (pm.x - (1 - m)$^3$p0.x - m$^3$p3.x) / (3m (1 - m)) - (1 - m) p0.x - m p3.x; (1 - m) k0 v0.y + m k3 v3.y = (pm.y - (1 - m)$^3$p0.y - m$^3$p3.y) / (3m (1 - m)) - (1 - m) p0.y - m p3.y. (1 - m) k0 v0.x + m k3 v3.x = (pm.x - (1 - m)$^2$(1+2m) p0.x - m$^2$(3 - 2m) p3.x) / (3m (1 - m)); (1 - m) k0 v0.y + m k3 v3.y = (pm.y - (1 - m)$^2$(1+2m) p0.y - m$^2$(3 - 2m) p3.y) / (3m (1 - m)).

Letting:
pk = (pm - (1 - m)$^2$(1+2m) p0 - m$^2$(3 - 2m) p3) / (3m (1 - m)).

reduces the above to this nal equations:


(1 - m) k0 v0.x + m k3 v3.x = pk.x; (1 - m) k0 v0.y + m k3 v3.y = pk.y.

If v0.x = 0, the system can be resolved for k0 and k3 calculated accordingly:


k0 = (pk.x - m k3 v3.x) / ((1 - m) v0.x); (pk.x - m k3 v3.x) v0.y / v0.x + m k3 v3.y = pk.y. k0 = (pk.x - m k3 v3.x) / ((1 - m) v0.x); k3 m (v3.y - v3.x v0.y / v0.x) = pk.y - pk.x v0.y / v0.x. k3 = (pk.y - pk.x v0.y / v0.x) / (m (v3.y - v3.x v0.y / v0.x)); k0 = (pk.x - m k3 v3.x) / ((1 - m) v0.x).

Otherwise, if v3.x = 0, the system can be solved for k3 and k0 calculated accordingly:
k3 = (pk.x - (1 - m) k0 v0.x) / (m v3.x); (1 - m) k0 v0.y + (pk.x - (1 - m) k0 v0.x) v3.y / v3.x = pk.y. k3 = (pk.x - (1 - m) k0 v0.x) / (m v3.x); k0 (1 - m) (v0.y - k0 v0.x v3.y / v3.x) = pk.y - pk.x v3.y / v3.x. k0 = (pk.y - pk.x v3.y / v3.x) / ((1 - m) (v0.y - v0.x v3.y / v3.x)); k3 = (pk.x - (1 - m) k0 v0.x) / (m v3.x).

The whole process must be guarded against division by 0 exceptions. If either v0.x and v3.x are 0, the rst equation will be inconsistent. More in general, the v0.x v3.y = v3.x v3.y condition must be avoided. This is the rst situation to avoid, in which case an alternative approach should be used.

Details
cpml_curve_put_pair_at_time ()

CPML reference manual


33 / 34

void

cpml_curve_put_pair_at_time

(const CpmlPrimitive *curve, double t, CpmlPair *pair);

Given the curve Bzier cubic, nds the coordinates at time t (where 0 is the start and 1 is the end) and stores the result in pair . Keep in mind t is not homogeneous, so 0.5 does not necessarily means the mid point.
curve : the CpmlPrimitive curve data t : the "time" value pair : the destination pair

Since 1.0
cpml_curve_put_vector_at_time ()

void

cpml_curve_put_vector_at_time

(const CpmlPrimitive *curve, double t, CpmlVector *vector);

Given the curve Bzier cubic, nds the slope at time t (where 0 is the start and 1 is the end) and stores the result in vector . Keep in mind t is not homogeneous, so 0.5 does not necessarily means the mid point.
curve : the CpmlPrimitive curve data t : the "time" value vector : the destination vector

Since 1.0

CPML reference manual


34 / 34

Chapter 7

Index
C cpml_angle, 2 cpml_arc_info, 29 cpml_arc_to_cairo, 29 cpml_arc_to_curves, 30 cpml_curve_put_pair_at_time, 32 cpml_curve_put_vector_at_time, 33 cpml_extents_add, 9 cpml_extents_copy, 9 cpml_extents_equal, 9 cpml_extents_from_cairo_text, 10 cpml_extents_is_inside, 10 cpml_extents_pair_add, 10 cpml_extents_pair_is_inside, 10 cpml_extents_transform, 11 CPML_GNUC_CONST, 2 cpml_pair_copy, 4 cpml_pair_distance, 4 cpml_pair_equal, 5 cpml_pair_from_cairo, 5 cpml_pair_squared_distance, 5 cpml_pair_to_cairo, 5 cpml_pair_transform, 6 cpml_path_is_empty, 14 cpml_primitive_copy, 22 cpml_primitive_dump, 22 cpml_primitive_from_segment, 22 cpml_primitive_get_closest_pos, 23 cpml_primitive_get_length, 23 cpml_primitive_get_n_points, 23 cpml_primitive_join, 23 cpml_primitive_next, 24 cpml_primitive_offset, 24 cpml_primitive_put_extents, 24 cpml_primitive_put_intersections, 25 cpml_primitive_put_intersections_with_segment, 25 cpml_primitive_put_pair_at, 26 cpml_primitive_put_point, 26 cpml_primitive_put_vector_at, 26 cpml_primitive_reset, 27 cpml_primitive_set_point, 27 cpml_primitive_to_cairo, 27 cpml_primitive_type_get_n_points, 27 cpml_segment_copy, 15 cpml_segment_dump, 15 cpml_segment_from_cairo, 15 cpml_segment_get_length, 15 cpml_segment_next, 16 cpml_segment_offset, 16 cpml_segment_put_extents, 16 cpml_segment_put_intersections, 17 cpml_segment_put_pair_at, 17 cpml_segment_put_vector_at, 17 cpml_segment_reset, 18 cpml_segment_reverse, 18 cpml_segment_to_cairo, 18 cpml_segment_transform, 19 cpml_vector_angle, 6 cpml_vector_from_angle, 6 cpml_vector_normal, 6 cpml_vector_set_length, 7 cpml_vector_transform, 7 CpmlExtents, 8 CpmlPair, 4 CpmlPath, 14 CpmlPrimitive, 21 CpmlPrimitiveType, 21 CpmlSegment, 14 CpmlVector, 4

Das könnte Ihnen auch gefallen