summaryrefslogtreecommitdiff
path: root/attic/astro-desktop/applications/contacts/clutter-reflect-texture.c
diff options
context:
space:
mode:
Diffstat (limited to 'attic/astro-desktop/applications/contacts/clutter-reflect-texture.c')
-rw-r--r--attic/astro-desktop/applications/contacts/clutter-reflect-texture.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/attic/astro-desktop/applications/contacts/clutter-reflect-texture.c b/attic/astro-desktop/applications/contacts/clutter-reflect-texture.c
new file mode 100644
index 0000000..5689d49
--- /dev/null
+++ b/attic/astro-desktop/applications/contacts/clutter-reflect-texture.c
@@ -0,0 +1,346 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#define CLUTTER_PARAM_READWRITE \
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB
+
+
+/**
+ * SECTION:clutter-reflect-texture
+ * @short_description: Actor for cloning existing textures in an
+ * efficient way.
+ *
+ * #ClutterReflectTexture allows the cloning of existing #ClutterTexture with
+ * a refelction like effect.
+ */
+
+#include <clutter/cogl.h>
+
+#include "clutter-reflect-texture.h"
+
+enum
+{
+ PROP_0,
+ PROP_REFLECTION_HEIGHT
+};
+
+G_DEFINE_TYPE (ClutterReflectTexture,
+ clutter_reflect_texture,
+ CLUTTER_TYPE_CLONE_TEXTURE);
+
+#define CLUTTER_REFLECT_TEXTURE_GET_PRIVATE(obj) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_REFLECT_TEXTURE, ClutterReflectTexturePrivate))
+
+struct _ClutterReflectTexturePrivate
+{
+ gint reflection_height;
+};
+
+static void
+reflect_texture_render_to_gl_quad (ClutterReflectTexture *ctexture,
+ int x1,
+ int y1,
+ int x2,
+ int y2)
+{
+ gint qx1 = 0, qx2 = 0, qy1 = 0, qy2 = 0;
+ gint qwidth = 0, qheight = 0;
+ gint x, y, i =0, lastx = 0, lasty = 0;
+ gint n_x_tiles, n_y_tiles;
+ gint pwidth, pheight, rheight;
+ float tx, ty, ty2 = 0.0;
+
+#ifdef CLUTTER_COGL_HAS_GL
+
+ ClutterReflectTexturePrivate *priv = ctexture->priv;
+ ClutterActor *parent_texture = CLUTTER_ACTOR(clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(ctexture)));
+
+ priv = ctexture->priv;
+
+ qwidth = x2 - x1;
+ qheight = y2 - y1;
+
+ rheight = priv->reflection_height;
+
+ if (rheight > qheight)
+ rheight = qheight;
+
+ if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture))
+ clutter_actor_realize (parent_texture);
+
+ /* Only paint if parent is in a state to do so */
+ if (!clutter_texture_has_generated_tiles (CLUTTER_TEXTURE(parent_texture)))
+ return;
+
+ clutter_texture_get_base_size (CLUTTER_TEXTURE(parent_texture),
+ &pwidth, &pheight);
+
+ if (!clutter_texture_is_tiled (CLUTTER_TEXTURE(parent_texture)))
+ {
+ clutter_texture_bind_tile (CLUTTER_TEXTURE(parent_texture), 0);
+
+ /* NPOTS textures *always* used if extension available
+ */
+ if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE))
+ {
+ tx = (float) pwidth;
+ ty = (float) pheight;
+ ty2 = (float)(clutter_actor_get_height (CLUTTER_ACTOR(ctexture)) * rheight)
+ / pheight;
+ ty2 = pheight - ty2;
+
+ }
+ else
+ {
+ tx = (float) pwidth / clutter_util_next_p2 (pwidth);
+ ty = (float) pheight / clutter_util_next_p2 (pheight);
+ }
+
+ qx1 = x1; qx2 = x2;
+ qy1 = y1; qy2 = y1 + rheight;
+
+ glBegin (GL_QUADS);
+
+ glColor4ub (255, 255, 255,
+ clutter_actor_get_opacity (CLUTTER_ACTOR(ctexture)));
+
+ glTexCoord2f (0, ty);
+ glVertex2i (qx1, qy1);
+
+ glTexCoord2f (tx, ty);
+ glVertex2i (qx2, qy1);
+
+ glColor4ub (255, 255, 255, 0);
+
+ glTexCoord2f (tx, ty2);
+ glVertex2i (qx2, qy2);
+
+ glTexCoord2f (0, ty2);
+ glVertex2i (qx1, qy2);
+
+ glEnd ();
+
+ return;
+ }
+
+ clutter_texture_get_n_tiles (CLUTTER_TEXTURE(parent_texture),
+ &n_x_tiles, &n_y_tiles);
+
+ for (x = 0; x < n_x_tiles; x++)
+ {
+ lasty = 0;
+
+ for (y = 0; y < n_y_tiles; y++)
+ {
+ gint actual_w, actual_h;
+ gint xpos, ypos, xsize, ysize, ywaste, xwaste;
+
+ clutter_texture_bind_tile (CLUTTER_TEXTURE(parent_texture), i);
+
+ clutter_texture_get_x_tile_detail (CLUTTER_TEXTURE(parent_texture),
+ x, &xpos, &xsize, &xwaste);
+
+ clutter_texture_get_y_tile_detail (CLUTTER_TEXTURE(parent_texture),
+ y, &ypos, &ysize, &ywaste);
+
+ actual_w = xsize - xwaste;
+ actual_h = ysize - ywaste;
+
+ tx = (float) actual_w / xsize;
+ ty = (float) actual_h / ysize;
+
+ qx1 = x1 + lastx;
+ qx2 = qx1 + ((qwidth * actual_w ) / pwidth );
+
+ qy1 = y1 + lasty;
+ qy2 = qy1 + ((qheight * actual_h) / pheight );
+
+ glBegin (GL_QUADS);
+ glTexCoord2f (tx, ty); glVertex2i (qx2, qy2);
+ glTexCoord2f (0, ty); glVertex2i (qx1, qy2);
+ glTexCoord2f (0, 0); glVertex2i (qx1, qy1);
+ glTexCoord2f (tx, 0); glVertex2i (qx2, qy1);
+ glEnd ();
+
+ lasty += qy2 - qy1;
+
+ i++;
+ }
+ lastx += qx2 - qx1;
+ }
+#endif
+
+}
+
+static void
+clutter_reflect_texture_paint (ClutterActor *self)
+{
+ ClutterReflectTexturePrivate *priv;
+ ClutterActor *parent_texture;
+ gint x1, y1, x2, y2;
+ GLenum target_type;
+
+#ifdef CLUTTER_COGL_HAS_GL
+
+ priv = CLUTTER_REFLECT_TEXTURE (self)->priv;
+
+ /* no need to paint stuff if we don't have a texture to reflect */
+ if (!clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(self)))
+ return;
+
+ /* parent texture may have been hidden, there for need to make sure its
+ * realised with resources available.
+ */
+ parent_texture = CLUTTER_ACTOR (clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(self)));
+ if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture))
+ clutter_actor_realize (parent_texture);
+
+ /* FIXME: figure out nicer way of getting at this info...
+ */
+ if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE) &&
+ clutter_texture_is_tiled (CLUTTER_TEXTURE (parent_texture)) == FALSE)
+ {
+ target_type = CGL_TEXTURE_RECTANGLE_ARB;
+ cogl_enable (CGL_ENABLE_TEXTURE_RECT | CGL_ENABLE_BLEND);
+ }
+ else
+ {
+ target_type = CGL_TEXTURE_2D;
+ cogl_enable (CGL_ENABLE_TEXTURE_2D|CGL_ENABLE_BLEND);
+ }
+
+ cogl_push_matrix ();
+
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glColor4ub (255, 255, 255, clutter_actor_get_opacity (self));
+
+ clutter_actor_get_coords (self, &x1, &y1, &x2, &y2);
+
+ /* Parent paint translated us into position */
+ reflect_texture_render_to_gl_quad (CLUTTER_REFLECT_TEXTURE (self),
+ 0, 0, x2 - x1, y2 - y1);
+
+ cogl_pop_matrix ();
+#endif
+}
+
+
+
+static void
+clutter_reflect_texture_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ClutterReflectTexture *ctexture = CLUTTER_REFLECT_TEXTURE (object);
+ ClutterReflectTexturePrivate *priv = ctexture->priv;
+
+ switch (prop_id)
+ {
+ case PROP_REFLECTION_HEIGHT:
+ priv->reflection_height = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+clutter_reflect_texture_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ClutterReflectTexture *ctexture = CLUTTER_REFLECT_TEXTURE (object);
+ ClutterReflectTexturePrivate *priv = ctexture->priv;
+
+ switch (prop_id)
+ {
+ case PROP_REFLECTION_HEIGHT:
+ g_value_set_int (value, priv->reflection_height);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+clutter_reflect_texture_class_init (ClutterReflectTextureClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+
+ actor_class->paint = clutter_reflect_texture_paint;
+
+ gobject_class->set_property = clutter_reflect_texture_set_property;
+ gobject_class->get_property = clutter_reflect_texture_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_REFLECTION_HEIGHT,
+ g_param_spec_int ("reflection-height",
+ "Reflection Height",
+ "",
+ 0, G_MAXINT,
+ 0,
+ (G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE)));
+
+ g_type_class_add_private (gobject_class, sizeof (ClutterReflectTexturePrivate));
+}
+
+static void
+clutter_reflect_texture_init (ClutterReflectTexture *self)
+{
+ ClutterReflectTexturePrivate *priv;
+
+ self->priv = priv = CLUTTER_REFLECT_TEXTURE_GET_PRIVATE (self);
+ priv->reflection_height = 100;
+}
+
+/**
+ * clutter_reflect_texture_new:
+ * @texture: a #ClutterTexture or %NULL
+ *
+ * Creates an efficient 'reflect' of a pre-existing texture if which it
+ * shares the underlying pixbuf data.
+ *
+ * You can use clutter_reflect_texture_set_parent_texture() to change the
+ * parent texture to be reflectd.
+ *
+ * Return value: the newly created #ClutterReflectTexture
+ */
+ClutterActor *
+clutter_reflect_texture_new (ClutterTexture *texture, gint reflection_height)
+{
+ g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
+
+ return g_object_new (CLUTTER_TYPE_REFLECT_TEXTURE,
+ "parent-texture", texture,
+ "reflection-height", reflection_height,
+ NULL);
+}
+