2 * gEDA - GNU Electronic Design Automation
3 * This is a part of gerbv
5 * Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
26 #include <math.h> /* pow() */
30 #include "gerb_error.h"
32 #define NOT_IMPL(fd, s) do { \
33 GERB_MESSAGE("Not Implemented:%s\n", s); \
34 while (gerb_fgetc(fd) != (int)'*'); \
38 #define A2I(a,b) (((a & 0xff) << 8) + (b & 0xff))
40 typedef struct gerb_state
{
50 enum polarity_t layer_polarity
;
51 enum aperture_state_t aperture_state
;
52 enum interpolation_t interpolation
;
53 enum interpolation_t prev_interpolation
;
54 gerb_net_t
*parea_start_node
;
61 /* Local function prototypes */
62 static void parse_G_code(gerb_file_t
*fd
, gerb_state_t
*state
,
63 gerb_format_t
*format
);
64 static void parse_D_code(gerb_file_t
*fd
, gerb_state_t
*state
);
65 static int parse_M_code(gerb_file_t
*fd
);
66 static void parse_rs274x(gerb_file_t
*fd
, gerb_image_t
*image
,
68 static int parse_aperture_definition(gerb_file_t
*fd
,
69 gerb_aperture_t
*aperture
,
71 static void calc_cirseg_sq(struct gerb_net
*net
, int cw
,
72 double delta_cp_x
, double delta_cp_y
);
73 static void calc_cirseg_mq(struct gerb_net
*net
, int cw
,
74 double delta_cp_x
, double delta_cp_y
);
78 parse_gerb(gerb_file_t
*fd
)
80 gerb_state_t
*state
= NULL
;
81 gerb_image_t
*image
= NULL
;
82 gerb_net_t
*curr_net
= NULL
;
84 double x_scale
= 0.0, y_scale
= 0.0;
85 double delta_cp_x
= 0.0, delta_cp_y
= 0.0;
89 state
= (gerb_state_t
*)malloc(sizeof(gerb_state_t
));
91 GERB_FATAL_ERROR("malloc state failed\n");
96 memset((void *)state
, 0, sizeof(gerb_state_t
));
97 state
->layer_polarity
= DARK
;
99 * "Inches are assumed if units are not specified"
100 * rs274xrevd_e.pdf, p. 39
107 image
= new_gerb_image(image
);
109 GERB_FATAL_ERROR("malloc image failed\n");
110 curr_net
= image
->netlist
;
115 while ((read
= gerb_fgetc(fd
)) != EOF
) {
116 switch ((char)(read
& 0xff)) {
118 parse_G_code(fd
, state
, image
->format
);
121 parse_D_code(fd
, state
);
124 switch(parse_M_code(fd
)) {
132 GERB_FATAL_ERROR("Strange M code found.\n");
136 if (image
->format
->coordinate
==INCREMENTAL
)
137 state
->curr_x
+= gerb_fgetint(fd
);
139 state
->curr_x
= gerb_fgetint(fd
);
143 if (image
->format
->coordinate
==INCREMENTAL
)
144 state
->curr_y
+= gerb_fgetint(fd
);
146 state
->curr_y
= gerb_fgetint(fd
);
150 state
->delta_cp_x
= gerb_fgetint(fd
);
154 state
->delta_cp_y
= gerb_fgetint(fd
);
158 parse_rs274x(fd
, image
, state
);
159 while (gerb_fgetc(fd
) != '%');
162 if (state
->changed
== 0) break;
165 curr_net
->next
= (gerb_net_t
*)malloc(sizeof(gerb_net_t
));
166 curr_net
= curr_net
->next
;
167 memset((void *)curr_net
, 0, sizeof(gerb_net_t
));
170 * Scale to given coordinate format
171 * XXX only "omit leading zeros".
173 if (image
&& image
->format
){
174 x_scale
= pow(10.0, (double)image
->format
->x_dec
);
175 y_scale
= pow(10.0, (double)image
->format
->y_dec
);
178 curr_net
->start_x
= (double)state
->prev_x
/ x_scale
;
179 curr_net
->start_y
= (double)state
->prev_y
/ y_scale
;
180 curr_net
->stop_x
= (double)state
->curr_x
/ x_scale
;
181 curr_net
->stop_y
= (double)state
->curr_y
/ y_scale
;
182 delta_cp_x
= (double)state
->delta_cp_x
/ x_scale
;
183 delta_cp_y
= (double)state
->delta_cp_y
/ y_scale
;
186 switch (state
->interpolation
) {
188 curr_net
->cirseg
= (gerb_cirseg_t
*)malloc(sizeof(gerb_cirseg_t
));
189 memset((void *)curr_net
->cirseg
, 0, sizeof(gerb_cirseg_t
));
191 calc_cirseg_mq(curr_net
, 1, delta_cp_x
, delta_cp_y
);
193 calc_cirseg_sq(curr_net
, 1, delta_cp_x
, delta_cp_y
);
196 curr_net
->cirseg
= (gerb_cirseg_t
*)malloc(sizeof(gerb_cirseg_t
));
197 memset((void *)curr_net
->cirseg
, 0, sizeof(gerb_cirseg_t
));
199 calc_cirseg_mq(curr_net
, 0, delta_cp_x
, delta_cp_y
);
201 calc_cirseg_sq(curr_net
, 0, delta_cp_x
, delta_cp_y
);
205 * To be able to get back and fill in number of polygon corners
207 state
->parea_start_node
= curr_net
;
208 state
->in_parea_fill
= 1;
211 state
->parea_start_node
= NULL
;
212 state
->in_parea_fill
= 0;
219 * Count number of points in Polygon Area
221 if (state
->in_parea_fill
&& state
->parea_start_node
)
222 state
->parea_start_node
->nuf_pcorners
++;
224 curr_net
->interpolation
= state
->interpolation
;
227 * If we detected the end of Polygon Area Fill we go back to
228 * the interpolation we had before that.
229 * Also if we detected any of the quadrant flags, since some
230 * gerbers don't reset the interpolation (EagleCad again).
232 if ((state
->interpolation
== PAREA_START
) ||
233 (state
->interpolation
== PAREA_END
) ||
234 (state
->interpolation
== MQ_START
) ||
235 (state
->interpolation
== MQ_END
))
236 state
->interpolation
= state
->prev_interpolation
;
239 * Save layer polarity and unit
241 curr_net
->layer_polarity
= state
->layer_polarity
;
242 curr_net
->unit
= state
->unit
;
244 state
->delta_cp_x
= 0.0;
245 state
->delta_cp_y
= 0.0;
246 curr_net
->aperture
= state
->curr_aperture
;
247 curr_net
->aperture_state
= state
->aperture_state
;
250 * Make sure we don't hit any undefined aperture
251 * In macros the first parameter could be basically anything
253 if ((curr_net
->aperture
!= 0) &&
254 (image
->aperture
[curr_net
->aperture
] != NULL
) &&
255 (image
->aperture
[curr_net
->aperture
]->type
!= MACRO
))
256 aperture_size
= image
->aperture
[curr_net
->aperture
]->parameter
[0];
261 * Find min and max of image with compensation for mm.
263 if (curr_net
->unit
== MM
)
267 if (image
->info
->min_x
> curr_net
->stop_x
)
268 image
->info
->min_x
= (curr_net
->stop_x
- aperture_size
) / scale
;
269 if (image
->info
->min_y
> curr_net
->stop_y
)
270 image
->info
->min_y
= (curr_net
->stop_y
- aperture_size
) / scale
;
271 if (image
->info
->max_x
< curr_net
->stop_x
)
272 image
->info
->max_x
= (curr_net
->stop_x
+ aperture_size
) / scale
;
273 if (image
->info
->max_y
< curr_net
->stop_y
)
274 image
->info
->max_y
= (curr_net
->stop_y
+ aperture_size
) / scale
;
276 state
->prev_x
= state
->curr_x
;
277 state
->prev_y
= state
->curr_y
;
280 case 10 : /* White space */
286 GERB_COMPILE_ERROR("Found unknown character (whitespace?) %c[%d]\n", read
, read
);
290 GERB_COMPILE_ERROR("File is missing gerber End-Of-File\n");
297 parse_G_code(gerb_file_t
*fd
, gerb_state_t
*state
, gerb_format_t
*format
)
302 op
[0] = gerb_fgetc(fd
);
303 op
[1] = gerb_fgetc(fd
);
305 if ((op
[0] == EOF
) || (op
[1] == EOF
))
306 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
308 if ((op
[0] < (int)'0') || (op
[0] > (int)'9') ||
309 (op
[1] < (int)'0') || (op
[1] > (int)'9'))
310 GERB_COMPILE_ERROR("Non numerical G opcode found [%c%c]\n", op
[0], op
[1]);
312 op_int
= (op
[0] - (int)'0');
313 op_int
= op_int
* 10 + (op
[1] - (int)'0');
317 /* Is this doing anything really? */
319 case 1: /* Linear Interpolation (1X scale) */
320 state
->interpolation
= LINEARx1
;
322 case 2: /* Clockwise Linear Interpolation */
323 state
->interpolation
= CW_CIRCULAR
;
325 case 3: /* Counter Clockwise Linear Interpolation */
326 state
->interpolation
= CCW_CIRCULAR
;
328 case 4: /* Ignore Data Block */
329 /* Don't do anything, just read 'til * */
330 while (gerb_fgetc(fd
) != '*');
332 case 10: /* Linear Interpolation (10X scale) */
333 state
->interpolation
= LINEARx10
;
335 case 11: /* Linear Interpolation (0.1X scale) */
336 state
->interpolation
= LINEARx01
;
338 case 12: /* Linear Interpolation (0.01X scale) */
339 state
->interpolation
= LINEARx001
;
341 case 36: /* Turn on Polygon Area Fill */
342 state
->prev_interpolation
= state
->interpolation
;
343 state
->interpolation
= PAREA_START
;
346 case 37: /* Turn off Polygon Area Fill */
347 state
->interpolation
= PAREA_END
;
350 case 54: /* Tool prepare */
351 /* XXX Maybe uneccesary??? */
352 if (gerb_fgetc(fd
) == 'D')
353 state
->curr_aperture
= gerb_fgetint(fd
);
355 GERB_COMPILE_WARNING("Strange code after G54\n");
357 case 55: /* Prepare for flash */
359 case 70: /* Specify inches */
362 case 71: /* Specify millimeters */
365 case 74: /* Disable 360 circular interpolation */
366 state
->prev_interpolation
= state
->interpolation
;
367 state
->interpolation
= MQ_END
;
370 case 75: /* Enable 360 circular interpolation */
371 state
->prev_interpolation
= state
->interpolation
;
372 state
->interpolation
= MQ_START
;
375 case 90: /* Specify absolut format */
376 if (format
) format
->coordinate
= ABSOLUTE
;
378 case 91: /* Specify incremental format */
379 if (format
) format
->coordinate
= INCREMENTAL
;
382 GERB_COMPILE_ERROR("Strange/unhandled G code : %c%c\n", op
[0], op
[1]);
390 parse_D_code(gerb_file_t
*fd
, gerb_state_t
*state
)
394 a
= gerb_fgetint(fd
);
396 case 1 : /* Exposure on */
397 state
->aperture_state
= ON
;
400 case 2 : /* Exposure off */
401 state
->aperture_state
= OFF
;
404 case 3 : /* Flash aperture */
405 state
->aperture_state
= FLASH
;
408 default: /* Aperture in use */
409 if ((a
>= APERTURE_MIN
) && (a
<= APERTURE_MAX
))
410 state
->curr_aperture
= a
;
412 GERB_COMPILE_ERROR("Aperture out of bounds:%d\n", a
);
421 parse_M_code(gerb_file_t
*fd
)
425 op
[0] = gerb_fgetc(fd
);
426 op
[1] = gerb_fgetc(fd
);
428 if ((op
[0] == EOF
) || (op
[1] == EOF
))
429 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
431 if (op
[0] != (int)'0')
432 GERB_COMPILE_ERROR("Strange M code [%c%c]\n", (char)op
[0], (char)op
[1]);
435 case '0': /* Program stop */
437 case '1': /* Optional stop */
439 case '2': /* End of program */
442 GERB_COMPILE_ERROR("Strange M code [%c%c]\n", (char)op
[0], (char)op
[1]);
449 parse_rs274x(gerb_file_t
*fd
, gerb_image_t
*image
, gerb_state_t
*state
)
454 gerb_aperture_t
*a
= NULL
;
455 amacro_t
*tmp_amacro
;
458 op
[0] = gerb_fgetc(fd
);
459 op
[1] = gerb_fgetc(fd
);
461 if ((op
[0] == EOF
) || (op
[1] == EOF
))
462 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
464 switch (A2I(op
[0], op
[1])){
466 /* Directive parameters */
467 case A2I('A','S'): /* Axis Select */
468 op
[0] = gerb_fgetc(fd
);
469 op
[1] = gerb_fgetc(fd
);
471 if ((op
[0] == EOF
) || (op
[1] == EOF
))
472 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
474 if (((op
[0] == 'A') && (op
[1] == 'Y')) ||
475 ((op
[0] == 'B') && (op
[1] == 'X'))) {
476 NOT_IMPL(fd
, "%MI with reversed axis not supported%");
480 op
[0] = gerb_fgetc(fd
);
481 op
[1] = gerb_fgetc(fd
);
483 if ((op
[0] == EOF
) || (op
[1] == EOF
))
484 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
486 if (((op
[0] == 'A') && (op
[1] == 'Y')) ||
487 ((op
[0] == 'B') && (op
[1] == 'X'))) {
488 NOT_IMPL(fd
, "%MI with reversed axis not supported%");
492 case A2I('F','S'): /* Format Statement */
493 image
->format
= (gerb_format_t
*)malloc(sizeof(gerb_format_t
));
494 if (image
->format
== NULL
)
495 GERB_FATAL_ERROR("Failed malloc for format\n");
496 memset((void *)image
->format
, 0, sizeof(gerb_format_t
));
498 switch (gerb_fgetc(fd
)) {
500 image
->format
->omit_zeros
= LEADING
;
503 image
->format
->omit_zeros
= TRAILING
;
506 image
->format
->omit_zeros
= EXPLICIT
;
509 GERB_MESSAGE("EagleCad bug detected: Defaults to omit leading zeroes\n");
511 image
->format
->omit_zeros
= LEADING
;
514 switch (gerb_fgetc(fd
)) {
516 image
->format
->coordinate
= ABSOLUTE
;
519 image
->format
->coordinate
= INCREMENTAL
;
522 GERB_COMPILE_ERROR("Format error: coordinate = %c\n", op
[0]);
525 while((op
[0] = gerb_fgetc(fd
)) != '*') {
528 op
[0] = (char)gerb_fgetc(fd
);
529 image
->format
->lim_seqno
= op
[0] - '0';
532 op
[0] = (char)gerb_fgetc(fd
);
533 image
->format
->lim_gf
= op
[0] - '0';
536 op
[0] = (char)gerb_fgetc(fd
);
537 image
->format
->lim_pf
= op
[0] - '0';
540 op
[0] = (char)gerb_fgetc(fd
);
541 image
->format
->lim_mf
= op
[0] - '0';
544 op
[0] = gerb_fgetc(fd
);
545 if ((op
[0] < '0') || (op
[0] > '6'))
546 GERB_COMPILE_ERROR("Illegal format size : %c\n", (char)op
[0]);
547 image
->format
->x_int
= op
[0] - '0';
548 op
[0] = gerb_fgetc(fd
);
549 if ((op
[0] < '0') || (op
[0] > '6'))
550 GERB_COMPILE_ERROR("Illegal format size : %c\n", (char)op
[0]);
551 image
->format
->x_dec
= op
[0] - '0';
554 op
[0] = gerb_fgetc(fd
);
555 if ((op
[0] < '0') || (op
[0] > '6'))
556 GERB_COMPILE_ERROR("Illegal format size : %c\n", (char)op
[0]);
557 image
->format
->y_int
= op
[0] - '0';
558 op
[0] = gerb_fgetc(fd
);
559 if ((op
[0] < '0') || (op
[0] > '6'))
560 GERB_COMPILE_ERROR("Illegal format size : %c\n", (char)op
[0]);
561 image
->format
->y_dec
= op
[0] - '0';
564 GERB_COMPILE_ERROR("Not handled type of format statement [%c]\n", op
[0]);
568 case A2I('M','I'): /* Mirror Image */
569 NOT_IMPL(fd
, "%MI%");
571 case A2I('M','O'): /* Mode of Units */
573 op
[0] = gerb_fgetc(fd
);
574 op
[1] = gerb_fgetc(fd
);
576 if ((op
[0] == EOF
) || (op
[1] == EOF
))
577 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
579 switch (A2I(op
[0],op
[1])) {
587 GERB_COMPILE_ERROR("Illegal unit:%c%c\n", op
[0], op
[1]);
590 case A2I('O','F'): /* Offset */
591 op
[0] = gerb_fgetc(fd
);
592 while (op
[0] != '*') {
595 image
->info
->offset_a
= gerb_fgetdouble(fd
);
598 image
->info
->offset_b
= gerb_fgetdouble(fd
);
601 GERB_COMPILE_ERROR("Wrong character in offset:%c\n", op
[0]);
603 op
[0] = gerb_fgetc(fd
);
606 case A2I('S','F'): /* Scale Factor */
607 if (gerb_fgetc(fd
) == 'A')
608 image
->info
->scale_factor_A
= gerb_fgetdouble(fd
);
611 if (gerb_fgetc(fd
) == 'B')
612 image
->info
->scale_factor_B
= gerb_fgetdouble(fd
);
615 if ((fabs(image
->info
->scale_factor_A
- 1.0) > 0.00001) ||
616 (fabs(image
->info
->scale_factor_B
- 1.0) > 0.00001))
617 NOT_IMPL(fd
, "%SF% != 1.0");
619 case A2I('I','C'): /* Input Code */
620 /* Thanks to Stephen Adam for providing this information. As he writes:
621 * btw, here's a logic puzzle for you. If you need to
622 * read the gerber file to see how it's encoded, then
623 * how can you read it?
625 op
[0] = gerb_fgetc(fd
);
626 op
[1] = gerb_fgetc(fd
);
628 if ((op
[0] == EOF
) || (op
[1] == EOF
))
629 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
631 switch (A2I(op
[0],op
[1])) {
633 image
->info
->encoding
= ASCII
;
636 image
->info
->encoding
= EBCDIC
;
639 image
->info
->encoding
= BCD
;
642 image
->info
->encoding
= ISO_ASCII
;
645 image
->info
->encoding
= EIA
;
648 GERB_COMPILE_ERROR("Strange inputcode : %c%c\n", op
[0], op
[1]);
652 /* Image parameters */
653 case A2I('I','J'): /* Image Justify */
654 NOT_IMPL(fd
, "%IJ%");
656 case A2I('I','N'): /* Image Name */
657 image
->info
->name
= gerb_fgetstring(fd
, '*');
659 case A2I('I','O'): /* Image Offset */
660 NOT_IMPL(fd
, "%IO%");
662 case A2I('I','P'): /* Image Polarity */
664 for (ano
= 0; ano
< 3; ano
++) {
665 op
[0] = gerb_fgetc(fd
);
667 GERB_COMPILE_ERROR("Unexpected EOF found.\n");
668 str
[ano
] = (char)op
[0];
671 if (strncmp(str
, "POS", 3) == 0)
672 image
->info
->polarity
= POSITIVE
;
673 else if (strncmp(str
, "NEG", 3) == 0)
674 image
->info
->polarity
= NEGATIVE
;
676 GERB_COMPILE_ERROR("Strange polarity : %c%c%c\n", str
[0], str
[1], str
[2]);
679 case A2I('I','R'): /* Image Rotation */
680 tmp
= gerb_fgetint(fd
);
682 NOT_IMPL(fd
, "%IR%");
684 case A2I('P','F'): /* Plotter Film */
685 NOT_IMPL(fd
, "%PF%");
688 /* Aperture parameters */
689 case A2I('A','D'): /* Aperture Description */
690 a
= (gerb_aperture_t
*)malloc(sizeof(gerb_aperture_t
));
691 memset((void *)a
, 0, sizeof(gerb_aperture_t
));
692 ano
= parse_aperture_definition(fd
, a
, image
->amacro
);
693 if ((ano
>= APERTURE_MIN
) && (ano
<= APERTURE_MAX
)) {
694 a
->unit
= state
->unit
;
695 image
->aperture
[ano
] = a
;
697 GERB_COMPILE_ERROR("Aperture number out of bounds : %d\n", ano
);
699 case A2I('A','M'): /* Aperture Macro */
700 tmp_amacro
= image
->amacro
;
701 image
->amacro
= parse_aperture_macro(fd
);
702 image
->amacro
->next
= tmp_amacro
;
704 print_program(image
->amacro
);
709 case A2I('L','N'): /* Layer Name */
710 state
->curr_layername
= gerb_fgetstring(fd
, '*');
712 case A2I('L','P'): /* Layer Polarity */
713 switch (gerb_fgetc(fd
)) {
714 case 'D': /* Dark Polarity (default) */
715 state
->layer_polarity
= DARK
;
717 case 'C': /* Clear Polarity */
718 state
->layer_polarity
= CLEAR
;
721 GERB_COMPILE_WARNING("Strange Layer Polarity: %c\n", op
[0]);
724 case A2I('K','O'): /* Knock Out */
725 NOT_IMPL(fd
, "%KO%");
727 case A2I('S','R'): /* Step and Repeat */
728 op
[0] = gerb_fgetc(fd
);
729 if (op
[0] == '*') { /* Disable previous SR parameters */
730 image
->info
->step_and_repeat
.X
= 1;
731 image
->info
->step_and_repeat
.Y
= 1;
732 image
->info
->step_and_repeat
.dist_X
= 0.0;
733 image
->info
->step_and_repeat
.dist_Y
= 0.0;
736 while (op
[0] != '*') {
739 image
->info
->step_and_repeat
.X
= gerb_fgetint(fd
);
742 image
->info
->step_and_repeat
.Y
= gerb_fgetint(fd
);
745 image
->info
->step_and_repeat
.dist_X
= gerb_fgetdouble(fd
);
748 image
->info
->step_and_repeat
.dist_Y
= gerb_fgetdouble(fd
);
751 GERB_COMPILE_ERROR("Step-and-repeat parameter error\n");
753 op
[0] = gerb_fgetc(fd
);
755 if ((image
->info
->step_and_repeat
.X
!= 1) ||
756 (image
->info
->step_and_repeat
.Y
!= 1) ||
757 (fabs(image
->info
->step_and_repeat
.dist_X
) > 0.000001) ||
758 (fabs(image
->info
->step_and_repeat
.dist_Y
) > 0.000001))
759 NOT_IMPL(fd
, "%SR%");
761 case A2I('R','O'): /* Rotate */
762 NOT_IMPL(fd
, "%RO%");
765 GERB_COMPILE_ERROR("Unknown extension found %%%c%c%%\n", op
[0], op
[1]);
773 parse_aperture_definition(gerb_file_t
*fd
, gerb_aperture_t
*aperture
,
779 amacro_t
*curr_amacro
;
781 if (gerb_fgetc(fd
) != 'D')
787 ano
= gerb_fgetint(fd
);
790 * Read in the whole aperture defintion and tokenize it
792 ad
= gerb_fgetstring(fd
, '*');
793 token
= strtok(ad
, ",");
795 if (strlen(token
) == 1) {
798 aperture
->type
= CIRCLE
;
801 aperture
->type
= RECTANGLE
;
804 aperture
->type
= OVAL
;
807 aperture
->type
= POLYGON
;
810 /* Here a should a T be defined, but I don't know what it represents */
812 aperture
->type
= MACRO
;
814 * In aperture definition, point to the aperture macro
815 * used in the defintion
817 curr_amacro
= amacro
;
818 while (curr_amacro
) {
819 if ((strlen(curr_amacro
->name
) == strlen(token
)) &&
820 (strcmp(curr_amacro
->name
, token
) == 0)) {
821 aperture
->amacro
= curr_amacro
;
824 curr_amacro
= curr_amacro
->next
;
829 * Parse all parameters
831 for (token
= strtok(NULL
, "X"), i
= 0; token
!= NULL
;
832 token
= strtok(NULL
, "X"), i
++)
833 aperture
->parameter
[i
] = strtod(token
, NULL
);
835 aperture
->nuf_parameters
= i
;
842 } /* parse_aperture_definition */
846 calc_cirseg_sq(struct gerb_net
*net
, int cw
,
847 double delta_cp_x
, double delta_cp_y
)
849 double d1x
, d1y
, d2x
, d2y
;
855 * Quadrant detection (based on ccw, coverted below if cw)
861 if (net
->start_x
> net
->stop_x
)
862 /* 1st and 2nd quadrant */
863 if (net
->start_y
< net
->stop_y
)
868 /* 3rd and 4th quadrant */
869 if (net
->start_y
> net
->stop_y
)
875 * If clockwise, rotate quadrant
892 GERB_COMPILE_ERROR("Unknow quadrant value while converting to cw\n");
897 * Calculate arc center point
901 net
->cirseg
->cp_x
= net
->start_x
- delta_cp_x
;
902 net
->cirseg
->cp_y
= net
->start_y
- delta_cp_y
;
905 net
->cirseg
->cp_x
= net
->start_x
+ delta_cp_x
;
906 net
->cirseg
->cp_y
= net
->start_y
- delta_cp_y
;
909 net
->cirseg
->cp_x
= net
->start_x
+ delta_cp_x
;
910 net
->cirseg
->cp_y
= net
->start_y
+ delta_cp_y
;
913 net
->cirseg
->cp_x
= net
->start_x
- delta_cp_x
;
914 net
->cirseg
->cp_y
= net
->start_y
+ delta_cp_y
;
917 GERB_COMPILE_ERROR("Strange quadrant : %d\n", quadrant
);
923 d1x
= fabs(net
->start_x
- net
->cirseg
->cp_x
);
924 d1y
= fabs(net
->start_y
- net
->cirseg
->cp_y
);
925 d2x
= fabs(net
->stop_x
- net
->cirseg
->cp_x
);
926 d2y
= fabs(net
->stop_y
- net
->cirseg
->cp_y
);
928 alfa
= atan2(d1y
, d1x
);
929 beta
= atan2(d2y
, d2x
);
932 * Avoid divide by zero when sin(0) = 0 and cos(90) = 0
934 net
->cirseg
->width
= alfa
< beta
?
935 2 * (d1x
/ cos(alfa
)) : 2 * (d2x
/ cos(beta
));
936 net
->cirseg
->height
= alfa
> beta
?
937 2 * (d1y
/ sin(alfa
)) : 2 * (d2y
/ sin(beta
));
939 if (alfa
< 0.000001 && beta
< 0.000001) {
940 net
->cirseg
->height
= 0;
943 #define RAD2DEG(a) (a * 180 / M_PI)
947 net
->cirseg
->angle1
= RAD2DEG(alfa
);
948 net
->cirseg
->angle2
= RAD2DEG(beta
);
951 net
->cirseg
->angle1
= 180.0 - RAD2DEG(alfa
);
952 net
->cirseg
->angle2
= 180.0 - RAD2DEG(beta
);
955 net
->cirseg
->angle1
= 180.0 + RAD2DEG(alfa
);
956 net
->cirseg
->angle2
= 180.0 + RAD2DEG(beta
);
959 net
->cirseg
->angle1
= 360.0 - RAD2DEG(alfa
);
960 net
->cirseg
->angle2
= 360.0 - RAD2DEG(beta
);
963 GERB_COMPILE_ERROR("Strange quadrant : %d\n", quadrant
);
966 if (net
->cirseg
->width
< 0.0)
967 GERB_COMPILE_WARNING("Negative width [%f] in quadrant %d [%f][%f]\n",
968 net
->cirseg
->width
, quadrant
, alfa
, beta
);
970 if (net
->cirseg
->height
< 0.0)
971 GERB_COMPILE_WARNING("Negative height [%f] in quadrant %d [%f][%f]\n",
972 net
->cirseg
->height
, quadrant
, RAD2DEG(alfa
), RAD2DEG(beta
));
976 } /* calc_cirseg_sq */
980 calc_cirseg_mq(struct gerb_net
*net
, int cw
,
981 double delta_cp_x
, double delta_cp_y
)
983 double d1x
, d1y
, d2x
, d2y
;
986 net
->cirseg
->cp_x
= net
->start_x
+ delta_cp_x
;
987 net
->cirseg
->cp_y
= net
->start_y
+ delta_cp_y
;
992 d1x
= net
->start_x
- net
->cirseg
->cp_x
;
993 d1y
= net
->start_y
- net
->cirseg
->cp_y
;
994 d2x
= net
->stop_x
- net
->cirseg
->cp_x
;
995 d2y
= net
->stop_y
- net
->cirseg
->cp_y
;
997 alfa
= atan2(d1y
, d1x
);
998 beta
= atan2(d2y
, d2x
);
1000 net
->cirseg
->width
= sqrt(delta_cp_x
*delta_cp_x
+ delta_cp_y
*delta_cp_y
);
1001 net
->cirseg
->width
*= 2.0;
1002 net
->cirseg
->height
= net
->cirseg
->width
;
1004 net
->cirseg
->angle1
= RAD2DEG(alfa
);
1005 net
->cirseg
->angle2
= RAD2DEG(beta
);
1008 * Make sure it's always positive angles
1010 if (net
->cirseg
->angle1
< 0) {
1011 net
->cirseg
->angle1
+= 360.0;
1012 net
->cirseg
->angle2
+= 360.0;
1015 if (net
->cirseg
->angle2
< 0.0)
1016 net
->cirseg
->angle2
+= 360.0;
1018 if(net
->cirseg
->angle2
== 0.0)
1019 net
->cirseg
->angle2
= 360.0;
1022 * This is a sanity check for angles after the nature of atan2.
1023 * If cw we must make sure angle1-angle2 are always positive,
1024 * If ccw we must make sure angle2-angle1 are always negative.
1025 * We should really return one angle and the difference as GTK
1026 * uses them. But what the heck, it works for me.
1029 if (net
->cirseg
->angle1
< net
->cirseg
->angle2
)
1030 net
->cirseg
->angle2
-= 360.0;
1032 if (net
->cirseg
->angle1
> net
->cirseg
->angle2
)
1033 net
->cirseg
->angle2
+= 360.0;
1037 } /* calc_cirseg_mq */