mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-24 17:10:11 +01:00
727 lines
28 KiB
XML
727 lines
28 KiB
XML
<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-callback"><function>cairo_pdf_surface_create_for_callback()</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 for the various types are listed after the type,
|
||
methods on that type are listed below)
|
||
</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
|
||
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>)
|
||
</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:
|
||
-->
|