[gegl] bin: bundle used luajit ffi bindings



commit 22f07ad39657ce2d5006b0f974b206b44ddb7f4e
Author: Øyvind Kolås <pippin gimp org>
Date:   Tue Feb 26 18:17:42 2019 +0100

    bin: bundle used luajit ffi bindings
    
    In the C code we now also look for lua packages in the install path for GEGL
    lua files.

 bin/lua/cairo.lua   |  936 +++++++++++++++++++++++++++++++++
 bin/lua/cairo_h.lua | 1270 +++++++++++++++++++++++++++++++++++++++++++++
 bin/lua/mime.lua    |   76 +++
 bin/lua/mrg.lua     | 1423 +++++++++++++++++++++++++++++++++++++++++++++++++++
 bin/lua/mrl.lua     |  146 ++++++
 bin/ui.c            |   23 +
 6 files changed, 3874 insertions(+)
---
diff --git a/bin/lua/cairo.lua b/bin/lua/cairo.lua
new file mode 100755
index 000000000..e129d6384
--- /dev/null
+++ b/bin/lua/cairo.lua
@@ -0,0 +1,936 @@
+--lightweight ffi binding for the cairo graphics library (Cosmin Apreutesei, public domain).
+
+--supports garbage collection, metatype methods, accepting and returning strings, returning multiple values
+--instead of passing output buffers, and API additions for completeness (drawing quad curves, getting
+--and setting pixel values etc).
+--note that methods from specific backends and extensions are not added and cannot be added after loading 
this
+--module due to limitations of ffi.metatype(). an exception is made for the pixman backend (image surface)
+--so that must be present in the cairo binary. still looking for a nice way to solve this.
+
+local ffi = require'ffi'
+require'cairo_h'
+local C = ffi.load'cairo'
+local M = setmetatable({C = C}, {__index = C})
+
+local function sym(name) return C[name] end
+local function if_exists(name) --return M[name] only if C[name] exists in the C library
+    return pcall(sym, name) and M[name] or nil
+end
+
+-- garbage collector / ref'counting integration
+-- note: free() and destroy() do not return a value as to enable the idiom self.obj = self.obj:free().
+
+local function free_ref_counted(o)
+       local n = o:get_reference_count() - 1
+       o:destroy()
+       if n ~= 0  then
+               error(string.format('refcount of %s is %d, should be 0', tostring(o), n))
+       end
+end
+
+function M.cairo_destroy(cr)
+       ffi.gc(cr, nil)
+       C.cairo_destroy(cr)
+end
+
+function M.cairo_surface_destroy(surface)
+       ffi.gc(surface, nil)
+       C.cairo_surface_destroy(surface)
+end
+
+function M.cairo_device_destroy(device)
+       ffi.gc(device, nil)
+       C.cairo_device_destroy(device)
+end
+
+function M.cairo_pattern_destroy(pattern)
+       ffi.gc(pattern, nil)
+       C.cairo_pattern_destroy(pattern)
+end
+
+function M.cairo_scaled_font_destroy(font)
+       ffi.gc(font, nil)
+       C.cairo_scaled_font_destroy(font)
+end
+
+function M.cairo_font_face_destroy(ff)
+       ffi.gc(ff, nil)
+       C.cairo_font_face_destroy(ff)
+end
+
+function M.cairo_font_options_destroy(ff)
+       ffi.gc(ff, nil)
+       C.cairo_font_options_destroy(ff)
+end
+
+function M.cairo_region_destroy(region)
+       ffi.gc(region, nil)
+       C.cairo_region_destroy(region)
+end
+
+function M.cairo_path_destroy(path)
+       ffi.gc(path, nil)
+       C.cairo_path_destroy(path)
+end
+
+function M.cairo_rectangle_list_destroy(rl)
+       ffi.gc(rl, nil)
+       C.cairo_rectangle_list_destroy(rl)
+end
+
+function M.cairo_glyph_free(c)
+       ffi.gc(c, nil)
+       C.cairo_glyph_free(c)
+end
+
+function M.cairo_text_cluster_free(c)
+       ffi.gc(c, nil)
+       C.cairo_text_cluster_free(c)
+end
+
+function M.cairo_create(...)
+       return ffi.gc(C.cairo_create(...), M.cairo_destroy)
+end
+
+function M.cairo_reference(...)
+       return ffi.gc(C.cairo_reference(...), M.cairo_destroy)
+end
+
+function M.cairo_pop_group(...)
+       return ffi.gc(C.cairo_pop_group(...), M.cairo_pattern_destroy)
+end
+
+local function check_surface(surface)
+       assert(surface:status() == C.CAIRO_STATUS_SUCCESS, surface:status_string())
+       return surface
+end
+
+function M.cairo_surface_create_similar(...)
+       return ffi.gc(check_surface(C.cairo_surface_create_similar(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_surface_create_similar_image(...)
+       return ffi.gc(check_surface(C.cairo_surface_create_similar_image(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_surface_create_for_rectangle(...)
+       return ffi.gc(check_surface(C.cairo_surface_create_for_rectangle(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_surface_create_for_data(...)
+       return ffi.gc(check_surface(C.cairo_surface_create_for_data(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_surface_create_observer(...)
+       return ffi.gc(check_surface(C.cairo_surface_create_observer(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_surface_reference(...)
+       return ffi.gc(C.cairo_surface_reference(...), M.cairo_surface_destroy)
+end
+
+function M.cairo_image_surface_create(...)
+       return ffi.gc(check_surface(C.cairo_image_surface_create(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_image_surface_create_for_data(...)
+       return ffi.gc(check_surface(C.cairo_image_surface_create_for_data(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_image_surface_create_from_png(...)
+       return ffi.gc(check_surface(C.cairo_image_surface_create_from_png(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_image_surface_create_from_png_stream(...)
+       return ffi.gc(check_surface(C.cairo_image_surface_create_from_png_stream(...)), 
M.cairo_surface_destroy)
+end
+
+function M.cairo_recording_surface_create(...)
+       return ffi.gc(check_surface(C.cairo_recording_surface_create(...)), M.cairo_surface_destroy)
+end
+
+function M.cairo_device_reference(...)
+       return ffi.gc(C.cairo_device_reference(...), M.cairo_device_destroy)
+end
+
+function M.cairo_pattern_create_raster_source(...)
+       return ffi.gc(C.cairo_pattern_create_raster_source(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_create_rgb(...)
+       return ffi.gc(C.cairo_pattern_create_rgb(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_create_rgba(...)
+       return ffi.gc(C.cairo_pattern_create_rgba(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_create_for_surface(...)
+       return ffi.gc(C.cairo_pattern_create_for_surface(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_create_linear(...)
+       return ffi.gc(C.cairo_pattern_create_linear(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_create_radial(...)
+       return ffi.gc(C.cairo_pattern_create_radial(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_create_mesh(...)
+       return ffi.gc(C.cairo_pattern_create_mesh(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_pattern_reference(...)
+       return ffi.gc(C.cairo_pattern_reference(...), M.cairo_pattern_destroy)
+end
+
+function M.cairo_scaled_font_create(...)
+       return ffi.gc(C.cairo_scaled_font_create(...), M.cairo_scaled_font_destroy)
+end
+
+function M.cairo_scaled_font_reference(...)
+       return ffi.gc(C.cairo_scaled_font_reference(...), M.cairo_scaled_font_destroy)
+end
+
+function M.cairo_toy_font_face_create(...)
+       return ffi.gc(C.cairo_toy_font_face_create(...), M.cairo_font_face_destroy)
+end
+
+function M.cairo_user_font_face_create(...)
+       return ffi.gc(C.cairo_user_font_face_create(...), M.cairo_font_face_destroy)
+end
+
+function M.cairo_font_face_reference(...)
+       return ffi.gc(C.cairo_font_face_reference(...), M.cairo_font_face_destroy)
+end
+
+function M.cairo_font_options_create(...)
+       return ffi.gc(C.cairo_font_options_create(...), M.cairo_font_options_destroy)
+end
+
+function M.cairo_region_create(...)
+       return ffi.gc(C.cairo_region_create(...), M.cairo_region_destroy)
+end
+
+function M.cairo_region_create_rectangle(...)
+       return ffi.gc(C.cairo_region_create_rectangle(...), M.cairo_region_destroy)
+end
+
+function M.cairo_region_create_rectangles(...)
+       return ffi.gc(C.cairo_region_create_rectangles(...), M.cairo_region_destroy)
+end
+
+function M.cairo_region_copy(...)
+       return ffi.gc(C.cairo_region_copy(...), M.cairo_region_destroy)
+end
+
+function M.cairo_region_reference(...)
+       return ffi.gc(C.cairo_region_reference(...), M.cairo_region_destroy)
+end
+
+function M.cairo_copy_path(...)
+       return ffi.gc(C.cairo_copy_path(...), M.cairo_path_destroy)
+end
+
+function M.cairo_copy_path_flat(...)
+       return ffi.gc(C.cairo_copy_path_flat(...), M.cairo_path_destroy)
+end
+
+function M.cairo_copy_clip_rectangle_list(...)
+       return ffi.gc(C.cairo_copy_clip_rectangle_list(...), M.cairo_rectangle_list_destroy)
+end
+
+function M.cairo_glyph_allocate(...)
+       return ffi.gc(C.cairo_glyph_allocate(...), M.cairo_glyph_free)
+end
+
+function M.cairo_text_cluster_allocate(...)
+       return ffi.gc(C.cairo_text_cluster_allocate(...), M.cairo_text_cluster_free)
+end
+
+-- char* return -> string return
+
+function M.cairo_version_string()
+       return ffi.string(C.cairo_version_string())
+end
+
+function M.cairo_status_to_string(status)
+       return ffi.string(C.cairo_status_to_string(status))
+end
+
+local function status_string(self)
+       return M.cairo_status_to_string(self:status())
+end
+
+-- int return -> bool return
+
+local function returns_bool(f)
+       return f and function(...)
+               return f(...) ~= 0
+       end
+end
+
+M.cairo_in_stroke = returns_bool(M.cairo_in_stroke)
+M.cairo_in_fill = returns_bool(M.cairo_in_fill)
+M.cairo_in_clip = returns_bool(M.cairo_in_clip)
+M.cairo_has_current_point = returns_bool(M.cairo_has_current_point)
+M.cairo_surface_has_show_text_glyphs = returns_bool(M.cairo_surface_has_show_text_glyphs)
+M.cairo_font_options_equal = returns_bool(M.cairo_font_options_equal)
+M.cairo_region_equal = returns_bool(M.cairo_region_equal)
+M.cairo_region_is_empty = returns_bool(M.cairo_region_is_empty)
+M.cairo_region_contains_point = returns_bool(M.cairo_region_contains_point)
+
+-- return multiple values instead of passing output buffers
+
+function M.cairo_get_matrix(cr, mt)
+       mt = mt or ffi.new'cairo_matrix_t'
+       C.cairo_get_matrix(cr, mt)
+       return mt
+end
+
+function M.cairo_pattern_get_matrix(pat, mt)
+       mt = mt or ffi.new'cairo_matrix_t'
+       C.cairo_pattern_get_matrix(pat, mt)
+       return mt
+end
+
+function M.cairo_get_current_point(cr, dx, dy)
+       dx = dx or ffi.new'double[1]'
+       dy = dy or ffi.new'double[1]'
+       C.cairo_get_current_point(cr, dx, dy)
+       return dx[0], dy[0]
+end
+
+local function extents_function(f)
+       return function(cr, dx1, dy1, dx2, dy2)
+               dx1 = dx1 or ffi.new'double[1]'
+               dy1 = dy1 or ffi.new'double[1]'
+               dx2 = dx2 or ffi.new'double[1]'
+               dy2 = dy2 or ffi.new'double[1]'
+               f(cr, dx1, dy1, dx2, dy2)
+               return dx1[0], dy1[0], dx2[0], dy2[0]
+       end
+end
+
+M.cairo_clip_extents = extents_function(C.cairo_clip_extents)
+M.cairo_fill_extents = extents_function(C.cairo_fill_extents)
+M.cairo_stroke_extents = extents_function(C.cairo_stroke_extents)
+M.cairo_path_extents = extents_function(C.cairo_path_extents)
+
+function M.cairo_pattern_get_surface(self, surface)
+       surface = surface or ffi.new'cairo_surface_t*[1]'
+       C.cairo_pattern_get_surface(self, surface)
+       return surface[0]
+end
+
+local function point_transform_function(f)
+       return function(cr, x, y, dx, dy)
+               dx = dx or ffi.new('double[1]', x)
+               dy = dy or ffi.new('double[1]', y)
+               f(cr, dx, dy)
+               return dx[0], dy[0]
+       end
+end
+
+M.cairo_device_to_user = point_transform_function(C.cairo_device_to_user)
+M.cairo_user_to_device = point_transform_function(C.cairo_user_to_device)
+M.cairo_user_to_device_distance = point_transform_function(C.cairo_user_to_device_distance)
+M.cairo_device_to_user_distance = point_transform_function(C.cairo_device_to_user_distance)
+
+function M.cairo_text_extents(cr, s, extents)
+       extents = extents or ffi.new'cairo_text_extents_t'
+       C.cairo_text_extents(cr, s, extents)
+       return extents
+end
+
+function M.cairo_glyph_extents(cr, glyphs, num_glyphs, extents)
+       extents = extents or ffi.new'cairo_text_extents_t'
+       C.cairo_glyph_extents(cr, glyphs, num_glyphs, extents)
+       return extents
+end
+
+function M.cairo_font_extents(cr, extents)
+       extents = extents or ffi.new'cairo_font_extents_t'
+       C.cairo_font_extents(cr, extents)
+       return extents
+end
+
+-- quad beziers addition
+
+function M.cairo_quad_curve_to(cr, x1, y1, x2, y2)
+       local x0, y0 = cr:get_current_point()
+       cr:curve_to((x0 + 2 * x1) / 3,
+                                       (y0 + 2 * y1) / 3,
+                                       (x2 + 2 * x1) / 3,
+                                       (y2 + 2 * y1) / 3,
+                                       x2, y2)
+end
+
+function M.cairo_rel_quad_curve_to(cr, x1, y1, x2, y2)
+       local x0, y0 = cr:get_current_point()
+       M.cairo_quad_curve_to(cr, x0+x1, y0+y1, x0+x2, y0+y2)
+end
+
+-- arcs addition
+
+local pi = math.pi
+function M.cairo_circle(cr, cx, cy, r)
+       cr:new_sub_path()
+       cr:arc(cx, cy, r, 0, 2 * pi)
+       cr:close_path()
+end
+
+function M.cairo_ellipse(cr, cx, cy, rx, ry, rotation)
+       local mt = cr:get_matrix()
+       cr:translate(cx, cy)
+       if rotation then cr:rotate(rotation) end
+       cr:scale(1, ry/rx)
+       cr:circle(0, 0, rx)
+       cr:set_matrix(mt)
+end
+
+-- matrix additions
+
+function M.cairo_matrix_transform(dmt, mt)
+       dmt:multiply(mt, dmt)
+       return dmt
+end
+
+function M.cairo_matrix_invertible(mt, tmt)
+       tmt = tmt or ffi.new'cairo_matrix_t'
+       ffi.copy(tmt, mt, ffi.sizeof(mt))
+       return tmt:invert() == 0
+end
+
+function M.cairo_matrix_safe_transform(dmt, mt)
+       if mt:invertible() then dmt:transform(mt) end
+end
+
+function M.cairo_matrix_skew(mt, ax, ay)
+       local sm = ffi.new'cairo_matrix_t'
+       sm:init_identity()
+       sm.xy = math.tan(ax)
+       sm.yx = math.tan(ay)
+       mt:transform(sm)
+end
+
+function M.cairo_matrix_rotate_around(mt, cx, cy, angle)
+       mt:translate(cx, cy)
+       mt:rotate(angle)
+       mt:translate(-cx, -cy)
+end
+
+function M.cairo_matrix_scale_around(mt, cx, cy, ...)
+       mt:translate(cx, cy)
+       mt:scale(...)
+       mt:translate(-cx, -cy)
+end
+
+function M.cairo_matrix_copy(mt)
+       local dmt = ffi.new'cairo_matrix_t'
+       ffi.copy(dmt, mt, ffi.sizeof(mt))
+       return dmt
+end
+
+function M.cairo_matrix_init_matrix(dmt, mt)
+       ffi.copy(dmt, mt, ffi.sizeof(mt))
+end
+
+-- context additions
+
+function M.cairo_safe_transform(cr, mt)
+       if mt:invertible() then cr:transform(mt) end
+end
+
+function M.cairo_rotate_around(cr, cx, cy, angle)
+       M.cairo_translate(cr, cx, cy)
+       M.cairo_rotate(cr, angle)
+       M.cairo_translate(cr, -cx, -cy)
+end
+
+function M.cairo_scale_around(cr, cx, cy, ...)
+       M.cairo_translate(cr, cx, cy)
+       M.cairo_scale(cr, ...)
+       M.cairo_translate(cr, -cx, -cy)
+end
+
+function M.cairo_skew(cr, ax, ay)
+       local sm = ffi.new'cairo_matrix_t'
+       sm:init_identity()
+       sm.xy = math.tan(ax)
+       sm.yx = math.tan(ay)
+       cr:transform(sm)
+end
+
+-- surface additions
+
+function M.cairo_surface_apply_alpha(surface, alpha)
+       if alpha >= 1 then return end
+       local cr = surface:create_context()
+       cr:set_source_rgba(0,0,0,alpha)
+       cr:set_operator(cairo.CAIRO_OPERATOR_DEST_IN) --alphas are multiplied, dest. color is preserved
+       cr:paint()
+       cr:free()
+end
+
+local image_surface_bpp = {
+    [C.CAIRO_FORMAT_ARGB32] = 32,
+    [C.CAIRO_FORMAT_RGB24] = 32,
+    [C.CAIRO_FORMAT_A8] = 8,
+    [C.CAIRO_FORMAT_A1] = 1,
+    [C.CAIRO_FORMAT_RGB16_565] = 16,
+    [C.CAIRO_FORMAT_RGB30] = 30,
+}
+
+function M.cairo_image_surface_get_bpp(surface)
+       return image_surface_bpp[tonumber(surface:get_image_format())]
+end
+
+--return a getpixel function for a surface that returns pixel components based on surface image format:
+--for ARGB32: getpixel(x, y) -> r, g, b, a
+--for RGB24:  getpixel(x, y) -> r, g, b
+--for A8:     getpixel(x, y) -> a
+--for A1:     getpixel(x, y) -> a
+--for RGB16:  getpixel(x, y) -> r, g, b
+--for RGB30:  getpixel(x, y) -> r, g, b
+function M.cairo_image_surface_get_pixel_function(surface)
+       local data   = surface:get_image_data()
+       local format = surface:get_image_format()
+       local w      = surface:get_image_width()
+       local h      = surface:get_image_height()
+       local stride = surface:get_image_stride()
+       local getpixel
+       data = ffi.cast('uint8_t*', data)
+       if format == C.CAIRO_FORMAT_ARGB32 then
+               if ffi.abi'le' then
+                       error'NYI'
+               else
+                       error'NYI'
+               end
+       elseif format == C.CAIRO_FORMAT_RGB24 then
+               function getpixel(x, y)
+                       assert(x < w and y < h and x >= 0 and y >= 0, 'out of range')
+                       return
+                               data[y * stride + x * 4 + 2],
+                               data[y * stride + x * 4 + 1],
+                               data[y * stride + x * 4 + 0]
+               end
+       elseif format == C.CAIRO_FORMAT_A8 then
+               function getpixel(x, y)
+                       assert(x < w and y < h and x >= 0 and y >= 0, 'out of range')
+                       return data[y * stride + x]
+               end
+       elseif format == C.CAIRO_FORMAT_A1 then
+               if ffi.abi'le' then
+                       error'NYI'
+               else
+                       error'NYI'
+               end
+       elseif format == C.CAIRO_FORMAT_RGB16_565 then
+               error'NYI'
+       elseif format == C.CAIRO_FORMAT_RGB30 then
+               error'NYI'
+       else
+               error'unsupported image format'
+       end
+       return getpixel
+end
+
+--return a setpixel function analog to getpixel above.
+function M.cairo_image_surface_set_pixel_function(surface)
+       local data   = surface:get_image_data()
+       local format = surface:get_image_format()
+       local w      = surface:get_image_width()
+       local h      = surface:get_image_height()
+       local stride = surface:get_image_stride()
+       data = ffi.cast('uint8_t*', data)
+       local setpixel
+       if format == C.CAIRO_FORMAT_ARGB32 then
+               if ffi.abi'le' then
+                       error'NYI'
+               else
+                       error'NYI'
+               end
+       elseif format == C.CAIRO_FORMAT_RGB24 then
+               function setpixel(x, y, r, g, b)
+                       assert(x < w and y < h and x >= 0 and y >= 0, 'out of range')
+                       data[y * stride + x * 4 + 2] = r
+                       data[y * stride + x * 4 + 1] = g
+                       data[y * stride + x * 4 + 0] = b
+               end
+       elseif format == C.CAIRO_FORMAT_A8 then
+               function setpixel(x, y, a)
+                       assert(x < w and y < h and x >= 0 and y >= 0, 'out of range')
+                       data[y * stride + x] = a
+               end
+       elseif format == C.CAIRO_FORMAT_A1 then
+               if ffi.abi'le' then
+                       error'NYI'
+               else
+                       error'NYI'
+               end
+       elseif format == C.CAIRO_FORMAT_RGB16_565 then
+               error'NYI'
+       elseif format == C.CAIRO_FORMAT_RGB30 then
+               error'NYI'
+       else
+               error'unsupported image format'
+       end
+       return setpixel
+end
+
+-- metamethods
+
+ffi.metatype('cairo_t', {__index = {
+       reference = M.cairo_reference,
+       destroy = M.cairo_destroy,
+       free = free_ref_counted,
+       get_reference_count = M.cairo_get_reference_count,
+       get_user_data = M.cairo_get_user_data,
+       set_user_data = M.cairo_set_user_data,
+       save = M.cairo_save,
+       restore = M.cairo_restore,
+       push_group = M.cairo_push_group,
+       push_group_with_content = M.cairo_push_group_with_content,
+       pop_group = M.cairo_pop_group,
+       pop_group_to_source = M.cairo_pop_group_to_source,
+       set_operator = M.cairo_set_operator,
+       set_source = M.cairo_set_source,
+       set_source_rgb = M.cairo_set_source_rgb,
+       set_source_rgba = M.cairo_set_source_rgba,
+       set_source_surface = M.cairo_set_source_surface,
+       set_tolerance = M.cairo_set_tolerance,
+       set_antialias = M.cairo_set_antialias,
+       set_fill_rule = M.cairo_set_fill_rule,
+       set_line_width = M.cairo_set_line_width,
+       set_line_cap = M.cairo_set_line_cap,
+       set_line_join = M.cairo_set_line_join,
+       set_dash = M.cairo_set_dash,
+       set_miter_limit = M.cairo_set_miter_limit,
+       translate = M.cairo_translate,
+       scale = M.cairo_scale,
+       rotate = M.cairo_rotate,
+       rotate_around = M.cairo_rotate_around,
+       scale_around = M.cairo_scale_around,
+       transform = M.cairo_transform,
+       safe_transform = M.cairo_safe_transform,
+       set_matrix = M.cairo_set_matrix,
+       identity_matrix = M.cairo_identity_matrix,
+       skew = M.cairo_skew,
+       user_to_device = M.cairo_user_to_device,
+       user_to_device_distance = M.cairo_user_to_device_distance,
+       device_to_user = M.cairo_device_to_user,
+       device_to_user_distance = M.cairo_device_to_user_distance,
+       new_path = M.cairo_new_path,
+       move_to = M.cairo_move_to,
+       new_sub_path = M.cairo_new_sub_path,
+       line_to = M.cairo_line_to,
+       curve_to = M.cairo_curve_to,
+       quad_curve_to = M.cairo_quad_curve_to,
+       arc = M.cairo_arc,
+       arc_negative = M.cairo_arc_negative,
+       circle = M.cairo_circle,
+       ellipse = M.cairo_ellipse,
+       --arc_to = M.cairo_arc_to, --abandoned? cairo_arc_to(x1, y1, x2, y2, radius)
+       rel_move_to = M.cairo_rel_move_to,
+       rel_line_to = M.cairo_rel_line_to,
+       rel_curve_to = M.cairo_rel_curve_to,
+       rel_quad_curve_to = M.cairo_rel_quad_curve_to,
+       rectangle = M.cairo_rectangle,
+       --stroke_to_path = M.cairo_stroke_to_path, --abandoned :(
+       close_path = M.cairo_close_path,
+       path_extents = M.cairo_path_extents,
+       paint = M.cairo_paint,
+       paint_with_alpha = M.cairo_paint_with_alpha,
+       mask = M.cairo_mask,
+       mask_surface = M.cairo_mask_surface,
+       stroke = M.cairo_stroke,
+       stroke_preserve = M.cairo_stroke_preserve,
+       fill = M.cairo_fill,
+       fill_preserve = M.cairo_fill_preserve,
+       copy_page = M.cairo_copy_page,
+       show_page = M.cairo_show_page,
+       in_stroke = M.cairo_in_stroke,
+       in_fill = M.cairo_in_fill,
+       in_clip = M.cairo_in_clip,
+       stroke_extents = M.cairo_stroke_extents,
+       fill_extents = M.cairo_fill_extents,
+       reset_clip = M.cairo_reset_clip,
+       clip = M.cairo_clip,
+       clip_preserve = M.cairo_clip_preserve,
+       clip_extents = M.cairo_clip_extents,
+       copy_clip_rectangle_list = M.cairo_copy_clip_rectangle_list,
+       select_font_face = M.cairo_select_font_face,
+       set_font_size = M.cairo_set_font_size,
+       set_font_matrix = M.cairo_set_font_matrix,
+       get_font_matrix = M.cairo_get_font_matrix,
+       set_font_options = M.cairo_set_font_options,
+       get_font_options = M.cairo_get_font_options,
+       set_font_face = M.cairo_set_font_face,
+       get_font_face = M.cairo_get_font_face,
+       set_scaled_font = M.cairo_set_scaled_font,
+       get_scaled_font = M.cairo_get_scaled_font,
+       show_text = M.cairo_show_text,
+       show_glyphs = M.cairo_show_glyphs,
+       show_text_glyphs = M.cairo_show_text_glyphs,
+       text_path = M.cairo_text_path,
+       glyph_path = M.cairo_glyph_path,
+       text_extents = M.cairo_text_extents,
+       glyph_extents = M.cairo_glyph_extents,
+       font_extents = M.cairo_font_extents,
+       get_operator = M.cairo_get_operator,
+       get_source = M.cairo_get_source,
+       get_tolerance = M.cairo_get_tolerance,
+       get_antialias = M.cairo_get_antialias,
+       has_current_point = M.cairo_has_current_point,
+       get_current_point = M.cairo_get_current_point,
+       get_fill_rule = M.cairo_get_fill_rule,
+       get_line_width = M.cairo_get_line_width,
+       get_line_cap = M.cairo_get_line_cap,
+       get_line_join = M.cairo_get_line_join,
+       get_miter_limit = M.cairo_get_miter_limit,
+       get_dash_count = M.cairo_get_dash_count,
+       get_dash = M.cairo_get_dash,
+       get_matrix = M.cairo_get_matrix,
+       get_target = M.cairo_get_target,
+       get_group_target = M.cairo_get_group_target,
+       copy_path = M.cairo_copy_path,
+       copy_path_flat = M.cairo_copy_path_flat,
+       append_path = M.cairo_append_path,
+       status = M.cairo_status,
+       status_string = status_string,
+}})
+
+ffi.metatype('cairo_surface_t', {__index = {
+       create_context = M.cairo_create,
+       create_similar = M.cairo_surface_create_similar,
+       create_for_rectangle = M.cairo_surface_create_for_rectangle,
+       reference = M.cairo_surface_reference,
+       finish = M.cairo_surface_finish,
+       destroy = M.cairo_surface_destroy,
+       free = free_ref_counted,
+       get_device = M.cairo_surface_get_device,
+       get_reference_count = M.cairo_surface_get_reference_count,
+       status = M.cairo_surface_status,
+       status_string = status_string,
+       get_type = M.cairo_surface_get_type,
+       get_content = M.cairo_surface_get_content,
+       write_to_png = M.cairo_surface_write_to_png,
+       write_to_png_stream = M.cairo_surface_write_to_png_stream,
+       get_user_data = M.cairo_surface_get_user_data,
+       set_user_data = M.cairo_surface_set_user_data,
+       get_mime_data = M.cairo_surface_get_mime_data,
+       set_mime_data = M.cairo_surface_set_mime_data,
+       get_font_options = M.cairo_surface_get_font_options,
+       flush = M.cairo_surface_flush,
+       mark_dirty = M.cairo_surface_mark_dirty,
+       mark_dirty_rectangle = M.cairo_surface_mark_dirty_rectangle,
+       set_device_offset = M.cairo_surface_set_device_offset,
+       get_device_offset = M.cairo_surface_get_device_offset,
+       set_fallback_resolution = M.cairo_surface_set_fallback_resolution,
+       get_fallback_resolution = M.cairo_surface_get_fallback_resolution,
+       copy_page = M.cairo_surface_copy_page,
+       show_page = M.cairo_surface_show_page,
+       has_show_text_glyphs = M.cairo_surface_has_show_text_glyphs,
+       create_pattern = M.cairo_pattern_create_for_surface,
+       apply_alpha = M.cairo_surface_apply_alpha,
+
+       --for image surfaces
+       get_image_data = M.cairo_image_surface_get_data,
+       get_image_format = M.cairo_image_surface_get_format,
+       get_image_width = M.cairo_image_surface_get_width,
+       get_image_height = M.cairo_image_surface_get_height,
+       get_image_stride = M.cairo_image_surface_get_stride,
+       get_image_bpp = M.cairo_image_surface_get_bpp,
+       get_image_pixel_function = M.cairo_image_surface_get_pixel_function,
+       set_image_pixel_function = M.cairo_image_surface_set_pixel_function,
+}})
+
+ffi.metatype('cairo_device_t', {__index = {
+       reference = M.cairo_device_reference,
+       get_type = M.cairo_device_get_type,
+       status = M.cairo_device_status,
+       status_string = status_string,
+       acquire = M.cairo_device_acquire,
+       release = M.cairo_device_release,
+       flush = M.cairo_device_flush,
+       finish = M.cairo_device_finish,
+       destroy = M.cairo_device_destroy,
+       free = free_ref_counted,
+       get_reference_count = M.cairo_device_get_reference_count,
+       get_user_data = M.cairo_device_get_user_data,
+       set_user_data = M.cairo_device_set_user_data,
+}})
+
+ffi.metatype('cairo_pattern_t', {__index = {
+       reference = M.cairo_pattern_reference,
+       destroy = M.cairo_pattern_destroy,
+       free = free_ref_counted,
+       get_reference_count = M.cairo_pattern_get_reference_count,
+       status = M.cairo_pattern_status,
+       status_string = status_string,
+       get_user_data = M.cairo_pattern_get_user_data,
+       set_user_data = M.cairo_pattern_set_user_data,
+       get_type = M.cairo_pattern_get_type,
+       add_color_stop_rgb = M.cairo_pattern_add_color_stop_rgb,
+       add_color_stop_rgba = M.cairo_pattern_add_color_stop_rgba,
+       set_matrix = M.cairo_pattern_set_matrix,
+       get_matrix = M.cairo_pattern_get_matrix,
+       set_extend = M.cairo_pattern_set_extend,
+       get_extend = M.cairo_pattern_get_extend,
+       set_filter = M.cairo_pattern_set_filter,
+       get_filter = M.cairo_pattern_get_filter,
+       get_rgba = M.cairo_pattern_get_rgba,
+       get_surface = M.cairo_pattern_get_surface,
+       get_color_stop_rgba = M.cairo_pattern_get_color_stop_rgba,
+       get_color_stop_count = M.cairo_pattern_get_color_stop_count,
+       get_linear_points = M.cairo_pattern_get_linear_points,
+       get_radial_circles = M.cairo_pattern_get_radial_circles,
+}})
+
+ffi.metatype('cairo_scaled_font_t', {__index = {
+       reference = M.cairo_scaled_font_reference,
+       destroy = M.cairo_scaled_font_destroy,
+       free = free_ref_counted,
+       get_reference_count = M.cairo_scaled_font_get_reference_count,
+       status = M.cairo_scaled_font_status,
+       status_string = status_string,
+       get_type = M.cairo_scaled_font_get_type,
+       get_user_data = M.cairo_scaled_font_get_user_data,
+       set_user_data = M.cairo_scaled_font_set_user_data,
+       extents = M.cairo_scaled_font_extents,
+       text_extents = M.cairo_scaled_font_text_extents,
+       glyph_extents = M.cairo_scaled_font_glyph_extents,
+       text_to_glyphs = M.cairo_scaled_font_text_to_glyphs,
+       get_font_face = M.cairo_scaled_font_get_font_face,
+       get_font_matrix = M.cairo_scaled_font_get_font_matrix,
+       get_ctm = M.cairo_scaled_font_get_ctm,
+       get_scale_matrix = M.cairo_scaled_font_get_scale_matrix,
+       get_font_options = M.cairo_scaled_font_get_font_options,
+}})
+
+ffi.metatype('cairo_font_face_t', {__index = {
+       reference = M.cairo_font_face_reference,
+       destroy = M.cairo_font_face_destroy,
+       free = free_ref_counted,
+       get_reference_count = M.cairo_font_face_get_reference_count,
+       status = M.cairo_font_face_status,
+       status_string = status_string,
+       get_type = M.cairo_font_face_get_type,
+       get_user_data = M.cairo_font_face_get_user_data,
+       set_user_data = M.cairo_font_face_set_user_data,
+       create_scaled_font = M.cairo_scaled_font_create,
+       toy_get_family = M.cairo_toy_font_face_get_family,
+       toy_get_slant = M.cairo_toy_font_face_get_slant,
+       toy_get_weight = M.cairo_toy_font_face_get_weight,
+       user_set_init_func = M.cairo_user_font_face_set_init_func,
+       user_set_render_glyph_func = M.cairo_user_font_face_set_render_glyph_func,
+       user_set_text_to_glyphs_func = M.cairo_user_font_face_set_text_to_glyphs_func,
+       user_set_unicode_to_glyph_func = M.cairo_user_font_face_set_unicode_to_glyph_func,
+       user_get_init_func = M.cairo_user_font_face_get_init_func,
+       user_get_render_glyph_func = M.cairo_user_font_face_get_render_glyph_func,
+       user_get_text_to_glyphs_func = M.cairo_user_font_face_get_text_to_glyphs_func,
+       user_get_unicode_to_glyph_func = M.cairo_user_font_face_get_unicode_to_glyph_func,
+}})
+
+ffi.metatype('cairo_font_options_t', {__index = {
+       copy = M.cairo_font_options_copy,
+       free = M.cairo_font_options_destroy,
+       status = M.cairo_font_options_status,
+       status_string = status_string,
+       merge = M.cairo_font_options_merge,
+       equal = M.cairo_font_options_equal,
+       hash = M.cairo_font_options_hash,
+       set_antialias = M.cairo_font_options_set_antialias,
+       get_antialias = M.cairo_font_options_get_antialias,
+       set_subpixel_order = M.cairo_font_options_set_subpixel_order,
+       get_subpixel_order = M.cairo_font_options_get_subpixel_order,
+       set_hint_style = M.cairo_font_options_set_hint_style,
+       get_hint_style = M.cairo_font_options_get_hint_style,
+       set_hint_metrics = M.cairo_font_options_set_hint_metrics,
+       get_hint_metrics = M.cairo_font_options_get_hint_metrics,
+       --private functions, only available in our custom build
+       set_lcd_filter = if_exists'_cairo_font_options_set_lcd_filter',
+       get_lcd_filter = if_exists'_cairo_font_options_get_lcd_filter',
+       set_round_glyph_positions = if_exists'_cairo_font_options_set_round_glyph_positions',
+       get_round_glyph_positions = if_exists'_cairo_font_options_get_round_glyph_positions',
+}})
+
+ffi.metatype('cairo_region_t', {__index = {
+       create = M.cairo_region_create,
+       create_rectangle = M.cairo_region_create_rectangle,
+       create_rectangles = M.cairo_region_create_rectangles,
+       copy = M.cairo_region_copy,
+       reference = M.cairo_region_reference,
+       destroy = M.cairo_region_destroy,
+       free = free_ref_counted,
+       equal = M.cairo_region_equal,
+       status = M.cairo_region_status,
+       status_string = status_string,
+       get_extents = M.cairo_region_get_extents,
+       num_rectangles = M.cairo_region_num_rectangles,
+       get_rectangle = M.cairo_region_get_rectangle,
+       is_empty = M.cairo_region_is_empty,
+       contains_rectangle = M.cairo_region_contains_rectangle,
+       contains_point = M.cairo_region_contains_point,
+       translate = M.cairo_region_translate,
+       subtract = M.cairo_region_subtract,
+       subtract_rectangle = M.cairo_region_subtract_rectangle,
+       intersect = M.cairo_region_intersect,
+       intersect_rectangle = M.cairo_region_intersect_rectangle,
+       union = M.cairo_region_union,
+       union_rectangle = M.cairo_region_union_rectangle,
+       xor = M.cairo_region_xor,
+       xor_rectangle = M.cairo_region_xor_rectangle,
+}})
+
+ffi.metatype('cairo_path_t', {__index = {
+       free = M.cairo_path_destroy,
+}})
+
+ffi.metatype('cairo_rectangle_list_t', {__index = {
+       free = M.cairo_rectangle_list_destroy,
+}})
+
+ffi.metatype('cairo_glyph_t', {__index = {
+       free = M.cairo_glyph_free,
+}})
+ffi.metatype('cairo_text_cluster_t', {__index = {
+       free = M.cairo_text_cluster_free,
+}})
+
+local function cairo_matrix_tostring(mt)
+       return string.format('[%12f%12f]\n[%12f%12f]\n[%12f%12f]',
+               mt.xx, mt.yx, mt.xy, mt.yy, mt.x0, mt.y0)
+end
+
+ffi.metatype('cairo_matrix_t', {__index = {
+       init = M.cairo_matrix_init,
+       init_identity = M.cairo_matrix_init_identity,
+       init_translate = M.cairo_matrix_init_translate,
+       init_scale = M.cairo_matrix_init_scale,
+       init_rotate = M.cairo_matrix_init_rotate,
+       translate = M.cairo_matrix_translate,
+       scale = M.cairo_matrix_scale,
+       rotate = M.cairo_matrix_rotate,
+       rotate_around = M.cairo_matrix_rotate_around,
+       scale_around = M.cairo_matrix_scale_around,
+       invert = M.cairo_matrix_invert,
+       multiply = M.cairo_matrix_multiply,
+       transform_distance = M.cairo_matrix_transform_distance,
+       transform_point = M.cairo_matrix_transform_point,
+       --additions
+       transform = M.cairo_matrix_transform,
+       invertible = M.cairo_matrix_invertible,
+       safe_transform = M.cairo_matrix_safe_transform,
+       skew = M.cairo_matrix_skew,
+       copy = M.cairo_matrix_copy,
+       init_matrix = M.cairo_matrix_init_matrix,
+}, __tostring = cairo_matrix_tostring})
+
+ffi.metatype('cairo_rectangle_int_t', {__index = {
+       create_region = M.cairo_region_create_rectangle,
+}})
+
+return M
diff --git a/bin/lua/cairo_h.lua b/bin/lua/cairo_h.lua
new file mode 100755
index 000000000..c5fee600e
--- /dev/null
+++ b/bin/lua/cairo_h.lua
@@ -0,0 +1,1270 @@
+--result of `cpp cairo.h` from cairo 1.12.3 (extensions in separate files)
+local ffi = require'ffi'
+ffi.cdef[[
+int cairo_version (void);
+const char* cairo_version_string (void);
+typedef int cairo_bool_t;
+typedef struct _cairo cairo_t;
+typedef struct _cairo_surface cairo_surface_t;
+typedef struct _cairo_device cairo_device_t;
+typedef struct _cairo_matrix {
+    double xx; double yx;
+    double xy; double yy;
+    double x0; double y0;
+} cairo_matrix_t;
+typedef struct _cairo_pattern cairo_pattern_t;
+typedef void (*cairo_destroy_func_t) (void *data);
+typedef struct _cairo_user_data_key {
+    int unused;
+} cairo_user_data_key_t;
+typedef enum _cairo_status {
+    CAIRO_STATUS_SUCCESS = 0,
+    CAIRO_STATUS_NO_MEMORY,
+    CAIRO_STATUS_INVALID_RESTORE,
+    CAIRO_STATUS_INVALID_POP_GROUP,
+    CAIRO_STATUS_NO_CURRENT_POINT,
+    CAIRO_STATUS_INVALID_MATRIX,
+    CAIRO_STATUS_INVALID_STATUS,
+    CAIRO_STATUS_NULL_POINTER,
+    CAIRO_STATUS_INVALID_STRING,
+    CAIRO_STATUS_INVALID_PATH_DATA,
+    CAIRO_STATUS_READ_ERROR,
+    CAIRO_STATUS_WRITE_ERROR,
+    CAIRO_STATUS_SURFACE_FINISHED,
+    CAIRO_STATUS_SURFACE_TYPE_MISMATCH,
+    CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
+    CAIRO_STATUS_INVALID_CONTENT,
+    CAIRO_STATUS_INVALID_FORMAT,
+    CAIRO_STATUS_INVALID_VISUAL,
+    CAIRO_STATUS_FILE_NOT_FOUND,
+    CAIRO_STATUS_INVALID_DASH,
+    CAIRO_STATUS_INVALID_DSC_COMMENT,
+    CAIRO_STATUS_INVALID_INDEX,
+    CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
+    CAIRO_STATUS_TEMP_FILE_ERROR,
+    CAIRO_STATUS_INVALID_STRIDE,
+    CAIRO_STATUS_FONT_TYPE_MISMATCH,
+    CAIRO_STATUS_USER_FONT_IMMUTABLE,
+    CAIRO_STATUS_USER_FONT_ERROR,
+    CAIRO_STATUS_NEGATIVE_COUNT,
+    CAIRO_STATUS_INVALID_CLUSTERS,
+    CAIRO_STATUS_INVALID_SLANT,
+    CAIRO_STATUS_INVALID_WEIGHT,
+    CAIRO_STATUS_INVALID_SIZE,
+    CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED,
+    CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
+    CAIRO_STATUS_DEVICE_ERROR,
+    CAIRO_STATUS_INVALID_MESH_CONSTRUCTION,
+    CAIRO_STATUS_DEVICE_FINISHED,
+    CAIRO_STATUS_LAST_STATUS
+} cairo_status_t;
+typedef enum _cairo_content {
+    CAIRO_CONTENT_COLOR = 0x1000,
+    CAIRO_CONTENT_ALPHA = 0x2000,
+    CAIRO_CONTENT_COLOR_ALPHA = 0x3000
+} cairo_content_t;
+typedef enum _cairo_format {
+    CAIRO_FORMAT_INVALID = -1,
+    CAIRO_FORMAT_ARGB32 = 0,
+    CAIRO_FORMAT_RGB24 = 1,
+    CAIRO_FORMAT_A8 = 2,
+    CAIRO_FORMAT_A1 = 3,
+    CAIRO_FORMAT_RGB16_565 = 4,
+    CAIRO_FORMAT_RGB30 = 5
+} cairo_format_t;
+typedef cairo_status_t (*cairo_write_func_t) (void *closure,
+           const void *data,
+           unsigned int length);
+typedef cairo_status_t (*cairo_read_func_t) (void *closure,
+          void *data,
+          unsigned int length);
+typedef struct _cairo_rectangle_int {
+    int x, y;
+    int width, height;
+} cairo_rectangle_int_t;
+ cairo_t *
+cairo_create (cairo_surface_t *target);
+ cairo_t *
+cairo_reference (cairo_t *cr);
+ void
+cairo_destroy (cairo_t *cr);
+ unsigned int
+cairo_get_reference_count (cairo_t *cr);
+ void *
+cairo_get_user_data (cairo_t *cr,
+       const cairo_user_data_key_t *key);
+ cairo_status_t
+cairo_set_user_data (cairo_t *cr,
+       const cairo_user_data_key_t *key,
+       void *user_data,
+       cairo_destroy_func_t destroy);
+ void
+cairo_save (cairo_t *cr);
+ void
+cairo_restore (cairo_t *cr);
+ void
+cairo_push_group (cairo_t *cr);
+ void
+cairo_push_group_with_content (cairo_t *cr, cairo_content_t content);
+ cairo_pattern_t *
+cairo_pop_group (cairo_t *cr);
+ void
+cairo_pop_group_to_source (cairo_t *cr);
+typedef enum _cairo_operator {
+    CAIRO_OPERATOR_CLEAR,
+    CAIRO_OPERATOR_SOURCE,
+    CAIRO_OPERATOR_OVER,
+    CAIRO_OPERATOR_IN,
+    CAIRO_OPERATOR_OUT,
+    CAIRO_OPERATOR_ATOP,
+    CAIRO_OPERATOR_DEST,
+    CAIRO_OPERATOR_DEST_OVER,
+    CAIRO_OPERATOR_DEST_IN,
+    CAIRO_OPERATOR_DEST_OUT,
+    CAIRO_OPERATOR_DEST_ATOP,
+    CAIRO_OPERATOR_XOR,
+    CAIRO_OPERATOR_ADD,
+    CAIRO_OPERATOR_SATURATE,
+    CAIRO_OPERATOR_MULTIPLY,
+    CAIRO_OPERATOR_SCREEN,
+    CAIRO_OPERATOR_OVERLAY,
+    CAIRO_OPERATOR_DARKEN,
+    CAIRO_OPERATOR_LIGHTEN,
+    CAIRO_OPERATOR_COLOR_DODGE,
+    CAIRO_OPERATOR_COLOR_BURN,
+    CAIRO_OPERATOR_HARD_LIGHT,
+    CAIRO_OPERATOR_SOFT_LIGHT,
+    CAIRO_OPERATOR_DIFFERENCE,
+    CAIRO_OPERATOR_EXCLUSION,
+    CAIRO_OPERATOR_HSL_HUE,
+    CAIRO_OPERATOR_HSL_SATURATION,
+    CAIRO_OPERATOR_HSL_COLOR,
+    CAIRO_OPERATOR_HSL_LUMINOSITY
+} cairo_operator_t;
+ void
+cairo_set_operator (cairo_t *cr, cairo_operator_t op);
+ void
+cairo_set_source (cairo_t *cr, cairo_pattern_t *source);
+ void
+cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue);
+ void
+cairo_set_source_rgba (cairo_t *cr,
+         double red, double green, double blue,
+         double alpha);
+ void
+cairo_set_source_surface (cairo_t *cr,
+     cairo_surface_t *surface,
+     double x,
+     double y);
+ void
+cairo_set_tolerance (cairo_t *cr, double tolerance);
+typedef enum _cairo_antialias {
+    CAIRO_ANTIALIAS_DEFAULT,
+    CAIRO_ANTIALIAS_NONE,
+    CAIRO_ANTIALIAS_GRAY,
+    CAIRO_ANTIALIAS_SUBPIXEL,
+    CAIRO_ANTIALIAS_FAST,
+    CAIRO_ANTIALIAS_GOOD,
+    CAIRO_ANTIALIAS_BEST
+} cairo_antialias_t;
+ void
+cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias);
+typedef enum _cairo_fill_rule {
+    CAIRO_FILL_RULE_WINDING,
+    CAIRO_FILL_RULE_EVEN_ODD
+} cairo_fill_rule_t;
+ void
+cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule);
+ void
+cairo_set_line_width (cairo_t *cr, double width);
+typedef enum _cairo_line_cap {
+    CAIRO_LINE_CAP_BUTT,
+    CAIRO_LINE_CAP_ROUND,
+    CAIRO_LINE_CAP_SQUARE
+} cairo_line_cap_t;
+ void
+cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap);
+typedef enum _cairo_line_join {
+    CAIRO_LINE_JOIN_MITER,
+    CAIRO_LINE_JOIN_ROUND,
+    CAIRO_LINE_JOIN_BEVEL
+} cairo_line_join_t;
+ void
+cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join);
+ void
+cairo_set_dash (cairo_t *cr,
+  const double *dashes,
+  int num_dashes,
+  double offset);
+ void
+cairo_set_miter_limit (cairo_t *cr, double limit);
+ void
+cairo_translate (cairo_t *cr, double tx, double ty);
+ void
+cairo_scale (cairo_t *cr, double sx, double sy);
+ void
+cairo_rotate (cairo_t *cr, double angle);
+ void
+cairo_transform (cairo_t *cr,
+   const cairo_matrix_t *matrix);
+ void
+cairo_set_matrix (cairo_t *cr,
+    const cairo_matrix_t *matrix);
+ void
+cairo_identity_matrix (cairo_t *cr);
+ 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_new_path (cairo_t *cr);
+ void
+cairo_move_to (cairo_t *cr, double x, double y);
+ void
+cairo_new_sub_path (cairo_t *cr);
+ void
+cairo_line_to (cairo_t *cr, double x, double y);
+ void
+cairo_curve_to (cairo_t *cr,
+  double x1, double y1,
+  double x2, double y2,
+  double x3, double y3);
+ void
+cairo_arc (cairo_t *cr,
+    double xc, double yc,
+    double radius,
+    double angle1, double angle2);
+ void
+cairo_arc_negative (cairo_t *cr,
+      double xc, double yc,
+      double radius,
+      double angle1, double angle2);
+ void
+cairo_rel_move_to (cairo_t *cr, double dx, double dy);
+ void
+cairo_rel_line_to (cairo_t *cr, double dx, double dy);
+ void
+cairo_rel_curve_to (cairo_t *cr,
+      double dx1, double dy1,
+      double dx2, double dy2,
+      double dx3, double dy3);
+ void
+cairo_rectangle (cairo_t *cr,
+   double x, double y,
+   double width, double height);
+ void
+cairo_close_path (cairo_t *cr);
+ void
+cairo_path_extents (cairo_t *cr,
+      double *x1, double *y1,
+      double *x2, double *y2);
+ void
+cairo_paint (cairo_t *cr);
+ void
+cairo_paint_with_alpha (cairo_t *cr,
+   double alpha);
+ 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);
+ void
+cairo_stroke (cairo_t *cr);
+ void
+cairo_stroke_preserve (cairo_t *cr);
+ void
+cairo_fill (cairo_t *cr);
+ void
+cairo_fill_preserve (cairo_t *cr);
+ void
+cairo_copy_page (cairo_t *cr);
+ void
+cairo_show_page (cairo_t *cr);
+ cairo_bool_t
+cairo_in_stroke (cairo_t *cr, double x, double y);
+ cairo_bool_t
+cairo_in_fill (cairo_t *cr, double x, double y);
+ cairo_bool_t
+cairo_in_clip (cairo_t *cr, double x, double y);
+ 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);
+ void
+cairo_reset_clip (cairo_t *cr);
+ void
+cairo_clip (cairo_t *cr);
+ void
+cairo_clip_preserve (cairo_t *cr);
+ void
+cairo_clip_extents (cairo_t *cr,
+      double *x1, double *y1,
+      double *x2, double *y2);
+typedef struct _cairo_rectangle {
+    double x, y, width, height;
+} cairo_rectangle_t;
+typedef struct _cairo_rectangle_list {
+    cairo_status_t status;
+    cairo_rectangle_t *rectangles;
+    int num_rectangles;
+} cairo_rectangle_list_t;
+ cairo_rectangle_list_t *
+cairo_copy_clip_rectangle_list (cairo_t *cr);
+ void
+cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list);
+typedef struct _cairo_scaled_font cairo_scaled_font_t;
+typedef struct _cairo_font_face cairo_font_face_t;
+typedef struct {
+    unsigned long index;
+    double x;
+    double y;
+} cairo_glyph_t;
+ cairo_glyph_t *
+cairo_glyph_allocate (int num_glyphs);
+ void
+cairo_glyph_free (cairo_glyph_t *glyphs);
+typedef struct {
+    int num_bytes;
+    int num_glyphs;
+} cairo_text_cluster_t;
+ cairo_text_cluster_t *
+cairo_text_cluster_allocate (int num_clusters);
+ void
+cairo_text_cluster_free (cairo_text_cluster_t *clusters);
+typedef enum _cairo_text_cluster_flags {
+    CAIRO_TEXT_CLUSTER_FLAG_BACKWARD = 0x00000001
+} cairo_text_cluster_flags_t;
+typedef struct {
+    double x_bearing;
+    double y_bearing;
+    double width;
+    double height;
+    double x_advance;
+    double y_advance;
+} cairo_text_extents_t;
+typedef struct {
+    double ascent;
+    double descent;
+    double height;
+    double max_x_advance;
+    double max_y_advance;
+} cairo_font_extents_t;
+typedef enum _cairo_font_slant {
+    CAIRO_FONT_SLANT_NORMAL,
+    CAIRO_FONT_SLANT_ITALIC,
+    CAIRO_FONT_SLANT_OBLIQUE
+} cairo_font_slant_t;
+typedef enum _cairo_font_weight {
+    CAIRO_FONT_WEIGHT_NORMAL,
+    CAIRO_FONT_WEIGHT_BOLD
+} cairo_font_weight_t;
+typedef enum _cairo_subpixel_order {
+    CAIRO_SUBPIXEL_ORDER_DEFAULT,
+    CAIRO_SUBPIXEL_ORDER_RGB,
+    CAIRO_SUBPIXEL_ORDER_BGR,
+    CAIRO_SUBPIXEL_ORDER_VRGB,
+    CAIRO_SUBPIXEL_ORDER_VBGR
+} cairo_subpixel_order_t;
+typedef enum _cairo_hint_style {
+    CAIRO_HINT_STYLE_DEFAULT,
+    CAIRO_HINT_STYLE_NONE,
+    CAIRO_HINT_STYLE_SLIGHT,
+    CAIRO_HINT_STYLE_MEDIUM,
+    CAIRO_HINT_STYLE_FULL
+} cairo_hint_style_t;
+typedef enum _cairo_hint_metrics {
+    CAIRO_HINT_METRICS_DEFAULT,
+    CAIRO_HINT_METRICS_OFF,
+    CAIRO_HINT_METRICS_ON
+} cairo_hint_metrics_t;
+typedef struct _cairo_font_options cairo_font_options_t;
+ cairo_font_options_t *
+cairo_font_options_create (void);
+ cairo_font_options_t *
+cairo_font_options_copy (const cairo_font_options_t *original);
+ void
+cairo_font_options_destroy (cairo_font_options_t *options);
+ cairo_status_t
+cairo_font_options_status (cairo_font_options_t *options);
+ void
+cairo_font_options_merge (cairo_font_options_t *options,
+     const cairo_font_options_t *other);
+ cairo_bool_t
+cairo_font_options_equal (const cairo_font_options_t *options,
+     const cairo_font_options_t *other);
+ unsigned long
+cairo_font_options_hash (const cairo_font_options_t *options);
+ void
+cairo_font_options_set_antialias (cairo_font_options_t *options,
+      cairo_antialias_t antialias);
+ cairo_antialias_t
+cairo_font_options_get_antialias (const cairo_font_options_t *options);
+ void
+cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
+           cairo_subpixel_order_t subpixel_order);
+ cairo_subpixel_order_t
+cairo_font_options_get_subpixel_order (const cairo_font_options_t *options);
+ void
+cairo_font_options_set_hint_style (cairo_font_options_t *options,
+       cairo_hint_style_t hint_style);
+ cairo_hint_style_t
+cairo_font_options_get_hint_style (const cairo_font_options_t *options);
+ void
+cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
+         cairo_hint_metrics_t hint_metrics);
+ cairo_hint_metrics_t
+cairo_font_options_get_hint_metrics (const cairo_font_options_t *options);
+ void
+cairo_select_font_face (cairo_t *cr,
+   const char *family,
+   cairo_font_slant_t slant,
+   cairo_font_weight_t weight);
+ void
+cairo_set_font_size (cairo_t *cr, double size);
+ void
+cairo_set_font_matrix (cairo_t *cr,
+         const cairo_matrix_t *matrix);
+ void
+cairo_get_font_matrix (cairo_t *cr,
+         cairo_matrix_t *matrix);
+ void
+cairo_set_font_options (cairo_t *cr,
+   const cairo_font_options_t *options);
+ void
+cairo_get_font_options (cairo_t *cr,
+   cairo_font_options_t *options);
+ void
+cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face);
+ cairo_font_face_t *
+cairo_get_font_face (cairo_t *cr);
+ void
+cairo_set_scaled_font (cairo_t *cr,
+         const cairo_scaled_font_t *scaled_font);
+ cairo_scaled_font_t *
+cairo_get_scaled_font (cairo_t *cr);
+ void
+cairo_show_text (cairo_t *cr, const char *utf8);
+ void
+cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
+ void
+cairo_show_text_glyphs (cairo_t *cr,
+   const char *utf8,
+   int utf8_len,
+   const cairo_glyph_t *glyphs,
+   int num_glyphs,
+   const cairo_text_cluster_t *clusters,
+   int num_clusters,
+   cairo_text_cluster_flags_t cluster_flags);
+ void
+cairo_text_path (cairo_t *cr, const char *utf8);
+ void
+cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
+ void
+cairo_text_extents (cairo_t *cr,
+      const char *utf8,
+      cairo_text_extents_t *extents);
+ void
+cairo_glyph_extents (cairo_t *cr,
+       const cairo_glyph_t *glyphs,
+       int num_glyphs,
+       cairo_text_extents_t *extents);
+ void
+cairo_font_extents (cairo_t *cr,
+      cairo_font_extents_t *extents);
+ cairo_font_face_t *
+cairo_font_face_reference (cairo_font_face_t *font_face);
+ void
+cairo_font_face_destroy (cairo_font_face_t *font_face);
+ unsigned int
+cairo_font_face_get_reference_count (cairo_font_face_t *font_face);
+ cairo_status_t
+cairo_font_face_status (cairo_font_face_t *font_face);
+typedef enum _cairo_font_type {
+    CAIRO_FONT_TYPE_TOY,
+    CAIRO_FONT_TYPE_FT,
+    CAIRO_FONT_TYPE_WIN32,
+    CAIRO_FONT_TYPE_QUARTZ,
+    CAIRO_FONT_TYPE_USER
+} cairo_font_type_t;
+ cairo_font_type_t
+cairo_font_face_get_type (cairo_font_face_t *font_face);
+ void *
+cairo_font_face_get_user_data (cairo_font_face_t *font_face,
+          const cairo_user_data_key_t *key);
+ cairo_status_t
+cairo_font_face_set_user_data (cairo_font_face_t *font_face,
+          const cairo_user_data_key_t *key,
+          void *user_data,
+          cairo_destroy_func_t destroy);
+ cairo_scaled_font_t *
+cairo_scaled_font_create (cairo_font_face_t *font_face,
+     const cairo_matrix_t *font_matrix,
+     const cairo_matrix_t *ctm,
+     const cairo_font_options_t *options);
+ cairo_scaled_font_t *
+cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font);
+ void
+cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font);
+ unsigned int
+cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font);
+ cairo_status_t
+cairo_scaled_font_status (cairo_scaled_font_t *scaled_font);
+ cairo_font_type_t
+cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font);
+ void *
+cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font,
+     const cairo_user_data_key_t *key);
+ cairo_status_t
+cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
+     const cairo_user_data_key_t *key,
+     void *user_data,
+     cairo_destroy_func_t destroy);
+ void
+cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
+      cairo_font_extents_t *extents);
+ void
+cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
+    const char *utf8,
+    cairo_text_extents_t *extents);
+ void
+cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
+     const cairo_glyph_t *glyphs,
+     int num_glyphs,
+     cairo_text_extents_t *extents);
+ cairo_status_t
+cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
+      double x,
+      double y,
+      const char *utf8,
+      int utf8_len,
+      cairo_glyph_t **glyphs,
+      int *num_glyphs,
+      cairo_text_cluster_t **clusters,
+      int *num_clusters,
+      cairo_text_cluster_flags_t *cluster_flags);
+ cairo_font_face_t *
+cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font);
+ void
+cairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font,
+       cairo_matrix_t *font_matrix);
+ void
+cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font,
+      cairo_matrix_t *ctm);
+ void
+cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font,
+        cairo_matrix_t *scale_matrix);
+ void
+cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
+        cairo_font_options_t *options);
+ cairo_font_face_t *
+cairo_toy_font_face_create (const char *family,
+       cairo_font_slant_t slant,
+       cairo_font_weight_t weight);
+ const char *
+cairo_toy_font_face_get_family (cairo_font_face_t *font_face);
+ cairo_font_slant_t
+cairo_toy_font_face_get_slant (cairo_font_face_t *font_face);
+ cairo_font_weight_t
+cairo_toy_font_face_get_weight (cairo_font_face_t *font_face);
+ cairo_font_face_t *
+cairo_user_font_face_create (void);
+typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_t *scaled_font,
+             cairo_t *cr,
+             cairo_font_extents_t *extents);
+typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scaled_font_t *scaled_font,
+              unsigned long glyph,
+              cairo_t *cr,
+              cairo_text_extents_t *extents);
+typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font,
+         const char *utf8,
+         int utf8_len,
+         cairo_glyph_t **glyphs,
+         int *num_glyphs,
+         cairo_text_cluster_t **clusters,
+         int *num_clusters,
+         cairo_text_cluster_flags_t *cluster_flags);
+typedef cairo_status_t (*cairo_user_scaled_font_unicode_to_glyph_func_t) (cairo_scaled_font_t *scaled_font,
+           unsigned long unicode,
+           unsigned long *glyph_index);
+ void
+cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
+        cairo_user_scaled_font_init_func_t init_func);
+ void
+cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
+         cairo_user_scaled_font_render_glyph_func_t render_glyph_func);
+ void
+cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
+           cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func);
+ void
+cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
+             cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func);
+ cairo_user_scaled_font_init_func_t
+cairo_user_font_face_get_init_func (cairo_font_face_t *font_face);
+ cairo_user_scaled_font_render_glyph_func_t
+cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face);
+ cairo_user_scaled_font_text_to_glyphs_func_t
+cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face);
+ cairo_user_scaled_font_unicode_to_glyph_func_t
+cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face);
+ cairo_operator_t
+cairo_get_operator (cairo_t *cr);
+ cairo_pattern_t *
+cairo_get_source (cairo_t *cr);
+ double
+cairo_get_tolerance (cairo_t *cr);
+ cairo_antialias_t
+cairo_get_antialias (cairo_t *cr);
+ cairo_bool_t
+cairo_has_current_point (cairo_t *cr);
+ void
+cairo_get_current_point (cairo_t *cr, double *x, double *y);
+ cairo_fill_rule_t
+cairo_get_fill_rule (cairo_t *cr);
+ double
+cairo_get_line_width (cairo_t *cr);
+ cairo_line_cap_t
+cairo_get_line_cap (cairo_t *cr);
+ cairo_line_join_t
+cairo_get_line_join (cairo_t *cr);
+ double
+cairo_get_miter_limit (cairo_t *cr);
+ int
+cairo_get_dash_count (cairo_t *cr);
+ void
+cairo_get_dash (cairo_t *cr, double *dashes, double *offset);
+ void
+cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
+ cairo_surface_t *
+cairo_get_target (cairo_t *cr);
+ cairo_surface_t *
+cairo_get_group_target (cairo_t *cr);
+typedef enum _cairo_path_data_type {
+    CAIRO_PATH_MOVE_TO,
+    CAIRO_PATH_LINE_TO,
+    CAIRO_PATH_CURVE_TO,
+    CAIRO_PATH_CLOSE_PATH
+} cairo_path_data_type_t;
+typedef union _cairo_path_data_t cairo_path_data_t;
+union _cairo_path_data_t {
+    struct {
+ cairo_path_data_type_t type;
+ int length;
+    } header;
+    struct {
+ double x, y;
+    } point;
+};
+typedef struct cairo_path {
+    cairo_status_t status;
+    cairo_path_data_t *data;
+    int num_data;
+} cairo_path_t;
+ cairo_path_t *
+cairo_copy_path (cairo_t *cr);
+ cairo_path_t *
+cairo_copy_path_flat (cairo_t *cr);
+ void
+cairo_append_path (cairo_t *cr,
+     const cairo_path_t *path);
+ void
+cairo_path_destroy (cairo_path_t *path);
+ cairo_status_t
+cairo_status (cairo_t *cr);
+ const char *
+cairo_status_to_string (cairo_status_t status);
+ cairo_device_t *
+cairo_device_reference (cairo_device_t *device);
+typedef enum _cairo_device_type {
+    CAIRO_DEVICE_TYPE_DRM,
+    CAIRO_DEVICE_TYPE_GL,
+    CAIRO_DEVICE_TYPE_SCRIPT,
+    CAIRO_DEVICE_TYPE_XCB,
+    CAIRO_DEVICE_TYPE_XLIB,
+    CAIRO_DEVICE_TYPE_XML,
+    CAIRO_DEVICE_TYPE_COGL,
+    CAIRO_DEVICE_TYPE_WIN32,
+    CAIRO_DEVICE_TYPE_INVALID = -1
+} cairo_device_type_t;
+ cairo_device_type_t
+cairo_device_get_type (cairo_device_t *device);
+ cairo_status_t
+cairo_device_status (cairo_device_t *device);
+ cairo_status_t
+cairo_device_acquire (cairo_device_t *device);
+ void
+cairo_device_release (cairo_device_t *device);
+ void
+cairo_device_flush (cairo_device_t *device);
+ void
+cairo_device_finish (cairo_device_t *device);
+ void
+cairo_device_destroy (cairo_device_t *device);
+ unsigned int
+cairo_device_get_reference_count (cairo_device_t *device);
+ void *
+cairo_device_get_user_data (cairo_device_t *device,
+       const cairo_user_data_key_t *key);
+ cairo_status_t
+cairo_device_set_user_data (cairo_device_t *device,
+       const cairo_user_data_key_t *key,
+       void *user_data,
+       cairo_destroy_func_t destroy);
+ cairo_surface_t *
+cairo_surface_create_similar (cairo_surface_t *other,
+         cairo_content_t content,
+         int width,
+         int height);
+ cairo_surface_t *
+cairo_surface_create_similar_image (cairo_surface_t *other,
+        cairo_format_t format,
+        int width,
+        int height);
+ cairo_surface_t *
+cairo_surface_map_to_image (cairo_surface_t *surface,
+       const cairo_rectangle_int_t *extents);
+ void
+cairo_surface_unmap_image (cairo_surface_t *surface,
+      cairo_surface_t *image);
+ cairo_surface_t *
+cairo_surface_create_for_rectangle (cairo_surface_t *target,
+                                    double x,
+                                    double y,
+                                    double width,
+                                    double height);
+typedef enum {
+ CAIRO_SURFACE_OBSERVER_NORMAL = 0,
+ CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS = 0x1
+} cairo_surface_observer_mode_t;
+ cairo_surface_t *
+cairo_surface_create_observer (cairo_surface_t *target,
+          cairo_surface_observer_mode_t mode);
+typedef void (*cairo_surface_observer_callback_t) (cairo_surface_t *observer,
+         cairo_surface_t *target,
+         void *data);
+ cairo_status_t
+cairo_surface_observer_add_paint_callback (cairo_surface_t *abstract_surface,
+        cairo_surface_observer_callback_t func,
+        void *data);
+ cairo_status_t
+cairo_surface_observer_add_mask_callback (cairo_surface_t *abstract_surface,
+       cairo_surface_observer_callback_t func,
+       void *data);
+ cairo_status_t
+cairo_surface_observer_add_fill_callback (cairo_surface_t *abstract_surface,
+       cairo_surface_observer_callback_t func,
+       void *data);
+ cairo_status_t
+cairo_surface_observer_add_stroke_callback (cairo_surface_t *abstract_surface,
+         cairo_surface_observer_callback_t func,
+         void *data);
+ cairo_status_t
+cairo_surface_observer_add_glyphs_callback (cairo_surface_t *abstract_surface,
+         cairo_surface_observer_callback_t func,
+         void *data);
+ cairo_status_t
+cairo_surface_observer_add_flush_callback (cairo_surface_t *abstract_surface,
+        cairo_surface_observer_callback_t func,
+        void *data);
+ cairo_status_t
+cairo_surface_observer_add_finish_callback (cairo_surface_t *abstract_surface,
+         cairo_surface_observer_callback_t func,
+         void *data);
+ cairo_status_t
+cairo_surface_observer_print (cairo_surface_t *surface,
+         cairo_write_func_t write_func,
+         void *closure);
+ double
+cairo_surface_observer_elapsed (cairo_surface_t *surface);
+ cairo_status_t
+cairo_device_observer_print (cairo_device_t *device,
+        cairo_write_func_t write_func,
+        void *closure);
+ double
+cairo_device_observer_elapsed (cairo_device_t *device);
+ double
+cairo_device_observer_paint_elapsed (cairo_device_t *device);
+ double
+cairo_device_observer_mask_elapsed (cairo_device_t *device);
+ double
+cairo_device_observer_fill_elapsed (cairo_device_t *device);
+ double
+cairo_device_observer_stroke_elapsed (cairo_device_t *device);
+ double
+cairo_device_observer_glyphs_elapsed (cairo_device_t *device);
+ cairo_surface_t *
+cairo_surface_reference (cairo_surface_t *surface);
+ void
+cairo_surface_finish (cairo_surface_t *surface);
+ void
+cairo_surface_destroy (cairo_surface_t *surface);
+ cairo_device_t *
+cairo_surface_get_device (cairo_surface_t *surface);
+ unsigned int
+cairo_surface_get_reference_count (cairo_surface_t *surface);
+ cairo_status_t
+cairo_surface_status (cairo_surface_t *surface);
+typedef enum _cairo_surface_type {
+    CAIRO_SURFACE_TYPE_IMAGE,
+    CAIRO_SURFACE_TYPE_PDF,
+    CAIRO_SURFACE_TYPE_PS,
+    CAIRO_SURFACE_TYPE_XLIB,
+    CAIRO_SURFACE_TYPE_XCB,
+    CAIRO_SURFACE_TYPE_GLITZ,
+    CAIRO_SURFACE_TYPE_QUARTZ,
+    CAIRO_SURFACE_TYPE_WIN32,
+    CAIRO_SURFACE_TYPE_BEOS,
+    CAIRO_SURFACE_TYPE_DIRECTFB,
+    CAIRO_SURFACE_TYPE_SVG,
+    CAIRO_SURFACE_TYPE_OS2,
+    CAIRO_SURFACE_TYPE_WIN32_PRINTING,
+    CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
+    CAIRO_SURFACE_TYPE_SCRIPT,
+    CAIRO_SURFACE_TYPE_QT,
+    CAIRO_SURFACE_TYPE_RECORDING,
+    CAIRO_SURFACE_TYPE_VG,
+    CAIRO_SURFACE_TYPE_GL,
+    CAIRO_SURFACE_TYPE_DRM,
+    CAIRO_SURFACE_TYPE_TEE,
+    CAIRO_SURFACE_TYPE_XML,
+    CAIRO_SURFACE_TYPE_SKIA,
+    CAIRO_SURFACE_TYPE_SUBSURFACE,
+    CAIRO_SURFACE_TYPE_COGL
+} cairo_surface_type_t;
+ cairo_surface_type_t
+cairo_surface_get_type (cairo_surface_t *surface);
+ cairo_content_t
+cairo_surface_get_content (cairo_surface_t *surface);
+ 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);
+ void *
+cairo_surface_get_user_data (cairo_surface_t *surface,
+        const cairo_user_data_key_t *key);
+ cairo_status_t
+cairo_surface_set_user_data (cairo_surface_t *surface,
+        const cairo_user_data_key_t *key,
+        void *user_data,
+        cairo_destroy_func_t destroy);
+ void
+cairo_surface_get_mime_data (cairo_surface_t *surface,
+                             const char *mime_type,
+                             const void **data,
+                             unsigned long *length);
+ cairo_status_t
+cairo_surface_set_mime_data (cairo_surface_t *surface,
+                             const char *mime_type,
+                             const void *data,
+                             unsigned long length,
+        cairo_destroy_func_t destroy,
+        void *closure);
+ cairo_bool_t
+cairo_surface_supports_mime_type (cairo_surface_t *surface,
+      const char *mime_type);
+ void
+cairo_surface_get_font_options (cairo_surface_t *surface,
+    cairo_font_options_t *options);
+ void
+cairo_surface_flush (cairo_surface_t *surface);
+ void
+cairo_surface_mark_dirty (cairo_surface_t *surface);
+ void
+cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
+        int x,
+        int y,
+        int width,
+        int height);
+ void
+cairo_surface_set_device_offset (cairo_surface_t *surface,
+     double x_offset,
+     double y_offset);
+ void
+cairo_surface_get_device_offset (cairo_surface_t *surface,
+     double *x_offset,
+     double *y_offset);
+ void
+cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
+           double x_pixels_per_inch,
+           double y_pixels_per_inch);
+ void
+cairo_surface_get_fallback_resolution (cairo_surface_t *surface,
+           double *x_pixels_per_inch,
+           double *y_pixels_per_inch);
+ void
+cairo_surface_copy_page (cairo_surface_t *surface);
+ void
+cairo_surface_show_page (cairo_surface_t *surface);
+ cairo_bool_t
+cairo_surface_has_show_text_glyphs (cairo_surface_t *surface);
+ cairo_surface_t *
+cairo_image_surface_create (cairo_format_t format,
+       int width,
+       int height);
+ int
+cairo_format_stride_for_width (cairo_format_t format,
+          int width);
+ cairo_surface_t *
+cairo_image_surface_create_for_data (void *data,
+         cairo_format_t format,
+         int width,
+         int height,
+         int stride);
+ void *
+cairo_image_surface_get_data (cairo_surface_t *surface);
+ cairo_format_t
+cairo_image_surface_get_format (cairo_surface_t *surface);
+ int
+cairo_image_surface_get_width (cairo_surface_t *surface);
+ int
+cairo_image_surface_get_height (cairo_surface_t *surface);
+ int
+cairo_image_surface_get_stride (cairo_surface_t *surface);
+ 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_surface_t *
+cairo_recording_surface_create (cairo_content_t content,
+                                const cairo_rectangle_t *extents);
+ void
+cairo_recording_surface_ink_extents (cairo_surface_t *surface,
+                                     double *x0,
+                                     double *y0,
+                                     double *width,
+                                     double *height);
+ cairo_bool_t
+cairo_recording_surface_get_extents (cairo_surface_t *surface,
+         cairo_rectangle_t *extents);
+typedef cairo_surface_t *
+(*cairo_raster_source_acquire_func_t) (cairo_pattern_t *pattern,
+           void *callback_data,
+           cairo_surface_t *target,
+           const cairo_rectangle_int_t *extents);
+typedef void
+(*cairo_raster_source_release_func_t) (cairo_pattern_t *pattern,
+           void *callback_data,
+           cairo_surface_t *surface);
+typedef cairo_status_t
+(*cairo_raster_source_snapshot_func_t) (cairo_pattern_t *pattern,
+     void *callback_data);
+typedef cairo_status_t
+(*cairo_raster_source_copy_func_t) (cairo_pattern_t *pattern,
+        void *callback_data,
+        const cairo_pattern_t *other);
+typedef void
+(*cairo_raster_source_finish_func_t) (cairo_pattern_t *pattern,
+          void *callback_data);
+ cairo_pattern_t *
+cairo_pattern_create_raster_source (void *user_data,
+        cairo_content_t content,
+        int width, int height);
+ void
+cairo_raster_source_pattern_set_callback_data (cairo_pattern_t *pattern,
+            void *data);
+ void *
+cairo_raster_source_pattern_get_callback_data (cairo_pattern_t *pattern);
+ void
+cairo_raster_source_pattern_set_acquire (cairo_pattern_t *pattern,
+      cairo_raster_source_acquire_func_t acquire,
+      cairo_raster_source_release_func_t release);
+ void
+cairo_raster_source_pattern_get_acquire (cairo_pattern_t *pattern,
+      cairo_raster_source_acquire_func_t *acquire,
+      cairo_raster_source_release_func_t *release);
+ void
+cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *pattern,
+       cairo_raster_source_snapshot_func_t snapshot);
+ cairo_raster_source_snapshot_func_t
+cairo_raster_source_pattern_get_snapshot (cairo_pattern_t *pattern);
+ void
+cairo_raster_source_pattern_set_copy (cairo_pattern_t *pattern,
+          cairo_raster_source_copy_func_t copy);
+ cairo_raster_source_copy_func_t
+cairo_raster_source_pattern_get_copy (cairo_pattern_t *pattern);
+ void
+cairo_raster_source_pattern_set_finish (cairo_pattern_t *pattern,
+     cairo_raster_source_finish_func_t finish);
+ cairo_raster_source_finish_func_t
+cairo_raster_source_pattern_get_finish (cairo_pattern_t *pattern);
+ cairo_pattern_t *
+cairo_pattern_create_rgb (double red, double green, double blue);
+ cairo_pattern_t *
+cairo_pattern_create_rgba (double red, double green, double blue,
+      double alpha);
+ cairo_pattern_t *
+cairo_pattern_create_for_surface (cairo_surface_t *surface);
+ cairo_pattern_t *
+cairo_pattern_create_linear (double x0, double y0,
+        double x1, double y1);
+ cairo_pattern_t *
+cairo_pattern_create_radial (double cx0, double cy0, double radius0,
+        double cx1, double cy1, double radius1);
+ cairo_pattern_t *
+cairo_pattern_create_mesh (void);
+ cairo_pattern_t *
+cairo_pattern_reference (cairo_pattern_t *pattern);
+ void
+cairo_pattern_destroy (cairo_pattern_t *pattern);
+ unsigned int
+cairo_pattern_get_reference_count (cairo_pattern_t *pattern);
+ cairo_status_t
+cairo_pattern_status (cairo_pattern_t *pattern);
+ void *
+cairo_pattern_get_user_data (cairo_pattern_t *pattern,
+        const cairo_user_data_key_t *key);
+ cairo_status_t
+cairo_pattern_set_user_data (cairo_pattern_t *pattern,
+        const cairo_user_data_key_t *key,
+        void *user_data,
+        cairo_destroy_func_t destroy);
+typedef enum _cairo_pattern_type {
+    CAIRO_PATTERN_TYPE_SOLID,
+    CAIRO_PATTERN_TYPE_SURFACE,
+    CAIRO_PATTERN_TYPE_LINEAR,
+    CAIRO_PATTERN_TYPE_RADIAL,
+    CAIRO_PATTERN_TYPE_MESH,
+    CAIRO_PATTERN_TYPE_RASTER_SOURCE
+} cairo_pattern_type_t;
+ cairo_pattern_type_t
+cairo_pattern_get_type (cairo_pattern_t *pattern);
+ void
+cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
+      double offset,
+      double red, double green, double blue);
+ void
+cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
+       double offset,
+       double red, double green, double blue,
+       double alpha);
+ void
+cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern);
+ void
+cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern);
+ void
+cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern,
+        double x1, double y1,
+        double x2, double y2,
+        double x3, double y3);
+ void
+cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
+       double x, double y);
+ void
+cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
+       double x, double y);
+ void
+cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
+          unsigned int point_num,
+          double x, double y);
+ void
+cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern,
+      unsigned int corner_num,
+      double red, double green, double blue);
+ void
+cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
+       unsigned int corner_num,
+       double red, double green, double blue,
+       double alpha);
+ void
+cairo_pattern_set_matrix (cairo_pattern_t *pattern,
+     const cairo_matrix_t *matrix);
+ void
+cairo_pattern_get_matrix (cairo_pattern_t *pattern,
+     cairo_matrix_t *matrix);
+typedef enum _cairo_extend {
+    CAIRO_EXTEND_NONE,
+    CAIRO_EXTEND_REPEAT,
+    CAIRO_EXTEND_REFLECT,
+    CAIRO_EXTEND_PAD
+} cairo_extend_t;
+ void
+cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend);
+ cairo_extend_t
+cairo_pattern_get_extend (cairo_pattern_t *pattern);
+typedef enum _cairo_filter {
+    CAIRO_FILTER_FAST,
+    CAIRO_FILTER_GOOD,
+    CAIRO_FILTER_BEST,
+    CAIRO_FILTER_NEAREST,
+    CAIRO_FILTER_BILINEAR,
+    CAIRO_FILTER_GAUSSIAN
+} cairo_filter_t;
+ void
+cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter);
+ cairo_filter_t
+cairo_pattern_get_filter (cairo_pattern_t *pattern);
+ cairo_status_t
+cairo_pattern_get_rgba (cairo_pattern_t *pattern,
+   double *red, double *green,
+   double *blue, double *alpha);
+ cairo_status_t
+cairo_pattern_get_surface (cairo_pattern_t *pattern,
+      cairo_surface_t **surface);
+ cairo_status_t
+cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
+       int index, double *offset,
+       double *red, double *green,
+       double *blue, double *alpha);
+ cairo_status_t
+cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
+        int *count);
+ cairo_status_t
+cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
+     double *x0, double *y0,
+     double *x1, double *y1);
+ cairo_status_t
+cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
+      double *x0, double *y0, double *r0,
+      double *x1, double *y1, double *r1);
+ cairo_status_t
+cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern,
+        unsigned int *count);
+ cairo_path_t *
+cairo_mesh_pattern_get_path (cairo_pattern_t *pattern,
+        unsigned int patch_num);
+ cairo_status_t
+cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern,
+       unsigned int patch_num,
+       unsigned int corner_num,
+       double *red, double *green,
+       double *blue, double *alpha);
+ cairo_status_t
+cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern,
+          unsigned int patch_num,
+          unsigned int point_num,
+          double *x, double *y);
+ void
+cairo_matrix_init (cairo_matrix_t *matrix,
+     double xx, double yx,
+     double xy, double yy,
+     double x0, double y0);
+ void
+cairo_matrix_init_identity (cairo_matrix_t *matrix);
+ void
+cairo_matrix_init_translate (cairo_matrix_t *matrix,
+        double tx, double ty);
+ void
+cairo_matrix_init_scale (cairo_matrix_t *matrix,
+    double sx, double sy);
+ void
+cairo_matrix_init_rotate (cairo_matrix_t *matrix,
+     double radians);
+ void
+cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty);
+ void
+cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy);
+ void
+cairo_matrix_rotate (cairo_matrix_t *matrix, double radians);
+ cairo_status_t
+cairo_matrix_invert (cairo_matrix_t *matrix);
+ void
+cairo_matrix_multiply (cairo_matrix_t *result,
+         const cairo_matrix_t *a,
+         const cairo_matrix_t *b);
+ void
+cairo_matrix_transform_distance (const cairo_matrix_t *matrix,
+     double *dx, double *dy);
+ void
+cairo_matrix_transform_point (const cairo_matrix_t *matrix,
+         double *x, double *y);
+typedef struct _cairo_region cairo_region_t;
+typedef enum _cairo_region_overlap {
+    CAIRO_REGION_OVERLAP_IN,
+    CAIRO_REGION_OVERLAP_OUT,
+    CAIRO_REGION_OVERLAP_PART
+} cairo_region_overlap_t;
+ cairo_region_t *
+cairo_region_create (void);
+ cairo_region_t *
+cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle);
+ cairo_region_t *
+cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
+    int count);
+ cairo_region_t *
+cairo_region_copy (const cairo_region_t *original);
+ cairo_region_t *
+cairo_region_reference (cairo_region_t *region);
+ void
+cairo_region_destroy (cairo_region_t *region);
+ cairo_bool_t
+cairo_region_equal (const cairo_region_t *a, const cairo_region_t *b);
+ cairo_status_t
+cairo_region_status (const cairo_region_t *region);
+ void
+cairo_region_get_extents (const cairo_region_t *region,
+     cairo_rectangle_int_t *extents);
+ int
+cairo_region_num_rectangles (const cairo_region_t *region);
+ void
+cairo_region_get_rectangle (const cairo_region_t *region,
+       int nth,
+       cairo_rectangle_int_t *rectangle);
+ cairo_bool_t
+cairo_region_is_empty (const cairo_region_t *region);
+ cairo_region_overlap_t
+cairo_region_contains_rectangle (const cairo_region_t *region,
+     const cairo_rectangle_int_t *rectangle);
+ cairo_bool_t
+cairo_region_contains_point (const cairo_region_t *region, int x, int y);
+ void
+cairo_region_translate (cairo_region_t *region, int dx, int dy);
+ cairo_status_t
+cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other);
+ cairo_status_t
+cairo_region_subtract_rectangle (cairo_region_t *dst,
+     const cairo_rectangle_int_t *rectangle);
+ cairo_status_t
+cairo_region_intersect (cairo_region_t *dst, const cairo_region_t *other);
+ cairo_status_t
+cairo_region_intersect_rectangle (cairo_region_t *dst,
+      const cairo_rectangle_int_t *rectangle);
+ cairo_status_t
+cairo_region_union (cairo_region_t *dst, const cairo_region_t *other);
+ cairo_status_t
+cairo_region_union_rectangle (cairo_region_t *dst,
+         const cairo_rectangle_int_t *rectangle);
+ cairo_status_t
+cairo_region_xor (cairo_region_t *dst, const cairo_region_t *other);
+ cairo_status_t
+cairo_region_xor_rectangle (cairo_region_t *dst,
+       const cairo_rectangle_int_t *rectangle);
+ void
+cairo_debug_reset_static_data (void);
+
+// private APIs
+
+typedef enum _cairo_lcd_filter {
+    CAIRO_LCD_FILTER_DEFAULT,
+    CAIRO_LCD_FILTER_NONE,
+    CAIRO_LCD_FILTER_INTRA_PIXEL,
+    CAIRO_LCD_FILTER_FIR3,
+    CAIRO_LCD_FILTER_FIR5
+} cairo_lcd_filter_t;
+
+typedef enum _cairo_round_glyph_positions {
+    CAIRO_ROUND_GLYPH_POS_DEFAULT,
+    CAIRO_ROUND_GLYPH_POS_ON,
+    CAIRO_ROUND_GLYPH_POS_OFF
+} cairo_round_glyph_positions_t;
+
+void _cairo_font_options_set_lcd_filter (cairo_font_options_t   *options, cairo_lcd_filter_t  lcd_filter);
+cairo_lcd_filter_t _cairo_font_options_get_lcd_filter (const cairo_font_options_t *options);
+void _cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options, 
cairo_round_glyph_positions_t  round);
+cairo_round_glyph_positions_t _cairo_font_options_get_round_glyph_positions (const cairo_font_options_t 
*options);
+
+]]
+
diff --git a/bin/lua/mime.lua b/bin/lua/mime.lua
new file mode 100755
index 000000000..1dbb4d928
--- /dev/null
+++ b/bin/lua/mime.lua
@@ -0,0 +1,76 @@
+local M = {}
+
+-- the api is possible to replace with something
+-- that sniffs magic, this is the simplest thing
+-- that almost works though
+
+
+function M.for_path(path)
+
+if path:match("mrl-") then
+  return "application/mmm"
+end
+if path:match("mmm-") then
+  return "application/mmm"
+end
+if path:match("mrg-") then
+  return "application/mmm"
+end
+
+   if path:has_suffix(".mp4") then
+     return "video/mpeg4"
+   elseif path:has_suffix(".ogv") then
+     return "video/ogv"
+   elseif path:has_suffix(".mpg") then
+     return "video/mpeg"
+   end
+
+   if path:has_prefix("/proc/") then
+     return "text/plain"
+   elseif path:has_suffix(".gif") or
+      path:has_suffix(".GIF") then
+     return "image/gif";
+   elseif path:has_suffix(".png") or 
+      path:has_suffix(".PNG") then
+      return "image/png"
+   elseif path:has_suffix(".svg") or 
+      path:has_suffix(".SVG") then
+      return "image/svg"
+   elseif path:has_suffix(".html") or 
+      path:has_suffix(".HTML") then
+      return "text/html"
+   elseif path:has_suffix(".jpg") or
+            path:has_suffix(".jpeg") or
+            path:has_suffix(".JPEG") or
+            path:has_suffix(".JPG") 
+     then
+       return "image/jpeg"
+   elseif path:has_suffix("README") or 
+      path:has_suffix(".txt") or
+      path:has_suffix("Makefile") or
+      path:has_suffix("Makefile.am") or
+      path:has_suffix("configure") or
+      path:has_suffix('.c') or 
+      path:has_suffix('.js') or 
+      path:has_suffix('.md') or 
+      path:has_suffix('.pc') or 
+      path:has_suffix('.inc') or 
+      path:has_suffix('.h') or 
+      path:has_suffix('.css') 
+     -- or 
+     -- path:has_suffix(".lua")
+     then
+      return "text/plain"
+   end
+
+  io.input(path)
+  document = io.read("*line")
+  io.close()
+
+  if document and document:match("luajit") then
+    return "application/mmm"
+  end
+  return "text/plain"
+end
+
+return M
diff --git a/bin/lua/mrg.lua b/bin/lua/mrg.lua
new file mode 100644
index 000000000..8ab6d842d
--- /dev/null
+++ b/bin/lua/mrg.lua
@@ -0,0 +1,1423 @@
+-- ffi lua binding for microraptor gui by Øyvind Kolås, public domain
+--
+local ffi = require('ffi')
+local cairo = require('cairo')
+local C = ffi.load('mrg')
+local M = setmetatable({C=C},{__index = C})
+
+ffi.cdef[[
+
+typedef struct _MrgList MrgList;
+
+struct _MrgList {
+  void *data;
+  MrgList *next;
+  void (*freefunc)(void *data, void *freefunc_data);
+  void *freefunc_data;
+}
+;
+void mrg_list_prepend_full (MrgList **list, void *data,
+    void (*freefunc)(void *data, void *freefunc_data),
+    void *freefunc_data);
+
+int mrg_list_length (MrgList *list);
+
+void mrg_list_prepend (MrgList **list, void *data);
+
+void mrg_list_append_full (MrgList **list, void *data,
+    void (*freefunc)(void *data, void *freefunc_data),
+    void *freefunc_data);
+
+void mrg_list_append (MrgList **list, void *data);
+
+void mrg_list_remove (MrgList **list, void *data);
+void mrg_list_free (MrgList **list);
+
+
+MrgList *mrg_list_nth (MrgList *list, int no);
+
+MrgList *mrg_list_find (MrgList *list, void *data);
+
+void mrg_list_sort (MrgList **list, 
+    int(*compare)(const void *a, const void *b, void *userdata),
+    void *userdata);
+
+void
+mrg_list_insert_sorted (MrgList **list, void *data,
+                       int(*compare)(const void *a, const void *b, void *userdata),
+                       void *userdata);
+
+typedef struct _Mrg Mrg;
+typedef struct _MrgColor     MrgColor;
+typedef struct _MrgStyle     MrgStyle;
+typedef struct _MrgRectangle MrgRectangle;
+typedef struct _MrgEvent     MrgEvent;
+
+enum _MrgType {
+  MRG_PRESS          = 1 << 0,
+  MRG_MOTION         = 1 << 1,
+  MRG_RELEASE        = 1 << 2,
+  MRG_ENTER          = 1 << 3,
+  MRG_LEAVE          = 1 << 4,
+  MRG_TAP            = 1 << 5, /* NYI */
+  MRG_TAP_AND_HOLD   = 1 << 6, /* NYI */
+  MRG_DRAG_PRESS     = 1 << 7,
+  MRG_DRAG_MOTION    = 1 << 8,
+  MRG_DRAG_RELEASE   = 1 << 9,
+  MRG_KEY_DOWN       = 1 << 10,
+  MRG_KEY_UP         = 1 << 11,
+  MRG_SCROLL         = 1 << 12,
+  MRG_MESSAGE        = 1 << 13,
+  MRG_DROP           = 1 << 14,
+
+  MRG_TAPS     = (MRG_TAP | MRG_TAP_AND_HOLD),
+  MRG_POINTER  = (MRG_PRESS | MRG_MOTION | MRG_RELEASE),
+  MRG_CROSSING = (MRG_ENTER | MRG_LEAVE),
+  MRG_DRAG     = (MRG_DRAG_PRESS | MRG_DRAG_MOTION | MRG_DRAG_RELEASE),
+  MRG_KEY      = (MRG_KEY_DOWN | MRG_KEY_UP),
+
+
+  MRG_COORD    = (MRG_POINTER | MRG_DRAG | MRG_CROSSING | MRG_TAPS),
+  MRG_ANY      = (MRG_POINTER | MRG_DRAG | MRG_CROSSING | MRG_KEY | MRG_TAPS),
+};
+
+
+typedef enum _MrgType MrgType;
+
+typedef void (*MrgCb) (MrgEvent *event,
+                       void     *data,
+                       void     *data2);
+
+typedef void (*MrgLinkCb) (MrgEvent *event,
+                           const char *href,
+                           void     *data);
+
+typedef void(*MrgDestroyNotify) (void     *data);
+typedef int(*MrgTimeoutCb) (Mrg *mrg, void  *data);
+typedef int(*MrgIdleCb)    (Mrg *mrg, void  *data);
+
+typedef void (*MrgNewText) (const char *new_text, void *data);
+typedef void (*UiRenderFun)(Mrg *mrg, void *ui_data);
+
+
+void  mrg_destroy       (Mrg *mrg);
+
+void mrg_clear_bindings (Mrg *mrg);
+void  mrg_set_size      (Mrg *mrg, int width, int height);
+void  mrg_set_position  (Mrg *mrg, int x, int y);
+void  mrg_get_position  (Mrg *mrg, int *x, int *y);
+
+void  mrg_message           (Mrg *mrg, const char *message);
+void  mrg_set_title         (Mrg *mrg, const char *title);
+void  mrg_window_set_value  (Mrg *mrg, const char *name, const char *value);
+const char *mrg_get_title   (Mrg *mrg);
+void *mrg_mmm               (Mrg *mrg);
+
+int   mrg_width         (Mrg *mrg);
+int   mrg_height        (Mrg *mrg);
+
+Mrg *mrg_new(int width, int height, const char *backend);
+
+void  mrg_set_ui        (Mrg *mrg, UiRenderFun, void *ui_data);
+
+void  mrg_main          (Mrg *mrg);
+void  mrg_quit          (Mrg *mrg);
+cairo_t *mrg_cr         (Mrg *mrg);
+void mrg_queue_draw     (Mrg *mrg, MrgRectangle *rectangle);
+
+int  mrg_is_terminal    (Mrg *mrg);
+void mrg_set_fullscreen (Mrg *mrg, int fullscreen);
+int  mrg_is_fullscreen  (Mrg *mrg);
+
+float mrg_ddpx          (Mrg *mrg);
+
+unsigned char *mrg_get_pixels (Mrg *mrg, int *rowstride);
+
+void mrg_restarter_add_path (Mrg *mrg, const char *path);
+/*********************************************/
+
+Mrg *mrg_new_mrg (Mrg *parent, int width, int height); // NYI
+
+typedef struct _MrgImage MrgImage;
+
+/* force a ui render, this is included for use with the headless backend.
+ */
+void  mrg_ui_update (Mrg *mrg);
+
+MrgImage *mrg_query_image (Mrg *mrg, const char *path,
+                           int *width,
+                           int *height);
+
+/* built in http / local file URI fetcher, this is the callback interface
+ * that needs to be implemented for mrg_xml_render if external resources (css
+ * files / png images) are to be retrieved and rendered.
+ */
+int mrg_get_contents (Mrg         *mrg,
+                      const char  *referer,
+                      const char  *input_uri,
+                      char       **contents,
+                      long        *length);
+
+int
+mrg_get_contents_default (const char  *referer,
+                          const char  *input_uri,
+                          char       **contents,
+                          long        *length,
+                          void        *ignored_user_data);
+
+void mrg_set_mrg_get_contents (Mrg *mrg,
+  int (*mrg_get_contents) (const char  *referer,
+                      const char  *input_uri,
+                      char       **contents,
+                      long        *length,
+                      void        *get_contents_data),
+  void *get_contents_data);
+
+
+void mrg_render_to_mrg (Mrg *mrg, Mrg *mrg2, float x, float y);
+
+int mrg_add_idle (Mrg *mrg, int (*idle_cb)(Mrg *mrg, void *idle_data), void *   idle_data);
+int mrg_add_timeout (Mrg *mrg, int ms, int (*idle_cb)(Mrg *mrg, void *          idle_data), void *idle_data);
+void mrg_remove_idle (Mrg *mrg, int handle);
+
+int mrg_add_idle_full (Mrg *mrg, int (*idle_cb)(Mrg *mrg, void *idle_data),     void *idle_data,
+                       void (*destroy_notify)(void *destroy_data),    void *destroy_data);
+
+int mrg_add_timeout_full (Mrg *mrg, int ms, MrgTimeoutCb idle_cb, void *idle_data,
+                       void (*destroy_notify)(void *destroy_data),    void *destroy_data);
+
+
+void  mrg_set_line_spacing (Mrg *mrg, float line_spacing);
+float mrg_line_spacing     (Mrg *mrg);
+
+int mrg_print (Mrg *mrg, const char *string);
+
+int   mrg_print_get_xy     (Mrg *mrg, const char *str, int no, float *x, float *y);
+
+
+int mrg_print_xml (Mrg *mrg, const char *string);
+
+void mrg_xml_render (Mrg *mrg, const char *uri_base,
+                     MrgLinkCb linkcb,
+                     void *link_data,
+                     void   (*finalize)(void *listen_data, void *listen_data2,  void *finalize_data),
+                     void    *finalize_data,
+                     const char *html);
+
+void mrg_set_target_fps (Mrg *mrg, float fps);
+float mrg_get_target_fps (Mrg *mrg);
+
+void mrg_listen      (Mrg     *mrg,
+                      MrgType  types,
+                      MrgCb    cb,
+                      void    *data1,
+                      void    *data2);
+
+void mrg_listen_full (Mrg     *mrg,
+                      MrgType  types,
+                      MrgCb    cb,
+                      void    *data1,
+                      void    *data2,
+                      void   (*finalize)(void *listen_data, void *listen_data2,  void *finalize_data),
+                      void    *finalize_data);
+
+uint32_t mrg_ms (Mrg *mrg);
+
+int mrg_pointer_press    (Mrg *mrg, float x, float y, int device_no, uint32_t time);
+int mrg_pointer_release  (Mrg *mrg, float x, float y, int device_no, uint32_t time);
+int mrg_pointer_motion   (Mrg *mrg, float x, float y, int device_no, uint32_t time);
+int mrg_key_press        (Mrg *mrg, unsigned int keyval, const char *string, uint32_t time);
+
+int mrg_is_printing      (Mrg *mrg);
+void mrg_new_page (Mrg *mrg);
+void mrg_render_pdf (Mrg *mrg, const char *pdf_path);
+void mrg_render_svg (Mrg *mrg, const char *svg_path);
+
+/* these deal with pointer_no 0 only
+ */
+void  mrg_warp_pointer (Mrg *mrg, float x, float y);
+float mrg_pointer_x    (Mrg *mrg);
+float mrg_pointer_y    (Mrg *mrg);
+
+float mrg_em (Mrg *mrg);
+void  mrg_set_xy (Mrg *mrg, float x, float y);
+float  mrg_x (Mrg *mrg);
+float  mrg_y (Mrg *mrg);
+
+typedef enum _MrgModifierState MrgModifierState;
+  
+enum _MrgModifierState
+{   
+  MRG_MODIFIER_STATE_SHIFT   = (1<<0), 
+  MRG_MODIFIER_STATE_CONTROL = (1<<1),
+  MRG_MODIFIER_STATE_ALT     = (1<<2),
+  MRG_MODIFIER_STATE_BUTTON1 = (1<<3),
+  MRG_MODIFIER_STATE_BUTTON2 = (1<<4),
+  MRG_MODIFIER_STATE_BUTTON3 = (1<<5)
+};
+
+typedef enum _MrgScrollDirection MrgScrollDirection;
+enum _MrgScrollDirection
+{
+  MRG_SCROLL_DIRECTION_UP,
+  MRG_SCROLL_DIRECTION_DOWN,
+  MRG_SCROLL_DIRECTION_LEFT,
+  MRG_SCROLL_DIRECTION_RIGHT
+};
+
+struct _MrgEvent {
+  MrgType  type;
+  Mrg     *mrg;
+  uint32_t time;
+
+  MrgModifierState state;
+
+  int      device_no; /* 0 = left mouse button / virtual focus */
+                      /* 1 = middle mouse button */
+                      /* 2 = right mouse button */
+                      /* 3 = first multi-touch .. (NYI) */
+
+  float   device_x; /* untransformed (device) coordinates  */
+  float   device_y;
+
+  /* coordinates; and deltas for motion/drag events in user-coordinates: */
+  float   x;
+  float   y;
+  float   start_x; /* start-coordinates (press) event for drag, */
+  float   start_y; /*    untransformed coordinates */
+  float   prev_x;  /* previous events coordinates */
+  float   prev_y;
+  float   delta_x; /* x - prev_x, redundant - but often useful */
+  float   delta_y; /* y - prev_y, redundant - ..  */
+
+  MrgScrollDirection scroll_direction;
+
+  /* only valid for key-events */
+  unsigned int unicode;
+  const char *string;   /* can be "up" "down" "space" "backspace" "a" "b" "ø" etc .. */
+                        /* this is also where the message is delivered for
+                         * MESSAGE events
+                         */
+//  int stop_propagate; /* */
+};
+
+void mrg_event_stop_propagate (MrgEvent *event);
+
+void  mrg_text_listen (Mrg *mrg, MrgType types,
+                       MrgCb cb, void *data1, void *data2);
+
+void  mrg_text_listen_full (Mrg *mrg, MrgType types,
+                            MrgCb cb, void *data1, void *data2,
+          void (*finalize)(void *listen_data, void *listen_data2, void *       finalize_data),
+          void  *finalize_data);
+
+void  mrg_text_listen_done (Mrg *mrg);
+
+struct _MrgColor {
+  float red;
+  float green;
+  float blue;
+  float alpha;
+};
+
+typedef enum {
+  MRG_DISPLAY_INLINE = 0,
+  MRG_DISPLAY_BLOCK,
+  MRG_DISPLAY_LIST_ITEM,
+  MRG_DISPLAY_HIDDEN
+} MrgDisplay;
+
+/* matches cairo order */
+typedef enum
+{
+  MRG_FONT_WEIGHT_NORMAL = 0,
+  MRG_FONT_WEIGHT_BOLD
+} MrgFontWeight;
+
+typedef enum
+{
+  MRG_FILL_RULE_NONZERO = 0,
+  MRG_FILL_RULE_EVEN_ODD
+} MrgFillRule;
+
+/* matches cairo order */
+typedef enum
+{
+  MRG_FONT_STYLE_NORMAL = 0,
+  MRG_FONT_STYLE_ITALIC,
+  MRG_FONT_STYLE_OBLIQUE
+} MrgFontStyle;
+
+typedef enum
+{
+  MRG_BOX_SIZING_CONTENT_BOX = 0,
+  MRG_BOX_SIZING_BORDER_BOX
+} MrgBoxSizing;
+
+/* matching nchanterm definitions */
+
+typedef enum {
+  MRG_REGULAR     = 0,
+  MRG_BOLD        = (1 << 0),
+  MRG_DIM         = (1 << 1),
+  MRG_UNDERLINE   = (1 << 2),
+  MRG_REVERSE     = (1 << 3),
+  MRG_OVERLINE    = (1 << 4),
+  MRG_LINETHROUGH = (1 << 5),
+  MRG_BLINK       = (1 << 6)
+} MrgTextDecoration;
+
+typedef enum {
+  MRG_POSITION_STATIC = 0,
+  MRG_POSITION_RELATIVE,
+  MRG_POSITION_FIXED,
+  MRG_POSITION_ABSOLUTE
+} MrgPosition;
+
+typedef enum {
+  MRG_OVERFLOW_VISIBLE = 0,
+  MRG_OVERFLOW_HIDDEN,
+  MRG_OVERFLOW_SCROLL,
+  MRG_OVERFLOW_AUTO
+} MrgOverflow;
+
+typedef enum {
+  MRG_FLOAT_NONE = 0,
+  MRG_FLOAT_LEFT,
+  MRG_FLOAT_RIGHT,
+  MRG_FLOAT_FIXED
+} MrgFloat;
+
+typedef enum {
+  MRG_CLEAR_NONE = 0,
+  MRG_CLEAR_LEFT,
+  MRG_CLEAR_RIGHT,
+  MRG_CLEAR_BOTH
+} MrgClear;
+
+typedef enum {
+  MRG_TEXT_ALIGN_LEFT = 0,
+  MRG_TEXT_ALIGN_RIGHT,
+  MRG_TEXT_ALIGN_JUSTIFY,
+  MRG_TEXT_ALIGN_CENTER
+} MrgTextAlign;
+
+typedef enum {
+  MRG_WHITE_SPACE_NORMAL = 0,
+  MRG_WHITE_SPACE_NOWRAP,
+  MRG_WHITE_SPACE_PRE,
+  MRG_WHITE_SPACE_PRE_LINE,
+  MRG_WHITE_SPACE_PRE_WRAP
+} MrgWhiteSpace;
+
+typedef enum {
+  MRG_VERTICAL_ALIGN_BASELINE = 0,
+  MRG_VERTICAL_ALIGN_MIDDLE,
+  MRG_VERTICAL_ALIGN_BOTTOM,
+  MRG_VERTICAL_ALIGN_TOP,
+  MRG_VERTICAL_ALIGN_SUB,
+  MRG_VERTICAL_ALIGN_SUPER
+} MrgVerticalAlign;
+
+typedef enum {
+  MRG_CURSOR_AUTO = 0,
+  MRG_CURSOR_ALIAS,
+  MRG_CURSOR_ALL_SCROLL,
+  MRG_CURSOR_CELL,
+  MRG_CURSOR_CONTEXT_MENU,
+  MRG_CURSOR_COL_RESIZE,
+  MRG_CURSOR_COPY,
+  MRG_CURSOR_CROSSHAIR,
+  MRG_CURSOR_DEFAULT,
+  MRG_CURSOR_E_RESIZE,
+  MRG_CURSOR_EW_RESIZE,
+  MRG_CURSOR_HELP,
+  MRG_CURSOR_MOVE,
+  MRG_CURSOR_N_RESIZE,
+  MRG_CURSOR_NE_RESIZE,
+  MRG_CURSOR_NESW_RESIZE,
+  MRG_CURSOR_NS_RESIZE,
+  MRG_CURSOR_NW_RESIZE,
+  MRG_CURSOR_NO_DROP,
+  MRG_CURSOR_NONE,
+  MRG_CURSOR_NOT_ALLOWED,
+  MRG_CURSOR_POINTER,
+  MRG_CURSOR_PROGRESS,
+  MRG_CURSOR_ROW_RESIZE,
+  MRG_CURSOR_S_RESIZE,
+  MRG_CURSOR_SE_RESIZE,
+  MRG_CURSOR_SW_RESIZE,
+  MRG_CURSOR_TEXT,
+  MRG_CURSOR_VERTICAL_TEXT,
+  MRG_CURSOR_W_RESIZE,
+  MRG_CURSOR_WAIT,
+  MRG_CURSOR_ZOOM_IN,
+  MRG_CURSOR_ZOOM_OUT
+} MrgCursor;
+
+typedef enum {
+  MRG_LINE_CAP_BUTT,
+  MRG_LINE_CAP_ROUND,
+  MRG_LINE_CAP_SQUARE
+} MrgLineCap;
+
+typedef enum {
+  MRG_LINE_JOIN_MITER,
+  MRG_LINE_JOIN_ROUND,
+  MRG_LINE_JOIN_BEVEL
+} MrgLineJoin;
+
+typedef enum {
+  MRG_UNICODE_BIDI_NORMAL = 0,
+  MRG_UNICODE_BIDI_EMBED,
+  MRG_UNICODE_BIDI_BIDI_OVERRIDE
+} MrgUnicodeBidi;
+
+typedef enum {
+  MRG_DIRECTION_LTR = 0,
+  MRG_DIRECTION_RTL
+} MrgDirection;
+
+typedef enum {
+  MRG_VISIBILITY_VISIBLE = 0,
+  MRG_VISIBILITY_HIDDEN
+} MrgVisibility;
+
+typedef enum {
+  MRG_LIST_STYLE_OUTSIDE = 0,
+  MRG_LIST_STYLE_INSIDE
+} MrgListStyle;
+
+struct _MrgStyle {
+  /* text-related */
+  float             font_size;
+  char              font_family[128];
+  MrgColor          color;
+  float             text_indent;
+  float             letter_spacing;
+  float             word_spacing;
+
+  MrgVisibility     visibility;
+
+  MrgTextDecoration text_decoration;
+  float             line_height;
+  float             line_width;
+
+  MrgColor          background_color;
+
+  float             stroke_width;
+  float             text_stroke_width;
+  MrgColor          text_stroke_color;
+  float             tab_size;
+
+  /* copying style structs takes quite a bit of the time in the system,
+   * packing bits ends up saving a lot
+   *
+   * XXX: this is a gcc extension...
+   */
+  MrgFillRule         fill_rule;
+  MrgFontStyle        font_style;
+  MrgFontWeight       font_weight;
+  MrgLineCap          stroke_linecap;
+  MrgLineJoin         stroke_linejoin;
+  MrgTextAlign        text_align;
+  MrgFloat            float_;
+  MrgClear            clear;
+  MrgOverflow         overflow;
+  MrgDisplay          display;
+  MrgPosition         position;
+  MrgBoxSizing        box_sizing;
+  MrgVerticalAlign    vertical_align;
+  MrgWhiteSpace       white_space;
+  MrgUnicodeBidi      unicode_bidi;
+  MrgDirection        direction;
+  MrgListStyle        list_style;
+  unsigned char       stroke;
+  unsigned char       fill;
+  unsigned char       width_auto;
+  unsigned char       margin_left_auto;
+  unsigned char       margin_right_auto;
+  unsigned char       print_symbols;
+  MrgColor            stroke_color;
+
+
+  /* vector shape / box related */
+  MrgColor          fill_color;
+
+  MrgColor          border_top_color;
+  MrgColor          border_left_color;
+  MrgColor          border_right_color;
+  MrgColor          border_bottom_color;
+
+  MrgCursor         cursor;
+
+  /* layout related */
+
+  float             top;
+  float             left;
+  float             right;
+  float             bottom;
+  float             width;
+  float             height;
+  float             min_height;
+  float             max_height;
+
+  float             border_top_width;
+  float             border_left_width;
+  float             border_right_width;
+  float             border_bottom_width;
+
+  float             padding_top;
+  float             padding_left;
+  float             padding_right;
+  float             padding_bottom;
+
+  float             margin_top;
+  float             margin_left;
+  float             margin_right;
+  float             margin_bottom;
+
+  void             *id_ptr;
+};
+
+/* XXX: need full version for lua ffi */
+void mrg_add_binding (Mrg *mrg,
+                      const char *key,
+                      const char *action,
+                      const char *label,
+                      MrgCb cb,
+                      void  *cb_data);
+
+
+void mrg_add_binding_full (Mrg *mrg,
+                           const char *key,
+                           const char *action,
+                           const char *label,
+                           MrgCb cb,
+                           void  *cb_data,
+                           MrgDestroyNotify destroy_notify,
+                           void  *destroy_data);
+/**
+ * mrg_style:
+ * @mrg the mrg-context
+ *
+ * Returns the currently 
+ *
+ */
+MrgStyle *mrg_style (Mrg *mrg);
+
+void mrg_start     (Mrg *mrg, const char *class_name, void *id_ptr);
+void mrg_start_with_style (Mrg        *mrg,
+                           const char *style_id,
+                           void       *id_ptr,
+                           const char *style);
+void mrg_end       (Mrg *mrg);
+
+
+void mrg_stylesheet_clear (Mrg *mrg);
+void mrg_stylesheet_add (Mrg *mrg, const char *css, const char *uri,
+                         int priority,
+                         char **error);
+
+void mrg_css_set (Mrg *mrg, const char *css);
+void mrg_css_add (Mrg *mrg, const char *css);
+
+void mrg_set_style (Mrg *mrg, const char *style);
+
+
+void  mrg_set_line_height (Mrg *mrg, float line_height);
+void  mrg_set_font_size (Mrg *mrg, float font_size);
+float  mrg_line_height (Mrg *mrg);
+
+/* XXX: doesnt feel like it belongs here */
+void mrg_image (Mrg *mrg, float x0, float y0, float width, float height, float opacity, const char *path, 
int *used_width, int *used_height);
+void mrg_image_memory (Mrg *mrg, float x0, float y0, float width, float height, float opacity, const char 
*data, int length, const char *eid, int *used_width, int *used_height);
+
+MrgImage *mrg_query_image_memory (Mrg *mrg,
+                                  const char *contents,
+                                  int         length,
+                                  const char *eid,
+                                  int        *width,
+                                  int        *height);
+
+
+int mrg_get_cursor_pos  (Mrg *mrg);
+void mrg_set_cursor_pos (Mrg *mrg, int pos);
+
+void mrg_edit_start (Mrg *mrg,
+                     MrgNewText update_string,
+                     void *user_data);
+
+void mrg_edit_start_full (Mrg *mrg,
+                           MrgNewText update_string,
+                           void *user_data,
+                           MrgDestroyNotify destroy,
+                           void *destroy_data);
+void  mrg_edit_end (Mrg *mrg);
+
+void  mrg_set_edge_left   (Mrg *mrg, float edge);
+void  mrg_set_edge_top    (Mrg *mrg, float edge);
+void  mrg_set_edge_right  (Mrg *mrg, float edge);
+void  mrg_set_edge_bottom (Mrg *mrg, float edge);
+float mrg_edge_left       (Mrg *mrg);
+float mrg_edge_top        (Mrg *mrg);
+float mrg_edge_right      (Mrg *mrg);
+float mrg_edge_bottom     (Mrg *mrg);
+
+typedef struct _MrgHost   MrgHost;
+typedef struct _MrgClient MrgClient;
+
+void       mrg_host_add_client_mrg   (MrgHost     *host,
+                                      Mrg         *mrg,
+                                      float        x,
+                                      float        y);
+MrgHost   *mrg_host_new              (Mrg *mrg, const char *path);
+void       mrg_host_destroy          (MrgHost *host);
+void       mrg_host_set_focused      (MrgHost *host, MrgClient *client);
+MrgClient *mrg_host_get_focused      (MrgHost *host);
+MrgClient *mrg_host_monitor_dir      (MrgHost *host);
+void       mrg_host_register_events  (MrgHost *host);
+MrgList   *mrg_host_clients          (MrgHost *host);
+
+void       mrg_host_set_default_size (MrgHost *host, int width, int height);
+void       mrg_host_get_default_size (MrgHost *host, int *width, int *height);
+
+void       mrg_client_render_sloppy  (MrgClient *client, float x, float y);
+int        mrg_client_get_pid        (MrgClient *client);
+void       mrg_client_kill           (MrgClient *client);
+void       mrg_client_raise_top      (MrgClient *client);
+void       mrg_client_render         (MrgClient *client, Mrg *mrg, float x, float y);
+void       mrg_client_maximize       (MrgClient *client);
+float      mrg_client_get_x          (MrgClient *client);
+float      mrg_client_get_y          (MrgClient *client);
+void       mrg_client_set_x          (MrgClient *client, float x);
+void       mrg_client_set_y          (MrgClient *client, float y);
+void       mrg_client_get_size       (MrgClient *client, int *width, int *height);
+void       mrg_client_set_size       (MrgClient *client, int width,  int height);
+const char *mrg_client_get_title     (MrgClient *client);
+const char *mrg_client_get_value     (MrgClient *client, const char *name);
+void        mrg_client_set_value     (MrgClient *client, const char *name, const char *value);
+
+void        mrg_client_send_message  (MrgClient *client, const char *message);
+
+const char *mrg_client_get_message   (MrgClient *client);
+int         mrg_client_has_message   (MrgClient *client);
+
+void mrg_client_set_stack_order (MrgClient *client, int zpos);
+int  mrg_client_get_stack_order (MrgClient *client);
+void        host_add_client_mrg      (MrgHost     *host,
+                                      Mrg         *mrg,
+                                      float        x,
+                                      float        y);
+
+typedef struct MrgBinding {
+  char *nick;
+  char *command;
+  char *label;
+  MrgCb cb;
+  void *cb_data;
+  MrgDestroyNotify destroy_notify;
+  void  *destroy_data;
+} MrgBinding;
+
+MrgBinding *mrg_get_bindings (Mrg *mrg);
+
+int mrg_parse_svg_path (Mrg *mrg, const char *str);
+
+
+
+
+typedef struct _MrgVT MrgVT;
+
+MrgVT      *mrg_vt_new                  (Mrg *mrg, const char *commandline);
+const char *mrg_vt_find_shell_command   (void);
+void        mrg_vt_poll                 (MrgVT *vt);
+long        mrg_vt_rev                  (MrgVT *vt);
+void        mrg_vt_destroy              (MrgVT *vt);
+void        mrg_vt_set_term_size        (MrgVT *vt, int cols, int rows);
+void        mrg_vt_feed_keystring       (MrgVT *vt, const char *str);
+void        mrg_vt_feed_byte            (MrgVT *vt, int byte);
+const char *mrg_vt_get_commandline      (MrgVT *vt);
+void        mrg_vt_set_scrollback_lines (MrgVT *vt, int scrollback_lines);
+int         mrg_vt_get_scrollback_lines (MrgVT *vt);
+int         mrg_vt_get_line_count       (MrgVT *vt);
+const char *mrg_vt_get_line             (MrgVT *vt, int no);
+int         mrg_vt_get_cols             (MrgVT *vt);
+int         mrg_vt_get_rows             (MrgVT *vt);
+int         mrg_vt_get_cursor_x         (MrgVT *vt);
+int         mrg_vt_get_cursor_y         (MrgVT *vt);
+int         mrg_vt_is_done              (MrgVT *vt);
+int         mrg_vt_get_result           (MrgVT *vt);
+
+void        mrg_vt_draw             (MrgVT *vt, Mrg *mrg, double x, double y, float font_size, float 
line_spacing);
+]]
+
+function M.new(width,height, backend)
+  return ffi.gc(
+           C.mrg_new(width, height, backend),
+           C.mrg_destroy)
+end
+
+ffi.metatype('Mrg', {__index = {
+  -- maybe we should add a _full version to this as well, then all callback
+  -- things in the code would be lifecycle managed.
+  set_ui           = function (mrg, uifun, uidata) C.mrg_set_ui(mrg, uifun, uidata) end,
+  style            = function (...) return C.mrg_style (...) end;
+  width            = function (...) return C.mrg_width (...) end,
+  mmm              = function (...) return C.mrg_mmm (...) end,
+  height           = function (...) return C.mrg_height (...) end,
+  pointer_x        = function (...) return C.mrg_pointer_x (...) end,
+  pointer_y        = function (...) return C.mrg_pointer_y (...) end,
+  text_listen_done = function (...) C.mrg_text_listen_done(...) end,
+  warp_pointer     = function (...) C.mrg_warp_pointer(...) end,
+  quit             = function (...) C.mrg_quit(...) end,
+  image_memory = function (mrg, x, y, w, h, opacity, data, len, eid)
+    local rw = ffi.new'int[1]'
+    local rh = ffi.new'int[1]'
+    C.mrg_image_memory(mrg, x, y, w, h, opacity, data, len, eid, rw, rh)
+    return rw[0], rh[0]
+  end,
+  image = function (mrg, x, y, w, h, opacity, path)
+    local rw = ffi.new'int[1]'
+    local rh = ffi.new'int[1]'
+    C.mrg_image (mrg, x, y, w, h, opacity, path, rw, rh)
+    return rw[0], rh[0]
+  end,
+  image            = function (...) C.mrg_image(...) end,
+  render_pdf       = function (...) C.mrg_render_pdf(...) end,
+  render_svg       = function (...) C.mrg_render_svg(...) end,
+  is_printing      = function (...) return C.mrg_is_printing (...) end,
+  new_page         = function (...) C.mrg_new_page(...) end,
+  message          = function (...) C.mrg_message(...) end,
+  parse_svg_path   = function (...) return C.mrg_parse_svg_path(...) end,
+  clear_bindings = function (...) C.mrg_clear_bindings(...) end,
+
+
+  stylesheet_add = function(...) C.mrg_stylesheet_add(...) end,
+  stylesheet_clear = function(...) C.mrg_stylesheet_clear(...) end,
+
+
+  image_size       = function (mrg, path)
+    local rw = ffi.new'int[1]'
+    local rh = ffi.new'int[1]'
+    rw[0] = -1
+    rh[0] = -1
+    C.mrg_query_image (mrg, path, rw, rh)
+    return rw[0], rh[0]
+  end,
+
+
+  image_size_memory       = function (mrg, data, len, eid)
+    local rw = ffi.new'int[1]'
+    local rh = ffi.new'int[1]'
+    rw[0] = -1
+    rh[0] = -1
+    C.mrg_query_image_memory (mrg, data,len,eid, rw, rh)
+    return rw[0], rh[0]
+  end,
+
+
+  css_set          = function (...) C.mrg_css_set(...) end,
+  set_style        = function (...) C.mrg_set_style(...) end,
+  css_add          = function (...) C.mrg_css_add(...) end,
+  set_em           = function (...) C.mrg_set_em(...) end,
+
+  edit_start = function (mrg, cb, data)
+    -- manually cast and destroy resources held by lua/C binding
+    local notify_fun, cb_fun;
+    local notify_cb = function (finalize_data)
+      cb_fun:free();
+      notify_fun:free();
+    end
+    notify_fun = ffi.cast ("MrgDestroyNotify", notify_cb)
+    local wrap_cb = function(new_text,data)
+      cb(ffi.string(new_text),data)
+    end
+    cb_fun = ffi.cast ("MrgNewText", wrap_cb)
+    return C.mrg_edit_start_full (mrg, cb_fun, data, notify_fun, NULL)
+  end,
+
+  edit_end = function (...) C.mrg_edit_end (...) end,
+  set_edge_top     = function (...) C.mrg_set_edge_top(...) end,
+  edge_top         = function (...) return C.mrg_get_edge_top(...) end,
+  set_edge_bottom     = function (...) C.mrg_set_edge_bottom(...) end,
+  edge_bottom         = function (...) return C.mrg_get_edge_bottom(...) end,
+  set_edge_left     = function (...) C.mrg_set_edge_left(...) end,
+  edge_left         = function (...) return C.mrg_get_edge_left(...) end,
+  set_edge_right     = function (...) C.mrg_set_edge_right(...) end,
+  edge_right         = function (...) return C.mrg_get_edge_right(...) end,
+  set_rem          = function (...) C.mrg_set_rem(...) end,
+  main             = function (...) C.mrg_main(...) end,
+  get_bindings     = function (...) return C.mrg_get_bindings(...) end,
+  start            = function (mrg, cssid) C.mrg_start(mrg, cssid, NULL) end,
+  start_with_style = function (mrg, cssid, style) C.mrg_start_with_style(mrg, cssid, NULL, style) end,
+  restarter_add_path = function (...) C.mrg_restarter_add_path(...) end,
+  close            = function (...) C.mrg_end(...) end,
+  queue_draw       = function (...) C.mrg_queue_draw(...) end,
+  ms               = function (...) return C.mrg_ms(...) end,
+  add_binding = function(mrg,key,action,label,cb,db_data)
+    local notify_fun, cb_fun;
+    local notify_cb = function (data1, data2,finalize_data)
+      cb_fun:free();
+      notify_fun:free();
+    end
+    notify_fun = ffi.cast ("MrgDestroyNotify", notify_cb)
+    cb_fun = ffi.cast ("MrgCb", cb)
+    return C.mrg_add_binding_full (mrg, key, action,label,cb_fun, cb_data, notify_fun, NULL)
+  end,
+
+  text_listen      = function (mrg, types, cb, data1, data2)
+    -- manually cast and destroy resources held by lua/C binding
+    local notify_fun, cb_fun;
+    local notify_cb = function (data1, data2,finalize_data)
+      cb_fun:free();
+      notify_fun:free();
+    end
+
+    notify_fun = ffi.cast ("MrgCb", notify_cb)
+    cb_fun = ffi.cast ("MrgCb", cb)
+    return C.mrg_text_listen_full (mrg, types, cb_fun, data1, data2, notify_fun, NULL)
+  end,
+  listen           = function (mrg, types, cb, data1, data2)
+    local notify_fun, cb_fun;
+    local notify_cb = function (data1, data2, finalize_data)
+      cb_fun:free();
+      notify_fun:free();
+    end
+    notify_fun = ffi.cast ("MrgCb", notify_cb)
+    cb_fun = ffi.cast ("MrgCb", cb)
+    return C.mrg_listen_full (mrg, types, cb_fun, data1, data2, notify_fun, NULL)
+  end,
+  print_get_xy     = function (mrg, str, no) 
+                         local rx = ffi.new'float[1]'
+                         local ry = ffi.new'float[1]'
+                         C.mrg_print_get_xy(mrg, str, no, rx, ry)
+                         return rx[0], ry[0]
+                       end,
+  get_cursor_pos   = function (...) return C.mrg_get_cursor_pos(...) end,
+  set_cursor_pos   = function (...) C.mrg_set_cursor_pos(...) end,
+  print            = function (...) C.mrg_print(...) end,
+  print_xml        = function (...) C.mrg_print_xml(...) end,
+
+  xml_render       = function (mrg, uri_base, link_cb, data, html)
+   local notify_fun, cb_fun;
+   local notify_cb = function (data, html, finalize_data)
+     cb_fun:free();
+     notify_fun:free();
+   end
+   local wrap_cb = function(event, href, data)
+      link_cb(event, ffi.string(href), data)
+   end
+   notify_fun = ffi.cast("MrgCb", notify_cb)
+   cb_fun = ffi.cast ("MrgLinkCb", wrap_cb)
+   return C.mrg_xml_render (mrg, uri_base, cb_fun, data, notify_fun, NULL, html)
+   end,
+  cr               = function (...) return C.mrg_cr (...) end,
+  width            = function (...) return C.mrg_width (...) end,
+  height           = function (...) return C.mrg_height (...) end,
+  set_fullscreen   = function (...) C.mrg_set_fullscreen(...) end,
+  is_fullscreen    = function (...) return C.mrg_is_fullscreen(...) ~= 0 end,
+  x                = function (...) return C.mrg_x (...) end,
+  y                = function (...) return C.mrg_y (...) end,
+  xy               = function (mrg) return mrg:x(), mrg:y() end,
+  em               = function (...) return C.mrg_em (...) end,
+  rem              = function (...) return C.mrg_rem (...) end,
+  set_xy           = function (...) C.mrg_set_xy (...) end,
+  set_size         = function (...) C.mrg_set_size (...) end,
+  set_position     = function (...) C.mrg_set_position(...) end,
+  set_title        = function (...) C.mrg_set_title (...) end,
+  window_set_value = function (...) C.mrg_window_set_value (...) end,
+  get_title        = function (...) return C.mrg_get_title (...) end,
+  set_font_size    = function (...) C.mrg_set_font_size (...) end,
+  set_target_fps   = function (...) C.mrg_set_target_fps (...) end,
+  target_fps       = function (...) return C.mrg_get_target_fps (...) end,
+
+  pointer_press = function (...) C.mrg_pointer_press (...) end,
+  pointer_release = function (...) C.mrg_pointer_release (...) end,
+  pointer_motion = function (...) C.mrg_pointer_motion (...) end,
+  key_press      = function (...) C.mrg_key_press (...) end,
+
+  add_idle = function (mrg, ms, cb, data1)
+    local notify_fun, cb_fun;
+    local notify_cb = function (a,b)
+      cb_fun:free();
+      notify_fun:free();
+    end
+    notify_fun = ffi.cast ("MrgDestroyNotify", notify_cb)
+    cb_fun = ffi.cast ("MrgIdleCb", cb)
+    return C.mrg_add_idle_full (mrg, cb_fun, data1, notify_fun, NULL)
+    -- XXX: wrap the callback so that the return isn't mandatory?
+  end,
+
+  add_timeout = function (mrg, ms, cb, data1)
+    local notify_fun, cb_fun;
+    local notify_cb = function (a,b)
+      cb_fun:free();
+      notify_fun:free();
+    end
+    notify_fun = ffi.cast ("MrgDestroyNotify", notify_cb)
+    cb_fun = ffi.cast ("MrgTimeoutCb", cb)
+    return C.mrg_add_timeout_full (mrg, ms, cb_fun, data1, notify_fun, NULL)
+  end,
+
+  host_new = function (...) 
+             return C.mrg_host_new(...)
+  end,
+  vt_new = function (...) 
+             return C.mrg_vt_new (...)
+  end,
+
+  remove_idle      = function (...) return C.mrg_remove_idle (...) end,
+  edge_left        = function (...) return C.mrg_edge_left (...) end,
+  set_edge_left    = function (...) C.mrg_set_edge_left (...) end,
+  edge_right       = function (...) return C.mrg_edge_right (...) end,
+  set_edge_right   = function (...) C.mrg_set_edge_right (...) end,
+  edge_top         = function (...) return C.mrg_edge_top (...) end,
+  set_edge_top     = function (...) C.mrg_set_edge_top (...) end,
+  edge_bottom      = function (...) return C.mrg_edge_bottom (...) end,
+  set_edge_bottom  = function (...) C.mrg_set_edge_bottom (...) end,
+}})
+ffi.metatype('MrgEvent',     {__index = { 
+
+  stop_propagate = function (...) return C.mrg_event_stop_propagate (...) end,
+  message = function (event) return ffi.string(event.string) end,
+
+}})
+
+ffi.metatype('MrgVT', {__index = {
+  poll = function (...) C.mrg_vt_poll (...) end,
+  draw = function (...) C.mrg_vt_draw (...) end,
+  rev  = function (...) return C.mrg_vt_rev (...) end,
+  destroy = function (vt) C.mrg_vt_destroy (vt); ffi.gc (vt, nil) end,
+  set_term_size = function (...) C.mrg_vt_set_term_size (...) end,
+  feed_keystring = function (...) C.mrg_vt_feed_keystring (...) end,
+  feed_byte = function (...) C.mrg_vt_feed_byte (...) end,
+  is_done = function (...) return C.mrg_vt_is_done (...) end,
+  get_result = function (...) return C.mrg_vt_get_result (...) end,
+  get_scrollback_lines = function (...) return C.mrg_vt_get_scrollback_lines (...) end,
+  set_scrollback_lines = function (...) C.mrg_vt_set_scrollback_lines (...) end,
+  get_commandline = function (...) return C.mrg_vt_get_commandline (...) end,
+  get_line_count = function (...) return C.mrg_vt_get_line_count (...) end,
+  get_line = function (...) return C.mrg_vt_get_line (...) end,
+  get_cols = function (...) return C.mrg_vt_get_cols (...) end,
+  get_rows = function (...) return C.mrg_vt_get_rows (...) end,
+  get_cursor_x = function (...) return C.mrg_vt_get_cursor_x (...) end,
+  get_cursor_y = function (...) return C.mrg_vt_get_cursor_y (...) end,
+
+}})
+
+
+ffi.metatype('MrgColor',     {__index = { }})
+ffi.metatype('MrgStyle',     {__index = { }})
+ffi.metatype('MrgRectangle', {__index = { }})
+ffi.metatype('MrgList',      {__index = { }})
+ffi.metatype('MrgHost',      {__index = {
+  set_default_size = function (...) C.mrg_host_set_default_size (...) end,
+  -- get_default_size not bound until needed
+  set_focused     = function (...) C.mrg_host_set_focused (...) end,
+  focused         = function (...) return C.mrg_host_get_focused (...) end,
+  monitor_dir     = function (...) return C.mrg_host_monitor_dir (...) end,
+  register_events = function (...) C.mrg_host_register_events (...) end,
+  destroy         = function (...) C.mrg_host_destroy (...) end,
+  clients         = function (...) 
+    local ret = {}
+    local iter = C.mrg_host_clients (...)
+    while iter ~= NULL do
+      local client 
+      ret[#ret+1] = ffi.cast("MrgClient*", iter.data)
+      iter = iter.next
+    end
+    return ret
+  end,
+
+  add_client_mrg  = function (...) C.mrg_host_add_client_mrg (...) end
+
+}})
+ffi.metatype('MrgClient',    {__index = {
+  render_sloppy = function (...) C.mrg_client_render_sloppy (...) end,
+  render        = function (...) C.mrg_client_render (...) end,
+  pid           = function (...) return C.mrg_client_get_pid (...) end,
+  kill          = function (...) C.mrg_client_kill (...) end,
+  raise_top     = function (...) C.mrg_client_raise_top (...) end,
+  set_stack_order = function (...) C.mrg_client_set_stack_order (...) end,
+  stack_order   = function (...) return C.mrg_client_get_stack_order (...) end,
+  send_message  = function (...) C.mrg_client_send_message (...) end,
+  set_value     = function (...) C.mrg_client_set_value (...) end,
+  get_value     = function (...) 
+    local f = C.mrg_client_get_value (...)
+    if f ~= NULL then
+      return ffi.string(f)
+    end
+    return nil
+  end,
+  has_message   = function (...) return C.mrg_client_has_message (...) end,
+  get_message   = function (...)
+    local f = C.mrg_client_get_message (...)
+    if f ~= NULL then
+      return ffi.string(f)
+    end
+    return nil 
+  end,
+  maximize      = function (...) C.mrg_client_maximize (...) end,
+  title         = function (...) return C.mrg_client_get_title (...) end,
+  x             = function (...) return C.mrg_client_get_x (...) end,
+  y             = function (...) return C.mrg_client_get_y (...) end,
+  set_x         = function (...) C.mrg_client_set_x (...) end,
+  set_y         = function (...) C.mrg_client_set_y (...) end,
+  set_xy        = function (client, x, y) client:set_x(x) client:set_y(y) end,
+  xy            = function (client) return client:x(), client:y() end,
+  set_size      = function (...) C.mrg_client_set_size (...) end,
+  size          = function (client)
+    local rw = ffi.new'int[1]'
+    local rh = ffi.new'int[1]'
+    C.mrg_client_get_size (client, rw, rh)
+    return rw[0], rh[0]
+  end,
+ }})
+
+  M.MOTION = C.MRG_MOTION;
+  M.ENTER = C.MRG_ENTER;
+  M.LEAVE = C.MRG_LEAVE;
+  M.PRESS = C.MRG_PRESS;
+  M.KEY_DOWN = C.MRG_KEY_DOWN;
+  M.KEY_UP = C.MRG_KEY_UP;
+  M.RELEASE = C.MRG_RELEASE;
+  M.TAP = C.MRG_TAP;
+  M.TAP_AND_HOLD = C.MRG_TAP_AND_HOLD;
+  M.DRAG_MOTION = C.MRG_DRAG_MOTION;
+  M.DRAG_PRESS = C.MRG_DRAG_PRESS;
+  M.DRAG_RELEASE = C.MRG_DRAG_RELEASE;
+  M.SCROLL = C.MRG_SCROLL;
+  M.MESSAGE= C.MRG_MESSAGE;
+  M.DRAG = C.MRG_DRAG;
+  M.ANY = C.MRG_ANY;
+  M.KEY = C.MRG_KEY;
+  M.COORD = C.MRG_COORD;
+
+
+  M.SCROLL_DIRECTION_UP = C.MRG_SCROLL_DIRECTION_UP
+  M.SCROLL_DIRECTION_DOWN = C.MRG_SCROLL_DIRECTION_DOWN
+
+keyboard_visible = false
+--local keyboard_visible = true
+
+
+local quite_complete={
+
+  {x=5,   y=26, w=44, label='esc'},
+  {x=55,   y=26, label='F1'},
+  {x=95,   y=26, label='F2'},
+  {x=135,   y=26, label='F3'},
+  {x=175,   y=26, label='F4'},
+  {x=215,   y=26, label='F5'},
+  {x=255,   y=26, label='F6'},
+  {x=295,   y=26, label='F7'},
+  {x=335,   y=26, label='F8'},
+  {x=375,   y=26, label='F9'},
+  {x=415,   y=26, label='F10'},
+  {x=455,   y=26, label='F11'},
+  {x=495,   y=26, label='F12'},
+
+
+  {x=5,   y=65, label='`', shifted='~'},
+  {x=45,   y=65, label='1', shifted='!'},
+  {x=85,  y=65, label='2', shifted='@'},
+  {x=125,  y=65, label='3', shifted='#'},
+  {x=165,  y=65, label='4', shifted='$'},
+  {x=205,  y=65, label='5', shifted='%'},
+  {x=245,  y=65, label='6', shifted='^'},
+  {x=285,  y=65, label='7', shifted='&'},
+  {x=325,  y=65, label='8', shifted='*'},
+  {x=365,  y=65, label='9', shifted='('},
+  {x=405,  y=65, label='0', shifted=')'},
+  {x=445,  y=65, label='-', shifted='_'},
+  {x=485,  y=65, label='=', shifted='+'},
+  {x=525,  w=40, y=65, label='⌫', code='backspace'},
+
+  --[[{x=355,  w=40, y=225, label='ins', code='insert'},
+  {x=400,  w=40, y=225, label='del', code='delete'},]]
+
+  {x=60,   y=105, label='q', shifted='Q'},
+  {x=100,  y=105, label='w', shifted='W'},
+  {x=140,  y=105, label='e', shifted='E'},
+  {x=180,  y=105, label='r', shifted='R'},
+  {x=220,  y=105, label='t', shifted='T'},
+  {x=260,  y=105, label='y', shifted='Y'},
+  {x=300,  y=105, label='u', shifted='U'},
+  {x=340,  y=105, label='i', shifted='I'},
+  {x=380,  y=105, label='o', shifted='O'},
+  {x=420,  y=105, label='p', shifted='P'},
+  {x=460,  y=105, label='[', shifted='{'},
+  {x=500,  y=105, label=']', shifted='}'},
+
+  {x=20,   y=105, label='↹', code='tab'},
+  {x=70,   y=145, label='a', shifted='A'},
+  {x=110,  y=145, label='s', shifted='S'},
+  {x=150,  y=145, label='d', shifted='D'},
+  {x=190,  y=145, label='f', shifted='F'},
+  {x=230,  y=145, label='g', shifted='G'},
+  {x=270,  y=145, label='h', shifted='H'},
+  {x=310,  y=145, label='j', shifted='J'},
+  {x=350,  y=145, label='k', shifted='K'},
+  {x=390,  y=145, label='l', shifted='L'},
+  {x=430,  y=145, label=';', shifted=':'},
+  {x=470,  y=145, label='\'', shifted='"'},
+  {x=510, w=45, y=145, label='⏎', code='return' },
+
+  {x=20,   w=45, y=145, label='⇧', type='modal', isshift='true'},  -- ⇧ XXX:  code relies on label
+  {x=40,  y=185, label='\\', shifted='|'},
+  {x=80,   y=185, label='z', shifted='Z'},
+  {x=120,  y=185, label='x', shifted='X'},
+  {x=160,  y=185, label='c', shifted='C'},
+  {x=200,  y=185, label='v', shifted='V'},
+  {x=240,  y=185, label='b', shifted='B'},
+  {x=280,  y=185, label='n', shifted='N'},
+  {x=320,  y=185, label='m', shifted='M'},
+  {x=360,  y=185, label=',', shifted='<'},
+  {x=400,  y=185, label='.', shifted='>'},
+  {x=440,  y=185, label='/', shifted='?'},
+
+  {x=20, w=50, y=225, label='ctrl', type='modal'},
+  {x=75, w=40,  y=225, label='alt', type='modal'},
+  {x=120,  y=225, w=230, label=' ', code='space'},
+
+  {x=440,  y=225, label='←', code='left'},
+  {x=480,  y=225, label='↓', code='down'},
+  {x=480,  y=185, label='↑', code='up'},
+  {x=520,  y=225, label='→', code='right'},
+
+  {x=355,  y=225, w=45, label='⌨', type='keyboard'},
+}
+
+local minimal={
+
+
+  --[[{x=355,  w=40, y=225, label='ins', code='insert'},
+  {x=400,  w=40, y=225, label='del', code='delete'},]]
+
+  {x=60,   y=105, label='q', shifted='Q', fn_label='1'},
+  {x=100,  y=105, label='w', shifted='W', fn_label='2'},
+  {x=140,  y=105, label='e', shifted='E', fn_label='3'},
+  {x=180,  y=105, label='r', shifted='R', fn_label='4'},
+  {x=220,  y=105, label='t', shifted='T', fn_label='5'},
+  {x=260,  y=105, label='y', shifted='Y', fn_label='6'},
+  {x=300,  y=105, label='u', shifted='U', fn_label='7'},
+  {x=340,  y=105, label='i', shifted='I', fn_label='8'},
+  {x=380,  y=105, label='o', shifted='O', fn_label='9'},
+  {x=420,  y=105, label='p', shifted='P', fn_label='0'},
+
+  {x=460,  y=105, w=28, label='[', shifted='{', fn_label='-'},
+  {x=490,  y=105, w=28, label=']', shifted='}', fn_label='+'},
+
+  {x=525,  w=40, y=105, label='⌫', code='backspace', fn_label='del', fn_code='delete'},
+
+  {x=20,   y=105, label='esc', code='escape', fn_label='↹', fn_code='tab'},
+  {x=70,   y=145, label='a', shifted='A', fn_label='!'},
+  {x=110,  y=145, label='s', shifted='S', fn_label='@'},
+  {x=150,  y=145, label='d', shifted='D', fn_label='#'},
+  {x=190,  y=145, label='f', shifted='F', fn_label='$'},
+  {x=230,  y=145, label='g', shifted='G', fn_label='%'},
+  {x=270,  y=145, label='h', shifted='H', fn_label='^'},
+  {x=310,  y=145, label='j', shifted='J', fn_label='&'},
+  {x=350,  y=145, label='k', shifted='K', fn_label='*'},
+  {x=390,  y=145, label='l', shifted='L', fn_label='('},
+  {x=430,  y=145, label=';', shifted=':', fn_label=')'},
+  {x=470,  y=145, label='\'', shifted='"', fn_label='_'},
+  {x=510, w=45, y=145, label='⏎', code='return' },
+
+  {x=20,   w=45, y=145, label='⇧', type='modal', isshift='true'},  --  XXX:  code relies on label
+  {x=40,  y=185, label='\\', shifted='|', fn_label='='},
+  {x=80,   y=185, label='z', shifted='Z', fn_label='Ø'},
+  {x=120,  y=185, label='x', shifted='X', fn_label='å'},
+  {x=160,  y=185, label='c', shifted='C', fn_label='ø'},
+  {x=200,  y=185, label='v', shifted='V', fn_label='Å'},
+  {x=240,  y=185, label='b', shifted='B', fn_label='æ'},
+  {x=280,  y=185, label='n', shifted='N', fn_label='Æ'},
+  {x=320,  y=185, label='m', shifted='M', fn_label='…'},
+  {x=360,  y=185, label=',', shifted='<', fn_label='“'},
+  {x=400,  y=185, label='.', shifted='>', fn_label='”'},
+  {x=480,  y=185, label='/', shifted='?', fn_label='€'},
+
+  {x=20,  y=225, w=30, label='Fn', shifted='Fx', type='modal'},
+  {x=55, w=50, y=225, label='ctrl', type='modal'},
+  {x=110, w=40,  y=225, label='alt', type='modal'},
+  {x=155,  y=225, w=230, label=' ', code='space'},
+
+  {x=400,  y=225, label='←', code='left', fn_label='pup', fn_code='page-up'},
+  {x=440,  y=225, label='↓', code='down', fn_label='end', fn_code='end'},
+  {x=440,  y=185, label='↑', code='up', fn_label='home', fn_code='home'},
+  {x=480 , y=225, label='→', code='right', fn_label='pdn', fn_code='page-down'},
+
+
+  {x=520,   y=185, label='`', shifted='~', fn_label='ins', fn_code='insert'},
+
+  {x=520, w=45, y=225, label='⌨', type='keyboard'},
+}
+
+local keys, y_start
+
+if false then
+  keys= quite_complete
+  y_start=42
+else
+  keys= minimal
+  y_start=82
+end
+
+local pan_y = 0
+local pan_x = 0
+local shifted = false
+local alted = false
+local ctrld = false
+local fnd = false
+local px = 0
+local py = 0
+
+M.draw_keyboard = function (mrg)
+  local em = 20
+  local cr = mrg:cr()
+  local fg = {r=0,g=0,b=0}
+  local bg = {r=1,g=1,b=1}
+
+
+  local dim = mrg:width() / 555
+
+  cr:set_font_size(em * 0.8)
+
+  cr:new_path()
+  if not keyboard_visible then
+    cr:rectangle (mrg:width() - 4 * em, mrg:height() - 3 * em, 4 * em, 3 * em)
+    mrg:listen(M.TAP+M.RELEASE, function(event)
+      keyboard_visible = true
+      mrg:queue_draw(nil)
+    end)
+    cr:set_source_rgba(bg.r,bg.g,bg.b,0.2)
+    cr:fill()
+    mrg:set_style('background:transparent; color: rgba(0,0,0,0.5); font-size: 1.9em')
+    mrg:set_xy(mrg:width() - 3 * em, mrg:height() - 0.5 * em)
+    mrg:print('⌨')
+  else
+    cr:translate(0,mrg:height()-250* dim)
+    cr:scale(dim, dim)
+    cr:translate(pan_x, pan_y)
+
+    cr:rectangle(0,y_start,620,166)
+    cr:set_source_rgba(bg.r,bg.g,bg.b,0.6)
+    mrg:listen(M.COORD, function(e) 
+        px = e.x;
+        py = e.y;
+        mrg:queue_draw(nil)
+       e:stop_propagate() end)
+    cr:fill()
+
+    for k,v in ipairs(keys) do
+      cr:new_path()
+      if not v.w then v.w = 34 end
+      if v.w then
+        cr:rectangle(v.x - em * 0.8, v.y - em, v.w, em * 1.8)
+      else
+        cr:arc (v.x, v.y, em, 0, 3.1415*2)
+      end
+      mrg:listen(M.TAP+M.RELEASE, function(event)
+        px = event.x;
+        py = event.y;
+        if v.type == 'keyboard' then
+          keyboard_visible = false
+        elseif (not v.isshift) and (v.label ~= 'Fn') and (v.label ~= 'ctrl') then
+          local keystr = v.label
+          if shifted and v.shifted then keystr = v.shifted end
+          if fnd and v.fn_label then keystr = v.fn_label end
+
+          if v.code            then keystr = v.code end
+          if fnd and v.fn_code then keystr = v.fn_code end
+          if alted             then keystr = 'alt-' .. keystr end
+          if ctrld             then keystr = 'control-' .. keystr end
+
+          mrg:key_press(0, keystr, 0)
+        end
+        mrg:queue_draw(nil)
+        event:stop_propagate()
+      end)
+      if v.active or cr:in_fill(px,py) then
+        cr:set_source_rgba (bg.r,bg.g,bg.b,0.8)
+      else
+        cr:set_source_rgba (fg.r,fg.g,fg.b,0.8)
+      end
+      cr:set_line_width(1)
+      cr:stroke_preserve()
+      if v.type == 'modal' then
+
+        mrg:listen(M.TAP+M.RELEASE, function(event)
+          if v.isshift then
+            shifted = not shifted
+            v.active = shifted
+            mrg:queue_draw(nil)
+          end
+          if v.label == 'ctrl' then
+            ctrld = not ctrld
+            v.active = ctrld
+            mrg:queue_draw(nil)
+          end
+          if v.label == 'alt' then
+            alted = not alted
+            v.active = alted
+            mrg:queue_draw(nil)
+          end
+          if v.label == 'Fn' then
+            fnd = not fnd
+            v.active = fnd
+            mrg:queue_draw(nil)
+          end
+        end)
+        if (v.active and false) then
+          cr:set_source_rgba (fg.r,fg.g,fg.b,0.8)
+          cr:set_line_width(4)
+          cr:stroke_preserve()
+        end
+
+      end
+      if v.active or cr:in_fill(px,py) then
+        cr:set_source_rgba (fg.r,fg.g,fg.b,0.5)
+      else
+        cr:set_source_rgba (bg.r,bg.g,bg.b,0.5)
+      end
+      cr:fill ()
+      cr:move_to (v.x - 6, v.y + 4)
+      if v.active then
+        cr:set_source_rgba (bg.r,bg.g,bg.b,1.0)
+      else
+        cr:set_source_rgba (fg.r,fg.g,fg.b,1.0)
+      end
+
+      if fnd then
+        if v.fn_label then
+            cr:show_text (v.fn_label)
+        else
+            cr:show_text (v.label)
+        end
+      else
+        if shifted then
+          if v.shifted then
+            cr:show_text (v.shifted)
+          else
+            cr:show_text (v.label)
+          end
+        else
+          cr:show_text (v.label)
+        end
+      end
+    end
+
+    cr:rectangle(340,205,30,35)
+    mrg:listen(M.DRAG, function(event)
+      if pan_y + event.delta_y < 0  and event.device_y > 180 then
+        pan_y = pan_y + event.delta_y
+      end
+      mrg:queue_draw(nil)
+      event.stop_propagate()
+    end)
+    cr:new_path()
+  end
+end
+
+return M
diff --git a/bin/lua/mrl.lua b/bin/lua/mrl.lua
new file mode 100755
index 000000000..b69953e08
--- /dev/null
+++ b/bin/lua/mrl.lua
@@ -0,0 +1,146 @@
+local Mrg = require('mrg')
+local M = {}
+local S = require('syscall')
+
+function M.serialize (o)
+  if type(o)     == "number" then return o
+  elseif type(o) == "nil" then return "nil"
+  elseif type(o) == "boolean" then
+    if o == true then
+      return "true" else
+      return "false"
+    end
+  elseif type(o) == "string" then return string.format("%q", o)
+  elseif type(o) == "table" then
+    local ret = "{"
+    for k,v in pairs(o) do
+      ret = ret .. k .. '=' .. M.serialize(v) .. ','
+    end
+    ret = ret .. '}'
+    return ret
+  else
+    error("cannot serialize a " .. type(o))
+  end
+end
+
+
+---------------
+
+local in_modal = false
+local modal_x, modal_y = 100, 100
+local modal_choices={}
+local modal_string=nil
+
+function M.modal(mrg, x, y, choices)
+  if choices then
+    modal_choices = choices
+  else
+    modal_choices = {}
+  end
+  local w, h = 100, 100
+  if x < w/2 then x = w/2 end
+  if y < h/2 then y = h/2 end
+  if x > mrg:width()  - w/2 then x = mrg:width ()-w/2 end
+  if y > mrg:height() - h/2 then y = mrg:height()-h/2 end
+  modal_x  = x
+  modal_y  = y
+  in_modal = true
+  modal_string = nil
+  mrg:set_cursor_pos(0)
+  mrg:queue_draw(nil)
+end
+
+function M.modal_end(mrg)
+  in_modal = false
+  mrg:queue_draw(nil)
+end
+
+function M.modal_draw(mrg)
+  if not in_modal then return end
+
+  local cr = mrg:cr()
+  -- block out all other events, making clicking outside cancel
+
+  cr:rectangle (0,0,mrg:width(),mrg:height())
+  cr:set_source_rgba(0,0,0,0.5)
+  mrg:listen(Mrg.COORD, function(event)
+    event:stop_propagate()
+  end)
+  mrg:listen(Mrg.TAP, function(event)
+    M.modal_end (mrg)
+  end)
+  cr:fill()
+  
+  cr:rectangle (modal_x - 50, modal_y - 50, 100, 100)
+  cr:set_source_rgba(0,0,0, 0.5)
+  mrg:listen(Mrg.COORD, function(event)
+    event:stop_propagate()
+  end)
+  cr:fill()
+
+  mrg:set_edge_left(modal_x - 50)
+  mrg:set_edge_top(modal_y - 50)
+  mrg:set_style('background:transparent; color: white; ')
+
+  for i,v in pairs(modal_choices) do
+    mrg:text_listen(Mrg.TAP, function(event)
+      if v.cb and v.type ~= 'edit' then 
+        M.modal_end (mrg)
+        v.cb() 
+      end
+      mrg:queue_draw(nil)
+    end)
+
+    if v.type == 'edit' then
+      mrg:edit_start(function(new_text)
+        modal_string = new_text
+      end)
+      
+      if modal_string then
+        mrg:print(modal_string)
+      else
+        mrg:print(v.title )
+      end
+
+      mrg:edit_end()  
+
+      mrg:add_binding("return", NULL, NULL, 
+        function (event)
+          if modal_string then
+            v.cb (modal_string) -- print ('return!!')
+            modal_string = nil
+          end
+          event:stop_propagate()
+        end)
+    else
+      mrg:print(v.title )
+    end
+    mrg:print("\n")
+
+    mrg:text_listen_done ()
+  end
+end
+
+
+function M.which(command)
+  local ret = ''
+  local PATH = '.:' .. S.getenv('PATH') 
+  for str in string.gmatch(PATH, "([^:]+)") do
+    if S.stat(str .. '/' .. command) then
+      local cmpstr = str
+      if cmpstr == '.' then cmpstr = S.getcwd() end
+      return cmpstr .. '/' .. command
+    end
+  end
+  return nil
+end
+
+
+function string.has_suffix(String,End)
+   return End=='' or string.sub(String,-string.len(End))==End
+end
+function string.has_prefix(String,Start)
+     return string.sub(String,1,string.len(Start))==Start
+end
+
+return M
diff --git a/bin/ui.c b/bin/ui.c
index f0b1da02b..a114b4626 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -843,12 +843,35 @@ int mrg_ui_main (int argc, char **argv, char **ops)
   {
     int status, result;
     char *init_path = resolve_lua_file ("init.lua");
+    const char * const *data_dirs = g_get_system_data_dirs ();
+
     L = luaL_newstate ();
     luaL_openlibs(L);
 
+    /* expose o as a global light user data for luajit ffi interactions */
     lua_pushlightuserdata (L, o);
     lua_setglobal(L, "STATE");
 
+    /* set up package path to permit using mrg, mmm and cairo ffi bindings
+       we ship with, making it easier to get all dependencies sorted.
+     */
+    status = luaL_loadstring(L, "package.path = package.path .. ';./lua/?.lua'\n"
+);
+    result = lua_pcall(L, 0, LUA_MULTRET, 0);
+    if (result){
+      fprintf (stderr, "lua exec problem %s\n", lua_tostring(L, -1));
+    }
+
+    for (int i = 0; data_dirs[i]; i++)
+    {
+      char *script = g_strdup_printf ("package.path = package.path .. ';%s/gegl-0.4/lua/?.lua'\n", 
data_dirs[i]);
+      status = luaL_loadstring(L, script);
+      result = lua_pcall(L, 0, LUA_MULTRET, 0);
+      if (result){
+        fprintf (stderr, "lua exec problem %s\n", lua_tostring(L, -1));
+      }
+    }
+
     if (init_path)
     {
       status = luaL_loadfile(L, init_path);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]