From f1fe73d1909a2448a004a88362a1a532d0d4f7c3 Mon Sep 17 00:00:00 2001 From: sanine Date: Sun, 12 Feb 2023 23:53:22 -0600 Subject: switch to tinyobj and nanovg from assimp and cairo --- libs/cairo-1.16.0/doc/public/language-bindings.xml | 745 --------------------- 1 file changed, 745 deletions(-) delete mode 100644 libs/cairo-1.16.0/doc/public/language-bindings.xml (limited to 'libs/cairo-1.16.0/doc/public/language-bindings.xml') diff --git a/libs/cairo-1.16.0/doc/public/language-bindings.xml b/libs/cairo-1.16.0/doc/public/language-bindings.xml deleted file mode 100644 index ce437ef..0000000 --- a/libs/cairo-1.16.0/doc/public/language-bindings.xml +++ /dev/null @@ -1,745 +0,0 @@ - - Creating a language binding for cairo - - 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 language - binding. 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. - - - General considerations - - The naming of the central cairo_t type is a - special exception. The object is “a cairo context” not “a - cairo”, and names such as cairo_t rather than - cairo_context_t and - cairo_set_source() rather than - cairo_context_set_source() 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 cairo_context_t. - - - 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 - cairo_set_source(cr,source), - cr.setSource(source). - 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(). - - - - Memory management - - The objects in cairo can roughly be divided into two types: - reference-counted, opaque types like - cairo_surface_t - and plain structures like - cairo_glyph_t. - cairo_path_t - and - cairo_path_data_t - are special cases and are treated separately in this appendix. - - - Refcounted opaque types all have a - ..._reference() - function to increase the refcount by one and a - ..._destroy() 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: - - - - - 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 pin table (a hash - table that goes from cairo object to language object). - For cairo_surface_t you can use also - cairo_surface_set_user_data() - instead of a separate pin table. - - - - - Derivation from the language object doesn't work because - you can lose the language object while keeping the Cairo - object. Code like: - - -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(); - - - Can result in surface containing an - ImageSurface not a MySurface. - This is not easily fixable without creating memory leaks, - and it's probably best to simply forbid deriving from the - language objects. - - - - - When a plain structure is used as a return value from cairo, - this is done by passing it as a “out parameter”. - - -cairo_font_extents_t extents; - -cairo_font_extents (cr, &extents); - - In a language binding, this should typically be treated - as a return value: - - -FontExtents extents = cr.fontExtents (); - - 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. - - - - Multiple return values - - There are a number of functions in the cairo API that have - multiple out parameters or - in-out parameters. In some languages - these can be translated into multiple return values. In Python, - what is: - - -cairo_user_to_device (cr, &x, &y); - - can by mapped to: - - -(x, y) = cr.user_to_device (cr, x, y); - - 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 - - -typedef struct _cairo_point cairo_point_t; -struct _cairo_point { - double x; - double y; -} - - 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. - - -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); - - - 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: - - -typedef struct _cairo_rectangle cairo_rectangle_t; -struct _cairo_rectangle { - double x; - double y; - double width; - double height; -} - - 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. - - - Q: Would it make sense here to define a standard - cairo_rectangle_round() method - that language bindings should map? - - -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); - - - - Overloading and optional arguments - - 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. - - - 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 - cairo_set_source_rgb() - an overload of cairo_set_source(), but future plans to add - cairo_set_source_rgb_premultiplied(), - 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 - - -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); - - - Note that there are cases where all constructors for a type - aren't overloaded together. For example - cairo_image_surface_create_from_png() - should not be overloaded together with - cairo_image_surface_create(). - In such cases, the remaining constructors will typically need to - be bound as static methods. In Java, for example, we might have: - - -Surface surface1 = ImageSurface(Format.RGB24, 100, 100); -Surface surface2 = ImageSurface.createFromPNG("camera.png"); - - Some other overloads that add combinations not found in C may be - convenient for users for language bindings that provide - cairo_point_t and cairo_rectangle_t - types, for example: - - -void -cairo_move_to (cairo_t *cr, - cairo_point_t *point); -void -cairo_rectangle (cairo_t *cr, - cairo_rectangle_t *rectangle); - - - - Streams and File I/O - - 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: - - -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); - - 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: - - -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; - - - 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 - createFromPNG() 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 - closure, and then rethrow it once - the function returns. - - - I'm not sure how to handle this for - cairo_pdf_surface_create_for_stream(). - Other than keep a “exception to rethrow” thread-specific - variable - that is checked after every call to a Cairo - function. - - - - Error handling - - The error handling approach in C for Cairo has multiple - elements: - - - - 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 status(). - - - Constructors, rather than - returning NULL on out-of-memory failure, - return a special singleton object on which all - operations do nothing. Retrieving the status of the - singleton object returns CAIRO_STATUS_NO_MEMORY - - - Is this going to apply to - cairo_surface_t as well? - - - What about cairo_copy_path_data()? It's probably going to - have to return NULL. - - - - Errors propagate from object to object. Setting a pattern - in an out-of-memory state as the source of a - cairo_t puts the type into an error state. - - - Much of the above is not yet implemented at the time of - this writing - - 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. - - - 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: - - -/* 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 - - - If we look at these, the - CAIRO_STATUS_NO_MEMORY - 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 CAIRO_STATUS_READ_ERROR, - and CAIRO_STATUS_WRITE_ERROR can occur - only in very specific places. (In fact, as described - in , 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. - - - - Patterns - - The cairo C API allows for creating a number of different types - of patterns. All of these different types of patterns map to - cairo_pattern_t - 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.) - - -cairo_pattern_t - cairo_pattern_set_matrix() - cairo_pattern_get_matrix() - cairo_solid_pattern_t (cairo_pattern_create_rgb() and cairo_pattern_create_rgba()) - cairo_surface_pattern_t (cairo_pattern_create_for_surface()) - cairo_pattern_set_extend() - cairo_pattern_get_extend() - cairo_pattern_set_filter() - cairo_pattern_get_filter() - cairo_gradient_t - cairo_pattern_add_color_stop_rgb() - cairo_pattern_add_color_stop_rgba() - cairo_linear_gradient_t (cairo_pattern_create_linear()) - cairo_radial_gradient_t (cairo_pattern_create_radial()) - cairo_mesh_t (cairo_pattern_create_mesh()) - cairo_mesh_pattern_begin_patch() - cairo_mesh_pattern_end_patch() - cairo_mesh_pattern_move_to() - cairo_mesh_pattern_line_to() - cairo_mesh_pattern_curve_to() - cairo_mesh_pattern_set_control_point() - cairo_mesh_pattern_set_corner_color_rgb() - cairo_mesh_pattern_set_corner_color_rgba() - cairo_mesh_pattern_get_patch_count() - cairo_mesh_pattern_get_path() - cairo_mesh_pattern_get_control_point() - cairo_mesh_pattern_get_corner_color_rgba() - - - - - - Surfaces - - Like patterns, surfaces, which use only the - cairo_surface_t - type in the C API should be broken up into a hierarchy of types - in a language binding. - - -cairo_surface_t - cairo_image_surface_t - cairo_atsui_surface_t - cairo_win32_surface_t - cairo_xlib_surface_t - cairo_beos_surface_t - - - 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 Display * in - that language. - - - 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 GTK+ widget - toolkit. In such a situation, the higher level toolkit provides - ways to get references to platform specific surfaces. - - - The cairo_surface_set_user_data(), - and cairo_surface_get_user_data() - 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: - - -cairo_surface_t * -cairo_image_surface_create_for_data (unsigned char *data, - cairo_format_t format, - int width, - int height, - int stride); - - - The memory block passed in for data 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 destroy - argument to cairo_surface_set_user_data(). - - - Some languages may not have a suitable “pointer to a block of - data” type to pass in for data. 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? - - - - Fonts - - Fonts are once more an area where there is a hierarchy of types: - - -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 - - - 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. - - - The cairo_font_face_set_user_data(), - and cairo_font_face_get_user_data() - methods are provided for use in language bindings, and should - not be directly exposed to applications. - - - - cairo_path_t - - The cairo_path_t type is one - area in which most language bindings will differ significantly - from the C API. The C API for cairo_path_t 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 cairo_path_t 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: - - -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); - - - 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: - - -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); - } -} - - And then in a hypothetical C++ binding: - - -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); - } -} - - And then finally in a Python binding: - - -for element in cr.copy_path(): - if element.getType == cairo.PATH_ELEMENT_MOVE_TO: - (x, y) = element.getPoint(0) - doMoveTo (x, y); - - 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. - - - You should not present an API for mutating or for creating new - cairo_path_t objects. In the future, these - guidelines may be extended to present an API for creating a - cairo_path_t from scratch for use with - cairo_append_path() - but the current expectation is that cairo_append_path() will - mostly be used with paths from - cairo_copy_path(). - - - - -- cgit v1.2.1