<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>cairo support</title> <link rel="stylesheet" type="text/css" href="default.css" /> </head> <body> <h1>cairo support</h1> <p>Cairo library is an important part of any GTK-based setup, because GTK internally uses cairo exclusively for painting. However, cairo itself is not built using GObject technology and thus imposes quite a problem for any GObject Introspection based binding, such as lgi.</p> <h2>Basic binding description</h2> <p>Although internal implementation is a bit different from other fully introspection-enabled libraries, this difference is not visible to lgi user. cairo must be imported in the same way as other libraries, e.g.</p> <pre><code>local lgi = require 'lgi' local cairo = lgi.cairo </code></pre> <p>Cairo library itself is organized using object-oriented style, using C structures as objects (e.g. <code>cairo_t</code>, <code>cairo_surface_t</code>) and functions as methods acting upon these objects. lgi exports objects as classes in the <code>cairo</code> namespace, e.g. <code>cairo.Context</code>, <code>cairo.Surface</code> etc. To create new object instance, cairo offers assorted <code>create</code> methods, e.g. <code>cairo_create</code> or <code>cairo_pattern_create</code>, which are mapped as expected to <code>cairo.Context.create</code> and <code>cairo.Pattern.create</code>. It is also possible to invoke them using lgi's 'constructor' syntax, i.e. to create new context on specified surface, it is possible to use either <code>local cr = cairo.Context.create(surface)</code> or `local cr = cairo.Context(surface)`.</p> <h3>Synthetic properties</h3> <p>There are many getter and setter functions for assorted cairo objects. lgi exports them in the form of method calls as the native C interface does, and it also provides property-like access, so that it is possible to query or assign named property of the object. Following example demonstrates two identical ways to set and get line width on cairo.Context instance:</p> <pre><code>local cr = cairo.Context(surface) cr:set_line_width(10) print('line width ', cr:get_line_width()) cr.line_width = 10 print('line width ', cr.line_width) </code></pre> <p>In general, any kind of <code>get_xxx()</code> method call on any cairo object can be replaced using <code>xxx</code> property on the object, and any <code>set_xxx()</code> method can be replaced by setting <code>xxx</code> property.</p> <h3>Surface hierarchy</h3> <p>Cairo provides basic rendering surface object <code>cairo.Surface</code>, and a bunch of specialized surfaces implementing rendering to assorted targets, e.g. <code>cairo.ImageSurface</code>, <code>cairo.PdfSurface</code> etc. These surface provide their own class, which is logically inherited from <code>cairo.Surface</code>. lgi fully implements this inheritance, so that calling <code>cairo.ImageSurface()</code> actually creates an instance of <code>cairo.ImageSurface</code> class, which provides all methods abd properties of <code>cairo.Surface</code> and and some specialized methods and properties like <code>width</code> and <code>height</code>.</p> <p>In addition, lgi always assigns the real type of the surface, so that even when <code>cairo.Context.get_target()</code> method (or <code>cairo.Context.target</code> property) is designated as returning <code>cairo.Surface</code> instance, upon the call the type of the surface is queried and proper kind of surface type is really returned. Following example demonstrates that it is possible to query <code>cairo.ImageSurface</code>-specific <code>width</code> property directly on the <code>cairo.Context.target</code> result.</p> <pre><code>-- Assumes the cr is cairo.Context instance with assigned surface print('width of the surface' cr.target.width) </code></pre> <p>It is also possible to use lgi generic typechecking machinery for checking the type of the surface:</p> <pre><code>if cairo.ImageSurface:is_type_of(cr.target) then print('width of the surface' cr.target.width) else print('unsupported type of the surface') end </code></pre> <h3>cairo.Context path iteration</h3> <p>cairo library offers iteration over the drawing path returned via <code>cairo.Context.copy_path()</code> method. Resulting path can be iterated using <code>pairs()</code> method of <code>cairo.Path</code> class. <code>pairs()</code> method returns iterator suitable to be used in Lua 'generic for' construct. Iterator returns type of the path element, optionally followed by 0, 1 or 3 points. Following example shows how to iterate the path.</p> <pre><code>local path = cr:copy_path() for kind, points in path:pairs() do io.write(kind .. ':') for pt in ipairs(points) do io.write((' { %g, %g }'):format(pt.x, pt.y)) end end end </code></pre> <h2>Impact of cairo on other libraries</h2> <p>In addition to cairo itself, there is a bunch of cairo-specific methods inside Gtk, Gdk and Pango libraries. lgi wires them up so that they can be called naturally as if they were built in to the cairo core itself.</p> <h3>Gdk and Gtk</h3> <p><code>Gdk.Rectangle</code> is just a link to <code>cairo.RectangleInt</code> (similar to C, where <code>GdkRectangle</code> is just a typedef of <code>cairo_rectangle_int_t</code>). <code>gdk_rectangle_union</code> and <code>gdk_rectangle_intersect</code> are wired as a methods of <code>Gdk.Rectangle</code> as expected.</p> <p><code>Gdk.cairo_create()</code> is aliased as a method <code>Gdk.Window.cairo_create()</code>. <code>Gdk.cairo_region_create_from_surface()</code> is aliased as <code>cairo.Region.create_from_surface()</code>.</p> <p><code>cairo.Context.set_source_rgba()</code> is overriden so that it also accepts <code>Gdk.RGBA</code> instance as an argument. Similarly, <code>cairo.Context.rectangle()</code> alternatively accepts <code>Gdk.Rectangle</code> as an argument.</p> <p><code>cairo.Context</code> has additional methods <code>get_clip_rectangle()</code>, <code>set_source_color()</code>, <code>set_source_pixbuf()</code>, <code>set_source_window</code> and <code>region</code>, implemented as calls to appropriate <code>Gdk.cairo_xxx</code> functions.</p> <p>Since all these extensions are implemented inside Gdk and Gtk libraries, they are present only when <code>lgi.Gdk</code> is loaded. When loading just pure <code>lgi.cairo</code>, they are not available.</p> <h3>PangoCairo</h3> <p>Pango library contains namespace <code>PangoCairo</code> which implements a bunch of cairo-specific helper functions to integrate Pango use with cairo library. It is of course possible to call them as global methods of PangoCairo interface, however lgi override maps the also to methods and attributes of other classes to which they logically belong.</p> </body></html>