2313 lines · 56.2 KB · C
RawDownload
/* *  li_recognizer.c * *	Copyright 2000 Compaq Computer Corporation. *	Copying or modifying this code for any purpose is permitted, *	provided that this copyright notice is preserved in its entirety *	in all copies or modifications. *	COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR *	IMPLIED, AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR * * *  Adapted from cmu_recognizer.c by Jay Kistler. *   *  Where is the CMU copyright???? Gotta track it down - Jim Gettys * *  Credit to Dean Rubine, Jim Kempf, and Ari Rapkin. */ #include <u.h>#include <libc.h>#include <stdio.h>#include <draw.h>#include <scribble.h>#include "scribbleimpl.h" #include "hre_internal.h"#include "li_recognizer_internal.h" int lidebug = 0; #define LI_MAGIC 0xACCBADDD #define CHECK_LI_MAGIC(_a) \  ((_a) != nil && ((li_recognizer*)(_a))->li_magic == LI_MAGIC)  static void lialg_initialize(rClassifier *);static int lialg_read_classifier_digest(rClassifier *);static int lialg_canonicalize_examples(rClassifier *);static char *lialg_recognize_stroke(rClassifier *, point_list *);static void lialg_compute_lpf_parameters(void);  char* li_err_msg = nil; #define bcopy(s1,s2,n) memmove(s2,s1,n) /*Freeing classifier*/ static voidfree_rClassifier(rClassifier* rc); /* * Point List Support*/ static point_list*add_example(point_list* l,int npts,pen_point* pts){	pen_point* lpts = mallocz(npts*sizeof(pen_point), 1);	point_list *p = malloc(sizeof(point_list)); 	p->npts = npts;	p->pts = lpts;	p->next = l;       /*Order doesn't matter, so we stick on end.*/ 	/*Copy points.*/ 	bcopy(pts, lpts, npts * sizeof(pen_point)); 	return(p);}	 static voiddelete_examples(point_list* l){	point_list* p; 	for( ; l != nil; l = p ) {		p = l->next;		free(l->pts);		free(l);	}} /* * Local functions */ /* * recognize_internal-Form Vector, use Classifier to classify, return char. */ static char*recognize_internal(rClassifier* rec, Stroke* str, int*){	char *res;	point_list *stroke; 	stroke = add_example(nil, str->npts, str->pts);	if (stroke == nil) return(nil); 	res = lialg_recognize_stroke(rec, stroke); 	delete_examples(stroke);	return(res);} /* * file_path-Construct pathname, check for proper extension. */ static int  file_path(char* dir,char* filename,char* pathname){	char* dot;		/*Check for proper extension on file name.*/		dot = strrchr(filename,'.');		if( dot == nil ) {		return(-1);	} 	/*Determine whether a gesture or character classifier.*/ 	if( strcmp(dot,LI_CLASSIFIER_EXTENSION) != 0 ) {		return(-1);	} 	/*Concatenate directory and filename into pathname.*/		strcpy(pathname,dir);	strcat(pathname,"/");	strcat(pathname,filename);		return(0);} /*read_classifier_points-Read points so classifier can be extended.*/ static int read_classifier_points(FILE* fd,int nclss,point_list** ex,char** cnames){	int i,j,k;	char buf[BUFSIZ];	int nex = 0;	char* names[MAXSCLASSES];	point_list* examples[MAXSCLASSES];	pen_point* pts;	int npts; 	/*Initialize*/ 		for( i = 0; i < MAXSCLASSES; i++ ) {				names[i] = nil;				examples[i] = nil;		} 		/*Go thru classes.*/ 		for( k = 0; k < nclss; k++ ) { 				/*Read class name and number of examples.*/						if( fscanf(fd,"%d %s",&nex,buf) != 2 )					goto unallocate;						/*Save class name*/						names[k] = strdup(buf);						/*Read examples.*/								for( i = 0; i < nex; i++ ) {										/*Read number of points.*/										if( fscanf(fd,"%d",&npts) != 1 )								goto unallocate; /*Boy would I like exceptions!*/										/*Allocate array for points.*/										if( (pts = mallocz(npts*sizeof(pen_point), 1)) == nil )								goto unallocate;										/*Read in points.*/										for( j = 0; j < npts; j++ ) {								int x,y;								if( fscanf(fd,"%d %d",&x,&y) != 2 ) {									delete_pen_point_array(pts);									goto unallocate;								}								pts[j].Point = Pt(x, y);					}										/*Add example*/										if( (examples[k] = add_example(examples[k],npts,pts)) == nil ) {								delete_pen_point_array(pts);								goto unallocate;					}										delete_pen_point_array(pts);							}		} /* ari -- end of list of classes *//* fprint(2, "]\n"); */ 		/*Transfer to recognizer.*/ 		bcopy(examples,ex,sizeof(examples));		bcopy(names,cnames,sizeof(names)); 		return(0); 		/*Error. Deallocate memory and return.*/ unallocate:		for( ; k >= 0; k-- ) {				delete_examples(examples[k]);				free(names[k]);		} 		return(-1);} /*read_classifier-Read a classifier file.*/ static int read_classifier(FILE* fd,rClassifier* rc){		li_err_msg = nil; 	/*Read in classifier file.*/ 	if(fscanf(fd, "%d", &rc->nclasses) != 1)		return -1; 	/*Read in the example points, so classifier can be extended.*/ 	if( read_classifier_points(fd,rc->nclasses,rc->ex,rc->cnames) != 0 )		return -1; 	return(0);} /* * Extension Functions*/ /* getClasses and clearState are by Ari */ static intrecognizer_getClasses (recognizer r, char ***list, int *nc){	int i, nclasses;	li_recognizer* rec;	char **ret; 		rec = (li_recognizer*)r->recognizer_specific; 		/*Check for LI recognizer.*/ 		if( !CHECK_LI_MAGIC(rec) ) {				li_err_msg = "Not a LI recognizer";				return(-1);	}		*nc = nclasses = rec->li_rc.nclasses;	ret = malloc(nclasses*sizeof(char*)); 	for (i = 0; i < nclasses; i++)				ret[i] = rec->li_rc.cnames[i];   /* only the 1st char of the cname */	*list = ret;		return 0;} static intrecognizer_clearState (recognizer){  /*This operation isn't supported by the LI recognizer.*/   li_err_msg = "Clearing state is not supported by the LI recognizer";   return(-1);} static bool isa_li(recognizer r){ return(CHECK_LI_MAGIC(r)); } static intrecognizer_train(recognizer, rc*, uint, Stroke*, rec_element*, bool){  /*This operation isn't supported by the LI recognizer.*/   li_err_msg = "Training is not supported by the LI recognizer";   return(-1);} intli_recognizer_get_example (recognizer r,						   int		class, 						   int		instance,						   char		**name, 						   pen_point	**points,						   int		*npts){	li_recognizer   *rec = (li_recognizer*)r->recognizer_specific;	int nclasses = rec->li_rc.nclasses;	point_list	    *pl;			if( !CHECK_LI_MAGIC(rec) ) {				li_err_msg = "Not a LI recognizer";				return(-1);		}		if (class > nclasses)				return -1;		pl = rec->li_rc.canonex[class];		while (instance && pl)		{				pl = pl->next;				instance--;		}		if (!pl)				return -1;		*name = rec->li_rc.cnames[class];		*points = pl->pts;		*npts = pl->npts;		return pl->npts; /* I hope [sjm] */} /* * API Functions */  /*li_recognizer_load-Load a classifier file.*/ static int li_recognizer_load(recognizer r, char* dir, char* filename){		FILE *fd;		char* pathname;		li_recognizer* rec;		rClassifier* rc;				rec = (li_recognizer*)r->recognizer_specific; 		/*Make sure recognizer's OK*/ 		if( !CHECK_LI_MAGIC(rec) ) {				li_err_msg = "Not a LI recognizer";				return(-1);		} 		rc = &(rec->li_rc); 		/*Check parameters.*/ 		if( filename == nil ) {				li_err_msg = "Invalid parameters";				return(-1);		} 		/*We let the directory be null.*/ 		if( dir == nil || (int)strlen(dir) <= 0 ) {				dir = ".";		} 		if(0)fprint(2, "dir = %s, filename = %s\n",				dir, filename); 		/*Make full pathname and check filename*/ 		pathname = malloc((strlen(dir) + strlen(filename) + 2)*sizeof(char));		if( file_path(dir, filename, pathname) == -1 ) {				free(pathname);				li_err_msg = "Not a LI recognizer classifier file";				return -1;		} 		/* Try to short-circuit the full classifier-file processing. */		rc->file_name = pathname;		if (lialg_read_classifier_digest(rc) == 0)				return(0);		rc->file_name = nil; 		/*Open the file*/ 		if( (fd = fopen(pathname,"r")) == nil ) {				li_err_msg = "Can't open classifier file";				if(0)fprint(2, "Can't open %s.\n", pathname);				free(pathname);				return(-1);		} 		/*If rClassifier is OK, then delete it first.*/ 		if( rc->file_name != nil ) {				free_rClassifier(rc);		} 		/*Read classifier.*/				if( read_classifier(fd,rc) < 0 ) {				free(pathname);				return(-1);		} 		/*Close file.*/ 		fclose(fd); 		/*Add classifier name.*/ 		rc->file_name = pathname; 		/* Canonicalize examples. */		if (lialg_canonicalize_examples(rc) != 0) {				free(pathname);				rc->file_name = nil;				return -1;		} 		return(0);} /*li_recognizer_save-Save a classifier file.*/ static int li_recognizer_save(recognizer, char*, char*){ 		/*This operation isn't supported by the LI recognizer.*/ 		li_err_msg = "Saving is not supported by the LI recognizer";		return -1;} static wordsetli_recognizer_load_dictionary(recognizer, char*, char*){		/*This operation isn't supported by the LI recognizer.*/ 		li_err_msg = "Dictionaries are not supported by the LI recognizer";		return nil;} static intli_recognizer_save_dictionary(recognizer, char*, char*, wordset){		/*This operation isn't supported by the LI recognizer.*/		li_err_msg = "Dictionaries are not supported by the LI recognizer";		return -1;} static intli_recognizer_free_dictionary(recognizer, wordset){  /*This operation isn't supported by the LI recognizer.*/   li_err_msg = "Dictionaries are not supported by the LI recognizer";   return -1; } static intli_recognizer_add_to_dictionary(recognizer, letterset*, wordset){		/*This operation isn't supported by the LI recognizer.*/		li_err_msg = "Dictionaries are not supported by the LI recognizer";		return -1;} static intli_recognizer_delete_from_dictionary(recognizer, letterset*, wordset){		/*This operation isn't supported by the LI recognizer.*/		li_err_msg = "Dictionaries are not supported by the LI recognizer";		return -1;} static char*li_recognizer_error(recognizer rec){	char* ret = li_err_msg; 	/*Check for LI recognizer.*/ 	if( !CHECK_LI_MAGIC(rec->recognizer_specific) ) {				li_err_msg = "Not a LI recognizer";				return nil;	}	li_err_msg = nil;

Lines 1–500 of 2313.