PageRenderTime 1632ms CodeModel.GetById 162ms app.highlight 905ms RepoModel.GetById 232ms app.codeStats 1ms

/src/fhw/fhw_primitive_recognizer.c

http://ftk.googlecode.com/
C | 352 lines | 253 code | 67 blank | 32 comment | 52 complexity | bf5686fe03b04294ed6d65debd9fd794 MD5 | raw file
  1/*
  2 * File: ftk_input_method.h    
  3 * Author:  Li XianJing <xianjimli@hotmail.com>
  4 * Brief:   FTK handwrite primtives
  5 *
  6 * Copyright (c) 2009 - 2010  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 * 2010-02-13 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_allocator.h"
 33#include "fhw_primitive_recognizer.h"
 34
 35#define FHW_MAX_PRIMITIVES 255
 36
 37struct _FhwPrimitiveRecognizer
 38{
 39	int nr;
 40	FtkRect rect;
 41	char results[FHW_MAX_PRIMITIVES + 1];
 42};
 43
 44FhwPrimitiveRecognizer* fhw_primitive_recognizer_create(FtkRect* rect)
 45{
 46	FhwPrimitiveRecognizer* thiz = FTK_ZALLOC(sizeof(FhwPrimitiveRecognizer));
 47
 48	if(thiz != NULL)
 49	{
 50		thiz->rect = *rect;
 51	}
 52
 53	return thiz;
 54}
 55
 56Ret  fhw_primitive_recognizer_reset(FhwPrimitiveRecognizer* thiz)
 57{
 58	return_val_if_fail(thiz != NULL, RET_FAIL);
 59
 60	thiz->nr = 0;
 61	thiz->results[0] = '\0';
 62
 63	return RET_OK;
 64}
 65
 66Ret  fhw_primitive_recognizer_flush(FhwPrimitiveRecognizer* thiz)
 67{
 68	return_val_if_fail(thiz != NULL, RET_FAIL);
 69	/*XXX: do nothing now.*/
 70
 71	return RET_OK;
 72}
 73
 74typedef struct _FhwPointsInfo
 75{
 76	/*some pre-computed values.*/
 77	int x;
 78	int y;
 79	int w;
 80	int h;
 81	int min_x;
 82	int min_y;
 83	int max_x;
 84	int max_y;
 85	int delta_x;
 86	int delta_y;
 87	int dot_range;
 88	
 89	int nr;
 90	FtkPoint* points;
 91}FhwPointsInfo;
 92
 93#define FHW_MAX_MISS  3
 94#define FHW_TOLERANCE 5
 95
 96static FhwPrimitiveType fhw_primitive_recognizer_dian(FhwPointsInfo* info)
 97{
 98	if(info->delta_x > info->dot_range || info->delta_y > info->dot_range)
 99	{
100		return FHW_PRIMITIVE_NONE;
101	}
102
103	if(info->delta_y > 3 * info->delta_x || info->delta_x > 3 * info->delta_y)
104	{
105		return FHW_PRIMITIVE_NONE;
106	}
107
108	return FHW_PRIMITIVE_DIAN;
109}
110
111static FhwPrimitiveType fhw_primitive_recognizer_heng(FhwPointsInfo* info)
112{
113	int i = 0;
114	int miss = 0;
115
116	if(4*(info->delta_y) > (info->delta_x))
117	{
118		return FHW_PRIMITIVE_NONE;
119	}
120
121	for(i = 1; i < info->nr ; i++)
122	{
123		if(miss >= FHW_MAX_MISS)
124		{
125			return FHW_PRIMITIVE_NONE;
126		}
127	
128		if((info->points[i].x + FHW_TOLERANCE) < info->points[i-1].x)
129		{
130			return FHW_PRIMITIVE_NONE;
131		}
132
133		miss = (info->points[i].x < info->points[i-1].x) ? miss + 1 : 0;
134	}
135
136	return FHW_PRIMITIVE_HENG;
137}
138
139static FhwPrimitiveType fhw_primitive_recognizer_shu(FhwPointsInfo* info)
140{
141	int i = 0;
142	int miss = 0;
143
144	if(4 * info->delta_x > info->delta_y)
145	{
146		return FHW_PRIMITIVE_NONE;
147	}
148
149	for(i = 1; i < info->nr ; i++)
150	{
151		if(miss >= FHW_MAX_MISS)
152		{
153			return FHW_PRIMITIVE_NONE;
154		}
155
156		if((info->points[i].y + FHW_TOLERANCE) < info->points[i-1].y)
157		{
158			return FHW_PRIMITIVE_NONE;
159		}
160
161		miss = info->points[i].y < info->points[i-1].y ? miss + 1 : 0;
162	}
163
164	return FHW_PRIMITIVE_SHU;
165}
166
167static FhwPrimitiveType fhw_primitive_recognizer_pie(FhwPointsInfo* info)
168{
169	int i = 0;
170	int miss = 0;
171
172	if(info->delta_x < info->dot_range || info->delta_y < info->dot_range)
173	{
174		return FHW_PRIMITIVE_NONE;
175	}
176
177	for(i = 1; i < info->nr ; i++)
178	{
179		if(miss >= FHW_MAX_MISS)
180		{
181			return FHW_PRIMITIVE_NONE;
182		}
183
184		if((info->points[i].y + FHW_TOLERANCE < info->points[i-1].y) 
185			|| (info->points[i].x - FHW_TOLERANCE > info->points[i-1].x))
186		{
187			return FHW_PRIMITIVE_NONE;
188		}
189
190		miss = ((info->points[i].y < info->points[i-1].y) || (info->points[i].x > info->points[i-1].x)) ?
191			miss + 1 : 0;
192	}
193
194	return FHW_PRIMITIVE_PIE;
195}
196
197static FhwPrimitiveType fhw_primitive_recognizer_na(FhwPointsInfo* info)
198{
199	int i = 0;
200	int miss = 0;
201
202	if(info->delta_x < info->dot_range || info->delta_y < info->dot_range)
203	{
204		return FHW_PRIMITIVE_NONE;
205	}
206
207	for(i = 1; i < info->nr ; i++)
208	{
209		if(miss >= FHW_MAX_MISS)
210		{
211			return FHW_PRIMITIVE_NONE;
212		}
213
214		if((info->points[i].y + FHW_TOLERANCE < info->points[i-1].y) 
215			|| (info->points[i].x + FHW_TOLERANCE < info->points[i-1].x))
216		{
217			return FHW_PRIMITIVE_NONE;
218		}
219
220		miss = ((info->points[i].y < info->points[i-1].y) || (info->points[i].x < info->points[i-1].x)) ?
221			miss + 1 : 0;
222	}
223
224	return FHW_PRIMITIVE_NA;
225}
226
227static FhwPrimitiveType fhw_primitive_recognizer_heng_zhe(FhwPointsInfo* info)
228{
229	int i = 0;
230	int miss = 0;
231
232	if(2*(info->delta_y) < (info->delta_x) || 2*(info->delta_x) < (info->delta_y))
233	{
234		return FHW_PRIMITIVE_NONE;
235	}
236
237	/*check heng*/
238	for(i = 1; i < info->nr ; i++)
239	{
240		if(miss >= FHW_MAX_MISS)
241		{
242			return FHW_PRIMITIVE_NONE;
243		}
244	
245		if((info->points[i].x + FHW_TOLERANCE) < info->points[i-1].x)
246		{
247			return FHW_PRIMITIVE_NONE;
248		}
249
250		miss = (info->points[i].x < info->points[i-1].x) ? miss + 1 : 0;
251
252		if((info->points[i].y - info->min_y) > info->dot_range)
253		{
254			break;
255		}
256	}
257
258	for(; i < info->nr ; i++)
259	{
260		if(miss >= FHW_MAX_MISS)
261		{
262			return FHW_PRIMITIVE_NONE;
263		}
264
265		if((info->points[i].y + FHW_TOLERANCE) < info->points[i-1].y)
266		{
267			return FHW_PRIMITIVE_NONE;
268		}
269
270		miss = info->points[i].y < info->points[i-1].y ? miss + 1 : 0;
271	}
272
273	return FHW_PRIMITIVE_HENG_ZHE;
274}
275
276typedef FhwPrimitiveType (*FhwPrimitiveRecognizerFunc)(FhwPointsInfo* info);
277
278static const FhwPrimitiveRecognizerFunc g_recognizers[] = 
279{
280	fhw_primitive_recognizer_dian,
281	fhw_primitive_recognizer_heng,
282	fhw_primitive_recognizer_heng_zhe,
283	fhw_primitive_recognizer_shu,
284	fhw_primitive_recognizer_pie,
285	fhw_primitive_recognizer_na,
286	NULL
287};
288
289Ret  fhw_primitive_recognizer_add_stroke(FhwPrimitiveRecognizer* thiz, FtkPoint* points, size_t nr)
290{
291	int i = 0;
292	FhwPointsInfo info = {0};
293	FhwPrimitiveType result = FHW_PRIMITIVE_NONE;
294	return_val_if_fail(thiz != NULL && points != NULL, RET_FAIL);
295	return_val_if_fail(thiz->nr < FHW_MAX_PRIMITIVES, RET_FAIL);
296
297	info.nr = nr;
298	info.points = points;
299	
300	info.x = thiz->rect.x;
301	info.y = thiz->rect.y;
302	info.w = thiz->rect.width;
303	info.h = thiz->rect.height;
304
305	info.min_x = points[0].x;
306	info.min_y = points[0].y;
307	info.max_x = points[0].x;
308	info.max_y = points[0].y;
309	info.dot_range = (info.w + info.h) >> 3;
310	for(i = 1; i < nr; i++)
311	{
312		info.min_x = FTK_MIN(info.min_x, points[i].x);
313		info.min_y = FTK_MIN(info.min_y, points[i].y);
314		info.max_x = FTK_MAX(info.max_x, points[i].x);
315		info.max_y = FTK_MAX(info.max_y, points[i].y);
316	}
317
318	info.delta_x = info.max_x - info.min_x;
319	info.delta_y = info.max_y - info.min_y;
320
321	for(i = 0; g_recognizers[i] != NULL; i++)
322	{
323		if((result = g_recognizers[i](&info)) != FHW_PRIMITIVE_NONE)
324		{
325			thiz->results[thiz->nr++] = result;
326			thiz->results[thiz->nr] = '\0';
327			break;
328		}
329	}
330
331	return RET_OK;
332}
333
334Ret  fhw_primitive_recognizer_get_result(FhwPrimitiveRecognizer* thiz, const char** results)
335{
336	return_val_if_fail(thiz != NULL && results != NULL, RET_FAIL);
337
338	*results = thiz->results;
339
340	return RET_OK;
341}
342
343void fhw_primitive_recognizer_destroy(FhwPrimitiveRecognizer* thiz)
344{
345	if(thiz != NULL)
346	{
347		FTK_ZFREE(thiz, sizeof(FhwPrimitiveRecognizer));
348	}
349
350	return;
351}
352