From b7c76a45bcab1d84d50e1144d5a9976f472ea503 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 3 May 2012 13:53:29 +0100 Subject: [PATCH] Add rounded corners rectangle example using Canvas An old request: how to create a rectangle with rounded corners with Clutter; we use ClutterCanvas and Cairo because we want anti-aliased edges. --- examples/Makefile.am | 1 + examples/rounded-rectangle.c | 107 +++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 examples/rounded-rectangle.c diff --git a/examples/Makefile.am b/examples/Makefile.am index bf203bd12..260c5d954 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -9,6 +9,7 @@ all_examples = \ drop-action \ easing-modes \ flow-layout \ + rounded-rectangle \ threads if PIXBUF_TESTS diff --git a/examples/rounded-rectangle.c b/examples/rounded-rectangle.c new file mode 100644 index 000000000..3858dd429 --- /dev/null +++ b/examples/rounded-rectangle.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +static gboolean +draw_content (ClutterCanvas *canvas, + cairo_t *cr, + int surface_width, + int surface_height) +{ + /* rounded rectangle taken from: + * + * http://cairographics.org/samples/rounded_rectangle/ + * + * we leave 1 pixel around the edges to avoid jagged edges + * when rotating the actor + */ + double x = 1.0, /* parameters like cairo_rectangle */ + y = 1.0, + width = surface_width - 2.0, + height = surface_height - 2.0, + aspect = 1.0, /* aspect ratio */ + corner_radius = height / 20.0; /* and corner curvature radius */ + + double radius = corner_radius / aspect; + double degrees = M_PI / 180.0; + + cairo_save (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_restore (cr); + + cairo_new_sub_path (cr); + cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees); + cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees); + cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees); + cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees); + cairo_close_path (cr); + + cairo_set_source_rgb (cr, 0.5, 0.5, 1); + cairo_fill (cr); + + /* we're done drawing */ + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + ClutterActor *stage, *actor; + ClutterContent *canvas; + ClutterTransition *transition; + + /* initialize Clutter */ + if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) + return EXIT_FAILURE; + + /* create a stage */ + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Rectangle with rounded corners"); + clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); + clutter_actor_set_size (stage, 500, 500); + clutter_actor_show (stage); + + /* our 2D canvas, courtesy of Cairo */ + canvas = clutter_canvas_new (); + clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300); + + /* the actor that will display the contents of the canvas */ + actor = clutter_actor_new (); + clutter_actor_set_content (actor, canvas); + clutter_actor_set_content_gravity (actor, CLUTTER_CONTENT_GRAVITY_CENTER); + clutter_actor_set_content_scaling_filters (actor, + CLUTTER_SCALING_FILTER_TRILINEAR, + CLUTTER_SCALING_FILTER_LINEAR); + clutter_actor_set_rotation (actor, CLUTTER_Y_AXIS, 0.0, 250.f, 0.f, 0.f); + clutter_actor_add_constraint (actor, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.f)); + clutter_actor_add_child (stage, actor); + + /* the actor now owns the canvas */ + g_object_unref (canvas); + + /* create the continuous animation of the actor spinning around its center */ + transition = clutter_property_transition_new ("rotation-angle-y"); + clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0); + clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0); + clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 2000); + clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1); + clutter_actor_add_transition (actor, "rotateActor", transition); + + /* the actor now owns the transition */ + g_object_unref (transition); + + /* quit on destroy */ + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + /* connect our drawing code */ + g_signal_connect (canvas, "draw", G_CALLBACK (draw_content), NULL); + + /* invalidate the canvas, so that we can draw before the main loop starts */ + clutter_content_invalidate (canvas); + + clutter_main (); + + return EXIT_SUCCESS; +}