Commit | Line | Data |
---|---|---|
a6a4e5d4 PH |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <sys/types.h> | |
5 | #include <sys/stat.h> | |
6 | #include <fcntl.h> | |
7 | #include <unistd.h> | |
8 | #include <ctype.h> | |
9 | ||
10 | /* #define DEBUG */ | |
11 | ||
12 | #include "hpgl.h" | |
13 | #include "optimize.h" | |
14 | ||
15 | #define BUFFER_SIZE (32*1024*1024) | |
16 | ||
17 | static char data[BUFFER_SIZE]; | |
18 | static int data_size; | |
19 | static int data_left; | |
20 | ||
21 | /*********************************++ | |
22 | * | |
23 | * Read input data into a buffer | |
24 | * | |
25 | */ | |
26 | static void read_file(int fd){ | |
27 | int res=0; | |
28 | data_size=0; | |
29 | while ((res=read(fd,data+data_size,BUFFER_SIZE-1-data_size))) data_size+=res; | |
30 | data_left=data_size; | |
31 | DBG("Read %i bytes.\n",data_left); | |
32 | } | |
33 | ||
34 | static int comp(char ** pptr, char * b){ | |
35 | char * ptr= *pptr; | |
36 | if (strncmp(ptr,b,strlen(b))==0){ | |
37 | (*pptr)+=strlen(b); | |
38 | data_left-=strlen(b); | |
39 | return 1; | |
40 | } else return 0; | |
41 | } | |
42 | ||
43 | static struct point * get_point(char ** pptr){ | |
44 | char * ptr2; | |
45 | struct point *result = (struct point *)malloc(sizeof(struct point)); | |
46 | result->valid=1; | |
47 | result->x=strtold(*pptr,&ptr2); | |
48 | if (ptr2==*pptr) result->valid=0; | |
49 | else { | |
50 | *pptr=ptr2; | |
51 | *pptr=index(*pptr,',')+1; | |
52 | result->y=strtold(*pptr,&ptr2); | |
53 | if (ptr2==*pptr) result->valid=0; | |
54 | else *pptr=ptr2; | |
55 | } | |
56 | result->next=NULL; | |
57 | result->previous_in_path=NULL; | |
58 | ||
59 | if (result->valid) | |
60 | (*pptr)++; /* Step over comma between point specs! */ | |
61 | return result; | |
62 | } | |
63 | ||
64 | static void output (struct path * first_path){ | |
65 | struct point * last_point=NULL; | |
66 | struct path * current_path; | |
67 | ||
68 | for (current_path=first_path; current_path != NULL; | |
69 | current_path=current_path->next){ | |
70 | ||
71 | struct point * current_point; | |
72 | ||
73 | /* Initial move to start of plot */ | |
74 | current_point=current_path->plot_start_point; | |
75 | if (!equal(current_point,last_point)) { | |
76 | printf("PU, %.2f,%.2f\n",current_point->x,current_point->y); | |
77 | } | |
78 | ||
79 | if (current_path->plot_start_point | |
80 | == current_path->first_point){ /* Forward */ | |
81 | ||
82 | for (current_point=current_point->next; current_point != NULL; | |
83 | current_point=current_point->next) { | |
84 | if (!equal(current_point,last_point)) { | |
85 | printf("PD, %.2f,%.2f\n",current_point->x,current_point->y); | |
86 | } | |
87 | last_point=current_point; | |
88 | } | |
89 | } else { /* Going backwards */ | |
90 | for (current_point=current_point->previous_in_path; current_point != NULL; | |
91 | current_point=current_point->previous_in_path) { | |
92 | if (!equal(current_point,last_point)) { | |
93 | printf("PD, %.2f,%.2f\n",current_point->x,current_point->y); | |
94 | } | |
95 | last_point=current_point; | |
96 | } | |
97 | } | |
98 | } | |
99 | } | |
100 | ||
101 | /******************************************************************************* | |
102 | * * | |
103 | * main() * | |
104 | * * | |
105 | ******************************************************************************* | |
106 | */ | |
107 | int main(int argc, char ** args){ | |
108 | ||
109 | int fd=0; /* File descriptor for data input, defaults to standard input */ | |
110 | ||
111 | char * ptr=data; /* Input buffer */ | |
112 | enum plot_mode_t plot_mode=absolute; /* Coordinate modus */ | |
113 | enum pen_state_t pen_state=up; | |
114 | ||
115 | struct point pen_pos={0,0,1}; | |
116 | ||
a6a4e5d4 PH |
117 | struct path * first_path=NULL; |
118 | struct path * current_path=NULL; | |
119 | ||
120 | int in_path=0; | |
121 | ||
122 | enum hpgl_cmd_t command; /* Current command being processed */ | |
123 | ||
124 | DBG("Start\n"); | |
125 | ||
126 | /* Open input file to read if specified. */ | |
127 | if (argc>1){ | |
128 | fd=open(args[1],O_RDONLY); | |
129 | if (fd < 0){ | |
130 | ERR("Could not open file: \"%s\"\n",args[1]); | |
131 | exit (-2); | |
132 | } | |
133 | } | |
134 | /* fd=open("haus.hpl",O_RDONLY); */ | |
135 | read_file(fd); | |
136 | ||
137 | ||
138 | ||
139 | /* Main-Loop */ | |
140 | while(data_left){ | |
141 | while(data_left-3 && isspace(ptr[0])) ptr++; | |
142 | ||
143 | /* Determine command */ | |
144 | command=0; | |
145 | if (comp(&ptr, "SC")) command=CMD_SC; | |
146 | if (comp(&ptr, "PU")) command=CMD_PU; | |
147 | if (comp(&ptr, "PD")) command=CMD_PD; | |
148 | if (comp(&ptr, "LB")) command=CMD_LB; | |
149 | if (comp(&ptr, "DI")) command=CMD_DI; | |
150 | if (comp(&ptr, "SP")) command=CMD_SP; | |
151 | if (comp(&ptr, "PA")) command=CMD_PA; | |
152 | if (comp(&ptr, "PR")) command=CMD_PR; | |
153 | if (comp(&ptr, "IN")) command=CMD_IN; | |
154 | if (command==0) {data_left-- ; ptr++;} | |
155 | else DBG("Command: %i %c%c\n",command,ptr[-2],ptr[-1]); | |
156 | ||
157 | int process_points=0; | |
158 | switch(command){ | |
159 | ||
160 | case CMD_NO_COMMAND: | |
161 | break; | |
162 | case CMD_PU: /* Pen up - not much to do here. */ | |
163 | pen_state=up; | |
164 | in_path=0; | |
165 | process_points=1; | |
166 | break; | |
167 | ||
168 | case CMD_PD: | |
169 | pen_state=down; | |
170 | if (!in_path){ /* Create and store a new path object with first point @pen_pos. */ | |
171 | ||
172 | struct point * new_point=(struct point *)malloc(sizeof(struct point)); | |
173 | new_point->x=pen_pos.x; | |
174 | new_point->y=pen_pos.y; | |
175 | new_point->next=NULL; | |
176 | new_point->previous_in_path=NULL; | |
177 | new_point->valid=1; | |
178 | ||
179 | struct path * new_path=(struct path *)malloc(sizeof(struct path)); | |
180 | new_path->next=NULL; /* This is the last in the chain. */ | |
181 | new_path->first_point=new_point; | |
182 | new_path->last_point=new_point; | |
183 | new_path->plot_start_point=new_path->first_point; | |
184 | ||
185 | if (first_path==NULL){ /* This is the first path */ | |
186 | first_path=new_path; | |
187 | } else { | |
188 | current_path->next=new_path; /* Append to linked list */ | |
189 | } | |
190 | current_path=new_path; /* Update pointer to current path. */ | |
191 | in_path=1; /* We're in a path now, fine! */ | |
192 | } | |
193 | process_points=1; | |
194 | break; | |
195 | ||
196 | case CMD_SC: | |
197 | break; | |
198 | ||
199 | case CMD_IN: | |
200 | plot_mode=absolute; | |
201 | pen_pos.x=0; | |
202 | pen_pos.y=0; | |
203 | pen_pos.valid=1; | |
a6a4e5d4 PH |
204 | pen_state=up; |
205 | break; | |
206 | ||
207 | case CMD_LB: | |
208 | break; | |
209 | case CMD_DI: /* Character direction */ | |
210 | break; | |
211 | case CMD_SI: /* Character size */ | |
212 | break; | |
213 | case CMD_SP: /* Select pen */ | |
214 | break; | |
215 | case CMD_PA: | |
216 | process_points=1; | |
217 | plot_mode=absolute; | |
218 | break; | |
219 | case CMD_PR: | |
220 | process_points=1; | |
221 | plot_mode=relative; | |
222 | break; | |
223 | } | |
224 | ||
225 | if (process_points) { /* Process point arguments */ | |
226 | struct point * new_point; | |
227 | do{ | |
228 | new_point=get_point(&ptr); | |
229 | ||
230 | if (new_point->valid) { /* The following only works if we got a good point! */ | |
231 | ||
232 | /* Scale: Plot in cm!! */ | |
233 | new_point->x = new_point->x / 500; | |
234 | new_point->y = new_point->y / 500; | |
235 | ||
236 | DBG("Found point: %6.2f,%6.2f\n",new_point->x,new_point->y); | |
237 | ||
238 | /* Convert relative coordinates to absolute coordinates if needed */ | |
239 | if (plot_mode==relative){ | |
240 | DBG("Relative -> absolute coordinate calculation!\n"); | |
241 | new_point->x += pen_pos.x; | |
242 | new_point->y += pen_pos.y; | |
243 | } | |
244 | ||
245 | if (pen_state==down) { /* We're in a path, so add the point to current path */ | |
246 | current_path->last_point->next=new_point; /* Add to the end of list */ | |
247 | new_point->previous_in_path=current_path->last_point; /* Backwards reference */ | |
248 | current_path->last_point=new_point; /* Fix the point */ | |
249 | } | |
250 | pen_pos.x=new_point->x; | |
251 | pen_pos.y=new_point->y; | |
252 | ||
253 | } | |
254 | } while (new_point->valid); | |
255 | } | |
256 | ||
257 | } /* while(data_left) */ | |
258 | ||
259 | struct path * output_paths; | |
260 | ||
261 | round_path(first_path); | |
262 | ||
263 | /* output_paths = optimize(first_path); */ | |
264 | output_paths=optimize(split_paths(first_path)); | |
265 | output(output_paths); | |
266 | DBG("Programmende\n"); | |
267 | return 0; | |
268 | } |