0f613ea134
By using a new signal, ::create-surface (width, height), it should be possible for third party code and sub-classes to override the default surface creation code in CairoSurface. This commit takes a bit of the patch from: http://bugzilla.clutter-project.org/show_bug.cgi?id=1878 which cleans up CairoTexture; the idea, mutuated from that bug, is that the CairoTexture actor checks whether the surface it has it's an image one, and in that case it uses a Cogl texture as the backing store. In case the surface is not an image one we assume that the surface itself has some way of updating the GL state and flush the surface.
224 lines
5.2 KiB
C
224 lines
5.2 KiB
C
/*
|
|
* Pretty cairo flower hack.
|
|
*/
|
|
|
|
#include <clutter/clutter.h>
|
|
|
|
#ifndef _MSC_VER
|
|
#include <unistd.h> /* for sleep(), used for screenshots */
|
|
#endif
|
|
#include <stdlib.h>
|
|
#ifdef _MSC_VER
|
|
#define _USE_MATH_DEFINES
|
|
#endif
|
|
#include <math.h>
|
|
|
|
#define PETAL_MIN 20
|
|
#define PETAL_VAR 40
|
|
#define N_FLOWERS 40 /* reduce if you have a small card */
|
|
|
|
typedef struct Flower
|
|
{
|
|
ClutterActor *ctex;
|
|
gint x,y,rot,v,rv;
|
|
}
|
|
Flower;
|
|
|
|
ClutterActor*
|
|
make_flower_actor (void)
|
|
{
|
|
/* No science here, just a hack from toying */
|
|
gint i, j;
|
|
|
|
double colors[] = {
|
|
0.71, 0.81, 0.83,
|
|
1.0, 0.78, 0.57,
|
|
0.64, 0.30, 0.35,
|
|
0.73, 0.40, 0.39,
|
|
0.91, 0.56, 0.64,
|
|
0.70, 0.47, 0.45,
|
|
0.92, 0.75, 0.60,
|
|
0.82, 0.86, 0.85,
|
|
0.51, 0.56, 0.67,
|
|
1.0, 0.79, 0.58,
|
|
|
|
};
|
|
|
|
gint size;
|
|
gint petal_size;
|
|
gint n_groups; /* Num groups of petals 1-3 */
|
|
gint n_petals; /* num of petals 4 - 8 */
|
|
gint pm1, pm2;
|
|
|
|
gint idx, last_idx = -1;
|
|
|
|
ClutterActor *ctex;
|
|
cairo_t *cr;
|
|
|
|
petal_size = PETAL_MIN + rand() % PETAL_VAR;
|
|
size = petal_size * 8;
|
|
|
|
n_groups = rand() % 3 + 1;
|
|
|
|
ctex = clutter_cairo_texture_new (size, size);
|
|
|
|
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (ctex));
|
|
|
|
cairo_set_tolerance (cr, 0.1);
|
|
|
|
/* Clear */
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
|
cairo_paint(cr);
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
|
|
|
cairo_translate(cr, size/2, size/2);
|
|
|
|
for (i=0; i<n_groups; i++)
|
|
{
|
|
n_petals = rand() % 5 + 4;
|
|
cairo_save (cr);
|
|
|
|
cairo_rotate (cr, rand() % 6);
|
|
|
|
do {
|
|
idx = (rand() % (sizeof (colors) / sizeof (double) / 3)) * 3;
|
|
} while (idx == last_idx);
|
|
|
|
cairo_set_source_rgba (cr, colors[idx], colors[idx+1],
|
|
colors[idx+2], 0.5);
|
|
|
|
last_idx = idx;
|
|
|
|
/* some bezier randomness */
|
|
pm1 = rand() % 20;
|
|
pm2 = rand() % 4;
|
|
|
|
for (j=1; j<n_petals+1; j++)
|
|
{
|
|
cairo_save (cr);
|
|
cairo_rotate (cr, ((2*M_PI)/n_petals)*j);
|
|
|
|
/* Petals are made up beziers */
|
|
cairo_new_path (cr);
|
|
cairo_move_to (cr, 0, 0);
|
|
cairo_rel_curve_to (cr,
|
|
petal_size, petal_size,
|
|
(pm2+2)*petal_size, petal_size,
|
|
(2*petal_size) + pm1, 0);
|
|
cairo_rel_curve_to (cr,
|
|
0 + (pm2*petal_size), -petal_size,
|
|
-petal_size, -petal_size,
|
|
-((2*petal_size) + pm1), 0);
|
|
cairo_close_path (cr);
|
|
cairo_fill (cr);
|
|
cairo_restore (cr);
|
|
}
|
|
|
|
petal_size -= rand() % (size/8);
|
|
|
|
cairo_restore (cr);
|
|
}
|
|
|
|
/* Finally draw flower center */
|
|
do {
|
|
idx = (rand() % (sizeof (colors) / sizeof (double) / 3)) * 3;
|
|
} while (idx == last_idx);
|
|
|
|
if (petal_size < 0)
|
|
petal_size = rand() % 10;
|
|
|
|
cairo_set_source_rgba (cr, colors[idx], colors[idx+1], colors[idx+2], 0.5);
|
|
|
|
cairo_arc(cr, 0, 0, petal_size, 0, M_PI * 2);
|
|
cairo_fill(cr);
|
|
|
|
cairo_destroy(cr);
|
|
|
|
return ctex;
|
|
}
|
|
|
|
static void
|
|
tick (ClutterTimeline *timeline,
|
|
gint msecs,
|
|
gpointer data)
|
|
{
|
|
Flower **flowers = (Flower**)data;
|
|
gint i = 0;
|
|
|
|
for (i = 0; i < N_FLOWERS; i++)
|
|
{
|
|
ClutterActor *stage;
|
|
|
|
flowers[i]->y += flowers[i]->v;
|
|
flowers[i]->rot += flowers[i]->rv;
|
|
|
|
stage = clutter_stage_get_default ();
|
|
if (flowers[i]->y > (gint) clutter_actor_get_height (stage))
|
|
flowers[i]->y = -clutter_actor_get_height (flowers[i]->ctex);
|
|
|
|
clutter_actor_set_position (flowers[i]->ctex,
|
|
flowers[i]->x, flowers[i]->y);
|
|
|
|
clutter_actor_set_rotation (flowers[i]->ctex,
|
|
CLUTTER_Z_AXIS,
|
|
flowers[i]->rot,
|
|
clutter_actor_get_width (flowers[i]->ctex)/2,
|
|
clutter_actor_get_height (flowers[i]->ctex)/2,
|
|
0);
|
|
}
|
|
}
|
|
|
|
int
|
|
test_cairo_flowers_main (int argc, char **argv)
|
|
{
|
|
int i;
|
|
ClutterActor *stage;
|
|
ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
|
ClutterTimeline *timeline;
|
|
Flower *flowers[N_FLOWERS];
|
|
|
|
srand (time (NULL));
|
|
|
|
clutter_init (&argc, &argv);
|
|
|
|
stage = clutter_stage_get_default ();
|
|
|
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
|
|
|
for (i=0; i< N_FLOWERS; i++)
|
|
{
|
|
flowers[i] = g_new0(Flower, 1);
|
|
flowers[i]->ctex = make_flower_actor();
|
|
flowers[i]->x = rand() % (int) clutter_actor_get_width (stage)
|
|
- (PETAL_MIN + PETAL_VAR) * 2;
|
|
flowers[i]->y = rand() % (int) clutter_actor_get_height (stage);
|
|
flowers[i]->rv = rand() % 5 + 1;
|
|
flowers[i]->v = rand() % 10 + 2;
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
|
|
flowers[i]->ctex);
|
|
clutter_actor_set_position (flowers[i]->ctex,
|
|
flowers[i]->x, flowers[i]->y);
|
|
}
|
|
|
|
/* Create a timeline to manage animation */
|
|
timeline = clutter_timeline_new (6000);
|
|
clutter_timeline_set_loop (timeline, TRUE);
|
|
|
|
/* fire a callback for frame change */
|
|
g_signal_connect (timeline, "new-frame", G_CALLBACK (tick), flowers);
|
|
|
|
clutter_actor_show (stage);
|
|
|
|
clutter_timeline_start (timeline);
|
|
|
|
g_signal_connect (stage, "key-press-event",
|
|
G_CALLBACK (clutter_main_quit),
|
|
NULL);
|
|
|
|
clutter_main();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|