1# cairo support 2 3Cairo library is an important part of any GTK-based setup, because GTK 4internally uses cairo exclusively for painting. However, cairo itself 5is not built using GObject technology and thus imposes quite a problem 6for any GObject Introspection based binding, such as lgi. 7 8## Basic binding description 9 10Although internal implementation is a bit different from other fully 11introspection-enabled libraries, this difference is not visible to lgi 12user. cairo must be imported in the same way as other libraries, e.g. 13 14 local lgi = require 'lgi' 15 local cairo = lgi.cairo 16 17Cairo library itself is organized using object-oriented style, using C 18structures as objects (e.g. `cairo_t`, `cairo_surface_t`) and 19functions as methods acting upon these objects. lgi exports objects 20as classes in the `cairo` namespace, e.g. `cairo.Context`, 21`cairo.Surface` etc. To create new object instance, cairo offers 22assorted `create` methods, e.g. `cairo_create` or 23`cairo_pattern_create`, which are mapped as expected to 24`cairo.Context.create` and `cairo.Pattern.create`. It is also 25possible to invoke them using lgi's 'constructor' syntax, i.e. to 26create new context on specified surface, it is possible to use either 27`local cr = cairo.Context.create(surface)` or `local cr = 28cairo.Context(surface)`. 29 30### Version checking 31 32`cairo.version` and `cairo.version_string` fields contain current 33runtime cairo library version, as returned by their C counterparts 34`cairo_version()` and `cairo_version_string()`. Original 35`CAIRO_VERSION_ENCODE` macro is reimplemented as 36`cairo.version_encode(major, minor, micro)`. For example, following 37section shows how to guard code which should be run only when cairo 38version is at least 1.12: 39 40 if cairo.version >= cairo.version_encode(1, 12, 0) then 41 -- Cairo 1.12-specific code 42 else 43 -- Fallback to older cairo version code 44 end 45 46### Synthetic properties 47 48There are many getter and setter functions for assorted cairo objects. 49lgi exports them in the form of method calls as the native C interface 50does, and it also provides property-like access, so that it is 51possible to query or assign named property of the object. Following 52example demonstrates two identical ways to set and get line width on 53cairo.Context instance: 54 55 local cr = cairo.Context(surface) 56 cr:set_line_width(10) 57 print('line width ', cr:get_line_width()) 58 59 cr.line_width = 10 60 print('line width ', cr.line_width) 61 62In general, any kind of `get_xxx()` method call on any cairo object 63can be replaced using `xxx` property on the object, and any 64`set_xxx()` method can be replaced by setting `xxx` property. 65 66### cairo.Surface hierarchy 67 68Cairo provides basic rendering surface object `cairo.Surface`, and a 69bunch of specialized surfaces implementing rendering to assorted 70targets, e.g. `cairo.ImageSurface`, `cairo.PdfSurface` etc. These 71surface provide their own class, which is logically inherited from 72`cairo.Surface`. lgi fully implements this inheritance, so that 73calling `cairo.ImageSurface()` actually creates an instance of 74`cairo.ImageSurface` class, which provides all methods abd properties 75of `cairo.Surface` and and some specialized methods and properties 76like `width` and `height`. 77 78In addition, lgi always assigns the real type of the surface, so that 79even when `cairo.Context.get_target()` method (or 80`cairo.Context.target` property) is designated as returning 81`cairo.Surface` instance, upon the call the type of the surface is 82queried and proper kind of surface type is really returned. Following 83example demonstrates that it is possible to query 84`cairo.ImageSurface`-specific `width` property directly on the 85`cairo.Context.target` result. 86 87 -- Assumes the cr is cairo.Context instance with assigned surface 88 print('width of the surface' cr.target.width) 89 90It is also possible to use lgi generic typechecking machinery for 91checking the type of the surface: 92 93 if cairo.ImageSurface:is_type_of(cr.target) then 94 print('width of the surface' cr.target.width) 95 else 96 print('unsupported type of the surface') 97 end 98 99### cairo.Pattern hierarchy 100 101cairo's pattern API actually hides the inheritance of assorted pattern 102types. lgi binding brings this hierarchy up in the same way as for 103surfaces described in previous section. Following hierarchy exists: 104 105 cairo.Pattern 106 cairo.SolidPattern 107 cairo.SurfacePattern 108 cairo.GradientPattern 109 cairo.LinearPattern 110 cairo.RadialPattern 111 cairo.MeshPattern 112 113Patterns can be created using static factory methods on 114`cairo.Pattern` as documented in cairo documentation. In addition, 115lgi maps creation methods to specific subclass constructors, so 116following snippets are equivalent: 117 118 local pattern = cairo.Pattern.create_linear(0, 0, 10, 10) 119 local pattern = cairo.LinearPattern(0, 0, 10, 10) 120 121### cairo.Context path iteration 122 123cairo library offers iteration over the drawing path returned via 124`cairo.Context.copy_path()` method. Resulting path can be iterated 125using `pairs()` method of `cairo.Path` class. `pairs()` method 126returns iterator suitable to be used in Lua 'generic for' construct. 127Iterator returns type of the path element, optionally followed by 0, 1 128or 3 points. Following example shows how to iterate the path. 129 130 local path = cr:copy_path() 131 for kind, points in path:pairs() do 132 io.write(kind .. ':') 133 for pt in ipairs(points) do 134 io.write((' { %g, %g }'):format(pt.x, pt.y)) 135 end 136 end 137 end 138 139## Impact of cairo on other libraries 140 141In addition to cairo itself, there is a bunch of cairo-specific 142methods inside Gtk, Gdk and Pango libraries. lgi wires them up so 143that they can be called naturally as if they were built in to the 144cairo core itself. 145 146### Gdk and Gtk 147 148`Gdk.Rectangle` is just a link to `cairo.RectangleInt` (similar to C, 149where `GdkRectangle` is just a typedef of `cairo_rectangle_int_t`). 150`gdk_rectangle_union` and `gdk_rectangle_intersect` are wired as a 151methods of `Gdk.Rectangle` as expected. 152 153`Gdk.cairo_create()` is aliased as a method 154`Gdk.Window.cairo_create()`. `Gdk.cairo_region_create_from_surface()` 155is aliased as `cairo.Region.create_from_surface()`. 156 157`cairo.Context.set_source_rgba()` is overriden so that it also accepts 158`Gdk.RGBA` instance as an argument. Similarly, 159`cairo.Context.rectangle()` alternatively accepts `Gdk.Rectangle` as 160an argument. 161 162`cairo.Context` has additional methods `get_clip_rectangle()`, 163`set_source_color()`, `set_source_pixbuf()`, `set_source_window` and 164`region`, implemented as calls to appropriate `Gdk.cairo_xxx` 165functions. 166 167Since all these extensions are implemented inside Gdk and Gtk 168libraries, they are present only when `lgi.Gdk` is loaded. When 169loading just pure `lgi.cairo`, they are not available. 170 171### PangoCairo 172 173Pango library contains namespace `PangoCairo` which implements a bunch 174of cairo-specific helper functions to integrate Pango use with cairo 175library. It is of course possible to call them as global methods of 176PangoCairo interface, however lgi override maps the also to methods 177and attributes of other classes to which they logically belong. 178