]> Pileus Git - ~andy/gtk/commitdiff
Add gdk_drawable_set_cairo_target().
authorOwen Taylor <otaylor@redhat.com>
Thu, 3 Feb 2005 23:29:02 +0000 (23:29 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Thu, 3 Feb 2005 23:29:02 +0000 (23:29 +0000)
2005-02-03  Owen Taylor  <otaylor@redhat.com>

        * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add
        gdk_drawable_set_cairo_target().

        * tests/testtreeflow.c (enum): Use grand not rand as a variable
        name because one of the cairo headers is pulling in stdlib.h.

        * tests/testcairo.c tests/Makefile.am: Add a simple cairo based
        example.

        * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0.

        * Require libpangocairo for all backends.

21 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
configure.in
docs/reference/gdk/tmpl/gdkdisplay.sgml
docs/reference/gdk/tmpl/x_interaction.sgml
docs/reference/gtk/tmpl/gtkcellrendererpixbuf.sgml
docs/reference/gtk/tmpl/gtkcellrenderertext.sgml
docs/reference/gtk/tmpl/gtkstock.sgml
gdk/gdkdraw.c
gdk/gdkdrawable.h
gdk/gdkpixmap.c
gdk/gdkwindow.c
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkdrawable-x11.h
gdk/x11/gdkpixmap-x11.c
gdk/x11/gdkwindow-x11.c
tests/.cvsignore
tests/Makefile.am
tests/testcairo.c [new file with mode: 0644]
tests/testtreeflow.c

index 1564d3fe844acef07ad0e32dc4b6d8c115534360..579b02923de5d25dac54db319a11e65b0cac3b35 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2005-02-03  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add
+       gdk_drawable_set_cairo_target().
+
+       * tests/testtreeflow.c (enum): Use grand not rand as a variable
+       name because one of the cairo headers is pulling in stdlib.h.
+
+       * tests/testcairo.c tests/Makefile.am: Add a simple cairo based
+       example.
+
+       * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0.
+
+       * Require libpangocairo for all backends.
+
 2005-02-03  Tor Lillqvist  <tml@novell.com>
 
        * modules/input/gtkimcontextime.c (get_pango_attr_list): Use the
index 1564d3fe844acef07ad0e32dc4b6d8c115534360..579b02923de5d25dac54db319a11e65b0cac3b35 100644 (file)
@@ -1,3 +1,18 @@
+2005-02-03  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add
+       gdk_drawable_set_cairo_target().
+
+       * tests/testtreeflow.c (enum): Use grand not rand as a variable
+       name because one of the cairo headers is pulling in stdlib.h.
+
+       * tests/testcairo.c tests/Makefile.am: Add a simple cairo based
+       example.
+
+       * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0.
+
+       * Require libpangocairo for all backends.
+
 2005-02-03  Tor Lillqvist  <tml@novell.com>
 
        * modules/input/gtkimcontextime.c (get_pango_attr_list): Use the
index 1564d3fe844acef07ad0e32dc4b6d8c115534360..579b02923de5d25dac54db319a11e65b0cac3b35 100644 (file)
@@ -1,3 +1,18 @@
+2005-02-03  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add
+       gdk_drawable_set_cairo_target().
+
+       * tests/testtreeflow.c (enum): Use grand not rand as a variable
+       name because one of the cairo headers is pulling in stdlib.h.
+
+       * tests/testcairo.c tests/Makefile.am: Add a simple cairo based
+       example.
+
+       * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0.
+
+       * Require libpangocairo for all backends.
+
 2005-02-03  Tor Lillqvist  <tml@novell.com>
 
        * modules/input/gtkimcontextime.c (get_pango_attr_list): Use the
index 54801f92eb909a5572a139735bc634b6ca498cda..fd1d9264d1c6ab792dc510b8e45f34acb4e4c2a6 100644 (file)
@@ -11,11 +11,11 @@ AC_PREREQ(2.54)
 # set GTK_BINARY_AGE and GTK_INTERFACE_AGE to 0.
 
 m4_define([gtk_major_version], [2])
-m4_define([gtk_minor_version], [6])
-m4_define([gtk_micro_version], [2])
+m4_define([gtk_minor_version], [7])
+m4_define([gtk_micro_version], [0])
 m4_define([gtk_version],
           [gtk_major_version.gtk_minor_version.gtk_micro_version])
-m4_define([gtk_interface_age], [2])
+m4_define([gtk_interface_age], [0])
 m4_define([gtk_binary_age],
           [m4_eval(100 * gtk_minor_version + gtk_micro_version)])
 # This is the X.Y used in -lgtk-FOO-X.Y
@@ -26,7 +26,7 @@ m4_define([gtk_api_version], [2.0])
 # locations. (Should this be backwards-compat instead?)
 #
 #GTK_BINARY_VERSION=$GTK_MAJOR_VERSION.$GTK_MINOR_VERSION.$LT_CURRENT
-m4_define([gtk_binary_version], [2.4.0])
+m4_define([gtk_binary_version], [2.7.0])
 
 # required versions of other packages
 m4_define([glib_required_version], [2.6.0])
@@ -1403,7 +1403,7 @@ fi
 #
 
 if test "x$gdktarget" = "xx11"; then
-        PANGO_PACKAGES=pangoxft
+        PANGO_PACKAGES="pangoxft pangocairo"
        
         # We no longer use pangox, but if we find it, we link to it 
        # for binary compatibility.
@@ -1411,11 +1411,11 @@ if test "x$gdktarget" = "xx11"; then
                PANGO_PACKAGES="$PANGO_PACKAGES pangox"
        fi
 elif test "x$gdktarget" = "xwin32"; then
-        PANGO_PACKAGES=pangowin32
+        PANGO_PACKAGES="pangowin32 pangocairo"
 elif test "x$gdktarget" = "xlinux-fb"; then
-        PANGO_PACKAGES=pangoft2
+        PANGO_PACKAGES="pangoft2 pangocairo"
 else
-        PANGO_PACKAGES=pango
+        PANGO_PACKAGES="pango pangocairo"
 fi
 
 # Check for Pango flags
@@ -1428,10 +1428,8 @@ if $PKG_CONFIG --exists $PANGO_PACKAGES ; then
         AC_MSG_RESULT($PANGO_CFLAGS $PANGO_LIBS)
 else
         AC_MSG_ERROR([
-*** Pango not found. Pango is required to build GTK+.
-*** See http://www.pango.org for Pango information.
-*** For the framebuffer target, you will need to build 
-*** Pango with freetype support.
+*** Pango not found. Pango built with Cairo support is required
+*** to build GTK+. See http://www.pango.org for Pango information.
 ])
 fi
 
index 8c87f9e0585ea779e560e06e88d60cdec0071a05..b0908fbdba4fa3e56303d98ced99ecfd87e765d5 100644 (file)
@@ -278,6 +278,17 @@ Applications should never have any reason to use this facility
 @Returns: 
 
 
+<!-- ##### FUNCTION gdk_display_warp_pointer ##### -->
+<para>
+
+</para>
+
+@display: 
+@screen: 
+@x: 
+@y: 
+
+
 <!-- ##### FUNCTION gdk_display_supports_cursor_color ##### -->
 <para>
 
index badef605cffd3c372262bb459e939606b6ca67fd..82ab674858a5e0c9f63f17853bd217be6e5ce9e3 100644 (file)
@@ -440,6 +440,15 @@ Since: 2.2
 @timestamp: 
 
 
+<!-- ##### FUNCTION gdk_x11_display_get_user_time ##### -->
+<para>
+
+</para>
+
+@display: 
+@Returns: 
+
+
 <!-- ##### FUNCTION gdk_x11_colormap_foreign_new ##### -->
 <para>
 
index 7ff0da00d1cbc4f369fe2bbb61e80c7c23f840e1..51da83bb0e1cb3d05aa8779523515d2a9f0759e2 100644 (file)
@@ -36,6 +36,11 @@ property is set to a pixbuf, it renders that one.
 </para>
 
 
+<!-- ##### ARG GtkCellRendererPixbuf:follow-state ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG GtkCellRendererPixbuf:pixbuf ##### -->
 <para>
 
index feafc320ff4d348f73dd087b9d7d033b0c605a53..01b12175bb5324713a4fc252057a825899ba507d 100644 (file)
@@ -237,6 +237,16 @@ the #GtkCellRendererText allows to edit its text using an entry.
 
 </para>
 
+<!-- ##### ARG GtkCellRendererText:wrap-mode ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkCellRendererText:wrap-width ##### -->
+<para>
+
+</para>
+
 <!-- ##### FUNCTION gtk_cell_renderer_text_new ##### -->
 <para>
 
index ffd4d0451cffa6213069fe8765844bb8cb264f57..42485c6b6701d7658ac5729f95707033d7474a9a 100644 (file)
@@ -96,6 +96,17 @@ used for right-to-left locales.
 @Returns: 
 
 
+<!-- ##### FUNCTION gtk_stock_set_translate_func ##### -->
+<para>
+
+</para>
+
+@domain: 
+@func: 
+@data: 
+@notify: 
+
+
 <!-- ##### MACRO GTK_STOCK_ABOUT ##### -->
 <para>
 The "About" item.
index f547fad9042e970dd1a2f1ca66a988cd047e9792..63951a024e79905707756bb59f8d06635e050b10 100644 (file)
@@ -1221,6 +1221,29 @@ gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
   return gdk_region_rectangle (&rect);
 }
 
+/**
+ * gdk_drawable_set_cairo_target:
+ * @drawable: a #GdkDrawable
+ * @cr: a cairo context
+ * 
+ * Sets the given drawable as the target surface for a Cairo context.
+ * Note that when @drawable is a window and gdk_window_begin_paint()
+ * has been called, the target surface will be set to the temporary
+ * backing pixmap, so you can only use the Cairo context until
+ * the matching call to gdk_window_end_paint().
+ *
+ * Since: 2.10
+ **/
+void
+gdk_drawable_set_cairo_target (GdkDrawable *drawable,
+                              cairo_t     *cr)
+{
+  g_return_if_fail (GDK_IS_DRAWABLE (drawable));
+  g_return_if_fail (cr != NULL);
+
+  return GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_target (drawable, cr);
+}
+
 static void
 composite (guchar *src_buf,
           gint    src_rowstride,
index 3fb9ea846a96a3b8dda77473230ae36455455dbc..612ce694fd45c5ef4e4c941b357400f6fafb599f 100644 (file)
@@ -6,6 +6,8 @@
 #include <gdk/gdkrgb.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
+#include <cairo.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -168,8 +170,10 @@ struct _GdkDrawableClass
                                   GdkTrapezoid     *trapezoids,
                                   gint              n_trapezoids);
 
+  void (*set_cairo_target)        (GdkDrawable      *drawable,
+                                  cairo_t          *cr);
+
   /* Padding for future expansion */
-  void         (*_gdk_reserved3)  (void);
   void         (*_gdk_reserved4)  (void);
   void         (*_gdk_reserved5)  (void);
   void         (*_gdk_reserved6)  (void);
@@ -388,6 +392,9 @@ GdkImage *gdk_drawable_copy_to_image (GdkDrawable  *drawable,
 GdkRegion *gdk_drawable_get_clip_region    (GdkDrawable *drawable);
 GdkRegion *gdk_drawable_get_visible_region (GdkDrawable *drawable);
 
+void       gdk_drawable_set_cairo_target (GdkDrawable *drawable,
+                                         cairo_t     *cr);
+
 gboolean gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,
                                               gint         x,
                                               gint         y,
index 978712a9e07c45e65955602e823ed4f7b0749172..d3012eb64e3950cfa2f778fdcc571f23e0e1100c 100644 (file)
@@ -144,6 +144,9 @@ static GdkImage* gdk_pixmap_copy_to_image (GdkDrawable *drawable,
                                           gint         width,
                                           gint         height);
 
+static void gdk_pixmap_set_cairo_target (GdkDrawable *drawable,
+                                        cairo_t     *cr);
+
 static GdkVisual*   gdk_pixmap_real_get_visual   (GdkDrawable *drawable);
 static gint         gdk_pixmap_real_get_depth    (GdkDrawable *drawable);
 static void         gdk_pixmap_real_set_colormap (GdkDrawable *drawable,
@@ -224,6 +227,7 @@ gdk_pixmap_class_init (GdkPixmapObjectClass *klass)
   drawable_class->get_colormap = gdk_pixmap_real_get_colormap;
   drawable_class->get_visual = gdk_pixmap_real_get_visual;
   drawable_class->_copy_to_image = gdk_pixmap_copy_to_image;
+  drawable_class->set_cairo_target = gdk_pixmap_set_cairo_target;
 }
 
 static void
@@ -517,6 +521,14 @@ gdk_pixmap_copy_to_image (GdkDrawable     *drawable,
                                     width, height);
 }
 
+static void
+gdk_pixmap_set_cairo_target (GdkDrawable *drawable,
+                            cairo_t     *cr)
+{
+  gdk_drawable_set_cairo_target (((GdkPixmapObject*)drawable)->impl,
+                                cr);
+}
+
 static GdkBitmap *
 make_solid_mask (GdkScreen *screen, gint width, gint height)
 {
index 41e5e2ab97cc796918868134b83c2402102b1c4e..4a27988c6718ae470925a410434af7fb1bf6eabc 100644 (file)
@@ -157,6 +157,9 @@ static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
                                           gint         width,
                                           gint         height);
 
+static void gdk_window_set_cairo_target (GdkDrawable *drawable,
+                                        cairo_t     *cr);
+
 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
                                          gint            *width,
                                          gint            *height);
@@ -263,6 +266,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   drawable_class->get_colormap = gdk_window_real_get_colormap;
   drawable_class->get_visual = gdk_window_real_get_visual;
   drawable_class->_copy_to_image = gdk_window_copy_to_image;
+  drawable_class->set_cairo_target = gdk_window_set_cairo_target;
   drawable_class->get_clip_region = gdk_window_get_clip_region;
   drawable_class->get_visible_region = gdk_window_get_visible_region;
   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
@@ -2091,6 +2095,26 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
                                     width, height);
 }
 
+static void
+gdk_window_set_cairo_target (GdkDrawable *drawable,
+                            cairo_t     *cr)
+{
+  GdkWindowObject *private = (GdkWindowObject*) drawable;
+  gint x_offset, y_offset;
+  
+  gdk_window_get_offsets (GDK_WINDOW (drawable), &x_offset, &y_offset);
+
+  if (private->paint_stack)
+    {
+      GdkWindowPaint *paint = private->paint_stack->data;
+      gdk_drawable_set_cairo_target (paint->pixmap, cr);
+    }
+  else
+    gdk_drawable_set_cairo_target (private->impl, cr);
+
+  cairo_translate (cr, - x_offset, - y_offset);
+}
+
 /* Code for dirty-region queueing
  */
 static GSList *update_windows = NULL;
index c6f3142072a2774932286e53afe91ecf23fea691..19c7b9264a0b2d905f36c5ac9ae3a17f7b0233ba 100644 (file)
@@ -147,6 +147,9 @@ static void gdk_x11_draw_trapezoids (GdkDrawable     *drawable,
                                     GdkTrapezoid    *trapezoids,
                                     gint             n_trapezoids);
 
+static void gdk_x11_set_cairo_target (GdkDrawable *drawable,
+                                     cairo_t     *cr);
+     
 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
                                     GdkColormap    *colormap);
 
@@ -215,6 +218,8 @@ gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
   drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
   drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids;
   
+  drawable_class->set_cairo_target = gdk_x11_set_cairo_target;
+
   drawable_class->set_colormap = gdk_x11_set_colormap;
   drawable_class->get_colormap = gdk_x11_get_colormap;
 
@@ -1558,6 +1563,51 @@ gdk_x11_draw_trapezoids (GdkDrawable  *drawable,
   g_free (xtrapezoids);
 }
 
+static cairo_surface_t *
+gdk_x11_drawable_get_cairo_surface (GdkDrawable *drawable)
+{
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  GdkColormap *colormap;
+  GdkVisual *visual;
+
+  if (GDK_IS_WINDOW_IMPL_X11 (drawable) &&
+      GDK_WINDOW_DESTROYED (impl->wrapper))
+    return NULL;
+
+  colormap = gdk_drawable_get_colormap (drawable);
+  if (!colormap)
+    {
+      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;
+    }
+
+  visual = gdk_colormap_get_visual (colormap);
+
+  if (!impl->cairo_surface)
+    {
+      impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
+                                                      impl->xid,
+                                                      GDK_VISUAL_XVISUAL (visual),
+                                                      CAIRO_FORMAT_RGB24,
+                                                      GDK_COLORMAP_XCOLORMAP (colormap));
+    }
+
+  return impl->cairo_surface;
+}
+
+static void
+gdk_x11_set_cairo_target (GdkDrawable *drawable,
+                         cairo_t     *cr)
+{
+  cairo_surface_t *surface = gdk_x11_drawable_get_cairo_surface (drawable);
+  if (surface)
+    cairo_set_target_surface (cr, surface);
+}
+
 /**
  * gdk_draw_rectangle_alpha_libgtk_only:
  * @drawable: The #GdkDrawable to draw on
index 45c8e38b8dd0167d887e861583cb8fff03d25359..1de1e50c3e270861f65136863bb72fc64a077b21 100644 (file)
@@ -71,6 +71,7 @@ struct _GdkDrawableImplX11
   GdkScreen *screen;
 
   XftDraw *xft_draw;
+  cairo_surface_t *cairo_surface;
 };
  
 struct _GdkDrawableImplX11Class 
index 1b7776fd46aeb1ed8a4d6bcd777174d0130e237c..9590aace03838be467ef30d1228975029c50cdeb 100644 (file)
@@ -135,6 +135,12 @@ gdk_pixmap_impl_x11_finalize (GObject *object)
       if (draw_impl->xft_draw)
        XftDrawDestroy (draw_impl->xft_draw);
 
+      if (draw_impl->cairo_surface)
+       {
+         cairo_surface_destroy (draw_impl->cairo_surface);
+         draw_impl->cairo_surface = NULL;
+       }
+
       if (!impl->is_foreign)
        XFreePixmap (GDK_DISPLAY_XDISPLAY (display), GDK_PIXMAP_XID (wrapper));
     }
index cb2b095ce7ed952244f21a0a302af152eaed80db..3c86ba9dc0b44342933bce0dcc30097856029b98 100644 (file)
@@ -1144,7 +1144,16 @@ _gdk_windowing_window_destroy (GdkWindow *window,
   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
     
   if (draw_impl->xft_draw)
-    XftDrawDestroy (draw_impl->xft_draw);
+    {
+      XftDrawDestroy (draw_impl->xft_draw);
+      draw_impl->xft_draw = NULL;
+    }
+
+  if (draw_impl->cairo_surface)
+    {
+      cairo_surface_destroy (draw_impl->cairo_surface);
+      draw_impl->cairo_surface = NULL;
+    }
 
   if (!recursing && !foreign_destroy)
     {
index 5f317de9b7876a7cd51455f26baa8885158f51b9..32d1b68443393d1869fe7c31439c8d0f3b443656 100644 (file)
@@ -14,6 +14,7 @@ pixbuf-threads
 simple
 stresstest-toolbar
 testactions
+testcairo
 testcalendar
 testcombo
 testcombochange
index eea2da8b8b76fb3659a61c853175a91ac87151ee..56cad512404a436bc50e8d4c02e83740d18a0f92 100644 (file)
@@ -28,6 +28,7 @@ endif
 
 noinst_PROGRAMS =                      \
        simple                          \
+       testcairo                       \
        testcalendar                    \
        testcombo                       \
        testcombochange                 \
@@ -72,6 +73,7 @@ noinst_PROGRAMS =                     \
 simple_DEPENDENCIES = $(TEST_DEPS)
 testicontheme_DEPENDENCIES = $(TEST_DEPS)
 testiconview_DEPENDENCIES = $(TEST_DEPS)
+testcairo_DEPENDENCIES = $(TEST_DEPS)
 testcalendar_DEPENDENCIES = $(TEST_DEPS)
 testcombo_DEPENDENCIES = $(TEST_DEPS)
 testcombochange_DEPENDENCIES = $(TEST_DEPS)
@@ -106,6 +108,7 @@ testmerge_DEPENDENCIES = $(TEST_DEPS)
 testactions_DEPENDENCIES = $(TEST_DEPS)
 
 simple_LDADD = $(LDADDS)
+testcairo_LDADD = $(LDADDS)
 testcalendar_LDADD = $(LDADDS)
 testcombo_LDADD = $(LDADDS)
 testcombochange_LDADD = $(LDADDS)
diff --git a/tests/testcairo.c b/tests/testcairo.c
new file mode 100644 (file)
index 0000000..9759adf
--- /dev/null
@@ -0,0 +1,243 @@
+/* testimage.c
+ * Copyright (C) 2005  Red Hat, Inc.
+ * Based on cairo-demo/X11/cairo-knockout.c
+ *
+ * Author: Owen Taylor
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+
+#include <gtk/gtk.h>
+
+static void
+oval_path (cairo_t *cr,
+           double xc, double yc,
+           double xr, double yr)
+{
+  cairo_matrix_t *matrix;
+
+  matrix = cairo_matrix_create ();
+  cairo_current_matrix (cr, matrix);
+
+  cairo_translate (cr, xc, yc);
+  cairo_scale (cr, 1.0, yr / xr);
+  cairo_move_to (cr, xr, 0.0);
+  cairo_arc (cr,
+            0, 0,
+            xr,
+            0, 2 * G_PI);
+  cairo_close_path (cr);
+
+  cairo_set_matrix (cr, matrix);
+  cairo_matrix_destroy (matrix);
+}
+
+/* Create a path that is a circular oval with radii xr, yr at xc,
+ * yc.
+ */
+/* Fill the given area with checks in the standard style
+ * for showing compositing effects.
+ *
+ * It would make sense to do this as a repeating surface,
+ * but most implementations of RENDER currently have broken
+ * implementations of repeat + transform, even when the
+ * transform is a translation.
+ */
+static void
+fill_checks (cairo_t *cr,
+             int x,     int y,
+             int width, int height)
+{
+  int i, j;
+  
+#define CHECK_SIZE 32
+
+  cairo_rectangle (cr, x, y, width, height);
+  cairo_set_rgb_color (cr, 0.4, 0.4, 0.4);
+  cairo_fill (cr);
+
+  /* Only works for CHECK_SIZE a power of 2 */
+  j = x & (-CHECK_SIZE);
+  
+  for (; j < height; j += CHECK_SIZE)
+    {
+      i = y & (-CHECK_SIZE);
+      for (; i < width; i += CHECK_SIZE)
+       if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0)
+         cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
+    }
+
+  cairo_set_rgb_color (cr, 0.7, 0.7, 0.7);
+  cairo_fill (cr);
+}
+
+/* Draw a red, green, and blue circle equally spaced inside
+ * the larger circle of radius r at (xc, yc)
+ */
+static void
+draw_3circles (cairo_t *cr,
+               double xc, double yc,
+               double radius)
+{
+  double subradius = radius * (2 / 3. - 0.1);
+    
+  cairo_set_rgb_color (cr, 1., 0., 0.);
+  oval_path (cr,
+            xc + radius / 3. * cos (G_PI * (0.5)),
+            yc - radius / 3. * sin (G_PI * (0.5)),
+            subradius, subradius);
+  cairo_fill (cr);
+    
+  cairo_set_rgb_color (cr, 0., 1., 0.);
+  oval_path (cr,
+            xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)),
+            yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)),
+            subradius, subradius);
+  cairo_fill (cr);
+    
+  cairo_set_rgb_color (cr, 0., 0., 1.);
+  oval_path (cr,
+            xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)),
+            yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)),
+            subradius, subradius);
+  cairo_fill (cr);
+}
+
+static void
+draw (cairo_t *cr,
+      int      width,
+      int      height)
+{
+  cairo_surface_t *overlay, *punch, *circles;
+
+  /* Fill the background */
+  double radius = 0.5 * (width < height ? width : height) - 10;
+  double xc = width / 2.;
+  double yc = height / 2.;
+
+  overlay = cairo_surface_create_similar (cairo_current_target_surface (cr),
+                                         CAIRO_FORMAT_ARGB32,
+                                         width, height);
+  if (overlay == NULL)
+    return;
+
+  punch = cairo_surface_create_similar (cairo_current_target_surface (cr),
+                                       CAIRO_FORMAT_A8,
+                                       width, height);
+  if (punch == NULL)
+    return;
+
+  circles = cairo_surface_create_similar (cairo_current_target_surface (cr),
+                                         CAIRO_FORMAT_ARGB32,
+                                         width, height);
+  if (circles == NULL)
+    return;
+    
+  fill_checks (cr, 0, 0, width, height);
+
+  cairo_save (cr);
+  cairo_set_target_surface (cr, overlay);
+  cairo_identity_matrix (cr);
+
+  /* Draw a black circle on the overlay
+   */
+  cairo_set_rgb_color (cr, 0., 0., 0.);
+  oval_path (cr, xc, yc, radius, radius);
+  cairo_fill (cr);
+
+  cairo_save (cr);
+  cairo_set_target_surface (cr, punch);
+
+  /* Draw 3 circles to the punch surface, then cut
+   * that out of the main circle in the overlay
+   */
+  draw_3circles (cr, xc, yc, radius);
+
+  cairo_restore (cr);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_OUT_REVERSE);
+  cairo_show_surface (cr, punch, width, height);
+
+  /* Now draw the 3 circles in a subgroup again
+   * at half intensity, and use OperatorAdd to join up
+   * without seams.
+   */
+  cairo_save (cr);
+  cairo_set_target_surface (cr, circles);
+
+  cairo_set_alpha (cr, 0.5);
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+  draw_3circles (cr, xc, yc, radius);
+
+  cairo_restore (cr);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
+  cairo_show_surface (cr, circles, width, height);
+
+  cairo_restore (cr);
+
+  cairo_show_surface (cr, overlay, width, height);
+
+  cairo_surface_destroy (overlay);
+  cairo_surface_destroy (punch);
+  cairo_surface_destroy (circles);
+}
+
+static gboolean
+on_expose_event (GtkWidget      *widget,
+                GdkEventExpose *event,
+                gpointer        data)
+{
+  cairo_t *cr;
+
+  cr = cairo_create ();
+  gdk_drawable_set_cairo_target (GDK_DRAWABLE (widget->window), cr);
+
+  draw (cr, widget->allocation.width, widget->allocation.height);
+
+  cairo_destroy (cr);
+
+  return FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+  GtkWidget *window, *darea;
+
+  gtk_init (&argc, &argv);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  
+  gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
+  gtk_window_set_title (GTK_WINDOW (window), "cairo: Knockout Groups");
+
+  darea = gtk_drawing_area_new ();
+  gtk_container_add (GTK_CONTAINER (window), darea);
+
+  g_signal_connect (darea, "expose-event",
+                   G_CALLBACK (on_expose_event), NULL);
+  g_signal_connect (window, "destroy-event",
+                   G_CALLBACK (gtk_main_quit), NULL);
+
+  gtk_widget_show_all (window);
+  
+  gtk_main ();
+
+  return 0;
+}
index 6f87df0cbac8eb3ac647d3c59b8a832e5711cf4c..979e1c8a8d72f06a53fda7c86a32a2df75925ca5 100644 (file)
@@ -2,7 +2,7 @@
 #include <gtk/gtk.h>
 
 GtkTreeModel *model = NULL;
-static GRand *rand = NULL;
+static GRand *grand = NULL;
 GtkTreeSelection *selection = NULL;
 enum
 {
@@ -32,12 +32,12 @@ initialize_model (void)
   GtkTreeIter iter;
 
   model = (GtkTreeModel *) gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING);
-  rand = g_rand_new ();
+  grand = g_rand_new ();
   for (i = 0; i < NUM_ROWS; i++)
     {
       gtk_list_store_append (GTK_LIST_STORE (model), &iter);
       gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                         TEXT_COLUMN, words[g_rand_int_range (rand, 0, NUM_WORDS)],
+                         TEXT_COLUMN, words[g_rand_int_range (grand, 0, NUM_WORDS)],
                          -1);
     }
 }
@@ -50,7 +50,7 @@ futz_row (void)
   GtkTreeIter iter;
   GtkTreeIter iter2;
 
-  i = g_rand_int_range (rand, 0,
+  i = g_rand_int_range (grand, 0,
                        gtk_tree_model_iter_n_children (model, NULL));
   path = gtk_tree_path_new ();
   gtk_tree_path_append_index (path, i);
@@ -59,14 +59,14 @@ futz_row (void)
 
   if (gtk_tree_selection_iter_is_selected (selection, &iter))
     return;
-  switch (g_rand_int_range (rand, 0, 3))
+  switch (g_rand_int_range (grand, 0, 3))
     {
     case 0:
       /* insert */
             gtk_list_store_insert_after (GTK_LIST_STORE (model),
                                           &iter2, &iter);
             gtk_list_store_set (GTK_LIST_STORE (model), &iter2,
-                                 TEXT_COLUMN, words[g_rand_int_range (rand, 0, NUM_WORDS)],
+                                 TEXT_COLUMN, words[g_rand_int_range (grand, 0, NUM_WORDS)],
                                  -1);
       break;
     case 1:
@@ -81,7 +81,7 @@ futz_row (void)
       if (gtk_tree_model_iter_n_children (model, NULL) == 0)
        return;
       gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                         TEXT_COLUMN, words[g_rand_int_range (rand, 0, NUM_WORDS)],
+                         TEXT_COLUMN, words[g_rand_int_range (grand, 0, NUM_WORDS)],
                          -1);
       break;
     }