Initial commit
[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 double character_angle=0;
118 double character_size=40;
119
120 struct path * first_path=NULL;
121 struct path * current_path=NULL;
122
123 int in_path=0;
124
125 enum hpgl_cmd_t command; /* Current command being processed */
126
127 DBG("Start\n");
128
129 /* Open input file to read if specified. */
130 if (argc>1){
131 fd=open(args[1],O_RDONLY);
132 if (fd < 0){
133 ERR("Could not open file: \"%s\"\n",args[1]);
134 exit (-2);
135 }
136 }
137 /* fd=open("haus.hpl",O_RDONLY); */
138 read_file(fd);
139
140
141
142 /* Main-Loop */
143 while(data_left){
144 while(data_left-3 && isspace(ptr[0])) ptr++;
145
146 /* Determine command */
147 command=0;
148 if (comp(&ptr, "SC")) command=CMD_SC;
149 if (comp(&ptr, "PU")) command=CMD_PU;
150 if (comp(&ptr, "PD")) command=CMD_PD;
151 if (comp(&ptr, "LB")) command=CMD_LB;
152 if (comp(&ptr, "DI")) command=CMD_DI;
153 if (comp(&ptr, "SP")) command=CMD_SP;
154 if (comp(&ptr, "PA")) command=CMD_PA;
155 if (comp(&ptr, "PR")) command=CMD_PR;
156 if (comp(&ptr, "IN")) command=CMD_IN;
157 if (command==0) {data_left-- ; ptr++;}
158 else DBG("Command: %i %c%c\n",command,ptr[-2],ptr[-1]);
159
160 int process_points=0;
161 switch(command){
162
163 case CMD_NO_COMMAND:
164 break;
165 case CMD_PU: /* Pen up - not much to do here. */
166 pen_state=up;
167 in_path=0;
168 process_points=1;
169 break;
170
171 case CMD_PD:
172 pen_state=down;
173 if (!in_path){ /* Create and store a new path object with first point @pen_pos. */
174
175 struct point * new_point=(struct point *)malloc(sizeof(struct point));
176 new_point->x=pen_pos.x;
177 new_point->y=pen_pos.y;
178 new_point->next=NULL;
179 new_point->previous_in_path=NULL;
180 new_point->valid=1;
181
182 struct path * new_path=(struct path *)malloc(sizeof(struct path));
183 new_path->next=NULL; /* This is the last in the chain. */
184 new_path->first_point=new_point;
185 new_path->last_point=new_point;
186 new_path->plot_start_point=new_path->first_point;
187
188 if (first_path==NULL){ /* This is the first path */
189 first_path=new_path;
190 } else {
191 current_path->next=new_path; /* Append to linked list */
192 }
193 current_path=new_path; /* Update pointer to current path. */
194 in_path=1; /* We're in a path now, fine! */
195 }
196 process_points=1;
197 break;
198
199 case CMD_SC:
200 break;
201
202 case CMD_IN:
203 plot_mode=absolute;
204 pen_pos.x=0;
205 pen_pos.y=0;
206 pen_pos.valid=1;
207 character_angle=0;
208 character_size=40;
209 pen_state=up;
210 break;
211
212 case CMD_LB:
213 break;
214 case CMD_DI: /* Character direction */
215 break;
216 case CMD_SI: /* Character size */
217 break;
218 case CMD_SP: /* Select pen */
219 break;
220 case CMD_PA:
221 process_points=1;
222 plot_mode=absolute;
223 break;
224 case CMD_PR:
225 process_points=1;
226 plot_mode=relative;
227 break;
228 }
229
230 if (process_points) { /* Process point arguments */
231 struct point * new_point;
232 do{
233 new_point=get_point(&ptr);
234
235 if (new_point->valid) { /* The following only works if we got a good point! */
236
237 /* Scale: Plot in cm!! */
238 new_point->x = new_point->x / 500;
239 new_point->y = new_point->y / 500;
240
241 DBG("Found point: %6.2f,%6.2f\n",new_point->x,new_point->y);
242
243 /* Convert relative coordinates to absolute coordinates if needed */
244 if (plot_mode==relative){
245 DBG("Relative -> absolute coordinate calculation!\n");
246 new_point->x += pen_pos.x;
247 new_point->y += pen_pos.y;
248 }
249
250 if (pen_state==down) { /* We're in a path, so add the point to current path */
251 current_path->last_point->next=new_point; /* Add to the end of list */
252 new_point->previous_in_path=current_path->last_point; /* Backwards reference */
253 current_path->last_point=new_point; /* Fix the point */
254 }
255 pen_pos.x=new_point->x;
256 pen_pos.y=new_point->y;
257
258 }
259 } while (new_point->valid);
260 }
261
262 } /* while(data_left) */
263
264 struct path * output_paths;
265
266 round_path(first_path);
267
268 /* output_paths = optimize(first_path); */
269 output_paths=optimize(split_paths(first_path));
270 output(output_paths);
271 DBG("Programmende\n");
272 return 0;
273 }