1 #include <stdlib.h>
2 #include <math.h>
3 #include <cairo.h>
4 #include <clutter/clutter.h>
5 
6 static gboolean
draw_content(ClutterCanvas * canvas,cairo_t * cr,int surface_width,int surface_height)7 draw_content (ClutterCanvas *canvas,
8               cairo_t       *cr,
9               int            surface_width,
10               int            surface_height)
11 {
12   /* rounded rectangle taken from:
13    *
14    *   http://cairographics.org/samples/rounded_rectangle/
15    *
16    * we leave 1 pixel around the edges to avoid jagged edges
17    * when rotating the actor
18    */
19   double x             = 1.0,        /* parameters like cairo_rectangle */
20          y             = 1.0,
21          width         = surface_width - 2.0,
22          height        = surface_height - 2.0,
23          aspect        = 1.0,     /* aspect ratio */
24          corner_radius = height / 20.0;   /* and corner curvature radius */
25 
26   double radius = corner_radius / aspect;
27   double degrees = M_PI / 180.0;
28 
29   cairo_save (cr);
30   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
31   cairo_paint (cr);
32   cairo_restore (cr);
33 
34   cairo_new_sub_path (cr);
35   cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
36   cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
37   cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
38   cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
39   cairo_close_path (cr);
40 
41   cairo_set_source_rgba (cr, 0.5, 0.5, 1, 0.95);
42   cairo_fill (cr);
43 
44   /* we're done drawing */
45   return TRUE;
46 }
47 
48 int
main(int argc,char * argv[])49 main (int argc, char *argv[])
50 {
51   ClutterActor *stage, *actor;
52   ClutterContent *canvas;
53   ClutterTransition *transition;
54 
55   /* initialize Clutter */
56   if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
57     return EXIT_FAILURE;
58 
59   /* create a stage */
60   stage = clutter_stage_new ();
61   clutter_stage_set_title (CLUTTER_STAGE (stage), "Rectangle with rounded corners");
62   clutter_stage_set_use_alpha (CLUTTER_STAGE (stage), TRUE);
63   clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
64   clutter_actor_set_size (stage, 500, 500);
65   clutter_actor_set_opacity (stage, 64);
66   clutter_actor_show (stage);
67 
68   /* our 2D canvas, courtesy of Cairo */
69   canvas = clutter_canvas_new ();
70   clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300);
71 
72   /* the actor that will display the contents of the canvas */
73   actor = clutter_actor_new ();
74   clutter_actor_set_content (actor, canvas);
75   clutter_actor_set_content_gravity (actor, CLUTTER_CONTENT_GRAVITY_CENTER);
76   clutter_actor_set_content_scaling_filters (actor,
77                                              CLUTTER_SCALING_FILTER_TRILINEAR,
78                                              CLUTTER_SCALING_FILTER_LINEAR);
79   clutter_actor_set_pivot_point (actor, 0.5f, 0.5f);
80   clutter_actor_add_constraint (actor, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
81   clutter_actor_set_request_mode (actor, CLUTTER_REQUEST_CONTENT_SIZE);
82   clutter_actor_add_child (stage, actor);
83 
84   /* the actor now owns the canvas */
85   g_object_unref (canvas);
86 
87   /* create the continuous animation of the actor spinning around its center */
88   transition = clutter_property_transition_new ("rotation-angle-y");
89   clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0);
90   clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0);
91   clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 2000);
92   clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
93   clutter_actor_add_transition (actor, "rotateActor", transition);
94 
95   /* the actor now owns the transition */
96   g_object_unref (transition);
97 
98   /* quit on destroy */
99   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
100 
101   /* connect our drawing code */
102   g_signal_connect (canvas, "draw", G_CALLBACK (draw_content), NULL);
103 
104   /* invalidate the canvas, so that we can draw before the main loop starts */
105   clutter_content_invalidate (canvas);
106 
107   clutter_main ();
108 
109   return EXIT_SUCCESS;
110 }
111