jpayne@68: jpayne@68: jpayne@68:
jpayne@68: jpayne@68:jpayne@68: | ![]() |
jpayne@68: ![]() |
jpayne@68: ![]() |
jpayne@68: ![]() |
jpayne@68:
jpayne@68: The cairo_path_t type is one jpayne@68: area in which most language bindings will differ significantly jpayne@68: from the C API. The C API for cairo_path_t is jpayne@68: designed for efficiency and to avoid auxiliary objects that jpayne@68: would be have to be manually memory managed by the jpayne@68: application. However, jpayne@68: a language binding should not present cairo_path_t as an jpayne@68: array, but rather as an opaque that can be iterated jpayne@68: over. Different languages have quite different conventions for jpayne@68: how iterators work, so it is impossible to give an exact jpayne@68: specification for how this API should work, but the type names jpayne@68: and methods should be similar to the language's mapping of the following: jpayne@68:
jpayne@68:jpayne@68: typedef struct cairo_path_iterator cairo_path_iterator_t; jpayne@68: typedef struct cairo_path_element cairo_path_element_t; jpayne@68: jpayne@68: cairo_path_iterator_t * jpayne@68: cairo_path_get_iterator (cairo_path_t *path); jpayne@68: jpayne@68: cairo_bool_t jpayne@68: cairo_path_iterator_has_next (cairo_path_iterator_t *iterator); jpayne@68: jpayne@68: cairo_path_element_t * jpayne@68: cairo_path_iterator_next (cairo_path_iterator_t *iterator); jpayne@68: jpayne@68: cairo_path_element_type_t jpayne@68: cairo_path_element_get_type (cairo_path_element_t *element); jpayne@68: jpayne@68: void jpayne@68: cairo_path_element_get_point (cairo_path_element_t *element, jpayne@68: int index, jpayne@68: double *x, jpayne@68: double *y); jpayne@68:jpayne@68:
jpayne@68: The above is written using the Java conventions for jpayne@68: iterators. To illustrate how the API for PathIterator might jpayne@68: depend on the native iteration conventions of the API, examine jpayne@68: three versions of the loop, first written in a hypothetical Java jpayne@68: binding: jpayne@68:
jpayne@68:jpayne@68: PathIterator iter = cr.copyPath().iterator(); jpayne@68: while (cr.hasNext()) { jpayne@68: PathElement element = iter.next(); jpayne@68: if (element.getType() == PathElementType.MOVE_TO) { jpayne@68: Point p = element.getPoint(0); jpayne@68: doMoveTo (p.x, p.y); jpayne@68: } jpayne@68: }jpayne@68:
jpayne@68: And then in a hypothetical C++ binding: jpayne@68:
jpayne@68:jpayne@68: Path path = cr.copyPath(); jpayne@68: for (PathIterator iter = path.begin(); iter != path.end(); iter++) { jpayne@68: PathElement element = *iter; jpayne@68: if (element.getType() == PathElementType.MOVE_TO) { jpayne@68: Point p = element.getPoint(0); jpayne@68: doMoveTo (p.x, p.y); jpayne@68: } jpayne@68: }jpayne@68:
jpayne@68: And then finally in a Python binding: jpayne@68:
jpayne@68:jpayne@68: for element in cr.copy_path(): jpayne@68: if element.getType == cairo.PATH_ELEMENT_MOVE_TO: jpayne@68: (x, y) = element.getPoint(0) jpayne@68: doMoveTo (x, y);jpayne@68:
jpayne@68: While many of the API elements stay the same in the three jpayne@68: examples, the exact iteration mechanism is quite different, to jpayne@68: match how users of the language would expect to iterate over jpayne@68: a container. jpayne@68:
jpayne@68:
jpayne@68: You should not present an API for mutating or for creating new
jpayne@68: cairo_path_t objects. In the future, these
jpayne@68: guidelines may be extended to present an API for creating a
jpayne@68: cairo_path_t from scratch for use with
jpayne@68: cairo_append_path()
jpayne@68: but the current expectation is that cairo_append_path()
will
jpayne@68: mostly be used with paths from
jpayne@68: cairo_copy_path()
.
jpayne@68: