diff -Nwur gerbv-1.0.2/example/sr/sr1.gbr gerbv-1.0.2-sr/example/sr/sr1.gbr --- gerbv-1.0.2/example/sr/sr1.gbr 1970-01-01 01:00:00.000000000 +0100 +++ gerbv-1.0.2-sr/example/sr/sr1.gbr 2007-07-20 10:47:56.000000000 +0200 @@ -0,0 +1,11 @@ +%FSLAX35Y35*% +%MOMM*% +%ADD11R,1.00000X1.00000*% +%ADD12R,0.10000X0.10000*% + +G54D11 +X00100000 Y00100000 D02* +%SRX3Y8I2J3*% +X00100000 Y00150000 D01* +M02* + diff -Nwur gerbv-1.0.2/example/sr/sr.gbr gerbv-1.0.2-sr/example/sr/sr.gbr --- gerbv-1.0.2/example/sr/sr.gbr 1970-01-01 01:00:00.000000000 +0100 +++ gerbv-1.0.2-sr/example/sr/sr.gbr 2007-07-20 10:49:46.000000000 +0200 @@ -0,0 +1,15 @@ +%FSLAX35Y35*% +%MOMM*% +%ADD11R,1.00000X1.00000*% +%ADD12R,0.10000X0.10000*% +G54D12 +X00545000 Y00000000 D02* +X00000000 Y00000000 D01* +X00000000 Y00795000 D01* + +G54D11 +X00100000 Y00100000 D02* +%SRX3Y3I2J3*% +X00100000 Y00150000 D01* +M02* + diff -Nwur gerbv-1.0.2/src/draw.c gerbv-1.0.2-sr/src/draw.c --- gerbv-1.0.2/src/draw.c 2005-04-25 00:03:23.000000000 +0200 +++ gerbv-1.0.2-sr/src/draw.c 2007-07-19 13:19:27.000000000 +0200 @@ -185,6 +185,25 @@ } for (net = image->netlist->next ; net != NULL; net = net->next) { + int repeat_X=1, repeat_Y=1; + double repeat_dist_X, repeat_dist_Y; + int repeat_i, repeat_j; + + /* + * If step_and_repeat (%SR%) used, repeat the drawing; + * if step_and_repeat not used, net->step_and_repeat will be NULL, and + * we repeat everything just once. + */ + if(net->step_and_repeat != NULL){ + repeat_X = net->step_and_repeat->X; + repeat_Y = net->step_and_repeat->Y; + repeat_dist_X = net->step_and_repeat->dist_X; + repeat_dist_Y = net->step_and_repeat->dist_Y; + } + for(repeat_i = 0; repeat_i < repeat_X; repeat_i++) { + for(repeat_j = 0; repeat_j < repeat_Y; repeat_j++) { + double sr_x = repeat_i * repeat_dist_X; + double sr_y = repeat_j * repeat_dist_Y; if (net->unit == MM) unit_scale = scale / 25.4; @@ -194,13 +213,13 @@ /* * Scale points with window scaling and translate them */ - x1 = (int)round((image->info->offset_a + net->start_x) * unit_scale + + x1 = (int)round((image->info->offset_a + net->start_x + sr_x) * unit_scale + trans_x); - y1 = (int)round((image->info->offset_b - net->start_y) * unit_scale + + y1 = (int)round((image->info->offset_b - net->start_y - sr_y) * unit_scale + trans_y); - x2 = (int)round((image->info->offset_a + net->stop_x) * unit_scale + + x2 = (int)round((image->info->offset_a + net->stop_x + sr_x) * unit_scale + trans_x); - y2 = (int)round((image->info->offset_b - net->stop_y) * unit_scale + + y2 = (int)round((image->info->offset_b - net->stop_y - sr_y) * unit_scale + trans_y); /* @@ -378,7 +397,8 @@ return 0; } } - + } + } /* * Destroy GCs before exiting */ diff -Nwur gerbv-1.0.2/src/gerber.c gerbv-1.0.2-sr/src/gerber.c --- gerbv-1.0.2/src/gerber.c 2006-07-26 15:31:35.000000000 +0200 +++ gerbv-1.0.2-sr/src/gerber.c 2007-07-20 11:15:56.000000000 +0200 @@ -76,6 +76,7 @@ double delta_cp_x, double delta_cp_y); static gerb_net_t *gen_circle_segments(gerb_net_t *curr_net, int cw, int *nuf_pcorners); +static void setminmax(double *min, double *max, double pos, double aperture); gerb_image_t * parse_gerb(gerb_file_t *fd) @@ -206,7 +207,11 @@ break; case '%': parse_rs274x(fd, image, state); - while (gerb_fgetc(fd) != '%'); + while (1){ + char c=gerb_fgetc(fd); + if(c==EOF || c=='%') + break; + } break; case '*': if (state->changed == 0) break; @@ -351,6 +356,17 @@ else aperture_size = 0.0; + if ((image->info->step_and_repeat.X != 1) || + (image->info->step_and_repeat.Y != 1) ){ + curr_net->step_and_repeat=(struct gerb_step_and_repeat *)malloc(sizeof(struct gerb_step_and_repeat)); + if(curr_net->step_and_repeat == NULL) + GERB_FATAL_ERROR("malloc curr_net->step_and_repeat failed\n"); + memcpy(curr_net->step_and_repeat, + &(image->info->step_and_repeat), + sizeof(struct gerb_step_and_repeat)); + } + + /* * For next round we save the current position as * the previous position @@ -370,14 +386,31 @@ else scale = 1.0; - if (image->info->min_x > curr_net->stop_x) - image->info->min_x = (curr_net->stop_x - aperture_size) / scale; - if (image->info->min_y > curr_net->stop_y) - image->info->min_y = (curr_net->stop_y - aperture_size) / scale; - if (image->info->max_x < curr_net->stop_x) - image->info->max_x = (curr_net->stop_x + aperture_size) / scale; - if (image->info->max_y < curr_net->stop_y) - image->info->max_y = (curr_net->stop_y + aperture_size) / scale; + { + double repeat_off_X=0, repeat_off_Y=0; + + /* + * If step_and_repeat (%SR%) is used, check min_x,max_y etc for the + * ends of the step_and_repeat lattice. This goes wrong in the case of + * negative dist_X or dist_Y, in which case we should compare against + * the startpoints of the lines, not the stoppoints, but that seems an + * uncommon case (and the error isn't very big any way). + * + */ + if(curr_net->step_and_repeat != NULL){ + repeat_off_X = (curr_net->step_and_repeat->X - 1)* + curr_net->step_and_repeat->dist_X; + repeat_off_Y = (curr_net->step_and_repeat->Y - 1)* + curr_net->step_and_repeat->dist_Y; + } + setminmax(&(image->info->min_x), &(image->info->max_x), + (curr_net->stop_x + repeat_off_X ) / scale, + aperture_size / scale); + + setminmax(&(image->info->min_y), &(image->info->max_y), + (curr_net->stop_y + repeat_off_Y) / scale, + aperture_size / scale); + } break; case 10 : /* White space */ @@ -841,13 +874,19 @@ default: GERB_COMPILE_ERROR("Step-and-repeat parameter error\n"); } + + /* + * Repeating 0 times in any direction would disable the whole plot, and + * is probably not intended. At least one other tool (viewmate) seems + * to interpret 0-time repeating as repeating just once too. + */ + if(image->info->step_and_repeat.X == 0) + image->info->step_and_repeat.X = 1; + if(image->info->step_and_repeat.Y == 0) + image->info->step_and_repeat.Y = 1; + op[0] = gerb_fgetc(fd); } - if ((image->info->step_and_repeat.X != 1) || - (image->info->step_and_repeat.Y != 1) || - (fabs(image->info->step_and_repeat.dist_X) > 0.000001) || - (fabs(image->info->step_and_repeat.dist_Y) > 0.000001)) - NOT_IMPL(fd, "%SR%"); break; case A2I('R','O'): /* Rotate */ NOT_IMPL(fd, "%RO%"); @@ -1205,3 +1244,12 @@ return curr_net; } /* gen_circle_segments */ + + +void +setminmax(double *min, double *max, double pos, double aperture){ + if(*min > (pos-aperture)) + *min=pos-aperture; + if(*max < (pos+aperture)) + *max=pos+aperture; +} diff -Nwur gerbv-1.0.2/src/gerb_image.h gerbv-1.0.2-sr/src/gerb_image.h --- gerbv-1.0.2/src/gerb_image.h 2006-07-23 23:28:11.000000000 +0200 +++ gerbv-1.0.2-sr/src/gerb_image.h 2007-07-19 13:15:59.000000000 +0200 @@ -54,6 +54,15 @@ double angle2; } gerb_cirseg_t; +typedef struct gerb_step_and_repeat{ /* SR parameters */ + int X; + int Y; + double dist_X; + double dist_Y; +} gerb_step_and_repeat_t; + + + typedef struct gerb_net { double start_x; @@ -68,6 +77,7 @@ int nuf_pcorners; /* If interpolation=PAREA_START, corners in polygon */ struct gerb_cirseg *cirseg; struct gerb_net *next; + struct gerb_step_and_repeat *step_and_repeat; /* SR parameters, NULL if not set */ } gerb_net_t; @@ -108,12 +118,7 @@ enum encoding_t encoding; double scale_factor_A; /* SF parameters */ double scale_factor_B; - struct { /* SR parameters */ - int X; - int Y; - double dist_X; - double dist_Y; - } step_and_repeat; + struct gerb_step_and_repeat step_and_repeat; /* SR parameters */ } gerb_image_info_t;