missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / stroke.c
blob6749e4b6c8ffce41911812dc71404d13d963ac73
1 /*
2 libstroke - a stroke interface library
3 Copyright (c) 1996,1997,1998,1999,2000 Mark F. Willey, ETLA Technical
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software, including the rights to use, copy,
8 modify, merge, publish, and distribute copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions:
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; version 2.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 The above copyright notice and this permission notice shall be included
26 in all copies or substantial portions of the Software.
28 See the file "LICENSE" for a copy of the GNU GPL terms.
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
34 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
35 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
36 OTHER DEALINGS IN THE SOFTWARE.
38 Except as contained in this notice, the name of the author shall
39 name be used in advertising or otherwise to promote the sale, use or
40 other dealings in this Software without prior written authorization
41 from the author.
43 Non-GPL commercial use licenses are available - contact copyright holder.
45 Author: Mark F. Willey -- willey@etla.net
46 http://www.etla.net/
49 #include "config.h"
50 #include "stroke.h"
52 #include <unistd.h>
53 #include <string.h>
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <math.h>
58 #ifndef TRUE
59 #define TRUE 1
60 #define FALSE 0
61 #endif
64 /* structure for holding point data */
65 typedef struct s_point *p_point;
67 struct s_point {
68 int x;
69 int y;
70 p_point next;
73 /* point list head and tail */
74 static p_point point_list_head;
75 static p_point point_list_tail;
79 /* determine which bin a point falls in */
80 static int stroke_bin (p_point point_p, int bound_x_1, int bound_x_2,
81 int bound_y_1, int bound_y_2);
85 /* point list head and tail */
86 static p_point point_list_head=NULL;
87 static p_point point_list_tail=NULL;
89 /* metrics fo input stroke */
90 static int min_x = 10000;
91 static int min_y = 10000;
92 static int max_x = -1;
93 static int max_y = -1;
94 static int point_count = 0;
96 static void init_stroke_data (void)
98 while (point_list_head != NULL) {
99 point_list_tail = point_list_head;
100 point_list_head = point_list_head->next;
101 free (point_list_tail);
103 point_list_tail = NULL;
106 void stroke_init (void)
108 init_stroke_data ();
113 int stroke_trans (char *sequence)
115 /* number of bins recorded in the stroke */
116 int sequence_count = 0;
118 /* points-->sequence translation scratch variables */
119 int prev_bin = 0;
120 int current_bin = 0;
121 int bin_count = 0;
123 /* flag indicating the start of a stroke - always count it in the sequence */
124 int first_bin = TRUE;
126 /* bin boundary and size variables */
127 int delta_x, delta_y;
128 int bound_x_1, bound_x_2;
129 int bound_y_1, bound_y_2;
131 /* determine size of grid */
132 delta_x = max_x - min_x;
133 delta_y = max_y - min_y;
135 /* calculate bin boundary positions */
136 bound_x_1 = min_x + (delta_x / 3);
137 bound_x_2 = min_x + 2 * (delta_x / 3);
139 bound_y_1 = min_y + (delta_y / 3);
140 bound_y_2 = min_y + 2 * (delta_y / 3);
142 if (delta_x > STROKE_SCALE_RATIO * delta_y) {
143 bound_y_1 = (max_y + min_y - delta_x) / 2 + (delta_x / 3);
144 bound_y_2 = (max_y + min_y - delta_x) / 2 + 2 * (delta_x / 3);
145 } else if (delta_y > STROKE_SCALE_RATIO * delta_x) {
146 bound_x_1 = (max_x + min_x - delta_y) / 2 + (delta_y / 3);
147 bound_x_2 = (max_x + min_x - delta_y) / 2 + 2 * (delta_y / 3);
151 printf ("DEBUG:: point count: %d\n",point_count);
152 printf ("DEBUG:: min_x: %d\n",min_x);
153 printf ("DEBUG:: max_x: %d\n",max_x);
154 printf ("DEBUG:: min_y: %d\n",min_y);
155 printf ("DEBUG:: max_y: %d\n",max_y);
156 printf ("DEBUG:: delta_x: %d\n",delta_x);
157 printf ("DEBUG:: delta_y: %d\n",delta_y);
158 printf ("DEBUG:: bound_x_1: %d\n",bound_x_1);
159 printf ("DEBUG:: bound_x_2: %d\n",bound_x_2);
160 printf ("DEBUG:: bound_y_1: %d\n",bound_y_1);
161 printf ("DEBUG:: bound_y_2: %d\n",bound_y_2);
165 build string by placing points in bins, collapsing bins and
166 discarding those with too few points...
169 while (point_list_head != NULL) {
171 /* figure out which bin the point falls in */
172 current_bin = stroke_bin(point_list_head,bound_x_1, bound_x_2,
173 bound_y_1, bound_y_2);
174 /* if this is the first point, consider it the previous bin,
175 too. */
176 prev_bin = (prev_bin == 0) ? current_bin : prev_bin;
177 /* printf ("DEBUG:: current bin: %d\n",current_bin); */
179 if (prev_bin == current_bin)
180 bin_count++;
181 else { /* we are moving to a new bin -- consider adding to the
182 sequence */
183 if ((bin_count > (point_count * STROKE_BIN_COUNT_PERCENT))
184 || (first_bin == TRUE)) {
185 first_bin = FALSE;
186 sequence[sequence_count++] = '0' + prev_bin;
187 /* printf ("DEBUG:: adding sequence: %d\n",prev_bin);
191 /* restart counting points in the new bin */
192 bin_count=0;
193 prev_bin = current_bin;
196 /* move to next point, freeing current point from list */
197 point_list_tail = point_list_head;
198 point_list_head = point_list_head->next;
199 free (point_list_tail);
201 point_list_tail = NULL;
203 /* add the last run of points to the sequence */
204 sequence[sequence_count++] = '0' + current_bin;
205 /* printf ("DEBUG:: adding final sequence: %d\n",current_bin); */
207 /* bail out on error cases */
208 if ((point_count < STROKE_MIN_POINTS)
209 || (sequence_count > STROKE_MAX_SEQUENCE)) {
210 point_count = 0;
211 strcpy (sequence,"0");
212 return FALSE;
215 /* add null termination and leave */
216 point_count = 0;
217 sequence[sequence_count] = '\0';
218 return TRUE;
221 /* figure out which bin the point falls in */
222 static int stroke_bin (p_point point_p, int bound_x_1, int bound_x_2,
223 int bound_y_1, int bound_y_2)
225 int bin_num = 1;
226 if (point_p->x > bound_x_1) bin_num += 1;
227 if (point_p->x > bound_x_2) bin_num += 1;
228 if (point_p->y > bound_y_1) bin_num += 3;
229 if (point_p->y > bound_y_2) bin_num += 3;
231 return bin_num;
234 void stroke_record (int x, int y)
236 p_point new_point_p;
237 int delx, dely;
238 float ix, iy;
240 if (point_count < STROKE_MAX_POINTS) {
241 new_point_p = (p_point) malloc (sizeof(struct s_point));
243 if (point_list_tail == NULL) {
245 /* first point in list - initialize list and metrics */
246 point_list_head = point_list_tail = new_point_p;
247 min_x = 10000;
248 min_y = 10000;
249 max_x = -1;
250 max_y = -1;
251 point_count = 0;
253 } else {
254 /* interpolate between last and current point */
255 delx = x - point_list_tail->x;
256 dely = y - point_list_tail->y;
258 /* step by the greatest delta direction */
259 if (abs(delx) > abs(dely)) {
260 iy = point_list_tail->y;
262 /* go from the last point to the current, whatever direction it
263 may be */
264 for (ix = point_list_tail->x;
265 (delx > 0) ? (ix < x) : (ix > x);
266 ix += (delx > 0) ? 1 : -1) {
268 /* step the other axis by the correct increment */
269 iy += fabs(((float) dely
270 / (float) delx)) * (float) ((dely < 0) ? -1.0 : 1.0);
272 /* add the interpolated point */
273 point_list_tail->next = new_point_p;
274 point_list_tail = new_point_p;
275 new_point_p->x = ix;
276 new_point_p->y = iy;
277 new_point_p->next = NULL;
279 /* update metrics */
280 if (((int) ix) < min_x) min_x = (int) ix;
281 if (((int) ix) > max_x) max_x = (int) ix;
282 if (((int) iy) < min_y) min_y = (int) iy;
283 if (((int) iy) > max_y) max_y = (int) iy;
284 point_count++;
286 new_point_p = (p_point) malloc (sizeof(struct s_point));
288 } else { /* same thing, but for dely larger than delx case... */
289 ix = point_list_tail->x;
291 /* go from the last point to the current, whatever direction
292 it may be */
293 for (iy = point_list_tail->y; (dely > 0) ? (iy < y) : (iy > y);
294 iy += (dely > 0) ? 1 : -1) {
296 /* step the other axis by the correct increment */
297 ix += fabs(((float) delx / (float) dely))
298 * (float) ((delx < 0) ? -1.0 : 1.0);
300 /* add the interpolated point */
301 point_list_tail->next = new_point_p;
302 point_list_tail = new_point_p;
303 new_point_p->y = iy;
304 new_point_p->x = ix;
305 new_point_p->next = NULL;
307 /* update metrics */
308 if (((int) ix) < min_x) min_x = (int) ix;
309 if (((int) ix) > max_x) max_x = (int) ix;
310 if (((int) iy) < min_y) min_y = (int) iy;
311 if (((int) iy) > max_y) max_y = (int) iy;
312 point_count++;
314 new_point_p = (p_point) malloc (sizeof(struct s_point));
318 /* add the sampled point */
319 point_list_tail->next = new_point_p;
320 point_list_tail = new_point_p;
323 /* record the sampled point values */
324 new_point_p->x = x;
325 new_point_p->y = y;
326 new_point_p->next = NULL;