⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 language-bindings.xml

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 XML
📖 第 1 页 / 共 2 页
字号:
<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, &amp;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, &amp;x, &amp;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>voidcairo_user_to_device (cairo_t *cr, double *x, double *y);voidcairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy);voidcairo_device_to_user (cairo_t *cr, double *x, double *y);voidcairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy);voidcairo_matrix_transform_distance (cairo_matrix_t *matrix, double *dx, double *dy);voidcairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y);voidcairo_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>voidcairo_stroke_extents (cairo_t *cr,		      double *x1, double *y1,		      double *x2, double *y2);voidcairo_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>voidcairo_set_source (cairo_t *cr, cairo_pattern_t *source);voidcairo_set_source_surface (cairo_t          *cr,                          cairo_surface_t  *source,                          double            surface_x,                          double            surface_y);      voidcairo_mask (cairo_t         *cr,	    cairo_pattern_t *pattern);voidcairo_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_tcairo_surface_write_to_png (cairo_surface_t	*surface,			    const char		*filename);cairo_status_tcairo_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>voidcairo_move_to (cairo_t       *cr,               cairo_point_t *point);voidcairo_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_tcairo_surface_write_to_png (cairo_surface_t	*surface,			    const char		*filename);cairo_status_tcairo_surface_write_to_png_stream (cairo_surface_t	*surface,				   cairo_write_func_t	write_func,				   void			*closure);</programlisting>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -