[cairo-commit] cairo-ocaml/src ml_cairo_lablgtk.c, 1.13, 1.14 cairo_lablgtk.mli, 1.6, 1.7 cairo_lablgtk.ml, 1.4, 1.5

Olivier Andrieu commit at pdx.freedesktop.org
Tue Dec 13 14:42:04 PST 2005


Committed by: oandrieu

Update of /cvs/cairo/cairo-ocaml/src
In directory gabe:/tmp/cvs-serv6245/src

Modified Files:
	ml_cairo_lablgtk.c cairo_lablgtk.mli cairo_lablgtk.ml 
Log Message:
* src/*lablgtk*: sync cairo_lablgtk module with the gdk_cairo_* API of GTK+ 2.8.
* test/*: adapt


Index: ml_cairo_lablgtk.c
===================================================================
RCS file: /cvs/cairo/cairo-ocaml/src/ml_cairo_lablgtk.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- ml_cairo_lablgtk.c	10 Aug 2005 23:45:15 -0000	1.13
+++ ml_cairo_lablgtk.c	13 Dec 2005 22:42:02 -0000	1.14
@@ -7,142 +7,201 @@
 /**************************************************************************/
 
 #include "ml_cairo.h"
-#if CAIRO_HAS_XLIB_SURFACE
-# include <cairo-xlib.h>
-#endif
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gdk/gdk.h>
-#include <gdk/gdkx.h>
 
 #include "wrappers.h"
 #include "ml_gobject.h"
 #include "ml_gdkpixbuf.h"
 #include "ml_gdk.h"
 
-CAMLprim value
-ml_cairo_lablgtk_of_pixbuf (value pb)
-{
-  GdkPixbuf *pixbuf = GdkPixbuf_val(pb);
-  cairo_format_t format;
-  gboolean alpha = gdk_pixbuf_get_has_alpha(pixbuf);
-  int nchan = gdk_pixbuf_get_n_channels(pixbuf);
-  int bps = gdk_pixbuf_get_bits_per_sample(pixbuf);
-  cairo_surface_t *surf;
-
-  if ((nchan == 4) && (bps == 8) && alpha)
-    format = CAIRO_FORMAT_ARGB32;
-  else 
-    caml_invalid_argument ("bad GdkPixbuf format");
 
-  surf = cairo_image_surface_create_for_data (gdk_pixbuf_get_pixels (pixbuf),
-					      format,
-					      gdk_pixbuf_get_width(pixbuf),
-					      gdk_pixbuf_get_height(pixbuf),
-					      gdk_pixbuf_get_rowstride(pixbuf));
-
-  ml_cairo_surface_set_image_data (surf, pb);
-
-  return Val_cairo_surface_t (surf);
-}
+#if ! GTK_CHECK_VERSION(2,8,0)
+/* For "old" versions of GTK+, provide the GTK+/cairo integration,
+   (stolen from GTK+)
+*/
+#include <gdk/gdkx.h>
+#ifdef CAIRO_HAS_XLIB_SURFACE
+#  include <cairo-xlib.h>
+#else
+#  error "Cairo was not compiled with support for the xlib backend"
+#endif
 
-CAMLprim value
-ml_cairo_lablgtk_shuffle_pixels (value pb)
+static cairo_t *
+gdk_cairo_create (GdkDrawable *target)
 {
-  GdkPixbuf *pixbuf = GdkPixbuf_val(pb);
-  guint w, h, s, i, j;
-  guchar *pixels, *p;
+  int width, height;
+  int x_off=0, y_off=0;
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  GdkDrawable *drawable = target;
+  GdkVisual *visual;
 
-  g_return_val_if_fail (gdk_pixbuf_get_has_alpha(pixbuf) &&
-			(gdk_pixbuf_get_n_channels(pixbuf) == 4) &&
-			(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8), Val_unit);
+  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
 
-  w = gdk_pixbuf_get_width (pixbuf);
-  h = gdk_pixbuf_get_height (pixbuf);
-  s = gdk_pixbuf_get_rowstride (pixbuf);
-  pixels = gdk_pixbuf_get_pixels (pixbuf);
+  if (GDK_IS_WINDOW(target)) {
+    /* query the window's backbuffer if it has one */
+    GdkWindow *window = GDK_WINDOW(target);
+    gdk_window_get_internal_paint_info (window,
+					&drawable, &x_off, &y_off);
+  }
+  visual = gdk_drawable_get_visual (drawable);
+  gdk_drawable_get_size (drawable, &width, &height);
 
-  for (i=0; i<h; i++) {
-    p = pixels;
-    for (j=0; j<w; j++) {
-      guchar red = p[0];
-      p[0] = p[2];
-      p[2] = red;
-      p += 4;
-    }
-    pixels += s;
+  if (visual) {
+    surface = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY (drawable),
+					 GDK_DRAWABLE_XID (drawable),
+					 GDK_VISUAL_XVISUAL (visual),
+					 width, height);
+  } else if (gdk_drawable_get_depth (drawable) == 1) {
+    surface = cairo_xlib_surface_create_for_bitmap
+      (GDK_PIXMAP_XDISPLAY (drawable),
+       GDK_PIXMAP_XID (drawable),
+       GDK_SCREEN_XSCREEN (gdk_drawable_get_screen (drawable)),
+       width, height);
+  } else {
+    g_warning ("Using Cairo rendering requires the drawable argument to\n"
+	       "have a specified colormap. All windows have a colormap,\n"
+	       "however, pixmaps only have colormap by default if they\n"
+	       "were created with a non-NULL window argument. Otherwise\n"
+	       "a colormap must be set on them with "
+	       "gdk_drawable_set_colormap");
+    return NULL;
   }
+  cairo_surface_set_device_offset (surface, -x_off, -y_off);
 
-  return Val_unit;
-}
+  cr = cairo_create (surface);
+  cairo_surface_destroy (surface);
 
+  return cr;
+}
 
-#if CAIRO_HAS_XLIB_SURFACE
-/* copied from pycairo, who got it from GTK+ */
-static cairo_surface_t *
-ml_gdk_cairo_surface_create (GdkDrawable *target)
+static void
+gdk_cairo_set_source_color (cairo_t  *cr,
+			    GdkColor *color)
 {
-    int width, height;
-    int x_off=0, y_off=0;
-    cairo_surface_t *surface;
-    GdkDrawable *drawable = target;
-    GdkVisual *visual;
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (color != NULL);
+    
+  cairo_set_source_rgb (cr,
+			color->red / 65535.,
+			color->green / 65535.,
+			color->blue / 65535.);
+}
 
-    if (GDK_IS_WINDOW(target)) {
-        /* query the window's backbuffer if it has one */
-	GdkWindow *window = GDK_WINDOW(target);
-	gdk_window_get_internal_paint_info (window,
-					    &drawable, &x_off, &y_off);
-    }
-    visual = gdk_drawable_get_visual (drawable);
-    gdk_drawable_get_size (drawable, &width, &height);
+static void
+gdk_cairo_rectangle (cairo_t      *cr,
+		     GdkRectangle *rectangle)
+{
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (rectangle != NULL);
 
-    if (visual) {
-	surface = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY (drawable),
-					     GDK_DRAWABLE_XID (drawable),
-					     GDK_VISUAL_XVISUAL (visual),
-					     width, height);
-    } else if (gdk_drawable_get_depth (drawable) == 1) {
-	surface = cairo_xlib_surface_create_for_bitmap
-	    (GDK_PIXMAP_XDISPLAY (drawable),
-	     GDK_PIXMAP_XID (drawable),
-	     GDK_SCREEN_XSCREEN (gdk_drawable_get_screen (drawable)),
-	     width, height);
-    } else {
-	g_warning ("Using Cairo rendering requires the drawable argument to\n"
-		   "have a specified colormap. All windows have a colormap,\n"
-		   "however, pixmaps only have colormap by default if they\n"
-		   "were created with a non-NULL window argument. Otherwise\n"
-		   "a colormap must be set on them with "
-		   "gdk_drawable_set_colormap");
-	return NULL;
-    }
-    cairo_surface_set_device_offset (surface, -x_off, -y_off);
-    return surface;
+  cairo_rectangle (cr,
+		   rectangle->x,     rectangle->y,
+		   rectangle->width, rectangle->height);
 }
 
-CAMLprim value
-ml_cairo_xlib_surface_create (value d)
+static void
+gdk_cairo_region (cairo_t   *cr,
+		  GdkRegion *region)
 {
-  return Val_cairo_surface_t (ml_gdk_cairo_surface_create (GdkDrawable_val(d)));
+  caml_failwith("Cairo_lablgtk.region is unsupported with this version of GTK+");
 }
 
-ML_3 (cairo_xlib_surface_set_size, cairo_surface_t_val, Int_val, Int_val, Unit)
-
-CAMLprim value
-ml_cairo_xlib_surface_set_drawable (value s, value d, value w, value h)
+static void
+gdk_cairo_set_source_pixbuf (cairo_t   *cr,
+			     GdkPixbuf *pixbuf,
+			     double     pixbuf_x,
+			     double     pixbuf_y)
 {
-  cairo_xlib_surface_set_drawable (cairo_surface_t_val (s),
-				   GDK_DRAWABLE_XID (GdkDrawable_val (d)),
-				   Int_val (w),
-				   Int_val (h));
-  return Val_unit;
-}
+  gint width = gdk_pixbuf_get_width (pixbuf);
+  gint height = gdk_pixbuf_get_height (pixbuf);
+  guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+  int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+  guchar *cairo_pixels;
+  cairo_format_t format;
+  cairo_surface_t *surface;
+  static const cairo_user_data_key_t key;
+  int j;
 
-#else
+  if (n_channels == 3)
+    format = CAIRO_FORMAT_RGB24;
+  else
+    format = CAIRO_FORMAT_ARGB32;
 
-Cairo_Unsupported(cairo_xlib_surface_create, "Xlib backend not supported");
-Cairo_Unsupported(cairo_xlib_surface_set_size, "Xlib backend not supported");
-Cairo_Unsupported(cairo_xlib_surface_set_drawable, "Xlib backend not supported");
+  cairo_pixels = g_malloc (4 * width * height);
+  surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels,
+						 format,
+						 width, height, 4 * width);
+  cairo_surface_set_user_data (surface, &key,
+			       cairo_pixels, (cairo_destroy_func_t)g_free);
 
-#endif /* CAIRO_HAS_XLIB_SURFACE */
+  for (j = height; j; j--)
+    {
+      guchar *p = gdk_pixels;
+      guchar *q = cairo_pixels;
+
+      if (n_channels == 3)
+	{
+	  guchar *end = p + 3 * width;
+	  
+	  while (p < end)
+	    {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+	      q[0] = p[2];
+	      q[1] = p[1];
+	      q[2] = p[0];
+#else	  
+	      q[1] = p[0];
+	      q[2] = p[1];
+	      q[3] = p[2];
+#endif
+	      p += 3;
+	      q += 4;
+	    }
+	}
+      else
+	{
+	  guchar *end = p + 4 * width;
+	  guint t1,t2,t3;
+	    
+#define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
+
+	  while (p < end)
+	    {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+	      MULT(q[0], p[2], p[3], t1);
+	      MULT(q[1], p[1], p[3], t2);
+	      MULT(q[2], p[0], p[3], t3);
+	      q[3] = p[3];
+#else	  
+	      q[0] = p[3];
+	      MULT(q[1], p[0], p[3], t1);
+	      MULT(q[2], p[1], p[3], t2);
+	      MULT(q[3], p[2], p[3], t3);
+#endif
+	      
+	      p += 4;
+	      q += 4;
+	    }
+	  
+#undef MULT
+	}
+
+      gdk_pixels += gdk_rowstride;
+      cairo_pixels += 4 * width;
+    }
+
+  cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y);
+  cairo_surface_destroy (surface);
+}
+
+#endif /* GTK_CHECK_VERSION(2,8,0) */
+
+wML_1(gdk_cairo_create, GdkDrawable_val, Val_cairo_t)
+wML_2(gdk_cairo_set_source_color, cairo_t_val, GdkColor_val, Unit)
+wML_2(gdk_cairo_rectangle, cairo_t_val, GdkRectangle_val, Unit)
+wML_2(gdk_cairo_region, cairo_t_val, GdkRegion_val, Unit)
+wML_4(gdk_cairo_set_source_pixbuf, cairo_t_val, GdkPixbuf_val, Double_val, Double_val, Unit)

Index: cairo_lablgtk.mli
===================================================================
RCS file: /cvs/cairo/cairo-ocaml/src/cairo_lablgtk.mli,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cairo_lablgtk.mli	10 Aug 2005 23:45:15 -0000	1.6
+++ cairo_lablgtk.mli	13 Dec 2005 22:42:02 -0000	1.7
@@ -6,16 +6,16 @@
 (*  GNU Lesser General Public License version 2.1 (the "LGPL").           *)
 (**************************************************************************)
 
-(** Xlib backend, via LablGTK *)
+(** GTK/Cairo integration *)
 
-type surface = [`Any|`Xlib] Cairo.surface
+(** These functions are available with GTK+ 2.8. 
+    For older versions of GTK+, an implementation is provided, except for [region].
 
-external image_of_pixbuf : GdkPixbuf.pixbuf -> Cairo.image_surface = "ml_cairo_lablgtk_of_pixbuf"
-external shuffle_pixels  : GdkPixbuf.pixbuf -> unit = "ml_cairo_lablgtk_shuffle_pixels"
+    cf. {{:"http://developer.gnome.org/doc/API/2.0/gdk/gdk-Cairo-Interaction.html"}Cairo Interaction} in the GDK Reference Manual. *)
 
-external surface_create : [> `drawable] Gobject.obj -> surface = "ml_cairo_xlib_surface_create"
-external surface_set_size : [> `Xlib] Cairo.surface -> int -> int -> unit = "ml_cairo_xlib_surface_set_size"
-external surface_set_drawable :
-  [> `Xlib] Cairo.surface -> 
-  [> `drawable] Gobject.obj -> 
-  int -> int -> unit = "ml_cairo_xlib_surface_set_drawable"
+external create           : [> `drawable] Gobject.obj -> Cairo.t = "ml_gdk_cairo_create"
+external set_source_color : Cairo.t -> Gdk.color -> unit = "ml_gdk_cairo_set_source_color"
+external rectangle        : Cairo.t -> Gdk.Rectangle.t -> unit = "ml_gdk_cairo_rectangle"
+external region           : Cairo.t -> Gdk.region -> unit = "ml_gdk_cairo_region"
+
+external set_source_pixbuf : Cairo.t -> GdkPixbuf.pixbuf -> float -> float -> unit = "ml_gdk_cairo_set_source_pixbuf"

Index: cairo_lablgtk.ml
===================================================================
RCS file: /cvs/cairo/cairo-ocaml/src/cairo_lablgtk.ml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cairo_lablgtk.ml	10 Aug 2005 23:45:15 -0000	1.4
+++ cairo_lablgtk.ml	13 Dec 2005 22:42:02 -0000	1.5
@@ -6,14 +6,9 @@
 (*  GNU Lesser General Public License version 2.1 (the "LGPL").           *)
 (**************************************************************************)
 
-type surface = [`Any|`Xlib] Cairo.surface
-
-external image_of_pixbuf : GdkPixbuf.pixbuf -> Cairo.image_surface = "ml_cairo_lablgtk_of_pixbuf"
-external shuffle_pixels  : GdkPixbuf.pixbuf -> unit = "ml_cairo_lablgtk_shuffle_pixels"
+external create           : [> `drawable] Gobject.obj -> Cairo.t = "ml_gdk_cairo_create"
+external set_source_color : Cairo.t -> Gdk.color -> unit = "ml_gdk_cairo_set_source_color"
+external rectangle        : Cairo.t -> Gdk.Rectangle.t -> unit = "ml_gdk_cairo_rectangle"
+external region           : Cairo.t -> Gdk.region -> unit = "ml_gdk_cairo_region"
 
-external surface_create : [> `drawable] Gobject.obj -> surface = "ml_cairo_xlib_surface_create"
-external surface_set_size : [> `Xlib] Cairo.surface -> int -> int -> unit = "ml_cairo_xlib_surface_set_size"
-external surface_set_drawable :
-  [> `Xlib] Cairo.surface -> 
-  [> `drawable] Gobject.obj -> 
-  int -> int -> unit = "ml_cairo_xlib_surface_set_drawable"
+external set_source_pixbuf : Cairo.t -> GdkPixbuf.pixbuf -> float -> float -> unit = "ml_gdk_cairo_set_source_pixbuf"



More information about the cairo-commit mailing list