2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
27 #include <Ecore_Evas.h>
34 #include <livebox-errno.h>
36 #include "script_port.h"
38 #define TEXT_CLASS "tizen"
39 #define BASE_WIDTH 720.0f
41 #define PUBLIC __attribute__((visibility("default")))
43 extern void evas_common_font_flush(void);
44 extern int evas_common_font_cache_get(void);
45 extern void evas_common_font_cache_set(int size);
83 Ecore_Event_Handler *property_handler;
87 .property_handler = NULL,
92 static inline double scale_get(void)
96 ecore_x_window_size_get(0, &width, &height);
97 return (double)width / BASE_WIDTH;
102 * Reservce this for future use
103 static inline void common_cache_flush(void *evas)
106 int collection_cache;
110 file_cache = edje_file_cache_get();
111 collection_cache = edje_collection_cache_get();
112 image_cache = evas_image_cache_get(evas);
113 font_cache = evas_font_cache_get(evas);
115 edje_file_cache_set(file_cache);
116 edje_collection_cache_set(collection_cache);
117 evas_image_cache_set(evas, 0);
118 evas_font_cache_set(evas, 0);
120 evas_image_cache_flush(evas);
121 evas_render_idle_flush(evas);
122 evas_font_cache_flush(evas);
124 edje_file_cache_flush();
125 edje_collection_cache_flush();
127 edje_file_cache_set(file_cache);
128 edje_collection_cache_set(collection_cache);
129 evas_image_cache_set(evas, image_cache);
130 evas_font_cache_set(evas, font_cache);
136 static inline Evas_Object *find_edje(struct info *handle, const char *id)
140 struct obj_info *obj_info;
142 EINA_LIST_FOREACH(handle->obj_list, l, edje) {
143 obj_info = evas_object_data_get(edje, "obj_info");
145 ErrPrint("Object info is not valid\n");
154 } else if (!obj_info->id) {
158 if (!strcmp(obj_info->id, id))
162 DbgPrint("EDJE[%s] is not found\n", id);
166 PUBLIC const char *script_magic_id(void)
171 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
173 struct info *handle = h;
175 int r[3], g[3], b[3], a[3];
178 edje = find_edje(handle, id);
180 return LB_STATUS_ERROR_NOT_EXIST;
182 ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
183 r, g, b, a, /* OBJECT */
184 r + 1, g + 1, b + 1, a + 1, /* OUTLINE */
185 r + 2, g + 2, b + 2, a + 2); /* SHADOW */
187 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
188 return LB_STATUS_ERROR_INVALID;
191 ret = edje_object_color_class_set(edje, part,
192 r[0], g[0], b[0], a[0], /* OBJECT */
193 r[1], g[1], b[1], a[1], /* OUTLINE */
194 r[2], g[2], b[2], a[2]); /* SHADOW */
196 DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
197 return LB_STATUS_SUCCESS;
200 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
202 struct info *handle = h;
205 edje = find_edje(handle, id);
207 return LB_STATUS_ERROR_NOT_EXIST;
209 edje_object_part_text_set(edje, part, text);
210 return LB_STATUS_SUCCESS;
213 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
215 while (len > 0 && *value == ' ') {
223 img_opt->aspect = !strncasecmp(value, "true", 4);
224 DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
227 static void parse_orient(struct image_option *img_opt, const char *value, int len)
229 while (len > 0 && *value == ' ') {
237 img_opt->orient = !strncasecmp(value, "true", 4);
238 DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->aspect, value);
241 static void parse_size(struct image_option *img_opt, const char *value, int len)
247 while (len > 0 && *value == ' ') {
252 buf = strndup(value, len);
254 ErrPrint("Heap: %s\n", strerror(errno));
258 if (sscanf(buf, "%dx%d", &width, &height) == 2) {
259 img_opt->width = width;
260 img_opt->height = height;
261 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
263 DbgPrint("Invalid size tag[%s]\n", buf);
269 static void parse_fill(struct image_option *img_opt, const char *value, int len)
271 while (len > 0 && *value == ' ') {
276 if (!strncasecmp(value, "in-size", len))
277 img_opt->fill = FILL_IN_SIZE;
278 else if (!strncasecmp(value, "over-size", len))
279 img_opt->fill = FILL_OVER_SIZE;
281 img_opt->fill = FILL_DISABLE;
283 DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
286 static inline void parse_image_option(const char *option, struct image_option *img_opt)
293 void (*handler)(struct image_option *img_opt, const char *value, int len);
296 .cmd = "aspect", /* Keep the aspect ratio */
297 .handler = parse_aspect,
300 .cmd = "orient", /* Keep the orientation value: for the rotated images */
301 .handler = parse_orient,
304 .cmd = "fill", /* Fill the image to its container */
305 .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
309 .handler = parse_size,
323 if (!option || !*option)
329 * GCC 4.7 warnings uninitialized idx and tag value.
330 * But it will be initialized by the state machine. :(
331 * Anyway, I just reset idx and tag for reducing the GCC4.7 complains.
338 for (ptr = option; state != STATE_END; ptr++) {
353 cmd = cmd_list[tag].cmd;
359 } else if (*ptr == '\0') {
364 if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
369 state = STATE_IGNORE;
372 } else if (*ptr == '\0') {
374 } else if (cmd[idx] == *ptr) {
380 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
384 cmd = cmd_list[tag].cmd;
390 if (*ptr == ';' || *ptr == '\0') {
391 cmd_list[tag].handler(img_opt, value + 1, idx);
392 state = *ptr ? STATE_START : STATE_END;
400 else if (*ptr == '\0')
409 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
411 struct info *handle = _h;
416 struct obj_info *obj_info;
418 struct image_option img_opt = {
421 .fill = FILL_DISABLE,
426 edje = find_edje(handle, id);
428 ErrPrint("No such object: %s\n", id);
429 return LB_STATUS_ERROR_NOT_EXIST;
432 obj_info = evas_object_data_get(edje, "obj_info");
434 ErrPrint("Object info is not available\n");
435 return LB_STATUS_ERROR_FAULT;
438 img = edje_object_part_swallow_get(edje, part);
443 edje_object_part_unswallow(edje, img);
445 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
446 if (child->obj != img)
449 obj_info->children = eina_list_remove(obj_info->children, child);
455 DbgPrint("delete object %s %p\n", part, img);
456 evas_object_del(img);
459 if (!path || !strlen(path) || access(path, R_OK) != 0) {
460 DbgPrint("SKIP - Path: [%s]\n", path);
461 return LB_STATUS_SUCCESS;
464 child = malloc(sizeof(*child));
466 ErrPrint("Heap: %s\n", strerror(errno));
467 return LB_STATUS_ERROR_MEMORY;
470 child->part = strdup(part);
472 ErrPrint("Heap: %s\n", strerror(errno));
474 return LB_STATUS_ERROR_MEMORY;
477 img = evas_object_image_add(e);
479 ErrPrint("Failed to add an image object\n");
482 return LB_STATUS_ERROR_FAULT;
485 evas_object_image_preload(img, EINA_FALSE);
486 parse_image_option(option, &img_opt);
487 evas_object_image_load_orientation_set(img, img_opt.orient);
489 evas_object_image_file_set(img, path, NULL);
490 err = evas_object_image_load_error_get(img);
491 if (err != EVAS_LOAD_ERROR_NONE) {
492 ErrPrint("Load error: %s\n", evas_load_error_str(err));
493 evas_object_del(img);
496 return LB_STATUS_ERROR_IO;
499 evas_object_image_size_get(img, &w, &h);
500 if (img_opt.aspect) {
501 if (img_opt.fill == FILL_OVER_SIZE) {
505 if (img_opt.width >= 0 && img_opt.height >= 0) {
506 part_w = img_opt.width * scale_get();
507 part_h = img_opt.height * scale_get();
511 edje_object_part_geometry_get(edje, part, NULL, NULL, &part_w, &part_h);
513 DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
515 if (part_w > w || part_h > h) {
519 fw = (double)part_w / (double)w;
520 fh = (double)part_h / (double)h;
530 DbgPrint("Size: %dx%d\n", w, h);
532 evas_object_image_load_size_set(img, w, h);
533 evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
534 evas_object_image_fill_set(img, 0, 0, part_w, part_h);
535 evas_object_image_reload(img);
537 evas_object_image_fill_set(img, 0, 0, w, h);
538 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
539 evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
542 if (img_opt.width >= 0 && img_opt.height >= 0) {
545 DbgPrint("Using given image size: %dx%d\n", w, h);
548 evas_object_image_fill_set(img, 0, 0, w, h);
549 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
550 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
555 * object will be shown by below statement automatically
557 DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
559 edje_object_part_swallow(edje, part, img);
560 obj_info->children = eina_list_append(obj_info->children, child);
562 return LB_STATUS_SUCCESS;
565 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
567 struct info *handle = data;
579 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
580 edje_object_part_geometry_get(obj, source, &px, &py, &pw, &ph);
584 sx = (double)px / (double)w;
585 ex = (double)(px + pw) / (double)w;
590 sy = (double)py / (double)h;
591 ey = (double)(py + ph) / (double)h;
594 DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
595 script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
598 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
600 struct info *handle = _info;
601 struct obj_info *obj_info;
604 handle->obj_list = eina_list_remove(handle->obj_list, obj);
606 obj_info = evas_object_data_del(obj, "obj_info");
608 ErrPrint("Object info is not valid\n");
612 DbgPrint("delete object %s %p\n", obj_info->id, obj);
614 edje_object_signal_callback_del_full(obj, "*", "*", script_signal_cb, handle);
616 EINA_LIST_FREE(obj_info->children, child) {
617 DbgPrint("delete object %s %p\n", child->part, child->obj);
619 evas_object_del(child->obj);
628 PUBLIC int script_update_script(void *h, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *group)
630 struct info *handle = h;
633 struct obj_info *obj_info;
636 DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
638 edje = find_edje(handle, src_id);
640 ErrPrint("Edje is not exists\n");
641 return LB_STATUS_ERROR_NOT_EXIST;
644 obj_info = evas_object_data_get(edje, "obj_info");
646 ErrPrint("Object info is not valid\n");
647 return LB_STATUS_ERROR_INVALID;
650 obj = edje_object_part_swallow_get(edje, part);
655 edje_object_part_unswallow(edje, obj);
657 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
658 if (child->obj != obj)
661 obj_info->children = eina_list_remove(obj_info->children, child);
667 DbgPrint("delete object %s %p\n", part, obj);
668 evas_object_del(obj);
671 if (!path || !strlen(path) || access(path, R_OK) != 0) {
672 DbgPrint("SKIP - Path: [%s]\n", path);
673 return LB_STATUS_SUCCESS;
676 obj = edje_object_add(e);
678 ErrPrint("Failed to add a new edje object\n");
679 return LB_STATUS_ERROR_FAULT;
682 if (!edje_object_file_set(obj, path, group)) {
686 err = edje_object_load_error_get(obj);
687 errmsg = edje_load_error_str(err);
688 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
689 evas_object_del(obj);
690 return LB_STATUS_ERROR_IO;
693 evas_object_show(obj);
695 obj_info = calloc(1, sizeof(*obj_info));
697 ErrPrint("Failed to add a obj_info\n");
698 evas_object_del(obj);
699 return LB_STATUS_ERROR_MEMORY;
702 obj_info->id = strdup(target_id);
704 ErrPrint("Failed to add a obj_info\n");
706 evas_object_del(obj);
707 return LB_STATUS_ERROR_MEMORY;
710 child = malloc(sizeof(*child));
712 ErrPrint("Error: %s\n", strerror(errno));
715 evas_object_del(obj);
716 return LB_STATUS_ERROR_MEMORY;
719 child->part = strdup(part);
721 ErrPrint("Error: %s\n", strerror(errno));
725 evas_object_del(obj);
726 return LB_STATUS_ERROR_MEMORY;
731 evas_object_data_set(obj, "obj_info", obj_info);
732 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
733 edje_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
734 handle->obj_list = eina_list_append(handle->obj_list, obj);
736 DbgPrint("%s part swallow edje %p\n", part, obj);
737 edje_object_part_swallow(edje, part, obj);
738 obj_info = evas_object_data_get(edje, "obj_info");
739 obj_info->children = eina_list_append(obj_info->children, child);
740 return LB_STATUS_SUCCESS;
743 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
745 struct info *handle = h;
748 DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
750 edje = find_edje(handle, id);
752 return LB_STATUS_ERROR_NOT_EXIST;
754 edje_object_signal_emit(edje, signal, part);
755 return LB_STATUS_SUCCESS;
758 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
760 struct info *handle = h;
763 DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
765 edje = find_edje(handle, id);
767 return LB_STATUS_ERROR_NOT_EXIST;
769 edje_object_part_drag_value_set(edje, part, x, y);
770 return LB_STATUS_SUCCESS;
773 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
775 struct info *handle = han;
778 edje = find_edje(handle, id);
780 return LB_STATUS_ERROR_NOT_EXIST;
787 DbgPrint("Resize object to %dx%d\n", w, h);
788 evas_object_resize(edje, w, h);
789 return LB_STATUS_SUCCESS;
792 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
794 struct info *handle = h;
796 DbgPrint("id[%s], category[%s]\n", id, category);
798 if (handle->category) {
799 free(handle->category);
800 handle->category = NULL;
804 return LB_STATUS_SUCCESS;
806 handle->category = strdup(category);
807 if (!handle->category) {
808 ErrPrint("Error: %s\n", strerror(errno));
809 return LB_STATUS_ERROR_MEMORY;
812 return LB_STATUS_SUCCESS;
815 PUBLIC void *script_create(const char *file, const char *group)
819 DbgPrint("file[%s], group[%s]\n", file, group);
821 handle = calloc(1, sizeof(*handle));
823 ErrPrint("Error: %s\n", strerror(errno));
827 handle->file = strdup(file);
829 ErrPrint("Error: %s\n", strerror(errno));
834 handle->group = strdup(group);
835 if (!handle->group) {
836 ErrPrint("Error: %s\n", strerror(errno));
845 PUBLIC int script_destroy(void *_handle)
852 edje = eina_list_nth(handle->obj_list, 0);
854 evas_object_del(edje);
856 free(handle->category);
860 return LB_STATUS_SUCCESS;
863 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
867 struct obj_info *obj_info;
871 obj_info = calloc(1, sizeof(*obj_info));
873 ErrPrint("Heap: %s\n", strerror(errno));
874 return LB_STATUS_ERROR_MEMORY;
877 edje = edje_object_add(e);
879 ErrPrint("Failed to create an edje object\n");
881 return LB_STATUS_ERROR_FAULT;
884 DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
885 if (!edje_object_file_set(edje, handle->file, handle->group)) {
889 err = edje_object_load_error_get(edje);
890 errmsg = edje_load_error_str(err);
891 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
892 evas_object_del(edje);
894 return LB_STATUS_ERROR_IO;
901 edje_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
902 evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
903 evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
904 evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
905 evas_object_resize(edje, handle->w, handle->h);
906 evas_object_show(edje);
907 evas_object_data_set(edje, "obj_info", obj_info);
909 handle->obj_list = eina_list_append(handle->obj_list, edje);
910 return LB_STATUS_SUCCESS;
913 PUBLIC int script_unload(void *_handle, Evas *e)
920 DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
921 edje = eina_list_nth(handle->obj_list, 0);
923 evas_object_del(edje);
925 return LB_STATUS_SUCCESS;
928 static inline int update_font(const char *font)
934 cache = evas_common_font_cache_get();
935 evas_common_font_cache_set(0);
936 evas_common_font_flush();
938 list = edje_text_class_list();
939 EINA_LIST_FREE(list, text) {
940 if (!strncasecmp(text, TEXT_CLASS, strlen(TEXT_CLASS))) {
941 edje_text_class_del(text);
942 edje_text_class_set(text, s_info.font, s_info.size);
943 DbgPrint("Update text class %s (%s, %d)\n", text, s_info.font, s_info.size);
945 DbgPrint("Skip text class %s\n", text);
948 DbgPrint("Font for text_class is updated\n");
950 evas_common_font_cache_set(cache);
951 return LB_STATUS_SUCCESS;
954 static Eina_Bool property_cb(void *data, int type, void *event)
956 Ecore_X_Event_Window_Property *info = (Ecore_X_Event_Window_Property *)event;
958 if (info->atom == ecore_x_atom_get("FONT_TYPE_change") || info->atom == ecore_x_atom_get("BADA_FONT_change")) {
961 font = vconf_get_str("db/setting/accessibility/font_name");
963 return ECORE_CALLBACK_PASS_ON;
965 if (s_info.font && !strcmp(s_info.font, font)) {
966 DbgPrint("Font is not changed (%s)\n", font);
968 return ECORE_CALLBACK_PASS_ON;
979 return ECORE_CALLBACK_PASS_ON;
982 static void font_name_cb(keynode_t *node, void *user_data)
989 font = vconf_keynode_get_str(node);
993 if (s_info.font && !strcmp(s_info.font, font)) {
994 DbgPrint("Font is not changed\n");
998 DbgPrint("Font changed to %s\n", font);
1003 s_info.font = strdup(font);
1005 ErrPrint("Heap: %s\n", strerror(errno));
1010 static void font_size_cb(keynode_t *node, void *user_data)
1018 DbgPrint("Size type: %d\n", vconf_keynode_get_int(node));
1021 PUBLIC int script_init(void)
1024 /* ecore is already initialized */
1026 edje_scale_set(scale_get());
1028 s_info.property_handler = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, property_cb, NULL);
1029 if (!s_info.property_handler)
1030 ErrPrint("Failed to add a property change event handler\n");
1032 ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb, NULL);
1034 ErrPrint("Failed to add vconf for font size change\n");
1036 ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_name_cb, NULL);
1038 ErrPrint("Failed to add vconf for font name change\n");
1040 return LB_STATUS_SUCCESS;
1043 PUBLIC int script_fini(void)
1045 vconf_ignore_key_changed("db/setting/accessibility/font_name", font_name_cb);
1046 vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_FONT_SIZE, font_size_cb);
1047 ecore_event_handler_del(s_info.property_handler);
1048 s_info.property_handler = NULL;
1050 return LB_STATUS_SUCCESS;