📄 li_recognizer.c
字号:
/* * 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; return ret;}static int li_recognizer_clear(recognizer r, bool){ li_recognizer* rec; rec = (li_recognizer*)r->recognizer_specific; /*Check for LI recognizer.*/ if( !CHECK_LI_MAGIC(rec) ) { li_err_msg = "Not a LI recognizer"; return 0; } return 0;}static int li_recognizer_set_context(recognizer, rc*){ /*This operation isn't supported by the LI recognizer.*/ li_err_msg = "Contexts are not supported by the LI recognizer"; return -1;}static rc*li_recognizer_get_context(recognizer){ /*This operation isn't supported by the LI recognizer.*/ li_err_msg = "Contexts are not supported by the LI recognizer"; return nil;}static int li_recognizer_get_buffer(recognizer, uint*, Stroke**){ /*This operation isn't supported by the LI recognizer.*/ li_err_msg = "Buffer get/set are not supported by the LI recognizer"; return -1;}static int li_recognizer_set_buffer(recognizer, uint, Stroke*){ /*This operation isn't supported by the LI recognizer.*/ li_err_msg = "Buffer get/set are not supported by the LI recognizer"; return -1;}static intli_recognizer_translate(recognizer r, uint ncs, Stroke* tps, bool, int* nret, rec_alternative** ret){ char* clss; li_recognizer* rec; int conf; rClassifier* rc; rec = (li_recognizer*)r->recognizer_specific; *nret = 0; *ret = nil; /*Check for LI recognizer.*/ if( !CHECK_LI_MAGIC(rec) ) { li_err_msg = "Not a LI recognizer"; return(-1); } rc = &(rec->li_rc); /*Check for valid parameters.*/ if (ncs < 1) { li_err_msg = "Invalid parameters: ncs"; return(-1); } if( tps == nil) { li_err_msg = "Invalid parameters: tps"; return(-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -