1 /* anchor_engine.c -- identify strokes along full-screen, non-uniform 3X3 grid
2 
3    Copyright (C) 2000 Carl Worth
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2, or (at your option)
8    any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <string.h>
20 
21 #include "rec.h"
22 #include "grid.h"
23 #include "regex_feature.h"
24 #include "anchor_engine.h"
25 #include "sprintf_alloc.h"
26 #include "fixed.h"
27 
28 #ifdef DMALLOC
29 #include "dmalloc.h"
30 #endif
31 
32 /* anchor_engine_funcs are defined statically in rec_engine.c
33 rec_engine_funcs_t engine_funcs =
34 {
35     anchor_priv_alloc,
36     anchor_priv_free,
37     anchor_feature_data_alloc,
38     anchor_feature_data_free,
39     anchor_classify_stroke,
40     anchor_classification_str_alloc,
41     anchor_free_classification,
42     anchor_recognize_feature
43 };
44 */
45 
anchor_priv_alloc(rec_engine_t * engine)46 int anchor_priv_alloc(rec_engine_t *engine)
47 {
48     anchor_priv_t *priv;
49 
50     priv = malloc(sizeof(anchor_priv_t));
51     if (priv == NULL) {
52 	fprintf(stderr, "%s: Out of memory\n", __FUNCTION__);
53 	return ENOMEM;
54     }
55 
56     priv->border_width_ratio = ANCHOR_DEFAULT_BORDER_WIDTH_PERCENT / 100.0;
57     engine->priv = priv;
58     return 0;
59 }
60 
anchor_priv_free(rec_engine_t * engine)61 void anchor_priv_free(rec_engine_t *engine)
62 {
63     free(engine->priv);
64     engine->priv = NULL;
65 }
66 
anchor_feature_data_alloc(rec_engine_t * engine,char * feature_data_str)67 void *anchor_feature_data_alloc(rec_engine_t *engine, char *feature_data_str)
68 {
69     return regex_feature_alloc(feature_data_str);
70 }
71 
anchor_feature_data_free(rec_engine_t * engine,void * feature_data)72 void anchor_feature_data_free(rec_engine_t *engine, void *feature_data)
73 {
74     regex_feature_free((regex_t *) feature_data);
75 }
76 
anchor_classify_stroke(rec_engine_t * engine,stroke_t * stroke)77 void anchor_classify_stroke(rec_engine_t *engine, stroke_t *stroke)
78 {
79     anchor_priv_t *priv = engine->priv;
80     double bwr = priv->border_width_ratio;
81     int x_thresh_low, x_thresh_high;
82     int y_thresh_low, y_thresh_high;
83 
84     x_thresh_low = f_to_fixed(engine->rec->width * bwr, stroke->precision_bits);
85     x_thresh_high = f_to_fixed(engine->rec->width * (1.0 - bwr), stroke->precision_bits);
86     y_thresh_low = f_to_fixed(engine->rec->height * bwr, stroke->precision_bits);
87     y_thresh_high = f_to_fixed(engine->rec->height * (1.0 - bwr), stroke->precision_bits);
88 
89     stroke->classifications[engine->num] =
90 	grid_stroke_sequence_alloc(stroke,
91 				   x_thresh_low, x_thresh_high,
92 				   y_thresh_low, y_thresh_high);
93 }
94 
anchor_classification_str_alloc(rec_engine_t * engine,stroke_t * stroke)95 char *anchor_classification_str_alloc(rec_engine_t *engine, stroke_t *stroke)
96 {
97     return strdup((char *) stroke->classifications[engine->num]);
98 }
99 
anchor_free_classification(rec_engine_t * engine,stroke_t * stroke)100 void anchor_free_classification(rec_engine_t *engine, stroke_t *stroke)
101 {
102     free(stroke->classifications[engine->num]);
103 }
104 
anchor_recognize_stroke(rec_engine_t * engine,stroke_t * stroke,void * feature_data)105 double anchor_recognize_stroke(rec_engine_t *engine, stroke_t *stroke,
106 			       void *feature_data)
107 {
108     char *sequence = (char *) stroke->classifications[engine->num];
109     regex_t *regex = (regex_t *) feature_data;
110 
111     return regex_feature_recognize(regex, sequence);
112 }
113 
anchor_set_option(rec_engine_t * engine,char * option,char * value)114 int anchor_set_option(rec_engine_t *engine, char *option, char *value)
115 {
116     anchor_priv_t *priv;
117 
118     priv = (anchor_priv_t *) engine->priv;
119     if (strcmp(option, "BorderWidthPercent") == 0) {
120 	priv->border_width_ratio = atof(value) / 100.0;
121 	return 0;
122     }
123 
124     return EINVAL;
125 }
126