1 #include <stdlib.h>
2 #include <gmodule.h>
3 #include <gdk-pixbuf/gdk-pixbuf.h>
4 #include <clutter/clutter.h>
5 
6 typedef struct _SolidContent {
7   GObject parent_instance;
8 
9   double red;
10   double green;
11   double blue;
12   double alpha;
13 
14   float padding;
15 } SolidContent;
16 
17 typedef struct _SolidContentClass {
18   GObjectClass parent_class;
19 } SolidContentClass;
20 
21 static void clutter_content_iface_init (ClutterContentIface *iface);
22 
G_DEFINE_TYPE_WITH_CODE(SolidContent,solid_content,G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,clutter_content_iface_init))23 G_DEFINE_TYPE_WITH_CODE (SolidContent, solid_content, G_TYPE_OBJECT,
24                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
25                                                 clutter_content_iface_init))
26 
27 static void
28 solid_content_paint_content (ClutterContent   *content,
29                              ClutterActor     *actor,
30                              ClutterPaintNode *root)
31 {
32   SolidContent *self = (SolidContent *) content;
33   ClutterActorBox box, content_box;
34   ClutterColor color;
35   PangoLayout *layout;
36   PangoRectangle logical;
37   ClutterPaintNode *node;
38 
39 #if 0
40   g_debug ("Painting content [%p] "
41            "{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } "
42            "for actor [%p] (context: [%p])",
43            content,
44            self->red,
45            self->green,
46            self->blue,
47            self->alpha,
48            actor, context);
49 #endif
50 
51   clutter_actor_get_content_box (actor, &content_box);
52 
53   box = content_box;
54   box.x1 += self->padding;
55   box.y1 += self->padding;
56   box.x2 -= self->padding;
57   box.y2 -= self->padding;
58 
59   color.alpha = self->alpha * 255;
60 
61   color.red = self->red * 255;
62   color.green = self->green * 255;
63   color.blue = self->blue * 255;
64 
65   node = clutter_color_node_new (&color);
66   clutter_paint_node_add_rectangle (node, &box);
67   clutter_paint_node_add_child (root, node);
68   clutter_paint_node_unref (node);
69 
70   color.red = (1.0 - self->red) * 255;
71   color.green = (1.0 - self->green) * 255;
72   color.blue = (1.0 - self->blue) * 255;
73 
74   layout = clutter_actor_create_pango_layout (actor, "A");
75   pango_layout_get_pixel_extents (layout, NULL, &logical);
76 
77   node = clutter_text_node_new (layout, &color);
78 
79   /* top-left */
80   box.x1 = clutter_actor_box_get_x (&content_box);
81   box.y1 = clutter_actor_box_get_y (&content_box);
82   box.x2 = box.x1 + logical.width;
83   box.y2 = box.y1 + logical.height;
84   clutter_paint_node_add_rectangle (node, &box);
85 
86   /* top-right */
87   box.x1 = clutter_actor_box_get_x (&content_box)
88          + clutter_actor_box_get_width (&content_box)
89          - logical.width;
90   box.y1 = clutter_actor_box_get_y (&content_box);
91   box.x2 = box.x1 + logical.width;
92   box.y2 = box.y1 + logical.height;
93   clutter_paint_node_add_rectangle (node, &box);
94 
95   /* bottom-right */
96   box.x1 = clutter_actor_box_get_x (&content_box)
97          + clutter_actor_box_get_width (&content_box)
98          - logical.width;
99   box.y1 = clutter_actor_box_get_y (&content_box)
100          + clutter_actor_box_get_height (&content_box)
101          - logical.height;
102   box.x2 = box.x1 + logical.width;
103   box.y2 = box.y1 + logical.height;
104   clutter_paint_node_add_rectangle (node, &box);
105 
106   /* bottom-left */
107   box.x1 = clutter_actor_box_get_x (&content_box);
108   box.y1 = clutter_actor_box_get_y (&content_box)
109          + clutter_actor_box_get_height (&content_box)
110          - logical.height;
111   box.x2 = box.x1 + logical.width;
112   box.y2 = box.y1 + logical.height;
113   clutter_paint_node_add_rectangle (node, &box);
114 
115   /* center */
116   box.x1 = clutter_actor_box_get_x (&content_box)
117          + (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0;
118   box.y1 = clutter_actor_box_get_y (&content_box)
119          + (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0;
120   box.x2 = box.x1 + logical.width;
121   box.y2 = box.y1 + logical.height;
122   clutter_paint_node_add_rectangle (node, &box);
123 
124   clutter_paint_node_add_child (root, node);
125   clutter_paint_node_unref (node);
126 
127   g_object_unref (layout);
128 }
129 
130 static void
clutter_content_iface_init(ClutterContentIface * iface)131 clutter_content_iface_init (ClutterContentIface *iface)
132 {
133   iface->paint_content = solid_content_paint_content;
134 }
135 
136 static void
solid_content_class_init(SolidContentClass * klass)137 solid_content_class_init (SolidContentClass *klass)
138 {
139 }
140 
141 static void
solid_content_init(SolidContent * self)142 solid_content_init (SolidContent *self)
143 {
144 }
145 
146 static ClutterContent *
solid_content_new(double red,double green,double blue,double alpha,float padding)147 solid_content_new (double red,
148                    double green,
149                    double blue,
150                    double alpha,
151                    float  padding)
152 {
153   SolidContent *self = g_object_new (solid_content_get_type (), NULL);
154 
155   self->red = red;
156   self->green = green;
157   self->blue = blue;
158   self->alpha = alpha;
159   self->padding = padding;
160 
161   return (ClutterContent *) self;
162 }
163 
164 G_MODULE_EXPORT const char *
test_image_describe(void)165 test_image_describe (void)
166 {
167   return "A test with image content.";
168 }
169 
170 G_MODULE_EXPORT int
test_image_main(int argc,char * argv[])171 test_image_main (int argc, char *argv[])
172 {
173   ClutterActor *stage, *grid;
174   ClutterContent *color, *image;
175   GdkPixbuf *pixbuf;
176   int i, n_rects;
177 
178   if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
179     return EXIT_FAILURE;
180 
181   stage = clutter_stage_new ();
182   clutter_actor_set_name (stage, "Stage");
183   clutter_stage_set_title (CLUTTER_STAGE (stage), "Content");
184   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
185   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
186   clutter_actor_show (stage);
187 
188   grid = clutter_actor_new ();
189   clutter_actor_set_name (grid, "Grid");
190   clutter_actor_set_margin_top (grid, 12);
191   clutter_actor_set_margin_right (grid, 12);
192   clutter_actor_set_margin_bottom (grid, 12);
193   clutter_actor_set_margin_left (grid, 12);
194   clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL));
195   clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0));
196   clutter_actor_add_child (stage, grid);
197 
198   color = solid_content_new (g_random_double_range (0.0, 1.0),
199                              g_random_double_range (0.0, 1.0),
200                              g_random_double_range (0.0, 1.0),
201                              1.0,
202                              2.0);
203 
204   pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL);
205   image = clutter_image_new ();
206   clutter_image_set_data (CLUTTER_IMAGE (image),
207                           gdk_pixbuf_get_pixels (pixbuf),
208                           gdk_pixbuf_get_has_alpha (pixbuf)
209                             ? COGL_PIXEL_FORMAT_RGBA_8888
210                             : COGL_PIXEL_FORMAT_RGB_888,
211                           gdk_pixbuf_get_width (pixbuf),
212                           gdk_pixbuf_get_height (pixbuf),
213                           gdk_pixbuf_get_rowstride (pixbuf),
214                           NULL);
215   g_object_unref (pixbuf);
216 
217   n_rects = g_random_int_range (12, 24);
218   for (i = 0; i < n_rects; i++)
219     {
220       ClutterActor *box = clutter_actor_new ();
221       ClutterColor bg_color = {
222         g_random_int_range (0, 255),
223         g_random_int_range (0, 255),
224         g_random_int_range (0, 255),
225         255
226       };
227       char *name, *str;
228 
229       str = clutter_color_to_string (&bg_color);
230       name = g_strconcat ("Box <", color, ">", NULL);
231       clutter_actor_set_name (box, name);
232 
233       free (name);
234       free (str);
235 
236       if ((i % 2) == 0)
237         clutter_actor_set_content (box, color);
238       else
239         clutter_actor_set_content (box, image);
240 
241       clutter_actor_set_size (box, 64, 64);
242 
243       clutter_actor_add_child (grid, box);
244     }
245 
246   clutter_main ();
247 
248   g_object_unref (color);
249   g_object_unref (image);
250 
251   return EXIT_SUCCESS;
252 }
253