Index: trunk/src/plugins/io_easyeda/read.c =================================================================== --- trunk/src/plugins/io_easyeda/read.c (revision 10637) +++ trunk/src/plugins/io_easyeda/read.c (revision 10638) @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,9 @@ csch_alien_read_ctx_t alien; + /* these are used by the pro format only */ csch_cgrp_t *pro_last; /* last group object (e.g. part, pin) created; ATTRs are added to this */ + htsi_t pro_pen_fill; int pass; /* do multiple passes because some objects can be created only when others are already created */ } read_ctx_t; Index: trunk/src/plugins/io_easyeda/read_hi_pro.c =================================================================== --- trunk/src/plugins/io_easyeda/read_hi_pro.c (revision 10637) +++ trunk/src/plugins/io_easyeda/read_hi_pro.c (revision 10638) @@ -47,11 +47,16 @@ #define GET_ARG_STR(dst, nd, num, errstr, errstmt) \ do { \ gdom_node_t *__tmp__ = nd->value.array.child[num]; \ - if (__tmp__->type != GDOM_STRING) { \ - error_at(ctx, nd, ("%s: wrong argument type for arg #%ld (expected string)\n", errstr, (long)num)); \ - errstmt; \ + if ((__tmp__->type == GDOM_DOUBLE) && (__tmp__->value.dbl == -1)) {\ + dst = NULL; \ } \ - dst = __tmp__->value.str; \ + else { \ + if (__tmp__->type != GDOM_STRING) { \ + error_at(ctx, nd, ("%s: wrong argument type for arg #%ld (expected string)\n", errstr, (long)num)); \ + errstmt; \ + } \ + dst = __tmp__->value.str; \ + } \ } while(0) #define GET_ARG_DBL(dst, nd, num, errstr, errstmt) \ @@ -94,6 +99,17 @@ }\ } while(0) +/* Look up style by name and return whether the given style fills */ +static int easypro_style_filled(read_ctx_t *ctx, gdom_node_t *obj, const char *sty) +{ + htsi_entry_t *e = htsi_getentry(&ctx->pro_pen_fill, sty); + if (e == NULL) { + error_at(ctx, obj, ("easypro_style_filled: undefined style '%s'\n", sty)); + return 0; + } + return e->value; +} + /*** parse obj subtrees (lines in the file) ***/ /* Mainly a placeholder for symbol attrs */ @@ -230,9 +246,11 @@ return 0; } +/* "POLY","e253",[758,10,758,70],false,"st6",0 + kw id coords ? sty ? */ static int easypro_parse_poly(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { - const char *penname = DECOR_PEN_NAME(parent); + const char *penname = DECOR_PEN_NAME(parent), *sty; gdom_node_t *coords; double x, y, lx, ly; long n, v; @@ -241,6 +259,7 @@ REQ_ARGC_GTE(obj, 6, "easypro_parse_poly", return -1); GET_ARG_ARRAY(coords, obj, 2, "easypro_parse_poly: coords", return -1); + GET_ARG_STR(sty, obj, 4, "easypro_parse_circle: style name", return -1); v = coords->value.array.used; @@ -254,8 +273,7 @@ } if (v > 4) { - int filled = 0; - TODO("^ filled is coming from linetype's arg 4"); + int filled = easypro_style_filled(ctx, obj, sty); poly = csch_alien_mkpoly(&ctx->alien, parent, penname, filled ? penname : NULL); } else @@ -294,7 +312,7 @@ start x y middle x y end x y linetype */ static int easypro_parse_arc(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { - const char *penname = DECOR_PEN_NAME(parent); + const char *penname = DECOR_PEN_NAME(parent), *sty; double sx, sy, mx, my, ex, ey; double sx2, sy2, mx2, my2, ex2, ey2; double A, B, C, D; @@ -309,6 +327,7 @@ GET_ARG_DBL(my, obj, 5, "easypro_parse_arc: coord my", return -1); GET_ARG_DBL(ex, obj, 6, "easypro_parse_arc: coord ex", return -1); GET_ARG_DBL(ey, obj, 7, "easypro_parse_arc: coord ey", return -1); + GET_ARG_STR(sty, obj, 8, "easypro_parse_arc: style name", return -1); /* figure the center and radius, see https://math.stackexchange.com/q/4000949 */ sx2 = sx*sx; sy2 = sy*sy; @@ -347,9 +366,7 @@ sa *= RND_RAD_TO_DEG; da *= RND_RAD_TO_DEG; - filled = 0; - TODO("filled is coming from linetype's arg 4"); - + filled = easypro_style_filled(ctx, obj, sty); if (filled) { csch_chdr_t *poly = csch_alien_mkpoly(&ctx->alien, parent, penname, penname); csch_alien_append_poly_arc(&ctx->alien, poly, cx, cy, r, sa, da); @@ -361,10 +378,10 @@ } /* "CIRCLE", "e42", 40,10, 10, "st5", 0 - x y r */ + x y r sty */ static int easypro_parse_circle(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { - const char *penname = DECOR_PEN_NAME(parent); + const char *penname = DECOR_PEN_NAME(parent), *sty; double cx, cy, r; int filled; @@ -373,6 +390,7 @@ GET_ARG_DBL(cx, obj, 2, "easypro_parse_circle: coord cx", return -1); GET_ARG_DBL(cy, obj, 3, "easypro_parse_circle: coord cy", return -1); GET_ARG_DBL(r, obj, 4, "easypro_parse_circle: coord r", return -1); + GET_ARG_STR(sty, obj, 5, "easypro_parse_circle: style name", return -1); if (r <= 0) { error_at(ctx, obj, ("easypro_parse_circle: invalid radius\n")); @@ -379,8 +397,7 @@ return -1; } - filled = 0; - TODO("filled is coming from linetype's arg 4"); + filled = easypro_style_filled(ctx, obj, sty); if (filled) { csch_chdr_t *poly = csch_alien_mkpoly(&ctx->alien, parent, penname, penname); @@ -396,7 +413,7 @@ x y rx ,ry ? pen ? */ static int easypro_parse_ellipse(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { - const char *penname = DECOR_PEN_NAME(parent); + const char *penname = DECOR_PEN_NAME(parent), *sty; double cx, cy, rx, ry, ex, ey; path_ctx_t pctx; int filled; @@ -407,6 +424,7 @@ GET_ARG_DBL(cy, obj, 3, "easypro_parse_ellipse: coord cy", return -1); GET_ARG_DBL(rx, obj, 4, "easypro_parse_ellipse: coord r", return -1); GET_ARG_DBL(ry, obj, 5, "easypro_parse_ellipse: coord r", return -1); + GET_ARG_STR(sty, obj, 7, "easypro_parse_ellipse: style name", return -1); if ((rx <= 0) || (ry <= 0)) { error_at(ctx, obj, ("easypro_parse_ellipse: invalid radius\n")); @@ -413,8 +431,7 @@ return -1; } - filled = 0; - TODO("filled is coming from linetype's arg 4"); + filled = easypro_style_filled(ctx, obj, sty); easyeda_svgpath_setup(); @@ -435,7 +452,7 @@ x1 y1 x2 y2 rx,ry ? pen ? */ static int easypro_parse_rect(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { - const char *penname = DECOR_PEN_NAME(parent); + const char *penname = DECOR_PEN_NAME(parent),*sty; double x1, y1, x2, y2, rx, ry, r; int filled; @@ -447,6 +464,7 @@ GET_ARG_DBL(y2, obj, 5, "easypro_parse_rect: coord y2", return -1); GET_ARG_DBL(rx, obj, 6, "easypro_parse_rect: coord rx", return -1); GET_ARG_DBL(ry, obj, 7, "easypro_parse_rect: coord ry", return -1); + GET_ARG_STR(sty, obj, 9, "easypro_parse_rect: style name", return -1); if ((rx < 0) || (ry < 0)) { error_at(ctx, obj, ("easypro_parse_rect: invalid radius\n")); @@ -456,8 +474,7 @@ if (x1 > x2) rnd_swap(double, x1, x2); if (y1 > y2) rnd_swap(double, y1, y2); - filled = 0; - TODO("filled is coming from linetype's arg 4"); + filled = easypro_style_filled(ctx, obj, sty); easyeda_svgpath_setup(); @@ -484,7 +501,7 @@ id start ctrl1 ctrl2 end ? */ static int easypro_parse_bezier(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { - const char *penname = DECOR_PEN_NAME(parent); + const char *penname = DECOR_PEN_NAME(parent), *sty; double sx, sy, ex, ey, c1x, c1y, c2x, c2y; path_ctx_t pctx; gdom_node_t *coords; @@ -493,6 +510,7 @@ REQ_ARGC_GTE(obj, 5, "easypro_parse_bezier", return -1); GET_ARG_ARRAY(coords, obj, 2, "easypro_parse_bezier: coords array", return -1); + GET_ARG_STR(sty, obj, 3, "easypro_parse_bezier: style name", return -1); REQ_ARGC_GTE(coords, 6, "easypro_parse_bezier: coords", return -1); GET_ARG_DBL(sx, coords, 0, "easypro_parse_bezier: coord sx", return -1); @@ -504,8 +522,7 @@ GET_ARG_DBL(ex, coords, 6, "easypro_parse_bezier: coord ex", return -1); GET_ARG_DBL(ey, coords, 7, "easypro_parse_bezier: coord ey", return -1); - filled = 0; - TODO("filled is coming from linetype's arg 4"); + filled = easypro_style_filled(ctx, obj, sty); easyeda_svgpath_setup(); @@ -584,7 +601,30 @@ return 0; } +/* "LINESTYLE","st12",null,null,"#99CCFF",null + kw name ? ? fill ? */ +static int easypro_parse_linestyle(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) +{ + gdom_node_t *ids; + const char *name, *fill; + int is_filled; + REQ_ARGC_GTE(obj, 6, "easypro_parse_linestyle", return -1); + + GET_ARG_STR(name, obj, 1, "easypro_parse_linestyle: name", return -1); + GET_ARG_STR(fill, obj, 4, "easypro_parse_linestyle: name", return -1); + + is_filled = ((fill != NULL) && (*fill == '#')); + + if (!htsi_has(&ctx->pro_pen_fill, name)) + htsi_insert(&ctx->pro_pen_fill, rnd_strdup(name), is_filled); + else + error_at(ctx, obj, ("easypro_parse_linestyle: style '%s' redefined (ignoring)\n", name)); + + return 0; +} + + /* object dispatcher */ static int easypro_parse_any_obj(read_ctx_t *ctx, gdom_node_t *obj, csch_cgrp_t *parent) { @@ -608,9 +648,9 @@ case easy_TEXT: return easypro_parse_text(ctx, obj, parent); case easy_GROUP: return easypro_parse_group(ctx, obj, parent); case easy_OBJ: return easypro_parse_obj(ctx, obj, parent); + case easy_LINESTYLE: return easypro_parse_linestyle(ctx, obj, parent); case easy_FONTSTYLE: return 0; /* ignore: sch-rnd uses pens */ - case easy_LINESTYLE: return 0; /* TODO: needed for fill */ case -1: default: @@ -657,7 +697,20 @@ return 2; } +static void easypro_init_ctx(read_ctx_t *ctx) +{ + ctx->pro_last = NULL; + htsi_init(&ctx->pro_pen_fill, strhash, strkeyeq); +} +static void easypro_uninit_ctx(read_ctx_t *ctx) +{ + htsi_entry_t *e; + for(e = htsi_first(&ctx->pro_pen_fill); e != NULL; e = htsi_next(&ctx->pro_pen_fill, e)) + free(e->key); + htsi_uninit(&ctx->pro_pen_fill); +} + /*** entry ***/ static csch_cgrp_t *easypro_load_sym(read_ctx_t *ctx) { @@ -680,7 +733,7 @@ src = csch_attrib_src_c(ctx->fn, 0, 0, NULL); /* whole-file context, no need to set location */ csch_cobj_attrib_set(ctx->sheet, resgrp, CSCH_ATP_HARDWIRED, "role", "symbol", src); - ctx->pro_last = NULL; + easypro_init_ctx(ctx); /* parse the data section of the tree */ for(n = starti; (rv == 0) && (n < ctx->root->value.array.used); n++) @@ -695,5 +748,7 @@ resgrp = NULL; } + easypro_uninit_ctx(ctx); + return resgrp; }