diff options
Diffstat (limited to 'libs/cairo-1.16.0/doc/public/language-bindings.xml')
-rw-r--r-- | libs/cairo-1.16.0/doc/public/language-bindings.xml | 745 |
1 files changed, 745 insertions, 0 deletions
diff --git a/libs/cairo-1.16.0/doc/public/language-bindings.xml b/libs/cairo-1.16.0/doc/public/language-bindings.xml new file mode 100644 index 0000000..ce437ef --- /dev/null +++ b/libs/cairo-1.16.0/doc/public/language-bindings.xml @@ -0,0 +1,745 @@ +<appendix id="language-bindings"> + <title>Creating a language binding for cairo</title> + <para> + While cairo is implemented and C, and has a C API, it is expected + that many users of cairo will be using it from languages other + than C. The glue that connects the core cairo library to another + language is known as a <firstterm>language + binding</firstterm>. This appendix attempts to collect together + issues that come up when creating a language bindings for cairo + and present standardized solutions to promote consistency among + the different language bindings. + </para> + <sect1 id="bindings-general"> + <title>General considerations</title> + <para> + The naming of the central <link + linkend="cairo-t"><type>cairo_t</type></link> type is a + special exception. The object is “a cairo context” not “a + cairo”, and names such as <type>cairo_t</type> rather than + <type>cairo_context_t</type> and + <function>cairo_set_source()</function> rather than + <function>cairo_context_set_source()</function> are simply + abbreviations to make the C API more palatable. In languages + which have object-oriented syntax, this abbreviation is much + less useful. In fact, if ‘Cairo’ is used as a namespace, then + in many languages, you'd end up with a ridiculous type name + like ‘Cairo.Cairo’. For this reason, and for inter-language + consistency all object-oriented languages should name this + type as if it were <type>cairo_context_t</type>. + </para> + <para> + The punctuation and casing of the type names and + method names of cairo should be changed to match the general + convention of the language. In Java, where type names are written + in StudlyCaps and method names in javaCaps, cairo_font_extents_t + will become FontExtents and + <literal>cairo_set_source(cr,source)</literal>, + <literal>cr.setSource(source)</literal>. + As compared to changing the punctuation, and casing, much + more reluctance should be used in changing the method names + themselves. Even if get is usually omitted from getters in + your language, you shouldn't bind cairo_get_source() as + cr.source(). + </para> + </sect1> + <sect1 id="bindings-memory"> + <title>Memory management</title> + <para> + The objects in cairo can roughly be divided into two types: + reference-counted, opaque types like + <link + linkend="cairo-surface-t"><type>cairo_surface_t</type></link> + and plain structures like + <link + linkend="cairo-glyph-t"><type>cairo_glyph_t</type></link>. + <link + linkend="cairo-path-t"><type>cairo_path_t</type></link> + and + <link + linkend="cairo-path-data-t"><type>cairo_path_data_t</type></link> + are special cases and are treated separately in this appendix. + </para> + <para> + Refcounted opaque types all have a + <function>..._reference()</function> + function to increase the refcount by one and a + <function>..._destroy()</function> to decrease the refcount + by one. These should not be exposed to the user of the language + binding, but rather used to implement memory management within + the language binding. The simplest way to do memory management + for a language binding is to treat the language binding object + as a simple handle to the cairo object. The language binding + object references the cairo object, and unreferences it when + finalized. This is the recommended method, though there are + a couple of caveats to be noted: + </para> + <itemizedlist> + <listitem> + <para> + Equality won't work as expected. You can have two language + objects for the same cairo and they won't necessarily + compare equal. If the language allows customizing the + equality operation, then this is fixable by comparing + the underlying pointers. It also can be fixed by creating + at most one language object per cairo object, and + uniquifying via a <firstterm>pin table</firstterm> (a hash + table that goes from cairo object to language object). + For <type>cairo_surface_t</type> you can use also + <link + linkend="cairo-surface-set-user-data"><function>cairo_surface_set_user_data()</function></link> + instead of a separate pin table. + </para> + </listitem> + <listitem> + <para> + Derivation from the language object doesn't work because + you can lose the language object while keeping the Cairo + object. Code like: + </para> +<programlisting> +public class MySurface (ImageSurface) { + public MySurface (width, height) { + super (Format.ARGB32, width, height); + } + public int get42 () { + return 42; + } +} + + cr = Cairo(MySurface(width, height)); + surface = cr.getTarget(); +</programlisting> + <para> + Can result in <varname>surface</varname> containing an + <classname>ImageSurface</classname> not a <classname>MySurface</classname>. + This is not easily fixable without creating memory leaks, + and it's probably best to simply forbid deriving from the + language objects. + </para> + </listitem> + </itemizedlist> + <para> + When a plain structure is used as a return value from cairo, + this is done by passing it as a “out parameter”. + </para> +<programlisting> +cairo_font_extents_t extents; + +cairo_font_extents (cr, &extents);</programlisting> + <para> + In a language binding, this should typically be treated + as a return value: + </para> +<programlisting> +FontExtents extents = cr.fontExtents ();</programlisting> + <para> + A language binding has a choice in how it implements the + language objects for plain structures. It can use a pure + language object with fields corresponding to those of the C + structure, and convert from and to the C structure when calling + cairo functions or converting cairo return values. Or it + can keep a pointer to the C structure internally and wrap + it inside a language object much like occurs for refcounted + objects. The choice should be invisible to the user: they should + be able to imagine that it is implemented as a pure language + object. + </para> + </sect1> + <sect1 id="bindings-return-values"> + <title>Multiple return values</title> + <para> + There are a number of functions in the cairo API that have + multiple <firstterm>out parameters</firstterm> or + <firstterm>in-out parameters</firstterm>. In some languages + these can be translated into multiple return values. In Python, + what is: + </para> + <programlisting> +cairo_user_to_device (cr, &x, &y);</programlisting> + <para> + can by mapped to: + </para> + <programlisting> +(x, y) = cr.user_to_device (cr, x, y);</programlisting> + <para> + but many languages don't have provisions for multiple return + values, so it is necessary to introduce auxiliary types. + Most of the functions that require the auxiliary types + require a type that would, in C, look like + </para> + <programlisting> +typedef struct _cairo_point cairo_point_t; +struct _cairo_point { + double x; + double y; +}</programlisting> + <para> + The same type should be used both for functions that use a pair + of coordinates as an absolute position, and functions that use + a pair of coordinates as a displacement. While an argument could + be made that having a separate “distance” type is more correct, + it is more likely just to confuse users. + </para> + <programlisting> +void +cairo_user_to_device (cairo_t *cr, double *x, double *y); + +void +cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy); + +void +cairo_device_to_user (cairo_t *cr, double *x, double *y); + +void +cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy); + +void +cairo_matrix_transform_distance (cairo_matrix_t *matrix, double *dx, double *dy); + +void +cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y); + +void +cairo_get_current_point (cairo_t *cr, double *x, double *y); + </programlisting> + <para> + There are also a couple of functions that return four values + representing a rectangle. These should be mapped to a + “rectangle” type that looks like: + </para> + <programlisting> +typedef struct _cairo_rectangle cairo_rectangle_t; +struct _cairo_rectangle { + double x; + double y; + double width; + double height; +}</programlisting> + <para> + The C function returns the rectangle as a set of two points to + facilitate rounding to integral extents, but this isn't worth + adding a “box” type to go along with the more obvious + “rectangle” representation. + </para> + <remark> + Q: Would it make sense here to define a standard + <function>cairo_rectangle_round()</function> method + that language bindings should map? + </remark> + <programlisting> +void +cairo_stroke_extents (cairo_t *cr, + double *x1, double *y1, + double *x2, double *y2); + +void +cairo_fill_extents (cairo_t *cr, + double *x1, double *y1, + double *x2, double *y2); + </programlisting> + </sect1> + <sect1 id="bindings-overloading"> + <title>Overloading and optional arguments</title> + <para> + Function overloading (having a several variants of a function + with the same name and different arguments) is a language + feature available in many languages but not in C. + </para> + <para> + In general, language binding authors should use restraint in + combining functions in the cairo API via function + overloading. What may seem like an obvious overload now may + turn out to be strange with future additions to cairo. + It might seem logical to make + <link + linkend="cairo-set-source-rgb"><function>cairo_set_source_rgb()</function></link> + an overload of <function>cairo_set_source()</function>, but future plans to add + <function>cairo_set_source_rgb_premultiplied()</function>, + which will also take three doubles make this a bad idea. For + this reason, only the following pairs of functions should + be combined via overloading + </para> + <programlisting> +void +cairo_set_source (cairo_t *cr, cairo_pattern_t *source); + +void +cairo_set_source_surface (cairo_t *cr, + cairo_surface_t *source, + double surface_x, + double surface_y); + +void +cairo_mask (cairo_t *cr, + cairo_pattern_t *pattern); + +void +cairo_mask_surface (cairo_t *cr, + cairo_surface_t *surface, + double surface_x, + double surface_y); + +cairo_surface_t * +cairo_image_surface_create (cairo_format_t format, + int width, + int height); +cairo_surface_t * +cairo_image_surface_create_for_data (unsigned char *data, + cairo_format_t format, + int width, + int height, + int stride); + +cairo_status_t +cairo_surface_write_to_png (cairo_surface_t *surface, + const char *filename); + +cairo_status_t +cairo_surface_write_to_png_stream (cairo_surface_t *surface, + cairo_write_func_t write_func, + void *closure); + +cairo_surface_t * +cairo_image_surface_create_from_png (const char *filename); + +cairo_surface_t * +cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, + void *closure); + </programlisting> + <para> + Note that there are cases where all constructors for a type + aren't overloaded together. For example + <link + linkend="cairo-image-surface-create-from-png"><function>cairo_image_surface_create_from_png()</function></link> + should <emphasis>not</emphasis> be overloaded together with + <link + linkend="cairo-image-surface-create"><function>cairo_image_surface_create()</function></link>. + In such cases, the remaining constructors will typically need to + be bound as static methods. In Java, for example, we might have: + </para> +<programlisting> +Surface surface1 = ImageSurface(Format.RGB24, 100, 100); +Surface surface2 = ImageSurface.createFromPNG("camera.png");</programlisting> + <para> + Some other overloads that add combinations not found in C may be + convenient for users for language bindings that provide + <type>cairo_point_t</type> and <type>cairo_rectangle_t</type> + types, for example: + </para> + <programlisting> +void +cairo_move_to (cairo_t *cr, + cairo_point_t *point); +void +cairo_rectangle (cairo_t *cr, + cairo_rectangle_t *rectangle); + </programlisting> + </sect1> + <sect1 id="bindings-streams"> + <title>Streams and File I/O</title> + <para> + Various places in the cairo API deal with reading and writing + data, whether from and to files, or to other sources and + destinations. In these cases, what is typically provided in the + C API is a simple version that just takes a filename, and a + complex version that takes a callback function. + An example is the PNG handling functions: + </para> +<programlisting> +cairo_surface_t * +cairo_image_surface_create_from_png (const char *filename); + +cairo_surface_t * +cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, + void *closure); + +cairo_status_t +cairo_surface_write_to_png (cairo_surface_t *surface, + const char *filename); + +cairo_status_t +cairo_surface_write_to_png_stream (cairo_surface_t *surface, + cairo_write_func_t write_func, + void *closure);</programlisting> + <para> + The expectation is that the filename version will be mapped + literally in the language binding, but the callback version + will be mapped to a version that takes a language stream + object. For example, in Java, the four functions above + might be mapped to: + </para> +<programlisting> +static public ImageSurface createFromPNG (String filename) throws IOException; +static public ImageSurface createFromPNG (InputStream stream) throws IOException; +public void writeToPNG (String filename) throws IOException; +public void writeToPNG (OutputStream stream) throws IOException; +</programlisting> + <para> + In many cases, it will be better to + implement the filename version internally + using the stream version, rather than building it on top of the + filename version in C. The reason for this is that will + naturally give a more standard handling of file errors for + the language, as seen in the above Java example, where + <methodname>createFromPNG()</methodname> is marked as raising + an exception. Propagating exceptions from inside the callback + function to the caller will pose a challenge to the language + binding implementor, since an exception must not propagate + through the Cairo code. A technique that will be useful in + some cases is to catch the exception in the callback, + store the exception object inside a structure pointed to by + <parameter>closure</parameter>, and then rethrow it once + the function returns. + </para> + <remark> + I'm not sure how to handle this for + <link + linkend="cairo-pdf-surface-create-for-stream"><function>cairo_pdf_surface_create_for_stream()</function></link>. + Other than keep a “exception to rethrow” thread-specific + variable + that is checked after <emphasis>every</emphasis> call to a Cairo + function. + </remark> + </sect1> + <sect1 id="bindings-errors"> + <title>Error handling</title> + <para> + The error handling approach in C for Cairo has multiple + elements: + </para> + <itemizedlist> + <listitem><para> + When a method on an object fails, the object is put into + an error state. Subsequent operations on the object do + nothing. The status of the object can be queried with + a function like <link + linkend="cairo-status"><function>status()</function></link>. + </para></listitem> + <listitem><para> + Constructors, rather than + returning <constant>NULL</constant> on out-of-memory failure, + return a special singleton object on which all + operations do nothing. Retrieving the status of the + singleton object returns <constant>CAIRO_STATUS_NO_MEMORY</constant> + </para> + <remark> + Is this going to apply to + <type>cairo_surface_t</type> as well? + </remark> + <remark> + What about cairo_copy_path_data()? It's probably going to + have to return <constant>NULL</constant>. + </remark> + </listitem> + <listitem><para> + Errors propagate from object to object. Setting a pattern + in an out-of-memory state as the source of a + <type>cairo_t</type> puts the type into an error state. + </para></listitem> + </itemizedlist> + <remark>Much of the above is not yet implemented at the time of + this writing</remark> + <para> + A language binding could copy the C approach, and for a + language without exceptions, this is likely the right thing + to do. However, for a language with exceptions, exposing + a completely different style of error handling for cairo + would be strange. So, instead, status should be checked + after every call to cairo, and exceptions thrown as necessary. + </para> + <para> + One problem that can arise with this, in languages + where handling exceptions is mandatory (like Java), is that almost + every cairo function can result in a status being set, + usually because of an out-of-memory condition. This could make + cairo hard to use. To resolve this problem, let's classify then + cairo status codes: + </para> +<programlisting> +/* Memory */ +CAIRO_STATUS_NO_MEMORY, + +/* Programmer error */ +CAIRO_STATUS_INVALID_RESTORE +CAIRO_STATUS_INVALID_POP_GROUP +CAIRO_STATUS_NO_CURRENT_POINT +CAIRO_STATUS_INVALID_MATRIX +CAIRO_STATUS_NO_TARGET_SURFACE +CAIRO_STATUS_INVALID_STRING +CAIRO_STATUS_SURFACE_FINISHED +CAIRO_STATUS_BAD_NESTING + +/* Language binding implementation */ +CAIRO_STATUS_NULL_POINTER +CAIRO_STATUS_INVALID_PATH_DATA +CAIRO_STATUS_SURFACE_TYPE_MISMATCH + +/* Other */ +CAIRO_STATUS_READ_ERROR +CAIRO_STATUS_WRITE_ERROR +</programlisting> + <para> + If we look at these, the + <constant>CAIRO_STATUS_NO_MEMORY</constant> + should map to the native out-of-memory exception, which could + happen at any point in any case. Most of the others indicate + programmer error, and handling them in user code would be + silly. These should be mapped into whatever the language uses + for assertion failures, rather than errors that are normally + handled. (In Java, a subclass of Error rather than Exception, + perhaps.) And <constant>CAIRO_STATUS_READ_ERROR</constant>, + and <constant>CAIRO_STATUS_WRITE_ERROR</constant> can occur + only in very specific places. (In fact, as described + in <xref linkend="bindings-streams"/>, these errors may be + mapped into the language's native I/O error types.) + So, there really aren't exceptions that the programmer must + handle at most points in the Cairo API. + </para> + </sect1> + <sect1 id="bindings-patterns"> + <title>Patterns</title> + <para> + The cairo C API allows for creating a number of different types + of patterns. All of these different types of patterns map to + <link + linkend="cairo-pattern-t"><type>cairo_pattern_t</type></link> + in C, but in an object oriented language, there should instead + be a hierarchy of types. (The functions that should map to + constructors or static methods for the various types are listed + after the type, methods on that type are listed below. Note that + cairo_pattern_create_rgb() and cairo_pattern_create_rgba() + should not be overloaded with each other as a SolidPattern() + constructor, but should appear as static methods instead. This + is to maintain code clarity by making it clear how the arguments + relate to color components.) + </para> + <programlisting> +cairo_pattern_t + <link linkend="cairo-pattern-set-matrix"><function>cairo_pattern_set_matrix()</function></link> + <link linkend="cairo-pattern-get-matrix"><function>cairo_pattern_get_matrix()</function></link> + cairo_solid_pattern_t (<link linkend="cairo-pattern-create-rgb"><function>cairo_pattern_create_rgb()</function></link> and <link linkend="cairo-pattern-create-rgba"><function>cairo_pattern_create_rgba()</function></link>) + cairo_surface_pattern_t (<link linkend="cairo-pattern-create-for-surface"><function>cairo_pattern_create_for_surface()</function></link>) + <link linkend="cairo-pattern-set-extend"><function>cairo_pattern_set_extend()</function></link> + <link linkend="cairo-pattern-get-extend"><function>cairo_pattern_get_extend()</function></link> + <link linkend="cairo-pattern-set-filter"><function>cairo_pattern_set_filter()</function></link> + <link linkend="cairo-pattern-get-filter"><function>cairo_pattern_get_filter()</function></link> + cairo_gradient_t + <link linkend="cairo-pattern-add-color-stop-rgb"><function>cairo_pattern_add_color_stop_rgb()</function></link> + <link linkend="cairo-pattern-add-color-stop-rgba"><function>cairo_pattern_add_color_stop_rgba()</function></link> + cairo_linear_gradient_t (<link linkend="cairo-pattern-create-linear"><function>cairo_pattern_create_linear()</function></link>) + cairo_radial_gradient_t (<link linkend="cairo-pattern-create-radial"><function>cairo_pattern_create_radial()</function></link>) + cairo_mesh_t (<link linkend="cairo-pattern-create-mesh"><function>cairo_pattern_create_mesh()</function></link>) + <link linkend="cairo-mesh-pattern-begin-patch"><function>cairo_mesh_pattern_begin_patch()</function></link> + <link linkend="cairo-mesh-pattern-end-patch"><function>cairo_mesh_pattern_end_patch()</function></link> + <link linkend="cairo-mesh-pattern-move-to"><function>cairo_mesh_pattern_move_to()</function></link> + <link linkend="cairo-mesh-pattern-line-to"><function>cairo_mesh_pattern_line_to()</function></link> + <link linkend="cairo-mesh-pattern-curve-to"><function>cairo_mesh_pattern_curve_to()</function></link> + <link linkend="cairo-mesh-pattern-set-control-point"><function>cairo_mesh_pattern_set_control_point()</function></link> + <link linkend="cairo-mesh-pattern-set-corner-color-rgb"><function>cairo_mesh_pattern_set_corner_color_rgb()</function></link> + <link linkend="cairo-mesh-pattern-set-corner-color-rgba"><function>cairo_mesh_pattern_set_corner_color_rgba()</function></link> + <link linkend="cairo-mesh-pattern-get-patch-count"><function>cairo_mesh_pattern_get_patch_count()</function></link> + <link linkend="cairo-mesh-pattern-get-path"><function>cairo_mesh_pattern_get_path()</function></link> + <link linkend="cairo-mesh-pattern-get-control-point"><function>cairo_mesh_pattern_get_control_point()</function></link> + <link linkend="cairo-mesh-pattern-get-corner-color-rgba"><function>cairo_mesh_pattern_get_corner_color_rgba()</function></link> + </programlisting> + <para> + </para> + </sect1> + <sect1 id="bindings-surfaces"> + <title>Surfaces</title> + <para> + Like patterns, surfaces, which use only the + <link + linkend="cairo-surface-t"><type>cairo_surface_t</type></link> + type in the C API should be broken up into a hierarchy of types + in a language binding. + </para> + <programlisting> +cairo_surface_t + cairo_image_surface_t + cairo_atsui_surface_t + cairo_win32_surface_t + cairo_xlib_surface_t + cairo_beos_surface_t + </programlisting> + <para> + Unlike patterns, the constructors and methods on these types are + clearly named, and can be trivially associated with the + appropriate subtype. Many language bindings will want to avoid + binding the platform-specific subtypes at all, since the + methods on these types are not useful without passing in native + C types. Unless there is a language binding for Xlib available, + there is no way to represent a XLib <type>Display</type> * in + that language. + </para> + <para> + This doesn't mean that platform-specific surface types can't + be used in a language binding that doesn't bind the constructor. + A very common situation is to use a cairo language binding in + combination with a binding for a higher level system like + the <ulink url="http://www.gtk.org/">GTK+</ulink> widget + toolkit. In such a situation, the higher level toolkit provides + ways to get references to platform specific surfaces. + </para> + <para> + The <link + linkend="cairo-surface-set-user-data"><function>cairo_surface_set_user_data()</function></link>, + and <link + linkend="cairo-surface-get-user-data"><function>cairo_surface_get_user_data()</function></link> + methods are provided for use in language bindings, and should + not be directly exposed to applications. One example of the use + of these functions in a language binding is creating a binding for: + </para> +<programlisting> +cairo_surface_t * +<link linkend="cairo-image-surface-create-for-data"><function>cairo_image_surface_create_for_data</function></link> (unsigned char *data, + cairo_format_t format, + int width, + int height, + int stride); +</programlisting> + <para> + The memory block passed in for <parameter>data</parameter> must be + kept around until the surface is destroyed, so the language + binding must have some way of determining when that happens. The + way to do this is to use the <parameter>destroy</parameter> + argument to <function>cairo_surface_set_user_data()</function>. + </para> + <remark> + Some languages may not have a suitable “pointer to a block of + data” type to pass in for <parameter>data</parameter>. And even + where a language does have such a type, the user will be + frequently able to cause the backing store to be reallocated + to a different location or truncated. Should we recommend a + standard type name and binding for a buffer object here? + </remark> + </sect1> + <sect1 id="bindings-fonts"> + <title>Fonts</title> + <para> + Fonts are once more an area where there is a hierarchy of types: + </para> +<programlisting> +cairo_font_face_t + cairo_ft_font_face_t + cairo_win32_font_face_t +cairo_scaled_font_t + cairo_ft_scaled_font_t + cairo_win32_scaled_font_t +</programlisting> + <para> + The methods on the subtypes are, however, not useful without + bindings for fontconfig and FreeType or for the Win32 GDI, + so most language bindings will choose not to bind these + types. + </para> + <para> + The <link + linkend="cairo-font-face-set-user-data"><function>cairo_font_face_set_user_data()</function></link>, + and <link + linkend="cairo-font-face-get-user-data"><function>cairo_font_face_get_user_data()</function></link> + methods are provided for use in language bindings, and should + not be directly exposed to applications. + </para> + </sect1> + <sect1 id="bindings-path"> + <title>cairo_path_t</title> + <para> + The <link linkend="cairo-path-t"><type>cairo_path_t</type></link> type is one + area in which most language bindings will differ significantly + from the C API. The C API for <type>cairo_path_t</type> is + designed for efficiency and to avoid auxiliary objects that + would be have to be manually memory managed by the + application. However, + a language binding should not present <type>cairo_path_t</type> as an + array, but rather as an opaque that can be iterated + over. Different languages have quite different conventions for + how iterators work, so it is impossible to give an exact + specification for how this API should work, but the type names + and methods should be similar to the language's mapping of the following: + </para> + <programlisting> +typedef struct cairo_path_iterator cairo_path_iterator_t; +typedef struct cairo_path_element cairo_path_element_t; + +cairo_path_iterator_t * +cairo_path_get_iterator (cairo_path_t *path); + +cairo_bool_t +cairo_path_iterator_has_next (cairo_path_iterator_t *iterator); + +cairo_path_element_t * +cairo_path_iterator_next (cairo_path_iterator_t *iterator); + +cairo_path_element_type_t +cairo_path_element_get_type (cairo_path_element_t *element); + +void +cairo_path_element_get_point (cairo_path_element_t *element, + int index, + double *x, + double *y); + </programlisting> + <para> + The above is written using the Java conventions for + iterators. To illustrate how the API for PathIterator might + depend on the native iteration conventions of the API, examine + three versions of the loop, first written in a hypothetical Java + binding: + </para> + <programlisting> +PathIterator iter = cr.copyPath().iterator(); +while (cr.hasNext()) { + PathElement element = iter.next(); + if (element.getType() == PathElementType.MOVE_TO) { + Point p = element.getPoint(0); + doMoveTo (p.x, p.y); + } +}</programlisting> + <para> + And then in a hypothetical C++ binding: + </para> + <programlisting> +Path path = cr.copyPath(); +for (PathIterator iter = path.begin(); iter != path.end(); iter++) { + PathElement element = *iter; + if (element.getType() == PathElementType.MOVE_TO) { + Point p = element.getPoint(0); + doMoveTo (p.x, p.y); + } +}</programlisting> + <para> + And then finally in a Python binding: + </para> +<programlisting> +for element in cr.copy_path(): + if element.getType == cairo.PATH_ELEMENT_MOVE_TO: + (x, y) = element.getPoint(0) + doMoveTo (x, y);</programlisting> + <para> + While many of the API elements stay the same in the three + examples, the exact iteration mechanism is quite different, to + match how users of the language would expect to iterate over + a container. + </para> + <para> + You should not present an API for mutating or for creating new + <type>cairo_path_t</type> objects. In the future, these + guidelines may be extended to present an API for creating a + <type>cairo_path_t</type> from scratch for use with + <link + linkend="cairo-append-path"><function>cairo_append_path()</function></link> + but the current expectation is that <function>cairo_append_path()</function> will + mostly be used with paths from + <link + linkend="cairo-append-path"><function>cairo_copy_path()</function></link>. + </para> + </sect1> +</appendix> +<!-- +Local variables: +mode: sgml +sgml-parent-document: ("cairo-docs.xml" "book" "book" "appendix") +End: +--> |