/src/ftk_animation_trigger_default.c

http://ftk.googlecode.com/ · C · 422 lines · 328 code · 64 blank · 30 comment · 86 complexity · 1f2ed5144d6e85ec5be14523f120926f MD5 · raw file

  1. /*
  2. * File: ftk_animation_trigger_default.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: default animation trigger.
  5. *
  6. * Copyright (c) 2009 - 2011 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2011-03-21 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk_log.h"
  31. #include "ftk_util.h"
  32. #include "ftk_mmap.h"
  33. #include "ftk_window.h"
  34. #include "ftk_globals.h"
  35. #include "ftk_xml_parser.h"
  36. #include "ftk_animation_alpha.h"
  37. #include "ftk_animation_scale.h"
  38. #include "ftk_animation_expand.h"
  39. #include "ftk_animation_trigger.h"
  40. #include "ftk_animation_translate.h"
  41. #define FTK_MAX_ANIM_EVT_NR 32
  42. #define FTK_MAX_ANIMATION_NR 3
  43. #define FTK_ANIM_EVENT_NAME_LEN 31
  44. typedef struct _TypeAndAnimation
  45. {
  46. char event[FTK_ANIM_EVENT_NAME_LEN+1];
  47. FtkAnimation* animations[FTK_MAX_ANIMATION_NR];
  48. }TypeAndAnimation;
  49. typedef struct _AnimationTriggerPrivInfo
  50. {
  51. FtkCanvas* old_window;
  52. FtkCanvas* new_window;
  53. int type_and_animations_nr;
  54. TypeAndAnimation type_and_animations[FTK_MAX_ANIM_EVT_NR];
  55. }PrivInfo;
  56. typedef struct _NameAndCreator
  57. {
  58. const char* name;
  59. FtkAnimationCreate create;
  60. }NameAndCreator;
  61. static const NameAndCreator s_name_and_creators[] =
  62. {
  63. {"scale", ftk_animation_scale_create},
  64. {"alpha", ftk_animation_alpha_create},
  65. {"expand", ftk_animation_expand_create},
  66. {"translate", ftk_animation_translate_create},
  67. {NULL, NULL}
  68. };
  69. static TypeAndAnimation* ftk_animation_trigger_default_find_by_event(FtkAnimationTrigger* thiz, const char* event)
  70. {
  71. size_t i = 0;
  72. DECL_PRIV(thiz, priv);
  73. return_val_if_fail(thiz != NULL, NULL);
  74. for(i = 0; i < FTK_MAX_ANIM_EVT_NR; i++)
  75. {
  76. if(strcmp(priv->type_and_animations[i].event, event) == 0)
  77. {
  78. return priv->type_and_animations+i;
  79. }
  80. }
  81. return NULL;
  82. }
  83. static Ret ftk_animation_trigger_default_ensure_canvas(FtkAnimationTrigger* thiz)
  84. {
  85. int w = 0;
  86. int h = 0;
  87. FtkColor bg = {0};
  88. DECL_PRIV(thiz, priv);
  89. if(priv->old_window && priv->new_window)
  90. {
  91. return RET_OK;
  92. }
  93. bg.a = 0xff;
  94. w = ftk_display_width(ftk_default_display());
  95. h = ftk_display_height(ftk_default_display());
  96. if(priv->old_window == NULL)
  97. {
  98. priv->old_window = ftk_canvas_create(w, h, &bg);
  99. }
  100. if(priv->new_window == NULL)
  101. {
  102. priv->new_window = ftk_canvas_create(w, h, &bg);
  103. }
  104. return priv->old_window && priv->new_window ? RET_OK : RET_FAIL;
  105. }
  106. static Ret ftk_animation_trigger_default_on_event(FtkAnimationTrigger* thiz, FtkAnimationEvent* evt)
  107. {
  108. size_t i = 0;
  109. DECL_PRIV(thiz, priv);
  110. const char* hint = NULL;
  111. FtkBitmap* bitmap = NULL;
  112. FtkBitmap* old_bitmap = NULL;
  113. FtkBitmap* new_bitmap = NULL;
  114. FtkCanvas* save_canvas = NULL;
  115. FtkRect old_win_rect = {0,0,0,0};
  116. FtkRect new_win_rect = {0,0,0,0};
  117. char event_name[FTK_ANIM_EVENT_NAME_LEN];
  118. TypeAndAnimation* type_and_animation = NULL;
  119. return_val_if_fail(evt != NULL, RET_FAIL);
  120. return_val_if_fail(ftk_animation_trigger_default_ensure_canvas(thiz) == RET_OK, RET_FAIL);
  121. if(evt->type == FTK_EVT_SHOW)
  122. {
  123. hint = ftk_window_get_animation_hint(evt->new_window);
  124. }
  125. else
  126. {
  127. FtkColor bg = {0xff, 0xff, 0xff, 0xff};
  128. hint = ftk_window_get_animation_hint(evt->old_window);
  129. if(evt->new_window == NULL)
  130. {
  131. ftk_canvas_lock_buffer(priv->new_window, &bitmap);
  132. ftk_bitmap_clear(bitmap, bg);
  133. ftk_canvas_unlock_buffer(priv->new_window);
  134. }
  135. }
  136. if(hint[0] == '\0')
  137. {
  138. return RET_OK;
  139. }
  140. ftk_snprintf(event_name, FTK_ANIM_EVENT_NAME_LEN, "%s_%s", hint, evt->type == FTK_EVT_SHOW ? "show" : "hide");
  141. type_and_animation = ftk_animation_trigger_default_find_by_event(thiz, event_name);
  142. if(type_and_animation == NULL)
  143. {
  144. ftk_logd("%s: %s not exist.\n", __func__, event_name);
  145. }
  146. return_val_if_fail(type_and_animation != NULL, RET_FAIL);
  147. save_canvas = ftk_shared_canvas();
  148. if(evt->old_window != NULL)
  149. {
  150. ftk_window_disable_update(evt->old_window);
  151. FTK_GET_PAINT_RECT(evt->old_window, old_win_rect);
  152. ftk_set_shared_canvas(priv->old_window);
  153. ftk_canvas_set_clip_region(priv->old_window, NULL);
  154. ftk_window_paint_forcely(evt->old_window);
  155. }
  156. if(evt->new_window != NULL)
  157. {
  158. ftk_window_disable_update(evt->new_window);
  159. FTK_GET_PAINT_RECT(evt->new_window, new_win_rect);
  160. ftk_set_shared_canvas(priv->new_window);
  161. ftk_canvas_set_clip_region(priv->new_window, NULL);
  162. ftk_window_paint_forcely(evt->new_window);
  163. }
  164. ftk_set_shared_canvas(save_canvas);
  165. if(evt->old_window != NULL)
  166. {
  167. ftk_window_enable_update(evt->old_window);
  168. }
  169. if(evt->new_window != NULL)
  170. {
  171. ftk_window_enable_update(evt->new_window);
  172. }
  173. ftk_canvas_lock_buffer(priv->old_window, &old_bitmap);
  174. ftk_canvas_lock_buffer(priv->new_window, &new_bitmap);
  175. for(i = 0; i < FTK_MAX_ANIMATION_NR; i++)
  176. {
  177. if(type_and_animation->animations[i] != NULL)
  178. {
  179. FtkAnimation* anim = type_and_animation->animations[i];
  180. ftk_animation_run(anim, old_bitmap, new_bitmap, &old_win_rect, &new_win_rect);
  181. }
  182. }
  183. ftk_canvas_unlock_buffer(priv->old_window);
  184. ftk_canvas_unlock_buffer(priv->new_window);
  185. ftk_logd("%s: type=%d %s - %s\n", __func__, evt->type,
  186. evt->old_window != NULL ? ftk_widget_get_text(evt->old_window) : "null",
  187. evt->new_window != NULL ? ftk_widget_get_text(evt->new_window) : "null");
  188. return RET_OK;
  189. }
  190. static void ftk_animation_trigger_default_destroy(FtkAnimationTrigger* thiz)
  191. {
  192. if(thiz != NULL)
  193. {
  194. int i = 0;
  195. DECL_PRIV(thiz, priv);
  196. for(i = 0; i < priv->type_and_animations_nr; i++)
  197. {
  198. size_t j = 0;
  199. for(j = 0; j < FTK_MAX_ANIMATION_NR; j++)
  200. {
  201. if(priv->type_and_animations[i].animations[j] != NULL)
  202. {
  203. ftk_animation_destroy(priv->type_and_animations[i].animations[j]);
  204. }
  205. }
  206. }
  207. ftk_canvas_destroy(priv->old_window);
  208. ftk_canvas_destroy(priv->new_window);
  209. FTK_FREE(thiz);
  210. }
  211. return;
  212. }
  213. typedef struct _BuilderInfo
  214. {
  215. TypeAndAnimation* current;
  216. FtkAnimationTrigger* trigger;
  217. }BuilderInfo;
  218. static void ftk_animation_builder_on_start(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
  219. {
  220. BuilderInfo* info = (BuilderInfo*)thiz->priv;
  221. DECL_PRIV(info->trigger, priv);
  222. return_if_fail(thiz != NULL && tag != NULL);
  223. if(strcmp(tag, "event") == 0)
  224. {
  225. const char* event = attrs[1];
  226. if(priv->type_and_animations_nr < FTK_MAX_ANIM_EVT_NR)
  227. {
  228. info->current = priv->type_and_animations + priv->type_and_animations_nr;
  229. priv->type_and_animations_nr++;
  230. ftk_strncpy(info->current->event, event, FTK_ANIM_EVENT_NAME_LEN);
  231. }
  232. }
  233. else if(strcmp(tag, "animations") != 0)
  234. {
  235. int i = 0;
  236. FtkAnimationCreate create = NULL;
  237. for(i = 0; s_name_and_creators[i].name != NULL; i++)
  238. {
  239. if(strcmp(s_name_and_creators[i].name, tag) == 0)
  240. {
  241. create = s_name_and_creators[i].create;
  242. break;
  243. }
  244. }
  245. if(create != NULL && info->current != NULL)
  246. {
  247. for(i = 0; i < FTK_MAX_ANIMATION_NR; i++)
  248. {
  249. if(info->current->animations[i] == NULL)
  250. {
  251. int j = 0;
  252. FtkAnimation* anim = create();
  253. for(j = 0; attrs[j] != NULL; j+=2)
  254. {
  255. ftk_animation_set_param(anim, attrs[j], attrs[j+1]);
  256. }
  257. info->current->animations[i] = anim;
  258. break;
  259. }
  260. }
  261. }
  262. }
  263. return;
  264. }
  265. static void ftk_animation_builder_destroy(FtkXmlBuilder* thiz)
  266. {
  267. if(thiz != NULL)
  268. {
  269. FTK_FREE(thiz);
  270. }
  271. return;
  272. }
  273. static FtkXmlBuilder* ftk_animation_builder_create(FtkAnimationTrigger* trigger)
  274. {
  275. FtkXmlBuilder* thiz = (FtkXmlBuilder*)FTK_ZALLOC(sizeof(FtkXmlBuilder) + sizeof(BuilderInfo));
  276. if(thiz != NULL)
  277. {
  278. BuilderInfo* info = (BuilderInfo*)thiz->priv;
  279. info->trigger = trigger;
  280. thiz->on_start_element = ftk_animation_builder_on_start;
  281. thiz->destroy = ftk_animation_builder_destroy;
  282. }
  283. return thiz;
  284. }
  285. static Ret ftk_animation_trigger_parse_data(FtkAnimationTrigger* thiz, const char* xml, size_t length)
  286. {
  287. FtkXmlParser* parser = NULL;
  288. FtkXmlBuilder* builder = NULL;
  289. return_val_if_fail(xml != NULL, RET_FAIL);
  290. parser = ftk_xml_parser_create();
  291. return_val_if_fail(parser != NULL, RET_FAIL);
  292. builder = ftk_animation_builder_create(thiz);
  293. if(builder != NULL)
  294. {
  295. ftk_xml_parser_set_builder(parser, builder);
  296. ftk_xml_parser_parse(parser, xml, length);
  297. }
  298. ftk_xml_builder_destroy(builder);
  299. ftk_xml_parser_destroy(parser);
  300. return RET_OK;
  301. }
  302. static Ret ftk_animation_trigger_parse_file(FtkAnimationTrigger* thiz, const char* filename)
  303. {
  304. FtkMmap* m = NULL;
  305. Ret ret = RET_FAIL;
  306. return_val_if_fail(thiz != NULL && filename != NULL, RET_FAIL);
  307. m = ftk_mmap_create(filename, 0, -1);
  308. if(m == NULL)
  309. {
  310. ftk_logd("%s: mmap %s failed.\n", __func__, filename);
  311. }
  312. return_val_if_fail(m != NULL, RET_FAIL);
  313. ret = ftk_animation_trigger_parse_data(thiz, (const char*)ftk_mmap_data(m), ftk_mmap_length(m));
  314. ftk_mmap_destroy(m);
  315. return ret;
  316. }
  317. void ftk_animation_trigger_default_dump(FtkAnimationTrigger* thiz)
  318. {
  319. int i = 0;
  320. int j = 0;
  321. DECL_PRIV(thiz, priv);
  322. for(i = 0; i < priv->type_and_animations_nr; i++)
  323. {
  324. ftk_logd("event: %s\n", priv->type_and_animations[i].event);
  325. for(j = 0; j < FTK_MAX_ANIMATION_NR; j++)
  326. {
  327. if(priv->type_and_animations[i].animations[j] != NULL)
  328. {
  329. ftk_logd("animation:%s\n", priv->type_and_animations[i].animations[j]->name);
  330. ftk_params_dump(priv->type_and_animations[i].animations[j]->params);
  331. }
  332. }
  333. }
  334. return;
  335. }
  336. FtkAnimationTrigger* ftk_animation_trigger_default_create(const char* theme, const char* name)
  337. {
  338. FtkAnimationTrigger* thiz = FTK_NEW_PRIV(FtkAnimationTrigger);
  339. if(thiz != NULL)
  340. {
  341. char filename[FTK_MAX_PATH + 1] = {0};
  342. ftk_strs_cat(filename, FTK_MAX_PATH,
  343. ftk_config_get_data_dir(ftk_default_config()), "/theme/", theme, "/", name, NULL);
  344. ftk_normalize_path(filename);
  345. thiz->on_event = ftk_animation_trigger_default_on_event;
  346. thiz->destroy = ftk_animation_trigger_default_destroy;
  347. if(ftk_animation_trigger_parse_file(thiz, filename) == RET_OK)
  348. {
  349. //ftk_animation_trigger_default_dump(thiz);
  350. ftk_logd("%s: them=%s\n", __func__, theme);
  351. }
  352. else
  353. {
  354. FTK_FREE(thiz);
  355. }
  356. }
  357. return thiz;
  358. }