[clutter/wip/actor-content: 21/23] Add BorderImage
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/wip/actor-content: 21/23] Add BorderImage
- Date: Fri, 15 Apr 2011 12:27:42 +0000 (UTC)
commit e5cf5927495b690e744af5992fb52fbd46ba0965
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Wed Dec 8 12:56:00 2010 +0000
Add BorderImage
ClutterBorderImage is a simple class implementing part of the semantics
of the border-image CSS3 pragma. It allows painting a content as a
background or a border, repeating a pattern to fill the paint area.
clutter/Makefile.am | 2 +
clutter/clutter-border-image.c | 468 ++++++++++++++++++++++++++++
clutter/clutter-border-image.h | 103 ++++++
clutter/clutter.h | 1 +
doc/reference/clutter/clutter-docs.xml.in | 3 +-
doc/reference/clutter/clutter-sections.txt | 19 ++
doc/reference/clutter/clutter.types | 1 +
tests/data/Makefile.am | 1 +
tests/data/border-image.png | Bin 0 -> 1355 bytes
tests/interactive/Makefile.am | 3 +-
tests/interactive/test-border-image.c | 105 +++++++
11 files changed, 704 insertions(+), 2 deletions(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index 6cfafab..024b018 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -90,6 +90,7 @@ source_h = \
$(srcdir)/clutter-binding-pool.h \
$(srcdir)/clutter-bin-layout.h \
$(srcdir)/clutter-blur-effect.h \
+ $(srcdir)/clutter-border-image.h \
$(srcdir)/clutter-box.h \
$(srcdir)/clutter-box-layout.h \
$(srcdir)/clutter-cairo-texture.h \
@@ -178,6 +179,7 @@ source_c = \
$(srcdir)/clutter-binding-pool.c \
$(srcdir)/clutter-bin-layout.c \
$(srcdir)/clutter-blur-effect.c \
+ $(srcdir)/clutter-border-image.c \
$(srcdir)/clutter-box.c \
$(srcdir)/clutter-box-layout.c \
$(srcdir)/clutter-cairo-texture.c \
diff --git a/clutter/clutter-border-image.c b/clutter/clutter-border-image.c
new file mode 100644
index 0000000..4ce1d23
--- /dev/null
+++ b/clutter/clutter-border-image.c
@@ -0,0 +1,468 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Emmanuele Bassi <ebassi linux intel com>
+ */
+
+/**
+ * SECTION:clutter-border-image
+ * @Title: ClutterBorderImage
+ * @Short_Description: A border image content
+ *
+ * #ClutterBorderImage is a #ClutterImage sub-class that is suitable for
+ * displaying backgrounds and borders that fit a given area.
+ *
+ * #ClutterBorderImage paints the image data using nine slices, defined
+ * by the area it has to fit and by four inward offsets from the edges
+ * of the image, expressed in floating point values between 0.0 and 1.0.
+ *
+ * #ClutterBorderImage is available since Clutter 1.6
+ */
+
+#include "config.h"
+
+#include <math.h>
+
+#include "clutter-border-image.h"
+
+#include "clutter-content.h"
+#include "clutter-private.h"
+
+enum
+{
+ TOP,
+ RIGHT,
+ BOTTOM,
+ LEFT,
+
+ N_SLICES
+};
+
+struct _ClutterBorderImagePrivate
+{
+ gdouble slices[N_SLICES];
+};
+
+enum
+{
+ PROP_0,
+
+ PROP_SLICE_TOP,
+ PROP_SLICE_RIGHT,
+ PROP_SLICE_BOTTOM,
+ PROP_SLICE_LEFT,
+
+ LAST_PROP
+};
+
+static GParamSpec *border_props[LAST_PROP] = { NULL, };
+
+static CoglMaterial *border_template_material = NULL;
+
+static void clutter_content_iface_init (ClutterContentIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (ClutterBorderImage,
+ clutter_border_image,
+ CLUTTER_TYPE_IMAGE,
+ G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
+ clutter_content_iface_init));
+
+static void
+clutter_border_image_update_geometry (ClutterContent *content,
+ ClutterActor *actor)
+{
+ ClutterBorderImagePrivate *priv = CLUTTER_BORDER_IMAGE (content)->priv;
+ ClutterImage *image = CLUTTER_IMAGE (content);
+ ClutterActorBox allocation;
+ gfloat width, height;
+ gint image_width, image_height;
+ float tx1, ty1, tx2, ty2;
+ float ex, ey;
+ float top, bottom, right, left;
+
+ clutter_image_get_size (image, &image_width, &image_height);
+ if (image_width == 0 && image_height == 0)
+ return;
+
+ clutter_actor_get_allocation_box (actor, &allocation);
+ clutter_actor_box_get_size (&allocation, &width, &height);
+
+ /* round to pixel-aligned positions */
+ top = ceilf (image_height * priv->slices[TOP]);
+ bottom = floorf (image_height * (1.0 - priv->slices[BOTTOM]));
+ left = ceilf (image_width * priv->slices[LEFT]);
+ right = floorf (image_width * (1.0 - priv->slices[RIGHT]));
+
+ tx1 = priv->slices[LEFT];
+ tx2 = 1.0 - priv->slices[RIGHT];
+ ty1 = priv->slices[TOP];
+ ty2 = 1.0 - priv->slices[BOTTOM];
+
+ ex = width - (image_width - right);
+ if (ex < left)
+ ex = left;
+
+ ey = height - (image_height - bottom);
+ if (ey < left)
+ ey = left;
+
+ {
+ GLfloat rectangles[] = {
+ /* top left corner */
+ 0, 0, left, top,
+ 0.0, 0.0,
+ tx1, ty1,
+
+ /* top middle */
+ left, 0, ex, top,
+ tx1, 0.0,
+ tx2, ty1,
+
+ /* top right */
+ ex, 0, width, top,
+ tx2, 0.0,
+ 1.0, ty1,
+
+ /* mid left */
+ 0, top, left, ey,
+ 0.0, ty1,
+ tx1, ty2,
+
+ /* center */
+ left, top, ex, ey,
+ tx1, ty1,
+ tx2, ty2,
+
+ /* mid right */
+ ex, top, width, ey,
+ tx2, ty1,
+ 1.0, ty2,
+
+ /* bottom left */
+ 0, ey, left, height,
+ 0.0, ty2,
+ tx1, 1.0,
+
+ /* bottom center */
+ left, ey, ex, height,
+ tx1, ty2,
+ tx2, 1.0,
+
+ /* bottom right */
+ ex, ey, width, height,
+ tx2, ty2,
+ 1.0, 1.0
+ };
+
+ cogl_rectangles_with_texture_coords (rectangles, 9);
+ }
+}
+
+static void
+clutter_content_iface_init (ClutterContentIface *iface)
+{
+ iface->update_geometry = clutter_border_image_update_geometry;
+}
+
+static CoglMaterial *
+clutter_border_image_create_material (ClutterImage *image)
+{
+ if (border_template_material == NULL)
+ {
+ CoglHandle dummy;
+
+ dummy = cogl_texture_new_with_size (1, 1,
+ COGL_TEXTURE_NO_SLICING,
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE);
+
+ border_template_material = cogl_material_new ();
+ cogl_material_set_layer (border_template_material, 0, dummy);
+ cogl_material_set_layer_filters (border_template_material, 0,
+ COGL_MATERIAL_FILTER_NEAREST,
+ COGL_MATERIAL_FILTER_NEAREST);
+ cogl_handle_unref (dummy);
+ }
+
+ return cogl_material_copy (border_template_material);
+}
+
+static inline void
+clutter_border_image_set_slice_internal (ClutterBorderImage *image,
+ int position,
+ gdouble new_value,
+ GParamSpec *pspec)
+{
+ ClutterBorderImagePrivate *priv = image->priv;
+
+ g_assert (position >= TOP && position < N_SLICES);
+
+ if (priv->slices[position] != new_value)
+ {
+ priv->slices[position] = new_value;
+ g_object_notify_by_pspec (G_OBJECT (image), pspec);
+ }
+}
+
+static void
+clutter_border_image_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ClutterBorderImage *image = CLUTTER_BORDER_IMAGE (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_SLICE_TOP:
+ clutter_border_image_set_slice_internal (image, TOP,
+ g_value_get_double (value),
+ pspec);
+ break;
+
+ case PROP_SLICE_RIGHT:
+ clutter_border_image_set_slice_internal (image, RIGHT,
+ g_value_get_double (value),
+ pspec);
+ break;
+
+ case PROP_SLICE_BOTTOM:
+ clutter_border_image_set_slice_internal (image, BOTTOM,
+ g_value_get_double (value),
+ pspec);
+ break;
+
+ case PROP_SLICE_LEFT:
+ clutter_border_image_set_slice_internal (image, LEFT,
+ g_value_get_double (value),
+ pspec);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+clutter_border_image_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{ ClutterBorderImagePrivate *priv = CLUTTER_BORDER_IMAGE (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_SLICE_TOP:
+ g_value_set_double (value, priv->slices[TOP]);
+ break;
+
+ case PROP_SLICE_RIGHT:
+ g_value_set_double (value, priv->slices[RIGHT]);
+ break;
+
+ case PROP_SLICE_BOTTOM:
+ g_value_set_double (value, priv->slices[BOTTOM]);
+ break;
+
+ case PROP_SLICE_LEFT:
+ g_value_set_double (value, priv->slices[LEFT]);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+clutter_border_image_class_init (ClutterBorderImageClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterImageClass *image_class = CLUTTER_IMAGE_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (ClutterBorderImagePrivate));
+
+ /**
+ * ClutterBorderImage:slice-top:
+ *
+ * The inward offset of the vertical slices from the top edge.
+ *
+ * Since: 1.6
+ */
+ border_props[PROP_SLICE_TOP] =
+ g_param_spec_double ("slice-top",
+ P_("Slice Top"),
+ P_("The relative size of the top slice"),
+ 0.0, 1.0,
+ 0.0,
+ CLUTTER_PARAM_READWRITE);
+
+ /**
+ * ClutterBorderImage:slice-right:
+ *
+ * The inward offset of the horizontal slices from the right edge.
+ *
+ * Since: 1.6
+ */
+ border_props[PROP_SLICE_RIGHT] =
+ g_param_spec_double ("slice-right",
+ P_("Slice Right"),
+ P_("The relative size of the right slice"),
+ 0.0, 1.0,
+ 0.0,
+ CLUTTER_PARAM_READWRITE);
+
+ /**
+ * ClutterBorderImage:slice-bottom:
+ *
+ * The inward offset of the vertical slices from the bottom edge.
+ *
+ * Since: 1.6
+ */
+ border_props[PROP_SLICE_BOTTOM] =
+ g_param_spec_double ("slice-bottom",
+ P_("Slice Bottom"),
+ P_("The relative size of the bottom slice"),
+ 0.0, 1.0,
+ 0.0,
+ CLUTTER_PARAM_READWRITE);
+
+ /**
+ * ClutterBorderImage:slice-left:
+ *
+ * The inward offset of the horizontal slices from the left edge.
+ *
+ * Since: 1.6
+ */
+ border_props[PROP_SLICE_LEFT] =
+ g_param_spec_double ("slice-left",
+ P_("Slice Left"),
+ P_("The relative size of the left slice"),
+ 0.0, 1.0,
+ 0.0,
+ CLUTTER_PARAM_READWRITE);
+
+ gobject_class->set_property = clutter_border_image_set_property;
+ gobject_class->get_property = clutter_border_image_get_property;
+ g_object_class_install_properties (gobject_class,
+ LAST_PROP,
+ border_props);
+
+ image_class->create_material = clutter_border_image_create_material;
+}
+
+static void
+clutter_border_image_init (ClutterBorderImage *image)
+{
+ image->priv = G_TYPE_INSTANCE_GET_PRIVATE (image, CLUTTER_TYPE_BORDER_IMAGE,
+ ClutterBorderImagePrivate);
+
+ memset (image->priv->slices, 0, sizeof (gdouble) * N_SLICES);
+}
+
+/**
+ * clutter_border_image_new:
+ *
+ * Creates a new #ClutterBorderImage
+ *
+ * Return value: (transfer full): the newly created #ClutterBorderImage
+ *
+ * Since: 1.6
+ */
+ClutterContent *
+clutter_border_image_new (void)
+{
+ return g_object_new (CLUTTER_TYPE_BORDER_IMAGE, NULL);
+}
+
+/**
+ * clutter_border_image_set_slices:
+ * @image: a #ClutterBorderImage
+ * @top: the offset from the top, between 0.0 and 1.0
+ * @right: the offset from the right, between 0.0 and 1.0
+ * @bottom: the offset from the bottom, between 0.0 and 1.0
+ * @left: the offset from the left, between 0.0 and 1.0
+ *
+ * Sets the inward offsets of @image. The offsets are relative
+ * to the current size of the image data.
+ *
+ * Since: 1.6
+ */
+void
+clutter_border_image_set_slices (ClutterBorderImage *image,
+ gdouble top,
+ gdouble right,
+ gdouble bottom,
+ gdouble left)
+{
+ g_return_if_fail (CLUTTER_IS_BORDER_IMAGE (image));
+
+ g_object_freeze_notify (G_OBJECT (image));
+
+ clutter_border_image_set_slice_internal (image, TOP,
+ top,
+ border_props[PROP_SLICE_TOP]);
+ clutter_border_image_set_slice_internal (image, RIGHT,
+ right,
+ border_props[PROP_SLICE_RIGHT]);
+ clutter_border_image_set_slice_internal (image, BOTTOM,
+ bottom,
+ border_props[PROP_SLICE_BOTTOM]);
+ clutter_border_image_set_slice_internal (image, LEFT,
+ left,
+ border_props[PROP_SLICE_LEFT]);
+
+ clutter_content_invalidate (CLUTTER_CONTENT (image));
+
+ g_object_thaw_notify (G_OBJECT (image));
+}
+
+/**
+ * clutter_border_image_get_slices:
+ * @image: a #ClutterBorderImage
+ * @top: (out): return location for the offset from the top, or %NULL
+ * @right: (out): return location for the offset from the right, or %NULL
+ * @bottom: (out): return location for the offset from the bottom, or %NULL
+ * @left: (out): return location for the offset from the left, or %NULL
+ *
+ * Retrieves the offsets set using clutter_border_image_set_slices().
+ *
+ * Since: 1.6
+ */
+void
+clutter_border_image_get_slices (ClutterBorderImage *image,
+ gdouble *top,
+ gdouble *right,
+ gdouble *bottom,
+ gdouble *left)
+{
+ g_return_if_fail (CLUTTER_IS_BORDER_IMAGE (image));
+
+ if (top)
+ *top = image->priv->slices[TOP];
+
+ if (right)
+ *right = image->priv->slices[RIGHT];
+
+ if (bottom)
+ *bottom = image->priv->slices[BOTTOM];
+
+ if (left)
+ *left = image->priv->slices[LEFT];
+}
diff --git a/clutter/clutter-border-image.h b/clutter/clutter-border-image.h
new file mode 100644
index 0000000..12c6ffa
--- /dev/null
+++ b/clutter/clutter-border-image.h
@@ -0,0 +1,103 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Emmanuele Bassi <ebassi linux intel com>
+ */
+
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <clutter/clutter.h> can be included directly."
+#endif
+
+#ifndef __CLUTTER_BORDER_IMAGE_H__
+#define __CLUTTER_BORDER_IMAGE_H__
+
+#include <clutter/clutter-image.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_BORDER_IMAGE (clutter_border_image_get_type ())
+#define CLUTTER_BORDER_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BORDER_IMAGE, ClutterBorderImage))
+#define CLUTTER_IS_BORDER_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BORDER_IMAGE))
+#define CLUTTER_BORDER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BORDER_IMAGE, ClutterBorderImageClass))
+#define CLUTTER_IS_BORDER_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BORDER_IMAGE))
+#define CLUTTER_BORDER_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BORDER_IMAGE, ClutterBorderImageClass))
+
+typedef struct _ClutterBorderImage ClutterBorderImage;
+typedef struct _ClutterBorderImagePrivate ClutterBorderImagePrivate;
+typedef struct _ClutterBorderImageClass ClutterBorderImageClass;
+
+/**
+ * ClutterBorderImage:
+ *
+ * The <structname>ClutterBorderImage</structname> structure contains
+ * private data and should only be accessed using the provided API.
+ *
+ * Since: 1.6
+ */
+struct _ClutterBorderImage
+{
+ /*< private >*/
+ ClutterImage parent_instance;
+
+ ClutterBorderImagePrivate *priv;
+};
+
+/**
+ * ClutterBorderImage:
+ *
+ * The <structname>ClutterBorderImageClass</structname> structure contains
+ * only private data.
+ *
+ * Since: 1.6
+ */
+struct _ClutterBorderImageClass
+{
+ /*< private >*/
+ ClutterImageClass parent_class;
+
+ void (* _clutter_border_image_0) (void);
+ void (* _clutter_border_image_1) (void);
+ void (* _clutter_border_image_2) (void);
+ void (* _clutter_border_image_3) (void);
+ void (* _clutter_border_image_4) (void);
+ void (* _clutter_border_image_5) (void);
+ void (* _clutter_border_image_6) (void);
+ void (* _clutter_border_image_7) (void);
+};
+
+GType clutter_border_image_get_type (void) G_GNUC_CONST;
+
+ClutterContent * clutter_border_image_new (void);
+
+void clutter_border_image_set_slices (ClutterBorderImage *image,
+ gdouble top,
+ gdouble right,
+ gdouble bottom,
+ gdouble left);
+void clutter_border_image_get_slices (ClutterBorderImage *image,
+ gdouble *top,
+ gdouble *right,
+ gdouble *bottom,
+ gdouble *left);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_BORDER_IMAGE_H__ */
diff --git a/clutter/clutter.h b/clutter/clutter.h
index a700fae..5029be4 100644
--- a/clutter/clutter.h
+++ b/clutter/clutter.h
@@ -52,6 +52,7 @@
#include "clutter-binding-pool.h"
#include "clutter-bin-layout.h"
#include "clutter-blur-effect.h"
+#include "clutter-border-image.h"
#include "clutter-box.h"
#include "clutter-box-layout.h"
#include "clutter-cairo-texture.h"
diff --git a/doc/reference/clutter/clutter-docs.xml.in b/doc/reference/clutter/clutter-docs.xml.in
index 81eaef4..3c7de11 100644
--- a/doc/reference/clutter/clutter-docs.xml.in
+++ b/doc/reference/clutter/clutter-docs.xml.in
@@ -126,8 +126,9 @@
<chapter>
<title>Content</title>
- <xi:include href="xml/clutter-image.xml"/>
<xi:include href="xml/clutter-rgba.xml"/>
+ <xi:include href="xml/clutter-image.xml"/>
+ <xi:include href="xml/clutter-border-image.xml"/>
</chapter>
</part>
diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt
index 395cd55..461741a 100644
--- a/doc/reference/clutter/clutter-sections.txt
+++ b/doc/reference/clutter/clutter-sections.txt
@@ -2749,3 +2749,22 @@ CLUTTER_IS_IMAGE_LOADER_CLASS
<SUBSECTION Private>
clutter_image_loader_get_type
</SECTION>
+
+<SECTION>
+<FILE>clutter-border-image</FILE>
+ClutterBorderImage
+ClutterBorderImageClass
+clutter_border_image_new
+clutter_border_image_set_slices
+clutter_border_image_get_slices
+<SUBSECTION Standard>
+CLUTTER_TYPE_BORDER_IMAGE
+CLUTTER_BORDER_IMAGE
+CLUTTER_BORDER_IMAGE_CLASS
+CLUTTER_BORDER_IMAGE_GET_CLASS
+CLUTTER_IS_BORDER_IMAGE
+CLUTTER_IS_BORDER_IMAGE_CLASS
+<SUBSECTION Private>
+ClutterBorderImagePrivate
+clutter_border_image_get_type
+</SECTION>
diff --git a/doc/reference/clutter/clutter.types b/doc/reference/clutter/clutter.types
index d35435a..7534628 100644
--- a/doc/reference/clutter/clutter.types
+++ b/doc/reference/clutter/clutter.types
@@ -19,6 +19,7 @@ clutter_bind_constraint_get_type
clutter_binding_pool_get_type
clutter_bin_layout_get_type
clutter_blur_effect_get_type
+clutter_border_image_get_type
clutter_box_get_type
clutter_box_layout_get_type
clutter_cairo_texture_get_type
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index f886a6d..e94cb21 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -20,6 +20,7 @@ png_files = \
redhand.png \
redhand_alpha.png \
light0.png \
+ border-image.png \
$(NULL)
EXTRA_DIST = $(json_files) $(png_files) clutter-1.0.suppressions
diff --git a/tests/data/border-image.png b/tests/data/border-image.png
new file mode 100644
index 0000000..c74ddc0
Binary files /dev/null and b/tests/data/border-image.png differ
diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am
index 666eaeb..b7d7598 100644
--- a/tests/interactive/Makefile.am
+++ b/tests/interactive/Makefile.am
@@ -57,7 +57,8 @@ UNIT_TESTS = \
test-path-constraint.c \
test-snap-constraint.c \
test-rgba-content.c \
- test-image-content.c
+ test-image-content.c \
+ test-border-image.c
if X11_TESTS
UNIT_TESTS += test-pixmap.c test-devices.c
diff --git a/tests/interactive/test-border-image.c b/tests/interactive/test-border-image.c
new file mode 100644
index 0000000..4b0cac7
--- /dev/null
+++ b/tests/interactive/test-border-image.c
@@ -0,0 +1,105 @@
+#include <stdlib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+#include <clutter/clutter.h>
+
+#define STAGE_WIDTH 400
+#define STAGE_HEIGHT 400
+#define PADDING 10
+#define SPACING 2
+#define RECT_SIZE 64
+
+static void
+load_async_done (GObject *gobject,
+ GAsyncResult *result,
+ gpointer dummy G_GNUC_UNUSED)
+{
+ GError *error = NULL;
+ gboolean res;
+ int width, height;
+
+ res = clutter_image_load_finish (CLUTTER_IMAGE (gobject), result,
+ &width,
+ &height,
+ &error);
+ if (!res)
+ {
+ g_print ("Unable to load 'border-image.png': %s", error->message);
+ g_error_free (error);
+ return;
+ }
+}
+
+G_MODULE_EXPORT int
+test_border_image_main (int argc,
+ char *argv[])
+{
+ ClutterActor *stage, *group;
+ ClutterContent *content;
+ int i, j, n_cols, n_rows;
+ float last_x, last_y;
+ GFile *gfile;
+
+ if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ stage = clutter_stage_new ();
+ clutter_stage_set_title (CLUTTER_STAGE (stage), "Border Image");
+ clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
+ clutter_actor_set_size (stage, 400, 400);
+ clutter_actor_show (stage);
+
+ g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
+
+ content = clutter_border_image_new ();
+ clutter_border_image_set_slices (CLUTTER_BORDER_IMAGE (content),
+ 0.26, 0.413, 0.26, 0.413);
+ gfile = g_file_new_for_path (TESTS_DATADIR "/border-image.png");
+ clutter_image_load_async (CLUTTER_IMAGE (content), gfile, NULL,
+ load_async_done,
+ NULL);
+ g_object_unref (gfile);
+
+ group = clutter_group_new ();
+ clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
+ clutter_actor_add_constraint (group, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
+ clutter_actor_add_constraint (group, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
+ clutter_actor_set_content (group, content);
+ g_object_unref (content);
+
+ content = clutter_rgba_new (g_random_double_range (0.0, 1.0),
+ g_random_double_range (0.0, 1.0),
+ g_random_double_range (0.0, 1.0),
+ 0.25);
+
+ n_cols = (STAGE_WIDTH - (2 * PADDING)) / (RECT_SIZE + (2 * SPACING));
+ n_rows = (STAGE_HEIGHT - (2 * PADDING)) / (RECT_SIZE + (2 * SPACING));
+
+ last_y = PADDING + SPACING;
+ for (i = 0; i < n_rows; i++)
+ {
+ last_x = PADDING + SPACING;
+ for (j = 0; j < n_cols; j++)
+ {
+ ClutterActor *rect = clutter_actor_new ();
+
+ clutter_actor_set_position (rect, last_x, last_y);
+ clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE);
+ clutter_actor_set_content (rect, content);
+
+ clutter_container_add_actor (CLUTTER_CONTAINER (group), rect);
+
+ last_x += RECT_SIZE + SPACING;
+ }
+
+ last_y += RECT_SIZE + SPACING;
+ }
+
+ clutter_actor_set_size (group, last_x + PADDING, last_y + PADDING);
+
+ g_object_unref (content);
+
+ clutter_main ();
+
+ return EXIT_SUCCESS;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]