diff --git a/sch2fig/Makefile b/sch2fig/Makefile index a16acff..45c060f 100644 --- a/sch2fig/Makefile +++ b/sch2fig/Makefile @@ -11,7 +11,7 @@ # NAME = sch2fig -OBJS = main.o sch-parse.o sch-render.o lib.o \ +OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.o \ style.o fig.o cairo.o gfx.o dwg.o text.o misc.o CFLAGS = -g -O -Wall -Wextra -Wno-unused-parameter -Wshadow \ diff --git a/sch2fig/lib-parse.c b/sch2fig/lib-parse.c new file mode 100644 index 0000000..e5bf7d6 --- /dev/null +++ b/sch2fig/lib-parse.c @@ -0,0 +1,265 @@ +/* + * lib.c - Parse Eeschema .lib file + * + * Written 2016 by Werner Almesberger + * Copyright 2016 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include + +#include "util.h" +#include "text.h" +#include "lib.h" + + +struct comp *comps = NULL; + +static struct comp *curr_comp; /* current component */ +static struct comp **next_comp = &comps; +static struct lib_obj **next_obj; + + +/* ----- Text -------------------------------------------------------------- */ + + +static enum text_style decode_style(const char *s) +{ + if (!strcmp(s, "Normal")) + return text_normal; + assert(0); +} + + +/* ----- Polygons ---------------------------------------------------------- */ + + +static bool parse_poly(struct lib_poly *poly, const char *line, int points) +{ + int i, n; + + poly->points = points; + poly->x = alloc_size(sizeof(int) * points); + poly->y = alloc_size(sizeof(int) * points); + for (i = 0; i != points; i++) { + if (sscanf(line, "%d %d %n", + poly->x + i, poly->y + i, &n) != 2) + return 0; + line += n; + } + if (sscanf(line, "%c", &poly->fill) != 1) + return 0; + return 1; +} + + +/* ----- Definitions ------------------------------------------------------- */ + + +static bool parse_def(const char *line) +{ + char *s; + char draw_num, draw_name; + unsigned name_offset; + unsigned units; + + if (sscanf(line, "DEF %ms %*s %*d %u %c %c %u", + &s, &name_offset, &draw_num, &draw_name, &units) != 5) + return 0; + + curr_comp = alloc_type(struct comp); + if (*s == '~') + s++; + curr_comp->name = s; + curr_comp->units = units; + + curr_comp->visible = 0; + curr_comp->show_pin_name = draw_name == 'Y'; + curr_comp->show_pin_num = draw_num == 'Y'; + curr_comp->name_offset = name_offset; + + curr_comp->objs = NULL; + next_obj = &curr_comp->objs; + + curr_comp->next = NULL; + *next_comp = curr_comp; + next_comp = &curr_comp->next; + + return 1; +} + + +/* ----- Arcs -------------------------------------------------------------- */ + + +static bool parse_arc(struct lib_obj *obj, const char *line) +{ + struct lib_arc *arc = &obj->u.arc; + int a1, a2; + + if (sscanf(line, "A %d %d %d %d %d %u %u %u %c", + &arc->x, &arc->y, &arc->r, &a1, &a2, &obj->unit, &obj->convert, + &arc->thick, &arc->fill) != 9) + return 0; + + /* + * KiCad arcs can be clockwise or counter-clockwise. They must always + * be smaller than 180 degrees. + */ + + while (a1 < 0) + a1 += 3600; + while (a2 < 0) + a2 += 3600; + a1 %= 3600; + a2 %= 3600; + if (a2 < a1) + a2 += 3600; + assert(a2 - a1 != 1800); + if (a2 - a1 > 1800) + swap(a1, a2); + + arc->start_a = (a1 % 3600) / 10; + arc->end_a = (a2 % 3600) / 10; + + return 1; +} + + +/* ----- Library parser ---------------------------------------------------- */ + + +bool lib_parse(struct lib_ctx *ctx, const char *line) +{ + int n = 0; + unsigned points; + struct lib_obj *obj; + char *style; + unsigned zero1, zero2; + char vis; + + ctx->lineno++; + + switch (ctx->state) { + case lib_skip: + if (parse_def(line)) { + ctx->state = lib_def; + return 1; + } + return 1; + case lib_def: + if (sscanf(line, "DRAW%n", &n) == 0 && n) { + ctx->state = lib_draw; + return 1; + } + if (sscanf(line, "F%d \"\" %*d %*d %*d %*c %c", &n, &vis) == 2 + || sscanf(line, "F%d \"%*[^\"]\" %*d %*d %*d %*c %c", + &n, &vis) == 2) { + if (vis == 'V') + curr_comp->visible |= 1 << n; + return 1; + } + /* @@@ explicitly ignore FPLIST */ + return 1; + case lib_draw: + if (sscanf(line, "ENDDRAW%n", &n) == 0 && n) { + ctx->state = lib_skip; + return 1; + } + + obj = alloc_type(struct lib_obj); + obj->next = NULL; + *next_obj = obj; + next_obj = &obj->next; + + if (sscanf(line, "P %u %u %u %u %n", + &points, &obj->unit, &obj->convert, &obj->u.poly.thick, + &n) == 4) { + obj->type = lib_obj_poly; + if (parse_poly(&obj->u.poly, line + n, points)) + return 1; + break; + } + if (sscanf(line, "S %d %d %d %d %u %u %d %c", + &obj->u.rect.sx, &obj->u.rect.sy, &obj->u.rect.ex, + &obj->u.rect.ey, &obj->unit, &obj->convert, + &obj->u.rect.thick, &obj->u.rect.fill) == 8) { + obj->type = lib_obj_rect; + return 1; + } + if (sscanf(line, "C %d %d %d %u %u %d %c", + &obj->u.circ.x, &obj->u.circ.y, &obj->u.circ.r, + &obj->unit, &obj->convert, &obj->u.circ.thick, + &obj->u.circ.fill) == 7) { + obj->type = lib_obj_circ; + return 1; + } + if (parse_arc(obj, line)) { + obj->type = lib_obj_arc; + return 1; + } + n = sscanf(line, + "T %d %d %d %d %u %u %u \"%m[^\"]\" %ms %u %c %c", + &obj->u.text.orient, &obj->u.text.x, &obj->u.text.y, + &obj->u.text.dim, &zero1, &obj->unit, &obj->convert, + &obj->u.text.s, &style, &zero2, + &obj->u.text.hor_align, &obj->u.text.vert_align); + if (n != 12) { + n = sscanf(line, + "T %d %d %d %d %u %u %u %ms %ms %u %c %c", + &obj->u.text.orient, &obj->u.text.x, &obj->u.text.y, + &obj->u.text.dim, &zero1, &obj->unit, &obj->convert, + &obj->u.text.s, &style, &zero2, + &obj->u.text.hor_align, &obj->u.text.vert_align); + while (n == 12) { + char *tilde; + + tilde = strchr(obj->u.text.s, '~'); + if (!tilde) + break; + *tilde = ' '; + } + } + /* + * zero2 seems to be the font style: 0 = normal, 1 = bold ? + */ + if (n == 12) { + if (zero1) { + fprintf(stderr, "%u: only understand 0 x x\n" + "\"%s\"\n", ctx->lineno, line); + exit(1); + } + obj->u.text.style = decode_style(style); + obj->type = lib_obj_text; + return 1; + } + if (sscanf(line, "X %ms %ms %d %d %d %c %d %d %u %u %c", + &obj->u.pin.name, &obj->u.pin.number, + &obj->u.pin.x, &obj->u.pin.y, &obj->u.pin.length, + &obj->u.pin.orient, + &obj->u.pin.number_size, &obj->u.pin.name_size, + &obj->unit, &obj->convert, &obj->u.pin.etype) == 11) { + obj->type = lib_obj_pin; + return 1; + } + break; + default: + abort(); + } + fprintf(stderr, "%u: cannot parse\n\"%s\"\n", ctx->lineno, line); + exit(1); +} + + +void lib_init(struct lib_ctx *ctx) +{ + ctx->state = lib_skip; + ctx->lineno = 0; +} diff --git a/sch2fig/lib.c b/sch2fig/lib-render.c similarity index 53% rename from sch2fig/lib.c rename to sch2fig/lib-render.c index ce0aed3..57d5687 100644 --- a/sch2fig/lib.c +++ b/sch2fig/lib-render.c @@ -1,5 +1,5 @@ /* - * lib.c - Parse Eeschema .lib file + * lib.c - Render component from library * * Written 2016 by Werner Almesberger * Copyright 2016 by Werner Almesberger @@ -13,8 +13,6 @@ #include #include -#include -#include #include #include "util.h" @@ -26,82 +24,9 @@ #include "lib.h" -enum text_style { - text_normal, -}; - -struct lib_obj { - enum lib_obj_type { - lib_obj_poly, - lib_obj_rect, - lib_obj_circ, - lib_obj_arc, - lib_obj_text, - lib_obj_pin, - } type; - unsigned unit; - unsigned convert; - union { - struct lib_poly { - int thick; - char fill; - int points; - int *x; - int *y; - } poly; - struct lib_rect { - int thick; - char fill; - int sx, sy; - int ex, ey; - } rect; - struct lib_circ { - int x, y; - int r; - int thick; - char fill; - } circ; - struct lib_arc { - int x, y; - int r; - int start_a, end_a; - int thick; - char fill; - } arc; - struct lib_text { - int orient; - int x, y; - int dim; - char *s; - enum text_style style; - char hor_align; - char vert_align; - } text; - struct lib_pin { - char *name; - char *number; - int x, y; - int length; - char orient; - int number_size; - int name_size; - char etype; - // @@@ shape - } pin; - } u; - struct lib_obj *next; -}; - - /* ----- Drawing ----------------------------------------------------------- */ -static struct comp *comps = NULL; -static struct comp *curr_comp; /* current component */ -static struct comp **next_comp = &comps; -static struct lib_obj **next_obj; - - static void draw_poly(const struct lib_poly *poly, const int m[6]) { int n = poly->points; @@ -457,7 +382,7 @@ bool lib_field_visible(const struct comp *comp, int n) } -void lib_exec(const struct comp *comp, unsigned unit, const int m[4]) +void lib_render(const struct comp *comp, unsigned unit, const int m[4]) { const struct lib_obj *obj; @@ -469,241 +394,3 @@ void lib_exec(const struct comp *comp, unsigned unit, const int m[4]) draw(comp, obj, m); } } - - -/* ----- Text -------------------------------------------------------------- */ - - -static enum text_style decode_style(const char *s) -{ - if (!strcmp(s, "Normal")) - return text_normal; - assert(0); -} - - -/* ----- Polygons ---------------------------------------------------------- */ - - -static bool parse_poly(struct lib_poly *poly, const char *line, int points) -{ - int i, n; - - poly->points = points; - poly->x = alloc_size(sizeof(int) * points); - poly->y = alloc_size(sizeof(int) * points); - for (i = 0; i != points; i++) { - if (sscanf(line, "%d %d %n", - poly->x + i, poly->y + i, &n) != 2) - return 0; - line += n; - } - if (sscanf(line, "%c", &poly->fill) != 1) - return 0; - return 1; -} - - -/* ----- Definitions ------------------------------------------------------- */ - - -static bool parse_def(const char *line) -{ - char *s; - char draw_num, draw_name; - unsigned name_offset; - unsigned units; - - if (sscanf(line, "DEF %ms %*s %*d %u %c %c %u", - &s, &name_offset, &draw_num, &draw_name, &units) != 5) - return 0; - - curr_comp = alloc_type(struct comp); - if (*s == '~') - s++; - curr_comp->name = s; - curr_comp->units = units; - - curr_comp->visible = 0; - curr_comp->show_pin_name = draw_name == 'Y'; - curr_comp->show_pin_num = draw_num == 'Y'; - curr_comp->name_offset = name_offset; - - curr_comp->objs = NULL; - next_obj = &curr_comp->objs; - - curr_comp->next = NULL; - *next_comp = curr_comp; - next_comp = &curr_comp->next; - - return 1; -} - - -/* ----- Arcs -------------------------------------------------------------- */ - - -static bool parse_arc(struct lib_obj *obj, const char *line) -{ - struct lib_arc *arc = &obj->u.arc; - int a1, a2; - - if (sscanf(line, "A %d %d %d %d %d %u %u %u %c", - &arc->x, &arc->y, &arc->r, &a1, &a2, &obj->unit, &obj->convert, - &arc->thick, &arc->fill) != 9) - return 0; - - /* - * KiCad arcs can be clockwise or counter-clockwise. They must always - * be smaller than 180 degrees. - */ - - while (a1 < 0) - a1 += 3600; - while (a2 < 0) - a2 += 3600; - a1 %= 3600; - a2 %= 3600; - if (a2 < a1) - a2 += 3600; - assert(a2 - a1 != 1800); - if (a2 - a1 > 1800) - swap(a1, a2); - - arc->start_a = (a1 % 3600) / 10; - arc->end_a = (a2 % 3600) / 10; - - return 1; -} - - -/* ----- Library parser ---------------------------------------------------- */ - - -bool lib_parse(struct lib_ctx *ctx, const char *line) -{ - int n = 0; - unsigned points; - struct lib_obj *obj; - char *style; - unsigned zero1, zero2; - char vis; - - ctx->lineno++; - - switch (ctx->state) { - case lib_skip: - if (parse_def(line)) { - ctx->state = lib_def; - return 1; - } - return 1; - case lib_def: - if (sscanf(line, "DRAW%n", &n) == 0 && n) { - ctx->state = lib_draw; - return 1; - } - if (sscanf(line, "F%d \"\" %*d %*d %*d %*c %c", &n, &vis) == 2 - || sscanf(line, "F%d \"%*[^\"]\" %*d %*d %*d %*c %c", - &n, &vis) == 2) { - if (vis == 'V') - curr_comp->visible |= 1 << n; - return 1; - } - /* @@@ explicitly ignore FPLIST */ - return 1; - case lib_draw: - if (sscanf(line, "ENDDRAW%n", &n) == 0 && n) { - ctx->state = lib_skip; - return 1; - } - - obj = alloc_type(struct lib_obj); - obj->next = NULL; - *next_obj = obj; - next_obj = &obj->next; - - if (sscanf(line, "P %u %u %u %u %n", - &points, &obj->unit, &obj->convert, &obj->u.poly.thick, - &n) == 4) { - obj->type = lib_obj_poly; - if (parse_poly(&obj->u.poly, line + n, points)) - return 1; - break; - } - if (sscanf(line, "S %d %d %d %d %u %u %d %c", - &obj->u.rect.sx, &obj->u.rect.sy, &obj->u.rect.ex, - &obj->u.rect.ey, &obj->unit, &obj->convert, - &obj->u.rect.thick, &obj->u.rect.fill) == 8) { - obj->type = lib_obj_rect; - return 1; - } - if (sscanf(line, "C %d %d %d %u %u %d %c", - &obj->u.circ.x, &obj->u.circ.y, &obj->u.circ.r, - &obj->unit, &obj->convert, &obj->u.circ.thick, - &obj->u.circ.fill) == 7) { - obj->type = lib_obj_circ; - return 1; - } - if (parse_arc(obj, line)) { - obj->type = lib_obj_arc; - return 1; - } - n = sscanf(line, - "T %d %d %d %d %u %u %u \"%m[^\"]\" %ms %u %c %c", - &obj->u.text.orient, &obj->u.text.x, &obj->u.text.y, - &obj->u.text.dim, &zero1, &obj->unit, &obj->convert, - &obj->u.text.s, &style, &zero2, - &obj->u.text.hor_align, &obj->u.text.vert_align); - if (n != 12) { - n = sscanf(line, - "T %d %d %d %d %u %u %u %ms %ms %u %c %c", - &obj->u.text.orient, &obj->u.text.x, &obj->u.text.y, - &obj->u.text.dim, &zero1, &obj->unit, &obj->convert, - &obj->u.text.s, &style, &zero2, - &obj->u.text.hor_align, &obj->u.text.vert_align); - while (n == 12) { - char *tilde; - - tilde = strchr(obj->u.text.s, '~'); - if (!tilde) - break; - *tilde = ' '; - } - } - /* - * zero2 seems to be the font style: 0 = normal, 1 = bold ? - */ - if (n == 12) { - if (zero1) { - fprintf(stderr, "%u: only understand 0 x x\n" - "\"%s\"\n", ctx->lineno, line); - exit(1); - } - obj->u.text.style = decode_style(style); - obj->type = lib_obj_text; - return 1; - } - if (sscanf(line, "X %ms %ms %d %d %d %c %d %d %u %u %c", - &obj->u.pin.name, &obj->u.pin.number, - &obj->u.pin.x, &obj->u.pin.y, &obj->u.pin.length, - &obj->u.pin.orient, - &obj->u.pin.number_size, &obj->u.pin.name_size, - &obj->unit, &obj->convert, &obj->u.pin.etype) == 11) { - obj->type = lib_obj_pin; - return 1; - } - break; - default: - abort(); - } - fprintf(stderr, "%u: cannot parse\n\"%s\"\n", ctx->lineno, line); - exit(1); -} - - -void lib_init(struct lib_ctx *ctx) -{ - ctx->state = lib_skip; - ctx->lineno = 0; -} diff --git a/sch2fig/lib.h b/sch2fig/lib.h index 91bcbfe..42558c8 100644 --- a/sch2fig/lib.h +++ b/sch2fig/lib.h @@ -28,7 +28,67 @@ struct lib_ctx { unsigned lineno; }; -struct lib_obj; +struct lib_obj { + enum lib_obj_type { + lib_obj_poly, + lib_obj_rect, + lib_obj_circ, + lib_obj_arc, + lib_obj_text, + lib_obj_pin, + } type; + unsigned unit; + unsigned convert; + union { + struct lib_poly { + int thick; + char fill; + int points; + int *x; + int *y; + } poly; + struct lib_rect { + int thick; + char fill; + int sx, sy; + int ex, ey; + } rect; + struct lib_circ { + int x, y; + int r; + int thick; + char fill; + } circ; + struct lib_arc { + int x, y; + int r; + int start_a, end_a; + int thick; + char fill; + } arc; + struct lib_text { + int orient; + int x, y; + int dim; + char *s; + enum text_style style; + char hor_align; + char vert_align; + } text; + struct lib_pin { + char *name; + char *number; + int x, y; + int length; + char orient; + int number_size; + int name_size; + char etype; + // @@@ shape + } pin; + } u; + struct lib_obj *next; +}; struct comp { const char *name; @@ -44,9 +104,12 @@ struct comp { }; +extern struct comp *comps; + + const struct comp *lib_find(const char *name); bool lib_field_visible(const struct comp *comp, int n); -void lib_exec(const struct comp *comp, unsigned unit, const int m[6]); +void lib_render(const struct comp *comp, unsigned unit, const int m[6]); bool lib_parse(struct lib_ctx *ctx, const char *line); void lib_init(struct lib_ctx *ctx); diff --git a/sch2fig/sch-render.c b/sch2fig/sch-render.c index 15c9f59..d9590bf 100644 --- a/sch2fig/sch-render.c +++ b/sch2fig/sch-render.c @@ -161,7 +161,7 @@ void sch_render(const struct sch_ctx *ctx) const struct sch_comp *comp = &obj->u.comp; const struct comp_field *field; - lib_exec(comp->comp, comp->unit, comp->m); + lib_render(comp->comp, comp->unit, comp->m); for (field = comp->fields; field; field = field->next) dump_field(field, comp->m); diff --git a/sch2fig/text.h b/sch2fig/text.h index 2d0fce5..05f1ffb 100644 --- a/sch2fig/text.h +++ b/sch2fig/text.h @@ -23,6 +23,10 @@ enum text_align { text_max = 2, // right or top }; +enum text_style { + text_normal, +}; + struct text { const char *s; int size;