>From 8e632532c6ef550961cd16ec668918b1e91b7935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Mon, 29 Apr 2019 12:36:53 +0200 Subject: [PATCH] Add bindings for cairo-xlib. This binds together cairo-xlib, guile-cairo, and guile-xlib. This code is semi-transpansparent, since guile-xlib and guile-cairo has different approaches to bindings (the former being opaque, the later transparent). Names are however kept in style with guile-cairo. --- configure.ac | 14 ++++ guile-cairo.pc.in | 2 +- guile-cairo/Makefile.am | 2 +- guile-cairo/guile-cairo.c | 165 +++++++++++++++++++++++++++++++++++++- 4 files changed, 179 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index a8ba654..1a7334e 100644 --- a/configure.ac +++ b/configure.ac @@ -97,6 +97,20 @@ PKG_CHECK_MODULES(CAIRO, cairo >= 1.10.0) AC_SUBST(CAIRO_LIBS) AC_SUBST(CAIRO_CFLAGS) +AC_ARG_WITH([xlib], + AS_HELP_STRING([--with-xlib], + [Add xlib bindings. @<:@default=false@:>@]), + [], + [with_xlib=no]) + +AC_SUBST(XLIB, guile2-xlib) +AS_IF([test "x$with_xlib" != "xno"], [ + PKG_CHECK_MODULES(GUILE_X, guile2-xlib >= 0.2) + AC_SUBST(GUILE_X_LIBS) + AC_SUBST(GUILE_X_CFLAGS) + AC_SUBST(XLIB, guile2-xlib) +]) + AC_ARG_VAR(CAIRO_XML_DIR, [path to Cairo *.xml documentation]) AC_CONFIG_FILES([env], [chmod +x env]) diff --git a/guile-cairo.pc.in b/guile-cairo.pc.in index dfe34df..223faf6 100644 --- a/guile-cairo.pc.in +++ b/guile-cairo.pc.in @@ -6,6 +6,6 @@ address@hidden@/guile-cairo Name: guile-cairo Description: Cairo binding for Guile Scheme Version: @VERSION@ -Requires: cairo address@hidden@ +Requires: cairo address@hidden@ @XLIB@ Libs: -L${libdir} -lguile-cairo Cflags: -I${includedir} diff --git a/guile-cairo/Makefile.am b/guile-cairo/Makefile.am index 12838bc..cae8ed2 100644 --- a/guile-cairo/Makefile.am +++ b/guile-cairo/Makefile.am @@ -29,7 +29,7 @@ libguile_cairo_la_SOURCES = guile-cairo.c \ libguile_cairo_la_CFLAGS = $(CAIRO_CFLAGS) $(AM_CFLAGS) $(GUILE_CFLAGS) -libguile_cairo_la_LIBADD = $(CAIRO_LIBS) $(GUILE_LIBS) +libguile_cairo_la_LIBADD = $(CAIRO_LIBS) $(GUILE_LIBS) $(GUILE_X_LIBS) libguile_cairo_la_LDFLAGS = -export-dynamic libguile_cairo_la_includedir = $(includedir)/guile-cairo diff --git a/guile-cairo/guile-cairo.c b/guile-cairo/guile-cairo.c index 4136915..1340297 100644 --- a/guile-cairo/guile-cairo.c +++ b/guile-cairo/guile-cairo.c @@ -36,11 +36,25 @@ #include #endif /* CAIRO_HAS_SVG_SURFACE */ +/* TODO this should be anded with a symbol from + automake showing that guile-xlib was available */ +#define WITH_XLIB CAIRO_HAS_XLIB_SURFACE + +#if WITH_XLIB +#include +#include +#endif /* WITH_XLIB */ + #include "guile-cairo-compat.h" #include "guile-cairo.h" static cairo_user_data_key_t scm_cairo_key; +#if WITH_XLIB +static SCM xlib_drawable_table; +static SCM xlib_screen_table; +#endif /* WITH_XLIB */ + #if SCM_MAJOR_VERSION >= 2 #define UNPROTECT (cairo_destroy_func_t)scm_gc_unprotect_object #else @@ -2342,7 +2356,7 @@ SCM_DEFINE_PUBLIC (scm_cairo_surface_mark_dirty_rectangle, "cairo-surface-mark-d scm_to_double (y), scm_to_double (width), scm_to_double (height)); - + SCHKRET (surf, SCM_UNSPECIFIED); } @@ -3465,7 +3479,149 @@ cairo_svg_version_to_string (cairo_svg_version_t version); #endif /* CAIRO_HAS_SVG_SURFACE */ - +#if WITH_XLIB + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_create, "cairo-xlib-surface-create", 3, 0, 0, + (SCM drawable, SCM width, SCM height), + "") +#define FUNC_NAME s_scm_cairo_xlib_surface_create +{ + xwindow_t *win = valid_win (drawable, SCM_ARG1, ~XWINDOW_STATE_DESTROYED, FUNC_NAME); + xdisplay_t *dsp = get_display (scm_x_display_of (drawable)); + + /* Visual set to DefaultVisual since Gulie2-Xlib currently lacks Visual support */ + Visual *v = DefaultVisual (dsp->dsp, XDefaultScreen(dsp->dsp)); + cairo_surface_t *surf = cairo_xlib_surface_create ( dsp->dsp, + win->win, + v, + scm_to_int (width), + scm_to_int (height)); + + /* Manual copying of SCONSRET to have time to run scm_hashq_set_x */ + scm_c_check_cairo_status (cairo_surface_status (surf), NULL); + SCM smob = scm_take_cairo_surface (surf); + scm_hashq_set_x (xlib_drawable_table, smob, drawable); + return smob; +} +#undef FUNC_NAME + +/* cairo_xlib_surface_create_for_bitmap */ + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_create_for_bitmap, "cairo-xlib-surface-create-for-bitmap", 4, 0, 0, + (SCM drawable, SCM screen, SCM width, SCM height), + "") +#define FUNC_NAME s_scm_cairo_xlib_surface_create_for_bitmap +{ + xwindow_t *pix = valid_win (drawable, SCM_ARG1, XWINDOW_STATE_PIXMAP, FUNC_NAME); + SCM display = scm_x_display_of (drawable); + xdisplay_t *dsp = get_display (display); + + xscreen_t *scr = ((xscreen_t *) SCM_SMOB_DATA (screen)); + + cairo_surface_t *surf = cairo_xlib_surface_create_for_bitmap ( dsp->dsp, + pix->win, + scr->scr, + scm_to_int (width), + scm_to_int (height)); + + /* Manual copying of SCONSRET to have time to run scm_hashq_set_x */ + scm_c_check_cairo_status (cairo_surface_status (surf), NULL); + SCM smob = scm_take_cairo_surface (surf); + scm_hashq_set_x (xlib_drawable_table, smob, drawable); + scm_hashq_set_x (xlib_screen_table, smob, screen); + return smob; +} +#undef FUNC_NAME + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_set_size, "cairo-xlib-surface-set-size", 3, 0, 0, + (SCM surf, SCM width, SCM height), + "") +{ + cairo_xlib_surface_set_size (scm_to_cairo_surface (surf), + scm_to_int (width), + scm_to_int (height)); + SCHKRET (surf, SCM_UNSPECIFIED); +} + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_set_drawable, "cairo-xlib-surface-set-drawable", 4, 0, 0, + (SCM surface, SCM drawable, SCM width, SCM height), + "") +#define FUNC_NAME s_scm_cairo_xlib_surface_set_drawable +{ + xwindow_t *win = valid_win (drawable, SCM_ARG1, ~XWINDOW_STATE_DESTROYED, FUNC_NAME); + cairo_xlib_surface_set_drawable (scm_to_cairo_surface (surface), + win->win, + scm_to_int (width), + scm_to_int (height)); + scm_hashq_set_x (xlib_drawable_table, surface, drawable); + SCHKRET (surface, SCM_UNSPECIFIED); +} +#undef FUNC_NAME + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_get_display, "cairo-xlib-surface-get-display", 1, 0, 0, + (SCM surface), + "") +#define FUNC_NAME s_scm_cairo_xlib_surface_get_display +{ + SCM ret = scm_hashq_ref (xlib_drawable_table, surface, SCM_BOOL_F); + if (scm_is_false (ret)) + scm_misc_error (FUNC_NAME, "No Display found for surface ~a.", scm_list_1 (surface)); + + return scm_x_display_of (ret); +} +#undef FUNC_NAME + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_get_drawable, "cairo-xlib-surface-get-drawable", 1, 0, 0, + (SCM surface), + "") +#define FUNC_NAME s_scm_cairo_xlib_surface_get_drawable +{ + SCM ret = scm_hashq_ref (xlib_drawable_table, surface, SCM_BOOL_F); + if (scm_is_false (ret)) + scm_misc_error (FUNC_NAME, "No Drawable found for surface ~a.", scm_list_1 (surface)); + + return ret; +} +#undef FUNC_NAME + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_get_screen, "cairo-xlib-surface-get-screen", 1, 0, 0, + (SCM surface), + "") +#define FUNC_NAME s_scm_cairo_xlib_surface_get_screen +{ + SCM ret = scm_hashq_ref (xlib_screen_table, surface, SCM_BOOL_F); + if (scm_is_false (ret)) + scm_misc_error (FUNC_NAME, "No Screen found for surface ~a.", scm_list_1 (surface)); + + return ret; +} +#undef FUNC_NAME + +/* Visual ommited since Gulie2-Xlib currently lacks Visual support */ +/* cairo_xlib_surface_get_visual */ + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_get_depth, "cairo-xlib-surface-get-depth", 1, 0, 0, + (SCM surface), + "") +{ + return scm_from_int (cairo_xlib_surface_get_depth (scm_to_cairo_surface (surface))); +} + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_get_width, "cairo-xlib-surface-get-width", 1, 0, 0, + (SCM surface), + "") +{ + return scm_from_int (cairo_xlib_surface_get_width (scm_to_cairo_surface (surface))); +} + +SCM_DEFINE_PUBLIC (scm_cairo_xlib_surface_get_height, "cairo-xlib-surface-get-height", 1, 0, 0, + (SCM surface), + "") +{ + return scm_from_int (cairo_xlib_surface_get_height (scm_to_cairo_surface (surface))); +} + +#endif /* WITH_XLIB */ void scm_init_cairo (void) @@ -3483,5 +3639,10 @@ scm_init_cairo (void) scm_init_cairo_vector_types (); scm_init_cairo_enum_types (); + // TODO check GC around this + SCM s = scm_from_int(0x10); + xlib_drawable_table = scm_make_weak_key_hash_table (s); + xlib_screen_table = scm_make_weak_key_hash_table (s); + initialized = 1; } -- 2.21.0