diff --git a/Makefile b/Makefile index 866a2b3..e87813f 100644 --- a/Makefile +++ b/Makefile @@ -16,9 +16,11 @@ OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \ gui_tool.o gui_over.o gui_meas.o gui_frame.o -XPMS = point.xpm delete.xpm vec.xpm frame.xpm frame_locked.xpm frame_ready.xpm \ - line.xpm rect.xpm pad.xpm circ.xpm meas.xpm meas_x.xpm meas_y.xpm \ - stuff.xpm stuff_off.xpm meas_off.xpm delete_off.xpm +XPMS = point.xpm delete.xpm delete_off.xpm \ + vec.xpm frame.xpm frame_locked.xpm frame_ready.xpm \ + line.xpm rect.xpm pad.xpm rpad.xpm circ.xpm \ + meas.xpm meas_x.xpm meas_y.xpm \ + stuff.xpm stuff_off.xpm meas_off.xpm CFLAGS_GTK = `pkg-config --cflags gtk+-2.0` LIBS_GTK = `pkg-config --libs gtk+-2.0` diff --git a/README b/README index 21ad555..a43c211 100644 --- a/README +++ b/README @@ -199,6 +199,16 @@ vec @(1mm, 1mm) pad "1" @ . +Rounded pads +- - - - - - + +Rounded pads are like rectangular pads except that they end with a +semi-circle at each of the smaller sides of the enclosing rectangle. +If enclosed in a square, rounded pads form a circle. + +rpad "" + + Measurements - - - - - - diff --git a/TODO b/TODO index f2adbaf..64fcea6 100644 --- a/TODO +++ b/TODO @@ -28,9 +28,6 @@ Bugs: - default silk width has no business being hard-coded in obj.c - undelete only works if not much has changed since the deletion - focus should return to canvas if nobody else wants it -- when in uninstantiated mode, objects can be changed and then manipulated - through the unchanged instance. Tricky to fix without an alternate means to - access the object list. (Getting there.) Code cleanup: - merge edit_unique with edit_name diff --git a/dump.c b/dump.c index 46f9515..01cab34 100644 --- a/dump.c +++ b/dump.c @@ -317,8 +317,8 @@ char *print_obj(const struct obj *obj, const struct vec *prev) break; case ot_pad: s1 = obj_base_name(obj->u.pad.other, prev); - s = stralloc_printf("pad \"%s\" %s %s", - obj->u.pad.name, base, s1); + s = stralloc_printf("%spad \"%s\" %s %s", + obj->u.pad.rounded ? "r" : "", obj->u.pad.name, base, s1); free(s1); break; case ot_arc: diff --git a/fbga.fpd b/fbga.fpd index 0c0a1d8..32d4d6c 100644 --- a/fbga.fpd +++ b/fbga.fpd @@ -12,7 +12,7 @@ frame pad { __0: vec @(col*e-Px/2, row*-e-Py/2) __1: vec .(0mm, Py) __2: vec __0(Px, 0mm) - pad "$rname$cname" __1 . + rpad "$rname$cname" __1 . } frame inner { diff --git a/fpd.l b/fpd.l index e5e5937..ae42c23 100644 --- a/fpd.l +++ b/fpd.l @@ -85,6 +85,8 @@ SP [\t ]* return TOK_VEC; } "pad" { BEGIN(NOKEYWORD); return TOK_PAD; } +"rpad" { BEGIN(NOKEYWORD); + return TOK_RPAD; } "rect" { BEGIN(NOKEYWORD); return TOK_RECT; } "line" { BEGIN(NOKEYWORD); diff --git a/fpd.y b/fpd.y index b59a3f8..2924439 100644 --- a/fpd.y +++ b/fpd.y @@ -151,7 +151,7 @@ static struct obj *new_obj(enum obj_type type) %token START_FPD START_EXPR %token TOK_SET TOK_LOOP TOK_PART TOK_FRAME TOK_TABLE TOK_VEC -%token TOK_PAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC +%token TOK_PAD TOK_RPAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC %token TOK_MEAS TOK_MEASX TOK_MEASY %token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED @@ -419,6 +419,15 @@ obj: $$->base = $3; $$->u.pad.name = $2; $$->u.pad.other = $4; + $$->u.pad.rounded = 0; + } + | TOK_RPAD STRING base base + { + $$ = new_obj(ot_pad); + $$->base = $3; + $$->u.pad.name = $2; + $$->u.pad.other = $4; + $$->u.pad.rounded = 1; } | TOK_RECT base base opt_expr { diff --git a/gui_frame.c b/gui_frame.c index e506706..faf636f 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -938,7 +938,8 @@ static void set_item_color(struct inst *inst, const char *color) label = inst->vec->list_widget; else label = inst->obj->list_widget; - label_in_box_bg(box_of_label(label), color); + if (label) + label_in_box_bg(box_of_label(label), color); } @@ -1100,6 +1101,18 @@ static GtkWidget *build_meas(struct frame *frame) } +static void dont_build_items(struct frame *frame) +{ + struct vec *vec; + struct obj *obj; + + for (vec = frame->vecs; vec; vec = vec->next) + vec->list_widget = NULL; + for (obj = frame->objs; obj; obj = obj->next) + obj->list_widget = NULL; +} + + /* ----- part name --------------------------------------------------------- */ @@ -1323,6 +1336,7 @@ void build_frames(GtkWidget *vbox) vars = build_vars(frame); gtk_table_attach_defaults(GTK_TABLE(tab), vars, 1, 2, n*2+2, n*2+3); + dont_build_items(frame); } else { items = build_items(frame); gtk_table_attach_defaults(GTK_TABLE(tab), items, diff --git a/gui_inst.c b/gui_inst.c index 0539b2f..79086d7 100644 --- a/gui_inst.c +++ b/gui_inst.c @@ -235,7 +235,7 @@ unit_type gui_dist_pad(struct inst *self, struct coord pos, unit_type scale) } -void gui_draw_pad(struct inst *self) +static void gui_draw_pad_text(struct inst *self) { struct coord min = translate(self->base); struct coord max = translate(self->u.pad.other); @@ -243,12 +243,8 @@ void gui_draw_pad(struct inst *self) struct coord c; unit_type h, w; - gc = gc_pad[get_mode(self)]; - sort_coord(&min, &max); - gdk_draw_rectangle(DA, gc, TRUE, - min.x, min.y, max.x-min.x, max.y-min.y); - gc = gc_ptext[get_mode(self)]; + sort_coord(&min, &max); c = add_vec(min, max); h = max.y-min.y; w = max.x-min.x; @@ -258,6 +254,48 @@ void gui_draw_pad(struct inst *self) } +void gui_draw_pad(struct inst *self) +{ + struct coord min = translate(self->base); + struct coord max = translate(self->u.pad.other); + GdkGC *gc; + + gc = gc_pad[get_mode(self)]; + sort_coord(&min, &max); + gdk_draw_rectangle(DA, gc, TRUE, + min.x, min.y, max.x-min.x, max.y-min.y); + + gui_draw_pad_text(self); +} + + +void gui_draw_rpad(struct inst *self) +{ + struct coord min = translate(self->base); + struct coord max = translate(self->u.pad.other); + GdkGC *gc; + unit_type h, w, r; + + gc = gc_pad[get_mode(self)]; + sort_coord(&min, &max); + h = max.y-min.y; + w = max.x-min.x; + if (h > w) { + r = w/2; + draw_arc(DA, gc, TRUE, min.x+r, max.y-r, r, 180, 0); + gdk_draw_rectangle(DA, gc, TRUE, min.x, min.y+r, w, h-2*r); + draw_arc(DA, gc, TRUE, min.x+r, min.y+r, r, 0, 180); + } else { + r = h/2; + draw_arc(DA, gc, TRUE, min.x+r, min.y+r, r, 90, 270); + gdk_draw_rectangle(DA, gc, TRUE, min.x+r, min.y, w-2*r, h); + draw_arc(DA, gc, TRUE, max.x-r, min.y+r, r, 270, 90); + } + + gui_draw_pad_text(self); +} + + /* ----- arc --------------------------------------------------------------- */ diff --git a/gui_inst.h b/gui_inst.h index 55a95c2..6205fd1 100644 --- a/gui_inst.h +++ b/gui_inst.h @@ -39,6 +39,7 @@ void gui_draw_vec(struct inst *self); void gui_draw_line(struct inst *self); void gui_draw_rect(struct inst *self); void gui_draw_pad(struct inst *self); +void gui_draw_rpad(struct inst *self); void gui_draw_arc(struct inst *self); void gui_draw_meas(struct inst *self); void gui_draw_frame(struct inst *self); diff --git a/gui_tool.c b/gui_tool.c index 0b8624c..9c2a4a8 100644 --- a/gui_tool.c +++ b/gui_tool.c @@ -39,6 +39,7 @@ #include "icons/meas_x.xpm" #include "icons/meas_y.xpm" #include "icons/pad.xpm" +#include "icons/rpad.xpm" #include "icons/point.xpm" #include "icons/delete.xpm" #include "icons/delete_off.xpm" @@ -377,6 +378,7 @@ static int end_new_pad(struct inst *from, struct inst *to) obj = new_obj(ot_pad, from); obj->u.pad.other = inst_get_vec(to); obj->u.pad.name = stralloc("?"); + obj->u.pad.rounded = 0; return 1; } @@ -393,6 +395,35 @@ static struct tool_ops pad_ops = { }; +/* ----- rounded pad ------------------------------------------------------- */ + + +static int end_new_rpad(struct inst *from, struct inst *to) +{ + struct obj *obj; + + if (from == to) + return 0; + obj = new_obj(ot_pad, from); + obj->u.pad.other = inst_get_vec(to); + obj->u.pad.name = stralloc("?"); + obj->u.pad.rounded = 1; + return 1; +} + + +struct pix_buf *draw_move_rpad(struct inst *inst, struct coord pos, int i) +{ + return draw_move_rect_common(inst, inst->u.pad.other, pos, i); +} + + +static struct tool_ops rpad_ops = { + .drag_new = drag_new_rect, + .end_new = end_new_rpad, +}; + + /* ----- circ -------------------------------------------------------------- */ @@ -989,6 +1020,8 @@ GtkWidget *gui_setup_tools(GdkDrawable *drawable) tool_button_press_event, &frame_ops); tool_button(bar, drawable, xpm_pad, tool_button_press_event, &pad_ops); + tool_button(bar, drawable, xpm_rpad, + tool_button_press_event, &rpad_ops); tool_button(bar, drawable, xpm_line, tool_button_press_event, &line_ops); tool_button(bar, drawable, xpm_rect, diff --git a/gui_tool.h b/gui_tool.h index e28a8f2..78a2d64 100644 --- a/gui_tool.h +++ b/gui_tool.h @@ -35,6 +35,7 @@ struct pix_buf *draw_move_vec(struct inst *inst, struct coord pos, int i); struct pix_buf *draw_move_line(struct inst *inst, struct coord pos, int i); struct pix_buf *draw_move_rect(struct inst *inst, struct coord pos, int i); struct pix_buf *draw_move_pad(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_rpad(struct inst *inst, struct coord pos, int i); struct pix_buf *draw_move_arc(struct inst *inst, struct coord pos, int i); struct pix_buf *draw_move_meas(struct inst *inst, struct coord pos, int i); struct pix_buf *draw_move_frame(struct inst *inst, struct coord pos, int i); diff --git a/icons/rpad.fig b/icons/rpad.fig new file mode 100644 index 0000000..18d7f3f --- /dev/null +++ b/icons/rpad.fig @@ -0,0 +1,17 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +5 1 0 0 0 4 50 -1 20 0.000 0 1 0 0 4800.000 3825.000 4125 3825 4800 4500 5475 3825 +5 1 0 0 0 4 50 -1 20 0.000 0 0 0 0 4800.000 3375.000 4125 3375 4800 2700 5475 3375 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 +2 1 0 15 7 7 45 -1 -1 0.000 1 1 -1 0 0 3 + 4875 4050 4875 3150 4650 3375 +2 2 0 0 0 4 50 -1 20 0.000 0 0 -1 0 0 5 + 4125 3375 5475 3375 5475 3825 4125 3825 4125 3375 diff --git a/inst.c b/inst.c index 5488068..45703fc 100644 --- a/inst.c +++ b/inst.c @@ -619,7 +619,7 @@ int inst_rect(struct obj *obj, struct coord a, struct coord b, unit_type width) } -/* ----- pad --------------------------------------------------------------- */ +/* ----- pad / rpad -------------------------------------------------------- */ static void pad_op_debug(struct inst *self) @@ -630,6 +630,13 @@ static void pad_op_debug(struct inst *self) } +static void rpad_op_debug(struct inst *self) +{ + printf("r"); + pad_op_debug(self); +} + + static int validate_pad_name(const char *s, void *ctx) { char *tmp; @@ -677,11 +684,21 @@ static struct inst_ops pad_ops = { }; +static struct inst_ops rpad_ops = { + .debug = rpad_op_debug, + .draw = gui_draw_rpad, + .distance = gui_dist_pad, /* @@@ */ + .select = pad_op_select, + .anchors = pad_op_anchors, + .draw_move = draw_move_rpad, +}; + + int inst_pad(struct obj *obj, const char *name, struct coord a, struct coord b) { struct inst *inst; - inst = add_inst(&pad_ops, ip_pad, a); + inst = add_inst(obj->u.pad.rounded ? &rpad_ops : &pad_ops, ip_pad, a); inst->obj = obj; inst->u.pad.name = stralloc(name); inst->u.pad.other = b; diff --git a/kicad.c b/kicad.c index 5213908..6fead13 100644 --- a/kicad.c +++ b/kicad.c @@ -78,8 +78,9 @@ static void kicad_pad(FILE *file, const struct inst *inst) /* * name, shape (rectangle), Xsize, Ysize, Xdelta, Ydelta, Orientation */ - fprintf(file, "Sh \"%s\" R %d %d 0 0 0\n", - inst->u.pad.name, max.x-min.x, max.y-min.y); + fprintf(file, "Sh \"%s\" %c %d %d 0 0 0\n", + inst->u.pad.name, inst->obj->u.pad.rounded ? 'O' : 'R', + max.x-min.x, max.y-min.y); /* * Attributes: pad type, N, layer mask diff --git a/obj.h b/obj.h index 37aa4fc..e272f8c 100644 --- a/obj.h +++ b/obj.h @@ -104,7 +104,7 @@ struct vec { struct sample *samples; /* for the GUI */ - GtkWidget *list_widget; + GtkWidget *list_widget; /* NULL if items aren't shown */ }; struct frame { @@ -148,6 +148,7 @@ struct rect { struct pad { char *name; struct vec *other; /* NULL if frame origin */ + int rounded; }; struct arc { @@ -175,7 +176,7 @@ struct obj { int dumped; /* for the GUI */ - GtkWidget *list_widget; + GtkWidget *list_widget; /* NULL if items are not shown */ }; diff --git a/postscript.c b/postscript.c index 7b54ed1..7030f48 100644 --- a/postscript.c +++ b/postscript.c @@ -48,6 +48,33 @@ static void ps_pad(FILE *file, const struct inst *inst) } +static void ps_rpad(FILE *file, const struct inst *inst) +{ + struct coord a = inst->base; + struct coord b = inst->u.pad.other; + unit_type h, w, r; + + sort_coord(&a, &b); + h = b.y-a.y; + w = b.x-a.x; + fprintf(file, "0 setgray %d setlinewidth\n", HATCH_LINE); + if (h > w) { + r = w/2; + fprintf(file, " %d %d moveto\n", b.x, b.y-r); + fprintf(file, " %d %d %d 0 180 arc\n", a.x+r, b.y-r, r); + fprintf(file, " %d %d lineto\n", a.x, a.y+r); + fprintf(file, " %d %d %d 180 360 arc\n", a.x+r, a.y+r, r); + } else { + r = h/2; + fprintf(file, " %d %d moveto\n", b.x-r, a.y); + fprintf(file, " %d %d %d -90 90 arc\n", b.x-r, a.y+r, r); + fprintf(file, " %d %d lineto\n", a.x+r, b.y); + fprintf(file, " %d %d %d 90 270 arc\n", a.x+r, a.y+r, r); + } + fprintf(file, " closepath gsave hatchpath grestore stroke\n"); +} + + static void ps_line(FILE *file, const struct inst *inst) { struct coord a = inst->base; @@ -131,7 +158,10 @@ static void ps_foreground(FILE *file, enum inst_prio prio, { switch (prio) { case ip_pad: - ps_pad(file, inst); + if (inst->obj->u.pad.rounded) + ps_rpad(file, inst); + else + ps_pad(file, inst); break; case ip_vec: if (postscript_params.show_stuff)