Index: trunk/src_plugins/io_altium/altium_kw.sphash =================================================================== --- trunk/src_plugins/io_altium/altium_kw.sphash (revision 35594) +++ trunk/src_plugins/io_altium/altium_kw.sphash (revision 35595) @@ -80,6 +80,8 @@ _bin_mid_ysize _bin_bottom_xsize _bin_bottom_ysize + _bin_layer_offs + _bin_layer_type layers top bottom Index: trunk/src_plugins/io_altium/pcbdoc.c =================================================================== --- trunk/src_plugins/io_altium/pcbdoc.c (revision 35594) +++ trunk/src_plugins/io_altium/pcbdoc.c (revision 35595) @@ -323,6 +323,27 @@ return conv_layer_field_(rctx, field, 1, &dummy); } +static pcb_layer_t *bin_layer(rctx_t *rctx, long lyt, long offs) +{ + rnd_layer_id_t lid, lids[PCB_MAX_LAYER]; + + if ((lyt & PCB_LYT_COPPER) && (lyt & PCB_LYT_INTERN)) { + int len; + + len = pcb_layer_list(rctx->pcb, lyt, lids, PCB_MAX_LAYER); + offs = offs - 1; + if ((offs < 0) || (offs >= len)) + return NULL; + lid = lids[offs]; + } + else { + if (pcb_layer_list(rctx->pcb, lyt, &lid, 1) != 1) + return NULL; + } + + return &rctx->pcb->Data->Layer[lid]; +} + #define BUMP_COORD(dst, src) do { if (src > dst) dst = src; } while(0) typedef struct { @@ -1268,17 +1289,20 @@ altium_field_t *ur = NULL; pcb_layer_t *ly = NULL; pcb_subc_t *sc; - altium_field_t *text = NULL; + altium_field_t *ly_ascii = NULL, *text = NULL; pcb_text_t *t; rnd_coord_t x = RND_COORD_MAX, y = RND_COORD_MAX, x1 = RND_COORD_MAX, y1 = RND_COORD_MAX, x2 = RND_COORD_MAX, y2 = RND_COORD_MAX, w = RND_COORD_MAX; double rot = 0; int mir = 0, designator = 0, comment = 0; long compid = -1; + long binly_lyt = 0, binly_offs = 0; for(field = gdl_first(&rec->fields); field != NULL; field = gdl_next(&rec->fields, field)) { switch(field->type) { case altium_kw_field_userrouted:ur = field; break; - case altium_kw_field_layer: ly = conv_layer_field(rctx, field); break; + case altium_kw_field__bin_layer_offs: binly_offs = conv_long_field(field); break; + case altium_kw_field__bin_layer_type: binly_lyt = conv_long_field(field); break; + case altium_kw_field_layer: ly_ascii = field; break; case altium_kw_field_text: text = field; break; case altium_kw_field_x: x = conv_coordx_field(rctx, field); break; case altium_kw_field_y: y = conv_coordy_field(rctx, field); break; @@ -1295,6 +1319,16 @@ default: break; } } + + if (binly_lyt != 0) + ly = bin_layer(rctx, binly_lyt, binly_offs); + else if (ly_ascii != NULL) + ly = conv_layer_field(rctx, ly_ascii); + else { + rnd_message(RND_MSG_ERROR, "Invalid text object: missing layer field (text not created)\n"); + continue; + } + if ((x1 == RND_COORD_MAX) || (y1 == RND_COORD_MAX) || (x2 == RND_COORD_MAX) || (y2 == RND_COORD_MAX) || (w == RND_COORD_MAX)) { if ((x == RND_COORD_MAX) || (y == RND_COORD_MAX)) { rnd_message(RND_MSG_ERROR, "Invalid text object: missing coordinate or width (text not created)\n"); Index: trunk/src_plugins/io_altium/pcbdoc_bin.c =================================================================== --- trunk/src_plugins/io_altium/pcbdoc_bin.c (revision 35594) +++ trunk/src_plugins/io_altium/pcbdoc_bin.c (revision 35595) @@ -419,12 +419,47 @@ return 0; } +/* For whatever reason, layer assigment for text doesn't really depend on + the layer field in d[0] (a.k.a. ly1 here), but has some sort of + type:offs pair of fields near the end of the record. Translate the + type:offs pair to pcb-rnd layer types and return offset in ly1 */ +static long altium_bin_text_layer(int *ly1, int offs, int type) +{ + int orig_ly1 = *ly1; +/* printf("aux=%d,%d,%d\n", *ly1, offs, type);*/ + + *ly1 = 0; + switch(type) { + case 0: /* copper */ + if (offs == -1) return PCB_LYT_BOTTOM | PCB_LYT_COPPER; + if (offs == 1) return PCB_LYT_TOP | PCB_LYT_COPPER; + if ((offs > 1) && (offs < 18)) { + *ly1 = offs - 1; + return PCB_LYT_INTERN | PCB_LYT_COPPER; + } + rnd_message(RND_MSG_ERROR, "Invalid text copper layer: %d:%d:%d\n", orig_ly1, offs, type); + return 0; + case 3: /* non-copper */ + if (offs == 6) return PCB_LYT_TOP | PCB_LYT_SILK; + if (offs == 7) return PCB_LYT_BOTTOM | PCB_LYT_SILK; + if (offs == 8) return PCB_LYT_TOP | PCB_LYT_PASTE; + if (offs == 9) return PCB_LYT_BOTTOM | PCB_LYT_PASTE; + if (offs == 10) return PCB_LYT_TOP | PCB_LYT_MASK; + if (offs == 11) return PCB_LYT_BOTTOM | PCB_LYT_MASK; + rnd_message(RND_MSG_ERROR, "Invalid text non-copper layer: %d:%d:%d\n", orig_ly1, offs, type); + return 0; + } + + rnd_message(RND_MSG_ERROR, "Unknown text layer: %d:%d:%d\n", orig_ly1, offs, type); + return 0; +} + int pcbdoc_bin_parse_texts6(rnd_hidlib_t *hidlib, altium_tree_t *tree, ucdf_file_t *fp, altium_buf_t *tmp) { for(;;) { unsigned char *d; - int rectype; + int rectype, lyt, lyoffs; long len; altium_record_t *rec; @@ -451,9 +486,23 @@ /* printf(" string='%s'\n", tmp->data+1);*/ rec = pcbdoc_ascii_new_rec(tree, "Text", altium_kw_record_text); - FIELD_LNG(rec, layer, d[0]+31); - FIELD_LNG(rec, net, load_int(d+3, 2)); - FIELD_LNG(rec, component, load_int(d+7, 2)); + + + lyoffs = d[0]; + lyt = altium_bin_text_layer(&lyoffs, load_int(d+226, 2), d[228]); + FIELD_LNG(rec, _bin_layer_offs, lyoffs); + FIELD_LNG(rec, _bin_layer_type, lyt); + +/* { + int n; + printf("aux="); + for(n = 226; n < 230; n++) + printf("%d ", d[n]); + printf("\n"); + }*/ + + if ((d[0] == 2) || (d[0] == 5)) + FIELD_LNG(rec, component, load_int(d+7, 2)); TODO("poly is not used by the high level code; find an example"); FIELD_CRD(rec, x, bmil(d+13)); FIELD_CRD(rec, y, bmil(d+17));