>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