/src/lib/evas/canvas/evas_smart.c

https://bitbucket.org/hchbaw/efl · C · 332 lines · 265 code · 61 blank · 6 comment · 54 complexity · e13aa02c4a62398a641d69d41a17f0ec MD5 · raw file

  1. #include "evas_common_private.h"
  2. #include "evas_private.h"
  3. static void _evas_smart_class_callbacks_create(Evas_Smart *s);
  4. static void _evas_smart_class_interfaces_create(Evas_Smart *s);
  5. /* all public */
  6. EAPI void
  7. evas_smart_free(Evas_Smart *s)
  8. {
  9. MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
  10. return;
  11. MAGIC_CHECK_END();
  12. s->delete_me = 1;
  13. if (s->usage > 0) return;
  14. if (s->class_allocated) free((void *)s->smart_class);
  15. free(s->callbacks.array);
  16. free(s->interfaces.array);
  17. free(s);
  18. }
  19. EAPI Evas_Smart *
  20. evas_smart_class_new(const Evas_Smart_Class *sc)
  21. {
  22. Evas_Smart *s;
  23. if (!sc) return NULL;
  24. /* api does not match abi! for now refuse as we only have 1 version */
  25. if (sc->version != EVAS_SMART_CLASS_VERSION) return NULL;
  26. s = evas_mem_calloc(sizeof(Evas_Smart));
  27. if (!s) return NULL;
  28. s->magic = MAGIC_SMART;
  29. s->smart_class = sc;
  30. _evas_smart_class_callbacks_create(s);
  31. _evas_smart_class_interfaces_create(s);
  32. return s;
  33. }
  34. EAPI const Evas_Smart_Class *
  35. evas_smart_class_get(const Evas_Smart *s)
  36. {
  37. MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
  38. return NULL;
  39. MAGIC_CHECK_END();
  40. return s->smart_class;
  41. }
  42. EAPI void *
  43. evas_smart_data_get(const Evas_Smart *s)
  44. {
  45. MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
  46. return NULL;
  47. MAGIC_CHECK_END();
  48. return (void *)s->smart_class->data;
  49. }
  50. EAPI const Evas_Smart_Cb_Description **
  51. evas_smart_callbacks_descriptions_get(const Evas_Smart *s, unsigned int *count)
  52. {
  53. MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
  54. if (count) *count = 0;
  55. return NULL;
  56. MAGIC_CHECK_END();
  57. if (count) *count = s->callbacks.size;
  58. return s->callbacks.array;
  59. }
  60. EAPI const Evas_Smart_Cb_Description *
  61. evas_smart_callback_description_find(const Evas_Smart *s, const char *name)
  62. {
  63. if (!name) return NULL;
  64. MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
  65. return NULL;
  66. MAGIC_CHECK_END();
  67. return evas_smart_cb_description_find(&s->callbacks, name);
  68. }
  69. EAPI Eina_Bool
  70. evas_smart_class_inherit_full(Evas_Smart_Class *sc, const Evas_Smart_Class *parent_sc, unsigned int parent_sc_size)
  71. {
  72. unsigned int off;
  73. /* api does not match abi! for now refuse as we only have 1 version */
  74. if (parent_sc->version != EVAS_SMART_CLASS_VERSION) return EINA_FALSE;
  75. #define _CP(m) sc->m = parent_sc->m
  76. _CP(add);
  77. _CP(del);
  78. _CP(move);
  79. _CP(resize);
  80. _CP(show);
  81. _CP(hide);
  82. _CP(color_set);
  83. _CP(clip_set);
  84. _CP(clip_unset);
  85. _CP(calculate);
  86. _CP(member_add);
  87. _CP(member_del);
  88. #undef _CP
  89. sc->parent = parent_sc;
  90. off = sizeof(Evas_Smart_Class);
  91. if (parent_sc_size == off) return EINA_TRUE;
  92. memcpy(((char *)sc) + off, ((char *)parent_sc) + off, parent_sc_size - off);
  93. return EINA_TRUE;
  94. }
  95. EAPI int
  96. evas_smart_usage_get(const Evas_Smart *s)
  97. {
  98. MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
  99. return 0;
  100. MAGIC_CHECK_END();
  101. return s->usage;
  102. }
  103. /* internal funcs */
  104. void
  105. evas_object_smart_use(Evas_Smart *s)
  106. {
  107. s->usage++;
  108. }
  109. void
  110. evas_object_smart_unuse(Evas_Smart *s)
  111. {
  112. s->usage--;
  113. if ((s->usage <= 0) && (s->delete_me)) evas_smart_free(s);
  114. }
  115. Eina_Bool
  116. evas_smart_cb_descriptions_resize(Evas_Smart_Cb_Description_Array *a, unsigned int size)
  117. {
  118. void *tmp;
  119. if (size == a->size)
  120. return EINA_TRUE;
  121. if (size == EINA_FALSE)
  122. {
  123. free(a->array);
  124. a->array = NULL;
  125. a->size = 0;
  126. return EINA_TRUE;
  127. }
  128. tmp = realloc(a->array, (size + 1) * sizeof(Evas_Smart_Cb_Description *));
  129. if (tmp)
  130. {
  131. a->array = tmp;
  132. a->size = size;
  133. a->array[size] = NULL;
  134. return EINA_TRUE;
  135. }
  136. else
  137. {
  138. ERR("realloc failed!");
  139. return EINA_FALSE;
  140. }
  141. }
  142. static int
  143. _evas_smart_cb_description_cmp_sort(const void *p1, const void *p2)
  144. {
  145. const Evas_Smart_Cb_Description **a = (const Evas_Smart_Cb_Description **)p1;
  146. const Evas_Smart_Cb_Description **b = (const Evas_Smart_Cb_Description **)p2;
  147. return strcmp((*a)->name, (*b)->name);
  148. }
  149. void
  150. evas_smart_cb_descriptions_fix(Evas_Smart_Cb_Description_Array *a)
  151. {
  152. unsigned int i, j;
  153. if (!a)
  154. {
  155. ERR("no array to fix!");
  156. return;
  157. }
  158. qsort(a->array, a->size, sizeof(Evas_Smart_Cb_Description *),
  159. _evas_smart_cb_description_cmp_sort);
  160. DBG("%u callbacks", a->size);
  161. if (a->size)
  162. DBG("%s [type=%s]", a->array[0]->name, a->array[0]->type);
  163. for (i = 0, j = 1; j < a->size; j++)
  164. {
  165. const Evas_Smart_Cb_Description *cur, *prev;
  166. cur = a->array[j];
  167. prev = a->array[i];
  168. DBG("%s [type=%s]", cur->name, cur->type);
  169. if (strcmp(cur->name, prev->name) != 0)
  170. {
  171. i++;
  172. if (i != j)
  173. a->array[i] = a->array[j];
  174. }
  175. else
  176. {
  177. if (strcmp(cur->type, prev->type) == 0)
  178. WRN("duplicated smart callback description"
  179. " with name '%s' and type '%s'", cur->name, cur->type);
  180. else
  181. ERR("callback descriptions named '%s' differ"
  182. " in type, keeping '%s', ignoring '%s'",
  183. cur->name, prev->type, cur->type);
  184. }
  185. }
  186. evas_smart_cb_descriptions_resize(a, i + 1);
  187. }
  188. static void
  189. _evas_smart_class_callbacks_create(Evas_Smart *s)
  190. {
  191. const Evas_Smart_Class *sc;
  192. unsigned int n = 0;
  193. for (sc = s->smart_class; sc; sc = sc->parent)
  194. {
  195. const Evas_Smart_Cb_Description *d;
  196. for (d = sc->callbacks; d && d->name; d++)
  197. n++;
  198. }
  199. if (n == 0) return;
  200. if (!evas_smart_cb_descriptions_resize(&s->callbacks, n)) return;
  201. s->callbacks.size = n;
  202. for (n = 0, sc = s->smart_class; sc; sc = sc->parent)
  203. {
  204. const Evas_Smart_Cb_Description *d;
  205. for (d = sc->callbacks; d && d->name; d++)
  206. s->callbacks.array[n++] = d;
  207. }
  208. evas_smart_cb_descriptions_fix(&s->callbacks);
  209. }
  210. static void
  211. _evas_smart_class_interfaces_create(Evas_Smart *s)
  212. {
  213. unsigned int i, total_priv_sz = 0;
  214. const Evas_Smart_Class *sc;
  215. /* get number of interfaces on the smart */
  216. for (i = 0, sc = s->smart_class; sc; sc = sc->parent)
  217. {
  218. const Evas_Smart_Interface **ifaces_array = sc->interfaces;
  219. if (!ifaces_array) continue;
  220. while (*ifaces_array)
  221. {
  222. const Evas_Smart_Interface *iface = *ifaces_array;
  223. if (!iface->name) break;
  224. i++;
  225. if (iface->private_size > 0)
  226. {
  227. unsigned int size = iface->private_size;
  228. if (size % sizeof(void *) != 0)
  229. size += sizeof(void *) - (size % sizeof(void *));
  230. total_priv_sz += size;
  231. }
  232. ifaces_array++;
  233. }
  234. }
  235. if (!i) return;
  236. s->interfaces.array = malloc(i * sizeof(Evas_Smart_Interface *));
  237. if (!s->interfaces.array)
  238. {
  239. ERR("malloc failed!");
  240. return;
  241. }
  242. s->interfaces.size = i;
  243. for (i = 0, sc = s->smart_class; sc; sc = sc->parent)
  244. {
  245. const Evas_Smart_Interface **ifaces_array = sc->interfaces;
  246. if (!ifaces_array) continue;
  247. while (*ifaces_array)
  248. {
  249. const Evas_Smart_Interface *iface = *ifaces_array;
  250. if (!iface->name) break;
  251. s->interfaces.array[i++] = iface;
  252. ifaces_array++;
  253. }
  254. }
  255. }
  256. static int
  257. _evas_smart_cb_description_cmp_search(const void *p1, const void *p2)
  258. {
  259. const char *name = p1;
  260. const Evas_Smart_Cb_Description **v = (const Evas_Smart_Cb_Description **)p2;
  261. /* speed up string shares searches (same pointers) */
  262. if (name == (*v)->name) return 0;
  263. return strcmp(name, (*v)->name);
  264. }
  265. const Evas_Smart_Cb_Description *
  266. evas_smart_cb_description_find(const Evas_Smart_Cb_Description_Array *a, const char *name)
  267. {
  268. if (!a->array) return NULL;
  269. return bsearch(name, a->array, a->size, sizeof(Evas_Smart_Cb_Description *),
  270. _evas_smart_cb_description_cmp_search);
  271. }