OSDN Git Service

added support for extra filters
[kp123/kp123.git] / src / recognize_extra.c
1
2 #include "defs.h"
3
4 #include "recognize_extra.h"
5
6 static gint eval_filter(GList *s, gunichar2 arg)
7 {
8     GdkPoint *p0 = (GdkPoint*)g_list_first(s)->data;
9     GdkPoint *pn = (GdkPoint*)g_list_last(s)->data;
10     switch( arg )
11     {
12         case 'x':
13             return p0->x;
14         case 'y':
15             return p0->y;
16         case 'i':
17             return pn->x;
18         case 'j':
19             return pn->y;
20         case 'a':
21             return ((p0->x + pn->x) >> 1);
22         case 'b':
23             return ((p0->y + pn->y) >> 1);
24         case 'l':
25             {
26                 int dx = p0->x - pn->x;
27                 int dy = p0->y - pn->y;
28                 return abs(dx) + abs(dy);
29             }
30     }
31     return 0;
32 }
33
34 static void get_sz(GList *strokes, gint *sz)
35 {
36     int xmin, ymin, xmax, ymax;
37     GdkPoint *pt = (GdkPoint*)(((GList*)strokes->data)->data);
38     xmin = xmax = pt->x;
39     ymin = ymax = pt->y;
40     GList *s, *s1;
41     for(s = g_list_first(strokes); s; s = g_list_next(s)) 
42     {
43         for(s1 = (GList*)s->data; s1; s1 = g_list_next(s1))
44         {
45             pt = (GdkPoint*)s1->data;
46             if(pt->x < xmin)
47                 xmin = pt->x;
48             if(pt->y < ymin)
49                 ymin = pt->y;
50             if(pt->x > xmax)
51                 xmax = pt->x;
52             if(pt->y > ymax)
53                 ymax = pt->y;
54         }
55     }
56     gint w = xmax - xmin, h = ymax - ymin;
57     *sz = (w > h) ? w : h;
58 }
59
60 gint pass_extra_filters(GList *strokes, gunichar2 *entry)
61 {
62     gunichar2 arg[2], fn, c;
63     gint stroke[2];
64     gint sc, val[2];
65     gint index = 0;
66     gboolean must = False;
67     gint score = 0;
68
69     arg[0] = arg[1] = 0;
70     stroke[0] = stroke[1] = 0;
71
72     /* Simple parser for Filter strings. assumes a1-b1 structure,
73      * where a and b can be any single alphabetic cmd char, the 
74      * numbers can be multiple digit, and b1 can optionally be 
75      * followed by '!' to insist on the filter passing.  There can
76      * be multiple filters but they have to be separated by '!' or
77      * space(s).  The filter string is terminated by a null byte
78      * or an 8-bit char, the beginning of the next entry.  
79      * Leading spaces and trailing spaces are ignored. -rwells, 970722.
80      */
81
82     for(c = *entry; True; entry++, c = *entry )
83     {
84         switch( c )
85         {
86             case 'x': 
87             case 'y':
88             case 'i':
89             case 'j':
90             case 'a':
91             case 'b':
92             case 'l':
93                 arg[index] = c;
94                 break;
95
96             case '0':
97             case '1':
98             case '2':
99             case '3':
100             case '4':
101             case '5':
102             case '6':
103             case '7':
104             case '8':
105             case '9':
106                 stroke[index] = stroke[index] * 10 + (c - '0');
107                 break;
108
109             case '-':
110             case '<':
111             case '=':
112                 fn = c;
113                 index = 1;
114                 break;
115
116             case '!':
117                 must = True;
118
119             case ' ':
120             default:
121                 if(index == 1) // second argument
122                 {
123                     gint n = g_list_length(strokes);
124                     if((n > stroke[0]) || (n > stroke[1]))
125                     {
126                         val[0] = eval_filter(g_list_nth_data(strokes, stroke[0] - 1), arg[0]);
127                         val[1] = eval_filter(g_list_nth_data(strokes, stroke[1] - 1), arg[1]);
128                         gint sz;
129                         get_sz(strokes, &sz);
130                         if(fn == '-')
131                         {
132                             sc = ((val[0] - val[1]) < 0) ? 1 : -1;
133                             if(must) sc *= 2;
134                             score += sc;
135                         }
136                         else if(fn == '=')
137                         {
138                             sc = ((val[0] - val[1]) > sz/4) ? 1 : -1;
139                             if(must) sc *= 2;
140                             score += sc;
141                         }
142                         else if(fn == '<')
143                         {
144                             sc = (abs(val[1] - val[0]) > sz/2) ? 1 : -1;
145                             if(must) sc *= 2;
146                             score += sc;
147                         }
148                     }
149
150                     // reset
151                     index = 0;
152                     must = False;
153                     arg[0] = arg[1] = 0;
154                     stroke[0] = stroke[1] = 0;
155                 }
156
157                 if( c == '\r' || c == '\0' )
158                     return score;
159         }
160     }
161     return score;
162 }
163