plot_hpgl: Cosmetic improvements
[pdp8.git] / sw / plot_hpgl / pc / hpgl.c
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
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;
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 }