doc: Add a Cairo/LGI introduction page
This commit is contained in:
parent
d4dc579105
commit
4b1ac54386
|
@ -0,0 +1,163 @@
|
|||
# Using Cairo and LGI
|
||||
|
||||
These days, Awesome interface is mostly based on a library called LGI. It allows
|
||||
to access C libraries such as GTK, GLib, Cairo, Pango, PangoCairo and RSVG using
|
||||
Lua code without having to write actual "glue" C code.
|
||||
|
||||
This is done using the GObject-introspection framework. The main advantage is
|
||||
the time saved and large number of features exposed for free. The downside is
|
||||
the lack of proper Lua centric documentation and examples. Some examples can be
|
||||
found in [LGI's own documentation](https://github.com/pavouk/lgi/tree/master/docs),
|
||||
but this does not directly explain how to use a concrete API.
|
||||
Using other APIs requires some trial and error, and can be even impossible if
|
||||
the introspection data is missing or inaccurate.
|
||||
Using low-level APIs directly can easily cause crashes.
|
||||
It is the programmer's responsibility to properly check return and error
|
||||
values.
|
||||
|
||||
## Using LGI in Awesome
|
||||
|
||||
GObject and Gnome centric libraries tend to use the common C practice of
|
||||
emulating namespaces using underscores in function names.
|
||||
LGI exposes a proper namespace based API. For example, if the C function is:
|
||||
|
||||
cairo_image_surface_create()
|
||||
|
||||
Then the LGI equivalent is:
|
||||
|
||||
lgi.cairo.ImageSurface.create()
|
||||
|
||||
The same goes for enums:
|
||||
|
||||
CAIRO_FORMAT_ARGB32
|
||||
|
||||
becomes:
|
||||
|
||||
lgi.cairo.Format.ARGB32
|
||||
|
||||
LGI is also object oriented while the C API is function based. When those
|
||||
functions take the "class" "object", then this:
|
||||
|
||||
cairo_line_to(cr, x, y)
|
||||
|
||||
can be expressed as:
|
||||
|
||||
cr:line_to(x, y)
|
||||
|
||||
It is however important to note some inconsistencies. For example, Cairo is
|
||||
called `lgi.cairo` while GLib is called `lgi.GLib`. Figuring this out will
|
||||
require some experimenting. The best way to do this without actually
|
||||
reloading Awesome is to open the `lua` command in a terminal and use `print`:
|
||||
|
||||
print("This will print a table address:", require("lgi").cairo)
|
||||
print("This will print an error:", require("lgi").Cairo)
|
||||
|
||||
It is recommended to avoid using `require` always when using a function, but
|
||||
include the libraries at the top of your `rc.lua` or Lua module instead:
|
||||
|
||||
local cairo = require("lgi").cairo
|
||||
|
||||
## The Cairo API
|
||||
|
||||
Cairo is a 2D graphic library used by Awesome, Gnome and XFCE. It allows to
|
||||
e.g. paint paths on a `surface`.
|
||||
Awesome uses it internally and being able to call it directly is a powerful
|
||||
feature.
|
||||
|
||||
The following concepts are necessary to be able to use Cairo:
|
||||
|
||||
**Surface**:
|
||||
|
||||
A surface is the area where the painting will be done. There are multiple types
|
||||
of surfaces including:
|
||||
|
||||
* Color images with transparency (`ARGB32`) or without (`RGB24`)
|
||||
* Monochrome image surfaces with transparency (`A8`) or without (`A1`)
|
||||
* SVG vectorial surfaces
|
||||
* Native (XCB) surfaces
|
||||
* Framebuffers and other less interesting ones (from an Awesome's point of
|
||||
view)
|
||||
|
||||
For more details see [Surfaces](https://cairographics.org/manual/cairo-Image-Surfaces.html).
|
||||
|
||||
**Sources**:
|
||||
|
||||
Sources are elements like colors, patterns or gradients. See `gears.color` for
|
||||
common sources.
|
||||
|
||||
For more details see [Pattern](http://cairographics.org/manual/cairo-cairo-pattern-t.html).
|
||||
|
||||
**Context and paths**:
|
||||
|
||||
A context is the proxy between the program and the surface, and holds a path.
|
||||
Paths are something like a line, circle or rectangle, which may or
|
||||
may not be closed (a shape).
|
||||
|
||||
All drawing operations on a surface are done via a context.
|
||||
The current path is extended until it is used and reset (see next section).
|
||||
Until then nothing will be drawn to the surface. For example:
|
||||
|
||||
cr:rectangle(0 , 0 , 10, 10)
|
||||
cr:rectangle(10, 10, 10, 10)
|
||||
|
||||
will not do anything until the operation is applied to the context.
|
||||
|
||||
For more details, read:
|
||||
|
||||
* [Path](http://cairographics.org/manual/cairo-Paths.html)
|
||||
* [Context](http://cairographics.org/manual/cairo-cairo-t.html)
|
||||
* [Transformation](http://cairographics.org/manual/cairo-Transformations.html)
|
||||
|
||||
A context also holds a transformation matrix (see `gears.matrix`), which is
|
||||
used when applying an operation.
|
||||
|
||||
**Operations**:
|
||||
|
||||
Multiple operations can be done with the paths. The most common are:
|
||||
|
||||
* *fill*: Fill the path with the current source.
|
||||
* *stroke*: Paint the path outline with the current source.
|
||||
* *mask*: Use the current source as an alpha mask while painting with the
|
||||
current operator.
|
||||
* *clip*: Crop the surface's workarea so nothing outside of the clip will be
|
||||
affected by all following operations.
|
||||
|
||||
**Operators**:
|
||||
|
||||
[Operators](http://cairographics.org/operators/) are modifiers used when
|
||||
applying operations.
|
||||
|
||||
### Cairo in Awesome
|
||||
|
||||
All of Awesome's `wibox`es, `awful.wibar`s, `gears.wallpaper`s and
|
||||
`awful.titlebar`s contain a Cairo surfaces, which can be accessed through the
|
||||
`drawin` API. This allows widgets to use the Cairo context directly.
|
||||
See the
|
||||
[declarative layout system](../documentation/03-declarative-layout.md.html)
|
||||
and [new widgets](../documentation/04-new-widgets.md.html) articles for more
|
||||
information and examples on how widgets work.
|
||||
|
||||
It is also possible to create surfaces manually. See `gears.surface` for
|
||||
some examples. Here is the most simple example you can get:
|
||||
|
||||
-- Create a surface
|
||||
local img = cairo.ImageSurface.create(cairo.Format.ARGB32, 50, 50)
|
||||
|
||||
-- Create a context
|
||||
local cr = cairo.Context(img)
|
||||
|
||||
-- Set a red source
|
||||
cr:set_source(1, 0, 0)
|
||||
-- Alternative:
|
||||
cr:set_source(gears.color("#ff0000"))
|
||||
|
||||
-- Add a 10px square path to the context at x=10, y=10
|
||||
cr:rectangle(10, 10, 10, 10)
|
||||
|
||||
-- Actually draw the rectangle on img
|
||||
cr:fill()
|
||||
|
||||
This can then be used as `bgimage` for a `wibox`, `awful.wibar` or
|
||||
`wibox.container.background`:
|
||||
|
||||
mywibox[screen.primary].bgimage = img
|
|
@ -21,6 +21,7 @@ topics={
|
|||
'02-contributing.md',
|
||||
'03-declarative-layout.md',
|
||||
'04-new-widgets.md',
|
||||
'16-using-cairo.md',
|
||||
'90-FAQ.md',
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue