PageRenderTime 23ms CodeModel.GetById 1ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/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/*
 26 * History:
 27 * ================================================================
 28 * 2011-03-21 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_log.h"
 33#include "ftk_util.h"
 34#include "ftk_mmap.h"
 35#include "ftk_window.h"
 36#include "ftk_globals.h"
 37#include "ftk_xml_parser.h"
 38#include "ftk_animation_alpha.h"
 39#include "ftk_animation_scale.h"
 40#include "ftk_animation_expand.h"
 41#include "ftk_animation_trigger.h"
 42#include "ftk_animation_translate.h"
 43
 44#define FTK_MAX_ANIM_EVT_NR 32
 45#define FTK_MAX_ANIMATION_NR 3
 46#define FTK_ANIM_EVENT_NAME_LEN 31
 47
 48typedef struct _TypeAndAnimation
 49{
 50	char event[FTK_ANIM_EVENT_NAME_LEN+1];
 51	FtkAnimation* animations[FTK_MAX_ANIMATION_NR];
 52}TypeAndAnimation;
 53
 54typedef struct _AnimationTriggerPrivInfo
 55{
 56	FtkCanvas* old_window;
 57	FtkCanvas* new_window;
 58	int type_and_animations_nr;
 59	TypeAndAnimation type_and_animations[FTK_MAX_ANIM_EVT_NR];
 60}PrivInfo;
 61
 62typedef struct _NameAndCreator
 63{
 64	const char* name;
 65	FtkAnimationCreate create;
 66}NameAndCreator;
 67
 68static const NameAndCreator s_name_and_creators[] =
 69{
 70	{"scale",     ftk_animation_scale_create},
 71	{"alpha",     ftk_animation_alpha_create},
 72	{"expand",    ftk_animation_expand_create},
 73	{"translate", ftk_animation_translate_create},
 74	{NULL, NULL}
 75};
 76
 77static TypeAndAnimation* ftk_animation_trigger_default_find_by_event(FtkAnimationTrigger* thiz, const char* event)
 78{
 79	size_t i = 0;
 80	DECL_PRIV(thiz, priv);
 81	return_val_if_fail(thiz != NULL, NULL);
 82
 83	for(i = 0; i < FTK_MAX_ANIM_EVT_NR; i++)
 84	{
 85		if(strcmp(priv->type_and_animations[i].event, event) == 0)
 86		{
 87			return priv->type_and_animations+i;
 88		}
 89	}
 90
 91	return NULL;
 92}
 93
 94static Ret ftk_animation_trigger_default_ensure_canvas(FtkAnimationTrigger* thiz)
 95{
 96	int w = 0;
 97	int h = 0;
 98	FtkColor bg = {0};
 99	DECL_PRIV(thiz, priv);
100
101	if(priv->old_window && priv->new_window)
102	{
103		return RET_OK;
104	}
105
106	bg.a = 0xff;
107	w = ftk_display_width(ftk_default_display());
108	h = ftk_display_height(ftk_default_display());
109
110	if(priv->old_window == NULL)
111	{
112		priv->old_window = ftk_canvas_create(w, h, &bg);
113	}
114	
115	if(priv->new_window == NULL)
116	{
117		priv->new_window = ftk_canvas_create(w, h, &bg);
118	}
119
120	return priv->old_window && priv->new_window ? RET_OK : RET_FAIL;
121}
122
123static Ret ftk_animation_trigger_default_on_event(FtkAnimationTrigger* thiz, FtkAnimationEvent* evt)
124{
125	size_t i = 0;
126	DECL_PRIV(thiz, priv);
127	const char* hint = NULL;
128	FtkBitmap* bitmap = NULL;
129	FtkBitmap* old_bitmap = NULL;
130	FtkBitmap* new_bitmap = NULL;
131	FtkCanvas* save_canvas = NULL;
132	FtkRect old_win_rect = {0,0,0,0};
133	FtkRect new_win_rect = {0,0,0,0};
134	char event_name[FTK_ANIM_EVENT_NAME_LEN];
135	TypeAndAnimation* type_and_animation = NULL;
136
137	return_val_if_fail(evt != NULL, RET_FAIL);
138	return_val_if_fail(ftk_animation_trigger_default_ensure_canvas(thiz) == RET_OK, RET_FAIL);
139
140	if(evt->type == FTK_EVT_SHOW)
141	{
142		hint = ftk_window_get_animation_hint(evt->new_window);
143	}
144	else
145	{
146		FtkColor bg = {0xff, 0xff, 0xff, 0xff};
147		hint = ftk_window_get_animation_hint(evt->old_window);
148		if(evt->new_window == NULL)
149		{
150			ftk_canvas_lock_buffer(priv->new_window, &bitmap);
151			ftk_bitmap_clear(bitmap, bg);
152			ftk_canvas_unlock_buffer(priv->new_window);
153		}
154	}
155
156	if(hint[0] == '\0')
157	{
158		return RET_OK;
159	}
160
161	ftk_snprintf(event_name, FTK_ANIM_EVENT_NAME_LEN, "%s_%s", hint, evt->type == FTK_EVT_SHOW ? "show" : "hide");
162	type_and_animation = ftk_animation_trigger_default_find_by_event(thiz, event_name);
163	if(type_and_animation == NULL)
164	{
165		ftk_logd("%s: %s not exist.\n", __func__, event_name);
166	}
167
168	return_val_if_fail(type_and_animation != NULL, RET_FAIL);
169	
170	save_canvas = ftk_shared_canvas();
171	
172  	if(evt->old_window != NULL)
173  	{
174		ftk_window_disable_update(evt->old_window);
175   		FTK_GET_PAINT_RECT(evt->old_window, old_win_rect);
176		ftk_set_shared_canvas(priv->old_window);
177		ftk_canvas_set_clip_region(priv->old_window, NULL);
178    	ftk_window_paint_forcely(evt->old_window);
179	}
180
181	if(evt->new_window != NULL)
182	{
183		ftk_window_disable_update(evt->new_window);
184   		FTK_GET_PAINT_RECT(evt->new_window, new_win_rect);
185   		ftk_set_shared_canvas(priv->new_window);
186		ftk_canvas_set_clip_region(priv->new_window, NULL);
187		ftk_window_paint_forcely(evt->new_window);
188	}
189
190	ftk_set_shared_canvas(save_canvas);
191	if(evt->old_window != NULL)
192	{
193    	ftk_window_enable_update(evt->old_window);
194	}
195
196	if(evt->new_window != NULL)
197	{
198    	ftk_window_enable_update(evt->new_window);
199  	}
200
201	ftk_canvas_lock_buffer(priv->old_window, &old_bitmap);
202	ftk_canvas_lock_buffer(priv->new_window, &new_bitmap);
203
204	for(i = 0; i < FTK_MAX_ANIMATION_NR; i++)
205	{
206		if(type_and_animation->animations[i] != NULL)
207		{
208			FtkAnimation* anim = type_and_animation->animations[i];
209			ftk_animation_run(anim, old_bitmap, new_bitmap, &old_win_rect, &new_win_rect);
210		}
211	}
212
213	ftk_canvas_unlock_buffer(priv->old_window);
214	ftk_canvas_unlock_buffer(priv->new_window);
215
216	ftk_logd("%s: type=%d %s - %s\n", __func__, evt->type, 
217		evt->old_window != NULL ? ftk_widget_get_text(evt->old_window) : "null",
218		evt->new_window != NULL ? ftk_widget_get_text(evt->new_window) : "null");
219
220	return RET_OK;
221}
222
223static void ftk_animation_trigger_default_destroy(FtkAnimationTrigger* thiz)
224{
225	if(thiz != NULL)
226	{
227		int i = 0;
228		DECL_PRIV(thiz, priv);
229
230		for(i = 0; i < priv->type_and_animations_nr; i++)
231		{
232			size_t j = 0;
233			for(j = 0; j < FTK_MAX_ANIMATION_NR; j++)
234			{
235				if(priv->type_and_animations[i].animations[j] != NULL)
236				{
237					ftk_animation_destroy(priv->type_and_animations[i].animations[j]);
238				}
239			}
240		}
241
242		ftk_canvas_destroy(priv->old_window);
243		ftk_canvas_destroy(priv->new_window);
244		FTK_FREE(thiz);
245	}
246
247	return;
248}
249
250typedef struct _BuilderInfo
251{
252	TypeAndAnimation* current;
253	FtkAnimationTrigger* trigger;
254}BuilderInfo;
255
256static void ftk_animation_builder_on_start(FtkXmlBuilder* thiz, const char* tag, const char** attrs)
257{
258	BuilderInfo* info = (BuilderInfo*)thiz->priv;
259	DECL_PRIV(info->trigger, priv);
260	return_if_fail(thiz != NULL && tag != NULL);
261
262	if(strcmp(tag, "event") == 0)
263	{
264		const char* event = attrs[1];
265		if(priv->type_and_animations_nr < FTK_MAX_ANIM_EVT_NR)
266		{
267			info->current = priv->type_and_animations + priv->type_and_animations_nr;
268			priv->type_and_animations_nr++;
269			ftk_strncpy(info->current->event, event, FTK_ANIM_EVENT_NAME_LEN);
270		}
271	}
272	else if(strcmp(tag, "animations") != 0)
273	{
274		int i = 0;
275		FtkAnimationCreate create = NULL;
276		for(i = 0; s_name_and_creators[i].name != NULL; i++)
277		{
278			if(strcmp(s_name_and_creators[i].name, tag) == 0)
279			{
280				create = s_name_and_creators[i].create;
281				break;
282			}
283		}
284	
285		if(create != NULL && info->current != NULL)
286		{
287			for(i = 0; i < FTK_MAX_ANIMATION_NR; i++)
288			{
289				if(info->current->animations[i] == NULL)
290				{
291					int j = 0;
292					FtkAnimation* anim = create();
293
294					for(j = 0; attrs[j] != NULL; j+=2)
295					{
296						ftk_animation_set_param(anim, attrs[j], attrs[j+1]);
297					}
298					info->current->animations[i] = anim;
299					break;
300				}
301			}
302		}
303	}
304
305	return;
306}
307
308static void ftk_animation_builder_destroy(FtkXmlBuilder* thiz)
309{
310	if(thiz != NULL)
311	{
312		FTK_FREE(thiz);
313	}
314
315	return;
316}
317
318static FtkXmlBuilder* ftk_animation_builder_create(FtkAnimationTrigger* trigger)
319{
320	FtkXmlBuilder* thiz = (FtkXmlBuilder*)FTK_ZALLOC(sizeof(FtkXmlBuilder) + sizeof(BuilderInfo));
321
322	if(thiz != NULL)
323	{
324		BuilderInfo* info = (BuilderInfo*)thiz->priv;
325		info->trigger = trigger;
326		thiz->on_start_element = ftk_animation_builder_on_start;
327		thiz->destroy          = ftk_animation_builder_destroy;
328	}
329
330	return thiz;
331}
332
333static Ret ftk_animation_trigger_parse_data(FtkAnimationTrigger* thiz, const char* xml, size_t length)
334{
335	FtkXmlParser*  parser = NULL;
336	FtkXmlBuilder* builder = NULL;
337	return_val_if_fail(xml != NULL, RET_FAIL);
338
339	parser  = ftk_xml_parser_create();
340	return_val_if_fail(parser != NULL, RET_FAIL);
341
342	builder = ftk_animation_builder_create(thiz);
343	if(builder != NULL)
344	{
345		ftk_xml_parser_set_builder(parser, builder);
346		ftk_xml_parser_parse(parser, xml, length);
347	}
348	ftk_xml_builder_destroy(builder);
349	ftk_xml_parser_destroy(parser);
350
351	return RET_OK;
352}
353
354static Ret ftk_animation_trigger_parse_file(FtkAnimationTrigger* thiz, const char* filename)
355{
356	FtkMmap* m = NULL;
357	Ret ret = RET_FAIL;
358	return_val_if_fail(thiz != NULL && filename != NULL, RET_FAIL);
359	
360	m = ftk_mmap_create(filename, 0, -1);
361	if(m == NULL)
362	{
363		ftk_logd("%s: mmap %s failed.\n", __func__, filename);
364	}
365	return_val_if_fail(m != NULL, RET_FAIL);
366	ret = ftk_animation_trigger_parse_data(thiz, (const char*)ftk_mmap_data(m), ftk_mmap_length(m));
367	ftk_mmap_destroy(m);
368
369	return ret;
370}
371
372void ftk_animation_trigger_default_dump(FtkAnimationTrigger* thiz)
373{
374	int i = 0;
375	int j = 0;
376	DECL_PRIV(thiz, priv);
377	
378	for(i = 0; i < priv->type_and_animations_nr; i++)
379	{
380		ftk_logd("event: %s\n", priv->type_and_animations[i].event);
381		for(j = 0; j < FTK_MAX_ANIMATION_NR; j++)
382		{
383			if(priv->type_and_animations[i].animations[j] != NULL)
384			{
385				ftk_logd("animation:%s\n", priv->type_and_animations[i].animations[j]->name);
386				ftk_params_dump(priv->type_and_animations[i].animations[j]->params);
387			}
388		}
389	}
390
391	return;
392}
393
394FtkAnimationTrigger* ftk_animation_trigger_default_create(const char* theme, const char* name)
395{
396	FtkAnimationTrigger* thiz = FTK_NEW_PRIV(FtkAnimationTrigger);
397
398	if(thiz != NULL)
399	{
400		char filename[FTK_MAX_PATH + 1] = {0};
401
402		ftk_strs_cat(filename, FTK_MAX_PATH, 
403			ftk_config_get_data_dir(ftk_default_config()), "/theme/", theme, "/", name, NULL);
404
405		ftk_normalize_path(filename);
406		thiz->on_event = ftk_animation_trigger_default_on_event;
407		thiz->destroy = ftk_animation_trigger_default_destroy;
408
409		if(ftk_animation_trigger_parse_file(thiz, filename) == RET_OK)
410		{	
411			//ftk_animation_trigger_default_dump(thiz);
412			ftk_logd("%s: them=%s\n", __func__, theme);
413		}
414		else
415		{
416			FTK_FREE(thiz);
417		}
418	}
419
420	return thiz;
421}
422