/* * 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. Load more
/* * 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 void free_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 void delete_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 int recognizer_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 int recognizer_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 int recognizer_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); } int li_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 wordset li_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 int li_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 int li_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 int li_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 int li_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;