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