Index: trunk/src/obj_pstk.c =================================================================== --- trunk/src/obj_pstk.c (revision 13400) +++ trunk/src/obj_pstk.c (revision 13401) @@ -70,7 +70,7 @@ free(ps); } -pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags, double rot, int xmirror) +pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags, double rot, int xmirror, int smirror) { pcb_pstk_t *ps; @@ -88,6 +88,7 @@ ps->ID = pcb_create_ID_get(); ps->rot = rot; ps->xmirror = xmirror; + ps->smirror = smirror; pcb_pstk_add(data, ps); pcb_poly_clear_from_poly(data, PCB_TYPE_PSTK, NULL, ps); return ps; @@ -95,7 +96,7 @@ pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags) { - return pcb_pstk_new_tr(data, proto, x, y, clearance, Flags, 0, 0); + return pcb_pstk_new_tr(data, proto, x, y, clearance, Flags, 0, 0, 0); } @@ -184,6 +185,7 @@ return NULL; dst->rot = src->rot; dst->xmirror = src->xmirror; + dst->smirror = src->smirror; dst->protoi = -1; /* invalidate the transformed index to get it recalculated */ return dst; } @@ -756,11 +758,11 @@ void pcb_pstk_mirror(pcb_pstk_t *ps, pcb_coord_t y_offs, int swap_side) { - int xmirror = ps->xmirror; + int xmirror = ps->xmirror, smirror = ps->smirror; /* change the mirror flag - this will automatically cause mirroring in every aspect */ - pcb_pstk_change_instance(ps, NULL, NULL, NULL, &xmirror); + pcb_pstk_change_instance(ps, NULL, NULL, NULL, &xmirror, &smirror); /* if mirror center is not 0, also move, to emulate that the mirror took place around that point */ @@ -811,7 +813,7 @@ pcb_cardinal_t proto; pcb_coord_t clearance; double rot; - int xmirror; + int xmirror, smirror; } padstack_change_instance_t; #define swap(a,b,type) \ @@ -864,6 +866,7 @@ swap(ps->Clearance, u->clearance, pcb_coord_t); swap(ps->rot, u->rot, double); swap(ps->xmirror, u->xmirror, int); + swap(ps->smirror, u->smirror, int); /* force re-render the prototype */ ps->protoi = -1; @@ -881,7 +884,7 @@ static void undo_change_instance_print(void *udata, char *dst, size_t dst_len) { padstack_change_instance_t *u = udata; - pcb_snprintf(dst, dst_len, "padstack change: clearance=%$mm rot=%.2f xmirror=%d\n", u->clearance, u->rot, u->xmirror); + pcb_snprintf(dst, dst_len, "padstack change: clearance=%$mm rot=%.2f xmirror=%d smirror=%d\n", u->clearance, u->rot, u->xmirror, u->smirror); } static const uundo_oper_t undo_pstk_change_instance = { @@ -892,7 +895,7 @@ undo_change_instance_print }; -int pcb_pstk_change_instance(pcb_pstk_t *ps, pcb_cardinal_t *proto, const pcb_coord_t *clearance, double *rot, int *xmirror) +int pcb_pstk_change_instance(pcb_pstk_t *ps, pcb_cardinal_t *proto, const pcb_coord_t *clearance, double *rot, int *xmirror, int *smirror) { padstack_change_instance_t *u; long int parent_ID; @@ -915,6 +918,7 @@ u->clearance = clearance ? *clearance : ps->Clearance; u->rot = rot ? *rot : ps->rot; u->xmirror = xmirror ? *xmirror : ps->xmirror; + u->smirror = smirror ? *smirror : ps->smirror; pcb_pstk_bbox(ps); ctx.clip.clear = 1; Index: trunk/src/obj_pstk.h =================================================================== --- trunk/src/obj_pstk.h (revision 13400) +++ trunk/src/obj_pstk.h (revision 13401) @@ -35,7 +35,7 @@ pcb_coord_t x, y; pcb_coord_t Clearance; double rot; /* rotation angle */ - int xmirror; + char xmirror, smirror; struct { unsigned long used; unsigned char *shape; /* indexed by layer ID */ @@ -64,7 +64,7 @@ pcb_coord_t hdia; /* if > 0, diameter of the hole (else there's no hole) */ int htop, hbottom; /* if hdia > 0, determine the hole's span, counted in copper layer groups from the top or bottom copper layer group */ - pcb_vtpadstack_tshape_t tr; /* [0] is the canonical prototype with rot=0 and xmirror=0; the rest is an unordered list of transformed entries */ + pcb_vtpadstack_tshape_t tr; /* [0] is the canonical prototype with rot=0, xmirror=0 and smirror=0; the rest is an unordered list of transformed entries */ /* local cache - not saved */ unsigned long hash; /* optimization: linear search compare speeded up: go into detailed match only if hash matches */ @@ -76,7 +76,7 @@ pcb_pstk_t *pcb_pstk_alloc(pcb_data_t *data); void pcb_pstk_free(pcb_pstk_t *ps); pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags); -pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags, double rot, int xmirror); +pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags, double rot, int xmirror, int smirror); void pcb_pstk_add(pcb_data_t *data, pcb_pstk_t *ps); void pcb_pstk_bbox(pcb_pstk_t *ps); @@ -86,7 +86,7 @@ pcb_pstk_t *pcb_pstk_by_id(pcb_data_t *base, long int ID); /* Undoably change the instance parameters of a padstack ref */ -int pcb_pstk_change_instance(pcb_pstk_t *ps, pcb_cardinal_t *proto, const pcb_coord_t *clearance, double *rot, int *xmirror); +int pcb_pstk_change_instance(pcb_pstk_t *ps, pcb_cardinal_t *proto, const pcb_coord_t *clearance, double *rot, int *xmirror, int *smirror); /* Return whether a group is empty (free of padstack shapes) */ pcb_bool pcb_pstk_is_group_empty(pcb_board_t *pcb, pcb_layergrp_id_t gid); @@ -138,7 +138,7 @@ int pcb_pstk_proto_change_hole(pcb_pstk_proto_t *proto, const int *hplated, const pcb_coord_t *hdia, const int *htop, const int *hbottom); /* Find or create a new transformed version of an existing proto */ -pcb_pstk_tshape_t *pcb_pstk_make_tshape(pcb_data_t *data, pcb_pstk_proto_t *proto, double rot, int xmirror, int *out_protoi); +pcb_pstk_tshape_t *pcb_pstk_make_tshape(pcb_data_t *data, pcb_pstk_proto_t *proto, double rot, int xmirror, int smirror, int *out_protoi); /* Deep copy a prototype or shape */ void pcb_pstk_proto_copy(pcb_pstk_proto_t *dst, const pcb_pstk_proto_t *src); Index: trunk/src/obj_pstk_inlines.h =================================================================== --- trunk/src/obj_pstk_inlines.h (revision 13400) +++ trunk/src/obj_pstk_inlines.h (revision 13401) @@ -84,7 +84,7 @@ pcb_pstk_proto_t *pr = pcb_pstk_get_proto_(ps->parent.data, ps->proto); if (pr == NULL) return NULL; - return pcb_pstk_make_tshape(ps->parent.data, pr, ps->rot, ps->xmirror, &ps->protoi); + return pcb_pstk_make_tshape(ps->parent.data, pr, ps->rot, ps->xmirror, ps->smirror, &ps->protoi); } return pcb_pstk_get_tshape_(ps->parent.data, ps->proto, ps->protoi); } Index: trunk/src/obj_pstk_op.c =================================================================== --- trunk/src/obj_pstk_op.c (revision 13400) +++ trunk/src/obj_pstk_op.c (revision 13401) @@ -32,7 +32,7 @@ return NULL; npid = pcb_pstk_proto_insert_dup(ctx->buffer.dst, proto, 1); - p = pcb_pstk_new_tr(ctx->buffer.dst, npid, ps->x, ps->y, ps->Clearance, pcb_flag_mask(ps->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg), ps->rot, ps->xmirror); + p = pcb_pstk_new_tr(ctx->buffer.dst, npid, ps->x, ps->y, ps->Clearance, pcb_flag_mask(ps->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg), ps->rot, ps->xmirror, ps->smirror); return pcb_pstk_copy_meta(p, ps); } @@ -76,7 +76,7 @@ return NULL; npid = pcb_pstk_proto_insert_dup(data, proto, 1); - nps = pcb_pstk_new_tr(data, npid, ps->x + ctx->copy.DeltaX, ps->y + ctx->copy.DeltaY, ps->Clearance, pcb_flag_mask(ps->Flags, PCB_FLAG_FOUND), ps->rot, ps->xmirror); + nps = pcb_pstk_new_tr(data, npid, ps->x + ctx->copy.DeltaX, ps->y + ctx->copy.DeltaY, ps->Clearance, pcb_flag_mask(ps->Flags, PCB_FLAG_FOUND), ps->rot, ps->xmirror, ps->smirror); if (nps == NULL) return NULL; @@ -199,7 +199,7 @@ if ((rot == 360.0) || (rot == -360.0)) rot = 0; - if (pcb_pstk_change_instance(ps, NULL, NULL, &rot, NULL) == 0) { + if (pcb_pstk_change_instance(ps, NULL, NULL, &rot, NULL, NULL) == 0) { pcb_coord_t nx = ps->x, ny = ps->y; @@ -266,7 +266,7 @@ if (nproto == PCB_PADSTACK_INVALID) return NULL; - if (pcb_pstk_change_instance(ps, &nproto, NULL, NULL, NULL) == 0) + if (pcb_pstk_change_instance(ps, &nproto, NULL, NULL, NULL, NULL) == 0) return ps; return NULL; @@ -288,7 +288,7 @@ if (ps->Clearance == value) return NULL; - if (pcb_pstk_change_instance(ps, NULL, &value, NULL, NULL) == 0) + if (pcb_pstk_change_instance(ps, NULL, &value, NULL, NULL, NULL) == 0) return ps; return NULL; @@ -318,7 +318,7 @@ if (nproto == PCB_PADSTACK_INVALID) return NULL; - if (pcb_pstk_change_instance(ps, &nproto, NULL, NULL, NULL) == 0) + if (pcb_pstk_change_instance(ps, &nproto, NULL, NULL, NULL, NULL) == 0) return ps; return NULL; Index: trunk/src/obj_pstk_proto.c =================================================================== --- trunk/src/obj_pstk_proto.c (revision 13400) +++ trunk/src/obj_pstk_proto.c (revision 13401) @@ -111,6 +111,7 @@ ts = pcb_vtpadstack_tshape_alloc_append(&dst->tr, 1); ts->rot = 0.0; ts->xmirror = 0; + ts->smirror = 0; ts->len = 0; for(n = 0, o = (pcb_any_obj_t **)objs->array; n < vtp0_len(objs); n++,o++) { switch((*o)->type) { @@ -315,6 +316,7 @@ ts_dst->rot = ts_src->rot; ts_dst->xmirror = ts_src->xmirror; + ts_dst->smirror = ts_src->smirror; ts_dst->shape = malloc(sizeof(pcb_pstk_shape_t) * ts_src->len); ts_dst->len = ts_src->len; memcpy(ts_dst->shape, ts_src->shape, sizeof(pcb_pstk_shape_t) * ts_src->len); @@ -382,6 +384,11 @@ } } +void pcb_pstk_tshape_smirror(pcb_pstk_tshape_t *ts) +{ +#warning padstack TODO +} + void pcb_pstk_proto_copy(pcb_pstk_proto_t *dst, const pcb_pstk_proto_t *src) { pcb_pstk_tshape_t *ts_dst, *ts_src; @@ -398,6 +405,7 @@ /* make sure it's the canonical form */ ts_dst->rot = 0.0; ts_dst->xmirror = 0; + ts_dst->smirror = 0; dst->in_use = 1; } @@ -608,15 +616,16 @@ #define TSHAPE_ANGLE_TOL 0.01 #define tshape_angle_eq(a1, a2) (((a1 - a2) >= -TSHAPE_ANGLE_TOL) && ((a1 - a2) <= TSHAPE_ANGLE_TOL)) -pcb_pstk_tshape_t *pcb_pstk_make_tshape(pcb_data_t *data, pcb_pstk_proto_t *proto, double rot, int xmirror, int *out_protoi) +pcb_pstk_tshape_t *pcb_pstk_make_tshape(pcb_data_t *data, pcb_pstk_proto_t *proto, double rot, int xmirror, int smirror, int *out_protoi) { size_t n; pcb_pstk_tshape_t *ts; xmirror = !!xmirror; + smirror = !!smirror; /* cheap case: canonical */ - if (tshape_angle_eq(rot, 0.0) && (xmirror == 0)) { + if (tshape_angle_eq(rot, 0.0) && (xmirror == 0) && (smirror == 0)) { if (out_protoi != NULL) *out_protoi = 0; return &proto->tr.array[0]; } @@ -624,7 +633,7 @@ /* search for an existing version in the cache - we expect only a few transformations per padstack, the result is cached -> linear search. */ for(n = 0; n < proto->tr.used; n++) { - if (tshape_angle_eq(proto->tr.array[n].rot, rot) && (proto->tr.array[n].xmirror == xmirror)) { + if (tshape_angle_eq(proto->tr.array[n].rot, rot) && (proto->tr.array[n].xmirror == xmirror) && (proto->tr.array[n].smirror == smirror)) { if (out_protoi != NULL) *out_protoi = n; return &proto->tr.array[n]; } @@ -643,8 +652,12 @@ if (xmirror) pcb_pstk_tshape_xmirror(ts); + if (smirror) + pcb_pstk_tshape_smirror(ts); + ts->rot = rot; ts->xmirror = xmirror; + ts->smirror = smirror; return ts; } Index: trunk/src/obj_pstk_shape.h =================================================================== --- trunk/src/obj_pstk_shape.h (revision 13400) +++ trunk/src/obj_pstk_shape.h (revision 13401) @@ -64,6 +64,7 @@ typedef struct pcb_pstk_tshape_s { double rot; unsigned xmirror:1; + unsigned smirror:1; unsigned char len; /* number of shapes (PCB_PADSTACK_MAX_SHAPES) */ pcb_pstk_shape_t *shape; /* list of layer-shape pairs */ Index: trunk/src/obj_subc.c =================================================================== --- trunk/src/obj_subc.c (revision 13400) +++ trunk/src/obj_subc.c (revision 13401) @@ -748,7 +748,7 @@ padstacklist_foreach(&src->data->padstack, &it, ps) { pcb_cardinal_t pid = pcb_pstk_proto_insert_dup(sc->data, pcb_pstk_get_proto(ps), 1); - nps = pcb_pstk_new_tr(sc->data, pid, ps->x+dx, ps->y+dy, ps->Clearance, ps->Flags, ps->rot, ps->xmirror); + nps = pcb_pstk_new_tr(sc->data, pid, ps->x+dx, ps->y+dy, ps->Clearance, ps->Flags, ps->rot, ps->xmirror, ps->smirror); pcb_pstk_copy_meta(nps, ps); MAYBE_KEEP_ID(nps, ps); if (nps != NULL) Index: trunk/src_plugins/dialogs/dlg_padstack.c =================================================================== --- trunk/src_plugins/dialogs/dlg_padstack.c (revision 13400) +++ trunk/src_plugins/dialogs/dlg_padstack.c (revision 13401) @@ -52,7 +52,7 @@ /* widget IDs */ int tab_instance, tab_prototype; int but_instance, but_prototype; - int proto_id, clearance, rot, xmirror; + int proto_id, clearance, rot, xmirror, smirror; int proto_shape[pse_num_layers]; int proto_info[pse_num_layers]; int proto_change[pse_num_layers]; @@ -126,6 +126,7 @@ PCB_DAD_SET_VALUE(hid_ctx, pse->clearance, coord_value, pse->ps->Clearance); PCB_DAD_SET_VALUE(hid_ctx, pse->rot, real_value, pse->ps->rot); PCB_DAD_SET_VALUE(hid_ctx, pse->xmirror, int_value, pse->ps->xmirror); + PCB_DAD_SET_VALUE(hid_ctx, pse->smirror, int_value, pse->ps->smirror); /* proto - layers */ for(n = 0; n < pse_num_layers; n++) { @@ -216,7 +217,8 @@ NULL, &pse->attrs[pse->clearance].default_val.coord_value, &pse->attrs[pse->rot].default_val.real_value, - &pse->attrs[pse->xmirror].default_val.int_value); + &pse->attrs[pse->xmirror].default_val.int_value, + &pse->attrs[pse->smirror].default_val.int_value); lock++; pse_ps2dlg(hid_ctx, pse); /* to get calculated text fields updated */ @@ -495,6 +497,10 @@ PCB_DAD_BOOL(dlg, ""); pse.xmirror = PCB_DAD_CURRENT(dlg); PCB_DAD_CHANGE_CB(dlg, pse_chg_instance); + PCB_DAD_LABEL(dlg, "S-mirror"); + PCB_DAD_BOOL(dlg, ""); + pse.smirror = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_instance); PCB_DAD_END(dlg); PCB_DAD_END(dlg); PCB_DAD_END(dlg); Index: trunk/src_plugins/io_lihata/read.c =================================================================== --- trunk/src_plugins/io_lihata/read.c (revision 13400) +++ trunk/src_plugins/io_lihata/read.c (revision 13401) @@ -778,6 +778,9 @@ tmp = 0; parse_int(&tmp, lht_dom_hash_get(obj, "xmirror")); ps->xmirror = tmp; + tmp = 0; + parse_int(&tmp, lht_dom_hash_get(obj, "smirror")); + ps->smirror = tmp; parse_coord(&ps->Clearance, lht_dom_hash_get(obj, "clearance")); parse_ulong(&ul, lht_dom_hash_get(obj, "proto")); ps->proto = ul; Index: trunk/src_plugins/io_lihata/write.c =================================================================== --- trunk/src_plugins/io_lihata/write.c (revision 13400) +++ trunk/src_plugins/io_lihata/write.c (revision 13401) @@ -614,6 +614,7 @@ lht_dom_hash_put(obj, build_textf("clearance", CFMT, ps->Clearance)); lht_dom_hash_put(obj, build_textf("rot", "%f", ps->rot)); lht_dom_hash_put(obj, build_textf("xmirror", "%d", ps->xmirror)); + lht_dom_hash_put(obj, build_textf("smirror", "%d", ps->smirror)); lht_dom_hash_put(obj, thr = lht_dom_node_alloc(LHT_LIST, "thermal")); for(n = 0; n < ps->thermals.used; n++) { Index: trunk/src_plugins/propedit/propsel.c =================================================================== --- trunk/src_plugins/propedit/propsel.c (revision 13400) +++ trunk/src_plugins/propedit/propsel.c (revision 13401) @@ -181,6 +181,7 @@ map_chk_skip(ctx, ps); map_add_prop(ctx, "p/padstack/xmirror", pcb_coord_t, ps->xmirror); + map_add_prop(ctx, "p/padstack/smirror", pcb_coord_t, ps->smirror); map_add_prop(ctx, "p/padstack/rotation", pcb_angle_t, ps->rot); map_add_prop(ctx, "p/padstack/proto", pcb_coord_t, ps->proto); @@ -461,9 +462,11 @@ if (st->d_valid && (strcmp(pn, "rotation") == 0) && pcb_obj_rotate(PCB_TYPE_PSTK, ps, ps, NULL, ps->x, ps->y, st->d)) DONE; if (st->c_valid && (strcmp(pn, "xmirror") == 0) && - (pcb_pstk_change_instance(ps, NULL, NULL, NULL, &i) == 0)) DONE; + (pcb_pstk_change_instance(ps, NULL, NULL, NULL, &i, NULL) == 0)) DONE; + if (st->c_valid && (strcmp(pn, "smirror") == 0) && + (pcb_pstk_change_instance(ps, NULL, NULL, NULL, NULL, &i) == 0)) DONE; if (st->c_valid && (strcmp(pn, "proto") == 0) && - (pcb_pstk_change_instance(ps, &ca, NULL, NULL, NULL) == 0)) DONE; + (pcb_pstk_change_instance(ps, &ca, NULL, NULL, NULL, NULL) == 0)) DONE; if (st->c_valid && (strcmp(pn, "hole") == 0) && (pcb_pstk_proto_change_hole(proto, NULL, &st->c, NULL, NULL) == 0)) DONE; if (st->c_valid && (strcmp(pn, "plated") == 0) && Index: trunk/src_plugins/query/fields.sphash =================================================================== --- trunk/src_plugins/query/fields.sphash (revision 13400) +++ trunk/src_plugins/query/fields.sphash (revision 13401) @@ -37,4 +37,5 @@ refdes length xmirror +smirror plated Index: trunk/src_plugins/query/query_access.c =================================================================== --- trunk/src_plugins/query/query_access.c (revision 13400) +++ trunk/src_plugins/query/query_access.c (revision 13401) @@ -516,6 +516,7 @@ case query_fields_clearance: PCB_QRY_RET_INT(res, p->Clearance); case query_fields_rotation: PCB_QRY_RET_DBL(res, p->rot); case query_fields_xmirror: PCB_QRY_RET_INT(res, p->xmirror); + case query_fields_smirror: PCB_QRY_RET_INT(res, p->smirror); case query_fields_plated: PCB_QRY_RET_INT(res, (proto->hdia > 0) && proto->hplated); case query_fields_hole: PCB_QRY_RET_INT(res, proto->hdia);