/* * 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 #include "style.h" #include "fig.h" #include "text.h" #include "lib.h" enum text_style { text_normal, }; struct obj { enum obj_type { obj_poly, obj_rect, obj_circ, obj_arc, obj_text, obj_pin, } type; unsigned unit; unsigned convert; union { struct poly { int thick; char fill; int points; int *x; int *y; } poly; struct { int thick; char fill; int sx, sy; int ex, ey; } rect; struct { int x, y; int r; int thick; char fill; } circ; struct text_obj { int orient; int x, y; int dim; char *s; enum text_style style; char hor_align; char vert_align; } text; struct pin_obj { char *name; char *number; int x, y; int length; char orient; int number_size; int name_size; char etype; // @@@ shape } pin; } u; struct obj *next; }; struct comp { const char *name; struct obj *objs; struct comp *next; }; static struct comp *comps = NULL; static struct comp **next_comp = &comps; static struct obj **next_obj; static inline int mx(int x, int y, int m[6]) { return m[0] + x * m[1] + y * m[2]; } static inline int my(int x, int y, int m[6]) { return m[3] + x * m[4] + y * m[5]; } static void draw_poly(const struct poly *poly, int m[6]) { int n = poly->points; int x[n]; int y[n]; int i; for (i = 0; i != n; i++) { x[i] = mx(poly->x[i], poly->y[i], m); y[i] = my(poly->x[i], poly->y[i], m); } fig_poly(n, x, y); } static void draw_pin(const struct pin_obj *pin, int m[6]) { int x[2], y[2]; int dx = 0, dy = 0; switch (pin->orient) { case 'U': dy = pin->length; break; case 'D': dy = -pin->length; break; case 'R': dx = pin->length; break; case 'L': dx = -pin->length; break; default: abort(); } x[0] = mx(pin->x, pin->y, m); y[0] = my(pin->x, pin->y, m); x[1] = mx(pin->x + dx, pin->y + dy, m); y[1] = my(pin->x + dx, pin->y + dy, m); fig_poly(2, x, y); } static bool eq(int m[6], int xx, int xy, int yx, int yy) { return m[1] == xx && m[2] == xy && m[4] == yx && m[5] == yy; } static unsigned matrix_to_angle(int m[6]) { if (eq(m, 1, 0, 0, -1)) return 0; if (eq(m, 0, -1, -1, 0)) return 90; if (eq(m, 0, 1, 1, 0)) return 270; fprintf(stderr, "unrecognized matrix %d %d %d %d\n", m[1], m[2], m[4], m[5]); exit(1); } static void draw_text(const struct text_obj *text, int m[6]) { struct text txt = { .s = text->s, .size = text->dim, .x = mx(text->x, text->y, m), .y = my(text->x, text->y, m), .rot = matrix_to_angle(m), .hor = text_mid, .vert = text_mid, }; text_fig(&txt, COLOR_COMP_DWG, WIDTH_COMP_DWG); } static void draw(const struct obj *obj, int m[6]) { switch (obj->type) { case obj_poly: draw_poly(&obj->u.poly, m); break; case obj_rect: fig_rect(mx(obj->u.rect.sx, obj->u.rect.sy, m), my(obj->u.rect.sx, obj->u.rect.sy, m), mx(obj->u.rect.ex, obj->u.rect.ey, m), my(obj->u.rect.ex, obj->u.rect.ey, m)); // @@@ break; case obj_circ: break; case obj_arc: break; case obj_text: draw_text(&obj->u.text, m); break; case obj_pin: draw_pin(&obj->u.pin, m); break; default: abort(); } } void lib_exec(const char *name, unsigned unit, int m[4]) { const struct comp *comp; const struct obj *obj; for (comp = comps; comp; comp = comp->next) if (!strcmp(comp->name, name)) goto found; fprintf(stderr, "\"%s\" not found\n", name); exit(1); found: for (obj = comp->objs; obj; obj = obj->next) { if (obj->unit && obj->unit != unit) continue; draw(obj, m); } } static enum text_style decode_style(const char *s) { if (!strcmp(s, "Normal")) return text_normal; abort(); } static bool parse_poly(struct obj *obj, const char *line, int points) { int i, n; obj->u.poly.points = points; obj->u.poly.x = malloc(sizeof(int) * points); obj->u.poly.y = malloc(sizeof(int) * points); for (i = 0; i != points; i++) { if (sscanf(line, "%d %d %n", obj->u.poly.x + i, obj->u.poly.y + i, &n) != 2) return 0; line += n; } if (sscanf(line, "%c", &obj->u.poly.fill) != 1) return 0; return 1; } bool lib_parse(struct lib_ctx *ctx, const char *line) { int n = 0; char *s; unsigned points; struct comp *comp; struct obj *obj; char *style; unsigned zero1, zero2; ctx->lineno++; switch (ctx->state) { case lib_skip: if (sscanf(line, "DEF %ms", &s) == 1) { ctx->state = lib_def; comp = malloc(sizeof(struct comp)); if (*s == '~') s++; comp->name = s; comp->objs = NULL; comp->next = NULL; *next_comp = comp; next_comp = &comp->next; next_obj = &comp->objs; return 1; } return 1; case lib_def: if (sscanf(line, "DRAW%n", &n) == 0 && n) { ctx->state = lib_draw; return 1; } return 1; case lib_draw: if (sscanf(line, "ENDDRAW%n", &n) == 0 && n) { ctx->state = lib_skip; return 1; } obj = malloc(sizeof(struct 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 = obj_poly; if (parse_poly(obj, 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 = 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 = obj_circ; return 1; } if (sscanf(line, "A %n", &n) == 0 && n) { obj->type = 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); if (n == 12) { if (zero1 || zero2) { fprintf(stderr, "%u: only understand 0 x x\n", ctx->lineno); exit(1); } obj->u.text.style = decode_style(style); obj->type = 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 = 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; }