diff --git a/Makefile b/Makefile index bbf77e0..a9a6e86 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ XPMS = point.xpm delete.xpm delete_off.xpm \ vec.xpm frame.xpm \ - line.xpm rect.xpm pad.xpm rpad.xpm arc.xpm circ.xpm \ + line.xpm rect.xpm pad.xpm rpad.xpm hole.xpm arc.xpm circ.xpm \ meas.xpm meas_x.xpm meas_y.xpm \ stuff.xpm stuff_off.xpm meas_off.xpm \ bright.xpm bright_off.xpm all.xpm all_off.xpm diff --git a/delete.c b/delete.c index 10cc285..93ac9ce 100644 --- a/delete.c +++ b/delete.c @@ -1,8 +1,8 @@ /* * delete.c - Object deletion * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -137,6 +137,8 @@ static int obj_has_ref(const struct obj *obj, const struct vec *ref) return obj->u.rect.other == ref; case ot_pad: return obj->u.pad.other == ref; + case ot_hole: + return obj->u.hole.other == ref; case ot_arc: return obj->u.arc.start == ref || obj->u.arc.end == ref; case ot_meas: @@ -210,6 +212,8 @@ static void destroy_obj(struct obj *obj) case ot_pad: free(obj->u.pad.name); break; + case ot_hole: + break; case ot_line: if (obj->u.line.width) free_expr(obj->u.line.width); diff --git a/dump.c b/dump.c index 8e4f738..1128fa6 100644 --- a/dump.c +++ b/dump.c @@ -111,6 +111,10 @@ static int may_put_obj_now(const struct obj *obj, const struct vec *prev) n |= need(obj->u.pad.other, prev); l |= later(obj->u.pad.other, prev); break; + case ot_hole: + n |= need(obj->u.hole.other, prev); + l |= later(obj->u.hole.other, prev); + break; case ot_arc: n |= need(obj->u.arc.start, prev); n |= need(obj->u.arc.end, prev); @@ -352,6 +356,10 @@ char *print_obj(const struct obj *obj, const struct vec *prev) obj->u.pad.rounded ? "r" : "", obj->u.pad.name, base, s1, s2); break; + case ot_hole: + s1 = obj_base_name(obj->u.hole.other, prev); + s = stralloc_printf("hole %s %s", base, s1); + break; case ot_arc: s1 = obj_base_name(obj->u.arc.start, prev); s2 = unparse(obj->u.arc.width); diff --git a/fpd.l b/fpd.l index 7697ede..1b1a1aa 100644 --- a/fpd.l +++ b/fpd.l @@ -104,6 +104,8 @@ SP [\t ]* return TOK_PAD; } "rpad" { BEGIN(NOKEYWORD); return TOK_RPAD; } +"hole" { BEGIN(NOKEYWORD); + return TOK_HOLE; } "rect" { BEGIN(NOKEYWORD); return TOK_RECT; } "line" { BEGIN(NOKEYWORD); diff --git a/fpd.y b/fpd.y index 0f23e7d..a834490 100644 --- a/fpd.y +++ b/fpd.y @@ -285,7 +285,7 @@ static void append_root_frame(void) %token START_FPD START_EXPR START_VAR START_VALUES %token TOK_SET TOK_LOOP TOK_PACKAGE TOK_FRAME TOK_TABLE TOK_VEC -%token TOK_PAD TOK_RPAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC +%token TOK_PAD TOK_RPAD TOK_HOLE TOK_RECT TOK_LINE TOK_CIRC TOK_ARC %token TOK_MEAS TOK_MEASX TOK_MEASY TOK_UNIT %token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED %token TOK_DBG_DEL TOK_DBG_MOVE TOK_DBG_PRINT TOK_DBG_DUMP @@ -653,6 +653,12 @@ obj: $$->u.pad.rounded = 1; $$->u.pad.type = $5; } + | TOK_HOLE base base + { + $$ = new_obj(ot_hole); + $$->base = $2; + $$->u.hole.other = $3; + } | TOK_RECT base base opt_expr { $$ = new_obj(ot_rect); diff --git a/gui_inst.c b/gui_inst.c index 44478ed..2658024 100644 --- a/gui_inst.c +++ b/gui_inst.c @@ -1,8 +1,8 @@ /* * gui_inst.c - GUI, instance functions * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -288,15 +288,13 @@ void gui_draw_pad(struct inst *self) } -void gui_draw_rpad(struct inst *self) +static void draw_rounded_rect(GdkGC *gc, struct coord a, struct coord b, + int fill) { - struct coord min = translate(self->base); - struct coord max = translate(self->u.pad.other); - GdkGC *gc; - int fill; + struct coord min = translate(a); + struct coord max = translate(b); unit_type h, w, r; - gc = pad_gc(self, &fill); sort_coord(&min, &max); h = max.y-min.y; w = max.x-min.x; @@ -323,11 +321,44 @@ void gui_draw_rpad(struct inst *self) } draw_arc(DA, gc, fill, max.x-r, min.y+r, r, 270, 90); } +} + +void gui_draw_rpad(struct inst *self) +{ + GdkGC *gc; + int fill; + + gc = pad_gc(self, &fill); + draw_rounded_rect(gc, self->base, self->u.pad.other, fill); gui_draw_pad_text(self); } +/* ----- hole -------------------------------------------------------------- */ + + +unit_type gui_dist_hole(struct inst *self, struct coord pos, unit_type scale) +{ + unit_type d; + + /* @@@ not quite right ... */ + if (inside_rect(pos, self->base, self->u.hole.other)) + return SELECT_R; + d = dist_rect(pos, self->base, self->u.hole.other)/scale; + return d > SELECT_R ? -1 : d; +} + + +void gui_draw_hole(struct inst *self) +{ + draw_rounded_rect(gc_hole[get_mode(self)], + self->base, self->u.hole.other, 1); + draw_rounded_rect(gc_rim[get_mode(self)], + self->base, self->u.hole.other, 0); +} + + /* ----- arc --------------------------------------------------------------- */ diff --git a/gui_inst.h b/gui_inst.h index 3397365..bd69edc 100644 --- a/gui_inst.h +++ b/gui_inst.h @@ -1,8 +1,8 @@ /* * gui_inst.h - GUI, instance functions * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ unit_type gui_dist_vec_fallback(struct inst *self, struct coord pos, unit_type gui_dist_line(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_rect(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_pad(struct inst *self, struct coord pos, unit_type scale); +unit_type gui_dist_hole(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_arc(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_meas(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_frame(struct inst *self, struct coord pos, unit_type scale); @@ -44,6 +45,7 @@ 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_hole(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_style.c b/gui_style.c index 04be766..c308c61 100644 --- a/gui_style.c +++ b/gui_style.c @@ -1,7 +1,7 @@ /* * gui_style.c - GUI, style definitions * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,8 @@ GdkGC *gc_pad[mode_n]; GdkGC *gc_pad_bare[mode_n]; GdkGC *gc_pad_mask[mode_n]; GdkGC *gc_ptext[mode_n]; +GdkGC *gc_rim[mode_n]; +GdkGC *gc_hole[mode_n]; GdkGC *gc_meas[mode_n]; GdkGC *gc_frame[mode_n]; @@ -61,13 +63,15 @@ void gui_setup_style(GdkDrawable *drawable) gc_bg = gc("#000000", 0); gc_bg_error = gc("#000040", 0); gc_drag = gc("#ffffff", 2); - /* inactive active selected */ + /* inactive active selected width */ style(gc_vec, "#202000", "#b0b050", "#ffff80", 1); style(gc_obj, "#006060", "#00ffff", "#ffff80", 1); style(gc_pad, "#400000", "#ff0000", "#ffff80", 1); style(gc_pad_bare, "#402000", "#ff6000", "#ffff80", 1); style(gc_pad_mask, "#000040", "#0000ff", "#ffff80", 2); style(gc_ptext, "#404040", "#ffffff", "#ffffff", 1); + style(gc_hole, "#000000", "#000000", "#000000", 0); + style(gc_rim, "#202020", "#606060", "#ffff80", 3); style(gc_meas, "#280040", "#ff00ff", "#ffff80", 1); style(gc_frame, "#005000", "#009000", "#ffff80", 1); diff --git a/gui_style.h b/gui_style.h index bd15109..604d734 100644 --- a/gui_style.h +++ b/gui_style.h @@ -116,6 +116,8 @@ extern GdkGC *gc_pad[mode_n]; extern GdkGC *gc_pad_bare[mode_n]; extern GdkGC *gc_pad_mask[mode_n]; extern GdkGC *gc_ptext[mode_n]; +extern GdkGC *gc_rim[mode_n]; +extern GdkGC *gc_hole[mode_n]; extern GdkGC *gc_meas[mode_n]; extern GdkGC *gc_frame[mode_n]; diff --git a/gui_tool.c b/gui_tool.c index dc0e34b..e81f13e 100644 --- a/gui_tool.c +++ b/gui_tool.c @@ -40,6 +40,7 @@ #include "icons/meas_y.xpm" #include "icons/pad.xpm" #include "icons/rpad.xpm" +#include "icons/hole.xpm" #include "icons/point.xpm" #include "icons/delete.xpm" #include "icons/delete_off.xpm" @@ -88,6 +89,7 @@ struct obj *new_obj_unconnected(enum obj_type type, struct inst *base) obj = alloc_type(struct obj); obj->type = type; + obj->name = NULL; obj->frame = active_frame; obj->base = inst_get_vec(base); obj->next = NULL; @@ -459,6 +461,33 @@ static struct tool_ops rpad_ops = { }; +/* ----- hole -------------------------------------------------------------- */ + + +static int end_new_hole(struct inst *from, struct inst *to) +{ + struct obj *obj; + + if (from == to) + return 0; + obj = new_obj(ot_hole, from); + obj->u.hole.other = inst_get_vec(to); + return 1; +} + + +struct pix_buf *draw_move_hole(struct inst *inst, struct coord pos, int i) +{ + return draw_move_rect_common(inst, inst->u.hole.other, pos, i); +} + + +static struct tool_ops hole_ops = { + .drag_new = drag_new_rect, + .end_new = end_new_hole, +}; + + /* ----- circ -------------------------------------------------------------- */ @@ -1049,6 +1078,9 @@ GtkWidget *get_icon_by_inst(const struct inst *inst) case ip_pad_special: image = inst->obj->u.pad.rounded ? xpm_rpad : xpm_pad; break; + case ip_hole: + image = xpm_hole; + break; case ip_circ: image = xpm_circ; break; @@ -1166,6 +1198,9 @@ GtkWidget *gui_setup_tools(GdkDrawable *drawable) tool_button(bar, drawable, xpm_rpad, "Add a rounded pad", tool_button_press_event, &rpad_ops); + tool_button(bar, drawable, xpm_hole, + "Add a hole", + tool_button_press_event, &hole_ops); tool_button(bar, drawable, xpm_line, "Add a silk screen line", tool_button_press_event, &line_ops); diff --git a/gui_tool.h b/gui_tool.h index c3bd48b..0dac3e5 100644 --- a/gui_tool.h +++ b/gui_tool.h @@ -36,6 +36,7 @@ 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_hole(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/hole.fig b/icons/hole.fig new file mode 100644 index 0000000..303a779 --- /dev/null +++ b/icons/hole.fig @@ -0,0 +1,24 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +6 3600 2400 6000 4800 +1 3 0 8 0 7 45 -1 20 0.000 1 0.0000 4800 3600 600 600 4800 3600 5400 3600 +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 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2 + 3900 4500 5700 2700 +2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2 + 3900 3900 5100 2700 +2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2 + 3900 3300 4500 2700 +2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2 + 4500 4500 5700 3300 +2 1 0 5 0 7 50 -1 20 0.000 0 1 -1 0 0 2 + 5100 4500 5700 3900 +-6 diff --git a/inst.c b/inst.c index 5de2f77..88a8804 100644 --- a/inst.c +++ b/inst.c @@ -909,6 +909,37 @@ int inst_pad(struct obj *obj, const char *name, struct coord a, struct coord b) } +/* ----- hole -------------------------------------------------------------- */ + + +static void hole_op_select(struct inst *self) +{ + rect_status_sort(self->base, self->u.hole.other, -1, 1); +} + + +static struct inst_ops hole_ops = { + .draw = gui_draw_hole, + .distance = gui_dist_hole, + .select = hole_op_select, + .draw_move = draw_move_hole, +}; + + +int inst_hole(struct obj *obj, struct coord a, struct coord b) +{ + struct inst *inst; + + inst = add_inst(&hole_ops, ip_hole, a); + inst->obj = obj; + inst->u.hole.other = b; + find_inst(inst); + update_bbox(&inst->bbox, b); + propagate_bbox(inst); + return 1; +} + + /* ----- arc --------------------------------------------------------------- */ diff --git a/inst.h b/inst.h index f8b63d6..bfa0efa 100644 --- a/inst.h +++ b/inst.h @@ -40,6 +40,7 @@ enum inst_prio { ip_frame, /* frames have their own selection */ ip_pad_copper, /* pads also accept clicks inside; pads with copper */ ip_pad_special, /* pads with only solder paste or mask, on top */ + ip_hole, /* holes in pads must be on top to be seen */ ip_circ, /* circles don't overlap easily */ ip_arc, /* arcs are like circles, just shorter */ ip_rect, /* rectangles have plenty of sides */ @@ -98,6 +99,9 @@ struct inst { struct coord other; layer_type layers; /* bit-set of layers */ } pad; + struct { + struct coord other; + } hole; struct { unit_type r; double a1, a2; @@ -173,6 +177,7 @@ int inst_vec(struct vec *vec, struct coord base); int inst_line(struct obj *obj, struct coord a, struct coord b, unit_type width); int inst_rect(struct obj *obj, struct coord a, struct coord b, unit_type width); int inst_pad(struct obj *obj, const char *name, struct coord a, struct coord b); +int inst_hole(struct obj *obj, struct coord a, struct coord b); int inst_arc(struct obj *obj, struct coord center, struct coord start, struct coord stop, unit_type width); int inst_meas(struct obj *obj, struct coord from, struct coord to); diff --git a/obj.c b/obj.c index 22f2ad5..8b566f2 100644 --- a/obj.c +++ b/obj.c @@ -112,6 +112,9 @@ int obj_anchors(struct obj *obj, struct vec ***anchors) case ot_pad: anchors[1] = &obj->u.pad.other; return 2; + case ot_hole: + anchors[1] = &obj->u.hole.other; + return 2; case ot_meas: anchors[1] = &obj->u.meas.high; return 2; @@ -234,6 +237,11 @@ static int generate_objs(struct frame *frame, struct coord base, int active) if (!ok) goto error; break; + case ot_hole: + if (!inst_hole(obj, obj->base ? obj->base->pos : base, + obj->u.hole.other ? obj->u.hole.other->pos : base)) + goto error; + break; case ot_arc: width = eval_unit_default(obj->u.arc.width, frame, DEFAULT_SILK_WIDTH); diff --git a/obj.h b/obj.h index e70f5e0..b232019 100644 --- a/obj.h +++ b/obj.h @@ -178,6 +178,7 @@ enum obj_type { ot_frame, ot_rect, ot_pad, + ot_hole, ot_line, ot_arc, ot_meas, @@ -200,6 +201,10 @@ struct pad { enum pad_type type; }; +struct hole { + struct vec *other; /* NULL if frame origin */ +}; + struct arc { struct vec *start; /* NULL if frame origin */ struct vec *end; /* NULL if this is a circle */ @@ -214,6 +219,7 @@ struct obj { struct rect rect; struct rect line; struct pad pad; + struct hole hole; struct arc arc; struct meas meas; } u;