summaryrefslogtreecommitdiff
path: root/doc/public/language-bindings.xml
blob: 26b98e1bef6c47c5af9722db3afab76b7e20996d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
<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>
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
    </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:
-->