1 #include <clutter/clutter.h>
2 #include <string.h>
3 #include <stdlib.h>
4 
5 #include "test-conform-common.h"
6 
7 #define TEST_FONT "Sans 10"
8 
9 typedef struct _CallbackData CallbackData;
10 
11 struct _CallbackData
12 {
13   ClutterActor *stage;
14   ClutterActor *label;
15   gint          offset;
16   gboolean      test_failed;
17 
18   gint          extents_x;
19   gint          extents_y;
20   gint          extents_width;
21   gint          extents_height;
22   GSList       *run_attributes;
23   GSList       *default_attributes;
24   CallbackData *next;
25 };
26 
27 
28 static gint
attribute_lookup_func(gconstpointer data,gconstpointer user_data)29 attribute_lookup_func (gconstpointer data,
30                        gconstpointer user_data)
31 {
32     AtkAttribute *lookup_attr = (AtkAttribute*) user_data;
33     AtkAttribute *at = (AtkAttribute *) data;
34     if (!data)
35         return -1;
36     if (!g_strcmp0 (at->name, lookup_attr->name))
37         return g_strcmp0 (at->value, lookup_attr->value);
38     return -1;
39 }
40 
41 /* check l1 is a sub-set of l2 */
42 static gboolean
compare_lists(GSList * l1,GSList * l2)43 compare_lists (GSList* l1, GSList* l2)
44 {
45   gboolean fail = FALSE;
46 
47   if (l2 && !l1)
48     return TRUE;
49 
50   while (l1)
51     {
52         AtkAttribute *at = (AtkAttribute *) l1->data;
53         GSList* result = g_slist_find_custom ((GSList*) l2,
54                                               (gconstpointer) at,
55                                               attribute_lookup_func);
56         if (!result)
57           {
58             fail = TRUE;
59             break;
60           }
61         l1 = g_slist_next (l1);
62     }
63 
64   return fail;
65 }
66 
67 static void
dump_attribute_set(AtkAttributeSet * at_set)68 dump_attribute_set (AtkAttributeSet *at_set)
69 {
70   GSList *attrs = (GSList*) at_set;
71 
72   while (attrs) {
73       AtkAttribute *at = (AtkAttribute *) attrs->data;
74       g_print ("text attribute %s = %s\n", at->name, at->value);
75       attrs = g_slist_next (attrs);
76   }
77 
78 }
79 
80 static gboolean
check_result(CallbackData * data)81 check_result (CallbackData *data)
82 {
83   gboolean fail = FALSE;
84   gchar *text = NULL;
85   const gchar *expected_text = NULL;
86   AtkObject *object = NULL;
87   AtkText *cally_text = NULL;
88   gunichar unichar;
89   gunichar expected_char;
90   gint x, y, width, height;
91   gint pos;
92   AtkAttributeSet *at_set = NULL;
93   GSList *attrs;
94   gint start = -1;
95   gint end = -1;
96 
97   object = atk_gobject_accessible_for_object (G_OBJECT (data->label));
98   cally_text = ATK_TEXT (object);
99 
100   if (!cally_text) {
101       g_print("no text\n");
102     return TRUE;
103   }
104 
105   text = atk_text_get_text (cally_text, 0, -1);
106   expected_text = clutter_text_get_text (CLUTTER_TEXT (data->label));
107 
108   if (g_strcmp0 (expected_text, text) != 0)
109     {
110       if (!g_test_quiet ())
111         g_print ("text value differs %s vs %s\n", expected_text, text);
112       fail = TRUE;
113     }
114 
115   unichar = atk_text_get_character_at_offset (cally_text, data->offset);
116   expected_char = g_utf8_get_char (g_utf8_offset_to_pointer (text,  data->offset));
117   if (expected_char != unichar)
118     {
119       if (!g_test_quiet ())
120         g_print ("text af offset differs\n");
121       fail = TRUE;
122     }
123 
124   atk_text_get_character_extents (cally_text, data->offset, &x, &y, &width, &height,
125                                   ATK_XY_WINDOW);
126   if (x != data->extents_x)
127     {
128       if (!g_test_quiet ())
129         g_print ("extents x position at index 0 differs (current value=%d)\n", x);
130       fail = TRUE;
131     }
132   if (y != data->extents_y)
133     {
134       if (!g_test_quiet ())
135         g_print ("extents y position at index 0 differs (current value=%d)\n", y);
136       fail = TRUE;
137     }
138   if (width != data->extents_width)
139     {
140       if (!g_test_quiet ())
141         g_print ("extents width at index 0 differs (current value=%d)\n", width);
142       fail = TRUE;
143     }
144   if (height != data->extents_height)
145     {
146       if (!g_test_quiet ())
147         g_print ("extents height at index 0 differs (current value=%d)\n", height);
148       fail = TRUE;
149     }
150 
151   pos = atk_text_get_offset_at_point (cally_text, x, y, ATK_XY_WINDOW);
152   if (pos != data->offset)
153     {
154       if (!g_test_quiet ())
155         g_print ("offset at position (%d, %d) differs (current value=%d)\n", x,
156                  y, pos);
157       fail = TRUE;
158     }
159 
160   at_set = atk_text_get_run_attributes (cally_text, 0,
161                                         &start, &end);
162   if (start != 0)
163     {
164       if (!g_test_quiet ())
165           g_print ("run attributes start offset is not 0: %d\n", start);
166       fail = TRUE;
167     }
168   if (end != g_utf8_strlen (text, -1))
169     {
170       if (!g_test_quiet ())
171           g_print ("run attributes end offset is not text length: %d\n", end);
172       fail = TRUE;
173     }
174 
175   attrs = (GSList*) at_set;
176   fail = compare_lists (attrs, data->run_attributes);
177   if (fail && !g_test_quiet ())
178     {
179       g_print ("run attributes mismatch\n");
180       dump_attribute_set (attrs);
181     }
182 
183   at_set = atk_text_get_default_attributes (cally_text);
184   attrs = (GSList*) at_set;
185   fail = compare_lists (attrs, data->default_attributes);
186   if (fail && !g_test_quiet ())
187     {
188       g_print ("default attributes mismatch\n");
189       dump_attribute_set (attrs);
190     }
191 
192   g_free (text);
193   text = NULL;
194 
195   if (fail)
196     {
197       if (!g_test_quiet ())
198         g_print ("FAIL\n");
199       data->test_failed = TRUE;
200     }
201   else if (!g_test_quiet ())
202     g_print ("pass\n");
203 
204   return fail;
205 }
206 
207 static gboolean
do_tests(CallbackData * data)208 do_tests (CallbackData *data)
209 {
210   while (data)
211     {
212         gboolean result = check_result (data);
213         g_assert (result == FALSE);
214         data = data->next;
215     }
216 
217   clutter_test_quit ();
218 
219   return FALSE;
220 }
221 
222 static GSList*
build_attribute_set(const gchar * first_attribute,...)223 build_attribute_set (const gchar* first_attribute, ...)
224 {
225   AtkAttributeSet *return_set = g_slist_alloc ();
226   va_list args;
227   const gchar *name;
228   const gchar *value;
229   gint i = 0;
230 
231   value = first_attribute;
232   va_start (args, first_attribute);
233 
234   while (value)
235     {
236         if ((i> 0) && (i % 2 != 0))
237           {
238             AtkAttribute *at = g_malloc (sizeof (AtkAttribute));
239             at->name = g_strdup (name);
240             at->value = g_strdup (value);
241             return_set = g_slist_prepend (return_set, at);
242           }
243         i++;
244         name = g_strdup (value);
245         value = va_arg (args, gchar*);
246     }
247   va_end (args);
248   return return_set;
249 }
250 
251 void
cally_text(void)252 cally_text (void)
253 {
254   CallbackData data;
255   CallbackData data1;
256   GSList* default_attributes =  build_attribute_set ("left-margin", "0",
257                                                  "right-margin", "0",
258                                                  "indent", "0",
259                                                  "invisible", "false",
260                                                  "editable", "false",
261                                                  "pixels-above-lines", "0",
262                                                  "pixels-below-lines", "0",
263                                                  "pixels-inside-wrap", "0",
264                                                  "bg-full-height", "0",
265                                                  "bg-stipple", "false",
266                                                  "fg-stipple", "false",
267                                                  "fg-color", "0,0,0",
268                                                  "wrap-mode", "word",
269                                                  "justification", "left",
270                                                  "size", "10",
271                                                  "weight", "400",
272                                                  "family-name", "Sans",
273                                                  "stretch", "normal",
274                                                  "variant", "normal",
275                                                  "style", "normal",
276                                                  "language", "en-us",
277                                                  "direction", "ltr",
278                                                  NULL);
279 
280   memset (&data, 0, sizeof (data));
281 
282   data.stage = clutter_test_get_stage ();
283 
284   data.default_attributes = default_attributes;
285   data.run_attributes = build_attribute_set ("fg-color", "0,0,0", NULL);
286 
287   data.label = clutter_text_new_with_text (TEST_FONT, "Lorem ipsum dolor sit amet");
288 
289   clutter_container_add (CLUTTER_CONTAINER (data.stage), data.label, NULL);
290   data.offset = 6;
291   data.extents_x = 64;
292   data.extents_y = 99;
293   data.extents_width = 3;
294   data.extents_height = 17;
295   clutter_actor_set_position (data.label, 20, 100);
296 
297   memset (&data1, 0, sizeof (data1));
298   data1.stage = data.stage;
299   data1.default_attributes = default_attributes;
300   data1.run_attributes = build_attribute_set ("bg-color", "0,65535,0",
301                                               "fg-color", "65535,65535,0",
302                                               "strikethrough", "true", NULL);
303 
304   data1.label = clutter_text_new_with_text (TEST_FONT, "");
305   clutter_text_set_markup (CLUTTER_TEXT(data1.label), "<span fgcolor=\"#FFFF00\" bgcolor=\"#00FF00\"><s>Lorem ipsum dolor sit amet</s></span>");
306 
307   clutter_container_add (CLUTTER_CONTAINER (data1.stage), data1.label, NULL);
308   data1.offset = 10;
309   data1.extents_x = 90;
310   data1.extents_y = 199;
311   data1.extents_width = 13;
312   data1.extents_height = 17;
313   clutter_actor_set_position (data1.label, 20, 200);
314   data.next = &data1;
315 
316   clutter_actor_show (data.stage);
317   clutter_threads_add_idle ((GSourceFunc) do_tests, &data);
318   clutter_test_main ();
319 
320   clutter_actor_destroy (data.stage);
321 
322   if (!g_test_quiet ())
323     g_print ("\nOverall result: ");
324 
325   if (!g_test_quiet ())
326     {
327       if (data.test_failed)
328         g_print ("FAIL\n");
329       else
330         g_print ("pass\n");
331     }
332   else
333     {
334       g_assert (data.test_failed != TRUE);
335       g_assert (data1.test_failed != TRUE);
336     }
337 }
338 
339