1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include "common.h"
6 
7 Eina_Bool
ex_is_original_app(void)8 ex_is_original_app(void)
9 {
10    const char *original_pid_env = getenv("EXACTNESS_ORIGINAL_PID");
11    if (original_pid_env)
12      {
13         pid_t original_pid = atoi(original_pid_env);
14         if (original_pid == getpid())
15           return EINA_TRUE;
16      }
17    return EINA_FALSE;
18 }
19 
20 void
ex_set_original_envvar(void)21 ex_set_original_envvar(void)
22 {
23    const char *original_pid_env = getenv("EXACTNESS_ORIGINAL_PID");
24    if (!original_pid_env)
25      {
26         char pid[30];
27         snprintf(pid, sizeof(pid), "%d", getpid());
28         setenv("EXACTNESS_ORIGINAL_PID", pid, 0);
29      }
30 }
31 
32 void
ex_prepare_elm_overlay(void)33 ex_prepare_elm_overlay(void)
34 {
35    elm_theme_overlay_add(NULL, DATA_DIR"/exactness_play.edj");
36 }
37 
38 typedef struct _Dummy
39 {
40 } _Dummy;
41 
42 static Eet_Data_Descriptor *
_mouse_wheel_desc_make(void)43 _mouse_wheel_desc_make(void)
44 {
45    Eet_Data_Descriptor_Class eddc;
46    Eet_Data_Descriptor *_d;
47    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Mouse_Wheel);
48    _d = eet_data_descriptor_stream_new(&eddc);
49 
50    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Mouse_Wheel, "direction", direction, EET_T_INT);
51    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Mouse_Wheel, "z", z, EET_T_INT);
52 
53    return _d;
54 }
55 
56 static Eet_Data_Descriptor *
_key_down_up_desc_make(void)57 _key_down_up_desc_make(void)
58 {
59    Eet_Data_Descriptor_Class eddc;
60    Eet_Data_Descriptor *_d;
61    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Key_Down_Up);
62    _d = eet_data_descriptor_stream_new(&eddc);
63 
64    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "keyname", keyname, EET_T_STRING);
65    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "key", key, EET_T_STRING);
66    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "string", string, EET_T_STRING);
67    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "compose", compose, EET_T_STRING);
68    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Key_Down_Up, "keycode", keycode, EET_T_INT);
69 
70    return _d;
71 }
72 
73 static Eet_Data_Descriptor *
_multi_event_desc_make(void)74 _multi_event_desc_make(void)
75 {
76    Eet_Data_Descriptor_Class eddc;
77    Eet_Data_Descriptor *_d;
78    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Multi_Event);
79    _d = eet_data_descriptor_stream_new(&eddc);
80 
81    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "d", d, EET_T_UINT);
82    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "b", b, EET_T_UINT);
83    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "x", x, EET_T_UINT);
84    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "y", y, EET_T_UINT);
85    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "rad", rad, EET_T_DOUBLE);
86    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "radx", radx, EET_T_DOUBLE);
87    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "rady", rady, EET_T_DOUBLE);
88    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "pres", pres, EET_T_DOUBLE);
89    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "ang", ang, EET_T_DOUBLE);
90    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "fx", fx, EET_T_DOUBLE);
91    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "fy", fy, EET_T_DOUBLE);
92    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Event, "flags", flags, EET_T_INT);
93 
94    return _d;
95 }
96 
97 static Eet_Data_Descriptor *
_multi_move_desc_make(void)98 _multi_move_desc_make(void)
99 {
100    Eet_Data_Descriptor_Class eddc;
101    Eet_Data_Descriptor *_d;
102    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Multi_Move);
103    _d = eet_data_descriptor_stream_new(&eddc);
104 
105    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "d", d, EET_T_UINT);
106    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "x", x, EET_T_UINT);
107    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "y", y, EET_T_UINT);
108    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "rad", rad, EET_T_DOUBLE);
109    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "radx", radx, EET_T_DOUBLE);
110    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "rady", rady, EET_T_DOUBLE);
111    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "pres", pres, EET_T_DOUBLE);
112    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "ang", ang, EET_T_DOUBLE);
113    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "fx", fx, EET_T_DOUBLE);
114    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Multi_Move, "fy", fy, EET_T_DOUBLE);
115 
116    return _d;
117 }
118 
119 static Eet_Data_Descriptor *
_efl_event_desc_make(void)120 _efl_event_desc_make(void)
121 {
122    Eet_Data_Descriptor_Class eddc;
123    Eet_Data_Descriptor *_d;
124    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Efl_Event);
125    _d = eet_data_descriptor_stream_new(&eddc);
126 
127    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Efl_Event, "wdg_name", wdg_name, EET_T_STRING);
128    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Efl_Event, "event_name", event_name, EET_T_STRING);
129 
130    return _d;
131 }
132 
133 static Eet_Data_Descriptor *
_click_on_desc_make(void)134 _click_on_desc_make(void)
135 {
136    Eet_Data_Descriptor_Class eddc;
137    Eet_Data_Descriptor *_d;
138    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action_Click_On);
139    _d = eet_data_descriptor_stream_new(&eddc);
140 
141    EET_DATA_DESCRIPTOR_ADD_BASIC(_d, Exactness_Action_Click_On, "wdg_name", wdg_name, EET_T_STRING);
142 
143    return _d;
144 }
145 
146 static Eet_Data_Descriptor *
_dummy_desc_make(void)147 _dummy_desc_make(void)
148 {
149    Eet_Data_Descriptor_Class eddc;
150    Eet_Data_Descriptor *_d;
151    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, _Dummy);
152    _d = eet_data_descriptor_stream_new(&eddc);
153 
154    return _d;
155 }
156 
157 /* !!! SAME ORDER AS Exactness_Action_Type */
158 static const char *_mapping[] =
159 {
160    "",
161    "exactness_action_mouse_in",
162    "exactness_action_mouse_out",
163    "exactness_action_mouse_wheel",
164    "exactness_action_multi_down",
165    "exactness_action_multi_up",
166    "exactness_action_multi_move",
167    "exactness_action_key_down",
168    "exactness_action_key_up",
169    "exactness_action_take_shot",
170    "exactness_action_efl_event",
171    "exactness_action_click_on",
172    "exactness_action_stabilize"
173 };
174 
175 const char *
_exactness_action_type_to_string_get(Exactness_Action_Type type)176 _exactness_action_type_to_string_get(Exactness_Action_Type type)
177 {
178    if (type <= EXACTNESS_ACTION_LAST) return _mapping[type];
179    return NULL;
180 }
181 
182 static const char *
_variant_type_get(const void * data,Eina_Bool * unknow)183 _variant_type_get(const void *data, Eina_Bool  *unknow)
184 {
185    const Exactness_Action *act = data;
186 
187    if (unknow) *unknow = EINA_FALSE;
188    if (act->type <= EXACTNESS_ACTION_LAST) return _mapping[act->type];
189 
190    return NULL;
191 }
192 
193 static Eina_Bool
_variant_type_set(const char * type,void * data,Eina_Bool unknow EINA_UNUSED)194 _variant_type_set(const char *type,
195                   void       *data,
196                   Eina_Bool   unknow EINA_UNUSED)
197 {
198    int i;
199    Exactness_Action *act = data;
200    for (i = 0; i <= EXACTNESS_ACTION_LAST; i++)
201      {
202         if (!strcmp(_mapping[i], type)) act->type = i;
203      }
204    return EINA_TRUE;
205 }
206 
207 static Eet_Data_Descriptor *
_unit_desc_make(void)208 _unit_desc_make(void)
209 {
210    Eet_Data_Descriptor_Class eddc;
211    static Eet_Data_Descriptor *unit_d = NULL;
212    static Eet_Data_Descriptor *action_d = NULL, *action_variant_d = NULL;
213    static Eet_Data_Descriptor *objs_d = NULL;
214    static Eet_Data_Descriptor *obj_d = NULL;
215    if (!obj_d)
216      {
217         EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Object);
218         obj_d = eet_data_descriptor_stream_new(&eddc);
219         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "kl_name", kl_name, EET_T_STRING);
220         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "id", id, EET_T_ULONG_LONG);
221         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "parent_id", parent_id, EET_T_ULONG_LONG);
222         /* Evas stuff */
223         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "x", x, EET_T_INT);
224         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "y", y, EET_T_INT);
225         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "w", w, EET_T_INT);
226         EET_DATA_DESCRIPTOR_ADD_BASIC(obj_d, Exactness_Object, "h", h, EET_T_INT);
227 
228         EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Objects);
229         objs_d = eet_data_descriptor_stream_new(&eddc);
230         EET_DATA_DESCRIPTOR_ADD_LIST(objs_d, Exactness_Objects, "objs", objs, obj_d);
231      }
232    if (!unit_d)
233      {
234         EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Action);
235         action_d = eet_data_descriptor_stream_new(&eddc);
236 
237         eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
238         eddc.func.type_get = _variant_type_get;
239         eddc.func.type_set = _variant_type_set;
240         action_variant_d = eet_data_descriptor_stream_new(&eddc);
241 
242         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
243               _mapping[EXACTNESS_ACTION_MOUSE_IN], _dummy_desc_make());
244         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
245               _mapping[EXACTNESS_ACTION_MOUSE_OUT], _dummy_desc_make());
246         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
247               _mapping[EXACTNESS_ACTION_MOUSE_WHEEL], _mouse_wheel_desc_make());
248         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
249               _mapping[EXACTNESS_ACTION_MULTI_DOWN], _multi_event_desc_make());
250         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
251               _mapping[EXACTNESS_ACTION_MULTI_UP], _multi_event_desc_make());
252         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
253               _mapping[EXACTNESS_ACTION_MULTI_MOVE], _multi_move_desc_make());
254         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
255               _mapping[EXACTNESS_ACTION_KEY_DOWN], _key_down_up_desc_make());
256         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
257               _mapping[EXACTNESS_ACTION_KEY_UP], _key_down_up_desc_make());
258         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
259               _mapping[EXACTNESS_ACTION_TAKE_SHOT], _dummy_desc_make());
260         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
261               _mapping[EXACTNESS_ACTION_EFL_EVENT], _efl_event_desc_make());
262         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
263               _mapping[EXACTNESS_ACTION_CLICK_ON], _click_on_desc_make());
264         EET_DATA_DESCRIPTOR_ADD_MAPPING(action_variant_d,
265               _mapping[EXACTNESS_ACTION_STABILIZE], _dummy_desc_make());
266 
267         EET_DATA_DESCRIPTOR_ADD_BASIC(action_d, Exactness_Action, "n_evas", n_evas, EET_T_UINT);
268         EET_DATA_DESCRIPTOR_ADD_BASIC(action_d, Exactness_Action, "delay_ms", delay_ms, EET_T_UINT);
269         EET_DATA_DESCRIPTOR_ADD_VARIANT(action_d, Exactness_Action, "data", data, type, action_variant_d);
270 
271         /* Exactness_Unit */
272         EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Exactness_Unit);
273         unit_d = eet_data_descriptor_stream_new(&eddc);
274         EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "actions", actions, action_d);
275         EET_DATA_DESCRIPTOR_ADD_LIST(unit_d, Exactness_Unit, "objs", objs, objs_d);
276         EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "fonts_path", fonts_path, EET_T_STRING);
277         EET_DATA_DESCRIPTOR_ADD_BASIC(unit_d, Exactness_Unit, "nb_shots", nb_shots, EET_T_UINT);
278      }
279 
280    return unit_d;
281 }
282 /* END   Event struct descriptors */
283 
284 Exactness_Unit *
exactness_unit_file_read(const char * filename)285 exactness_unit_file_read(const char *filename)
286 {
287    int i;
288    Eina_List *itr, *itr2;
289    Exactness_Objects *e_objs;
290    Exactness_Object *e_obj, *e_parent;
291    Exactness_Unit *unit = NULL;
292    Eet_File *file;
293    eet_init();
294    file = eet_open(filename, EET_FILE_MODE_READ);
295    if (!file)
296      {
297         fprintf(stderr, "Impossible to extract EET from %s\n", filename);
298         return NULL;
299      }
300    unit = eet_data_read(file, _unit_desc_make(), "cache");
301    for (i = 0; i < unit->nb_shots; i++)
302      {
303         char entry[32];
304         Exactness_Image *ex_img = malloc(sizeof(*ex_img));
305         sprintf(entry, "images/%d", i + 1);
306         ex_img->pixels = eet_data_image_read(file, entry,
307               &ex_img->w, &ex_img->h, NULL,
308               NULL, NULL, NULL);
309         unit->imgs = eina_list_append(unit->imgs, ex_img);
310      }
311    EINA_LIST_FOREACH(unit->objs, itr, e_objs)
312      {
313         Eina_Hash *hash = eina_hash_pointer_new(NULL);
314         EINA_LIST_FOREACH(e_objs->objs, itr2, e_obj)
315           {
316              eina_hash_set(hash, &(e_obj->id), e_obj);
317           }
318         EINA_LIST_FOREACH(e_objs->objs, itr2, e_obj)
319           {
320              if (!e_obj->parent_id)
321                 e_objs->main_objs = eina_list_append(e_objs->main_objs, e_obj);
322              else
323                {
324                   e_parent = eina_hash_find(hash, &(e_obj->parent_id));
325                   if (e_parent) e_parent->children = eina_list_append(e_parent->children, e_obj);
326                }
327           }
328         eina_hash_free(hash);
329      }
330    eet_close(file);
331    eet_shutdown();
332    return unit;
333 }
334 
335 Eina_Bool
exactness_unit_file_write(Exactness_Unit * unit,const char * filename)336 exactness_unit_file_write(Exactness_Unit *unit, const char *filename)
337 {
338    Eina_List *itr;
339    Exactness_Image *ex_img;
340    Eet_File *file;
341    int i = 1;
342    int bytes;
343    Eina_Bool ret = EINA_TRUE;
344 
345    eet_init();
346    file = eet_open(filename, EET_FILE_MODE_WRITE);
347    eet_data_write(file, _unit_desc_make(), "cache", unit, EINA_TRUE);
348    EINA_LIST_FOREACH(unit->imgs, itr, ex_img)
349      {
350         char entry[32];
351         sprintf(entry, "images/%d", i++);
352         bytes = eet_data_image_write(file, entry, ex_img->pixels, ex_img->w, ex_img->h, 0xFF,
353                                      0, 100, EET_IMAGE_LOSSLESS);
354         if (bytes == 0)
355           {
356              ret = EINA_FALSE;
357              break;
358 	  }
359      }
360    eet_close(file);
361    eet_shutdown();
362    return ret;
363 }
364 
365 Eina_Bool
exactness_image_compare(Exactness_Image * img1,Exactness_Image * img2,Exactness_Image ** imgO)366 exactness_image_compare(Exactness_Image *img1, Exactness_Image *img2, Exactness_Image **imgO)
367 {
368    unsigned int w, h;
369    int *pxs1, *pxs2, *pxsO = NULL;
370    unsigned int w1 = img1 ? img1->w : 0, h1 = img1 ? img1->h : 0;
371    unsigned int w2 = img2 ? img2->w : 0, h2 = img2 ? img2->h : 0;
372    unsigned int wO = MAX(w1, w2);
373    unsigned int hO = MAX(h1, h2);
374    Eina_Bool ret = EINA_FALSE;
375    if (imgO) *imgO = NULL;
376    if (!wO || !hO) return EINA_FALSE;
377 
378    pxs1 = img1 ? img1->pixels : NULL;
379    pxs2 = img2 ? img2->pixels : NULL;
380    if (imgO) pxsO = malloc(wO * hO * 4);
381 
382    for (w = 0; w < wO; w++)
383      {
384         for (h = 0; h < hO; h++)
385           {
386              Eina_Bool valid1 = img1 ? w < w1 && h < h1 : EINA_FALSE;
387              Eina_Bool valid2 = img2 ? w < w2 && h < h2 : EINA_FALSE;
388              int px1 = valid1 ? pxs1[h * w1 + w] : 0;
389              int px2 = valid2 ? pxs2[h * w2 + w] : 0;
390              int r1 = (px1 & 0x00FF0000) >> 16;
391              int r2 = (px2 & 0x00FF0000) >> 16;
392              int g1 = (px1 & 0x0000FF00) >> 8;
393              int g2 = (px2 & 0x0000FF00) >> 8;
394              int b1 = (px1 & 0x000000FF);
395              int b2 = (px2 & 0x000000FF);
396              int new_r, new_g, new_b;
397              if (valid1 || valid2)
398                {
399                   if (px1 != px2)
400                     {
401                        new_r = 0xFF;
402                        new_g = ((g1 + g2) >> 1) >> 2;
403                        new_b = ((b1 + b2) >> 1) >> 2;
404                        ret = EINA_TRUE;
405                     }
406                   else
407                     {
408                        new_r = (((r1 + r2) >> 1) >> 2) + 0xC0;
409                        new_g = (((g1 + g2) >> 1) >> 2) + 0xC0;
410                        new_b = (((b1 + b2) >> 1) >> 2) + 0xC0;
411                     }
412                }
413              else
414                {
415                   new_r = new_g = new_b = 0x0;
416                }
417              if (pxsO) pxsO[h * wO + w] = 0xFF000000 | new_r << 16 | new_g << 8 | new_b;
418           }
419      }
420    if (imgO)
421      {
422         Exactness_Image *imgR = calloc(1, sizeof(Exactness_Image));
423         *imgO = imgR;
424         imgR->w = wO;
425         imgR->h = hO;
426         imgR->pixels = pxsO;
427      }
428    return ret;
429 }
430 
exactness_image_free(Exactness_Image * img)431 void exactness_image_free(Exactness_Image *img)
432 {
433    if (!img) return;
434    free(img->pixels);
435    free(img);
436 }
437