Root/eeshow/gfx/fig.c

1/*
2 * gfx/fig.c - Generate FIG output for Eeschema items
3 *
4 * Written 2016 by Werner Almesberger
5 * Copyright 2016 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdbool.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <math.h>
20#include <assert.h>
21
22#include "misc/util.h"
23#include "misc/diag.h"
24#include "gfx/style.h"
25#include "gfx/text.h"
26#include "main.h"
27#include "gfx/fig.h"
28
29
30/*
31 * FIG works with 1/1200 in
32 * KiCad works with mil
33 * 1 point = 1/72 in
34 */
35
36
37static inline int cx(int x)
38{
39    return x * 1200 / 1000;
40}
41
42
43static inline int cy(int y)
44{
45    return y * 1200 / 1000;
46}
47
48
49static inline float pt(int x)
50{
51    return cx(x) * 72 * 1.5 / 1200.0;
52}
53
54
55/* ----- Schematics items -------------------------------------------------- */
56
57
58static void fig_line(void *ctx, int sx, int sy, int ex, int ey,
59    int color, unsigned layer)
60{
61    // TypeStyle FillCol AreaFil Cap FwdAr
62    // SubTy Color Pen StyleV Rad BwdAr
63    // Thick Depth Join Points
64    printf("2 1 2 %d %d 7 %d -1 -1 3.0 1 1 -1 0 0 2\n",
65        WIDTH_LINE, color, layer);
66    printf("\t%d %d %d %d\n", cx(sx), cy(sy), cx(ex), cy(ey));
67}
68
69
70/* ----- General items ----------------------------------------------------- */
71
72
73static void fig_rect(void *ctx, int sx, int sy, int ex, int ey,
74    int color, int fill_color, unsigned layer)
75{
76    // Type Thick Depth StyleV Rad
77    // SubTy Color Pen Join FwdAr
78    // Style FillCol AreaFil Cap BwdAr
79    printf("2 2 0 %d %d %d %d -1 %d 0.0 1 1 -1 0 0 5\n",
80        color == -1 ? 0 : WIDTH_COMP_DWG, color, fill_color, layer,
81        fill_color == -1 ? -1 : 20);
82    printf("\t%d %d %d %d %d %d %d %d %d %d\n",
83        cx(sx), cy(sy), cx(ex), cy(sy), cx(ex), cy(ey), cx(sx), cy(ey),
84        cx(sx), cy(sy));
85}
86
87
88static void fig_poly(void *ctx,
89    int points, const int x[points], const int y[points],
90    int color, int fill_color, unsigned layer)
91{
92    int i;
93    char ch = '\t';
94
95    // Type Thick Depth StyleV Rad
96    // SubTy Color Pen Join FwdAr
97    // Style FillCol AreaFil Cap BwdAr
98    printf("2 1 0 %d %d %d %d -1 %d 0.0 1 1 -1 0 0 %d\n",
99        color == -1 ? 0 : WIDTH_COMP_DWG, color, fill_color, layer,
100        fill_color == -1 ? -1 : 20, points);
101    for (i = 0; i != points; i++) {
102        printf("%c%d %d", ch, cx(x[i]), cy(y[i]));
103        ch = ' ';
104    }
105    printf("\n");
106}
107
108
109static void fig_circ(void *ctx, int x, int y, int r,
110    int color, int fill_color, unsigned layer)
111{
112    // Type Thick Depth StyleV Cx Rx Sx Ex
113    // SubTy Color Pen Dir Cy Ry Sy Ey
114    // Style FillCol AreaFil Angle
115    printf("1 3 0 %d %d %d %d -1 %d 0.0 1 0.0 %d %d %d %d %d %d %d %d\n",
116        color == -1 ? 0 : WIDTH_COMP_DWG, color, fill_color, layer,
117        fill_color == -1 ? -1 : 20,
118        cx(x), cy(y), r, r,
119        cx(x), cy(y), cx(x) + r, cy(y));
120}
121
122
123static int ax(int x, int y, int r, int angle)
124{
125    float a = angle / 180.0 * M_PI;
126
127    return cx(x + r * cos(a));
128}
129
130
131static int ay(int x, int y, int r, int angle)
132{
133    float a = angle / 180.0 * M_PI;
134
135    return cy(y - r * sin(a));
136}
137
138
139static void fig_arc(void *ctx, int x, int y, int r, int sa, int ea,
140    int color, int fill_color, unsigned layer)
141{
142    int ma = (sa + ea) / 2;
143
144    // Type Thick Depth StyleV FwdAr
145    // SubTy Color Pen Cap BwdAr
146    // Style FillCol AreaFil Dir points
147    printf("5 1 0 %d %d %d %d -1 %d 0.0 1 1 0 0 %d %d %d %d %d %d %d %d\n",
148        color == -1 ? 0 : WIDTH_COMP_DWG, color, fill_color, layer,
149        fill_color == -1 ? -1 : 20,
150        cx(x), cy(y),
151        ax(x, y, r, sa), ay(x, y, r, sa),
152        ax(x, y, r, ma), ay(x, y, r, ma),
153        ax(x, y, r, ea), ay(x, y, r, ea));
154}
155
156
157static void fig_tag(void *ctx, const char *s,
158    int points, const int x[points], const int y[points])
159{
160    printf("# href=\"%s\" alt=\"\"\n", s);
161    fig_poly(ctx, points, x, y, COLOR_NONE, COLOR_NONE, 999);
162}
163
164
165static void fig_text(void *ctx, int x, int y, const char *s, unsigned size,
166    enum text_align align, int rot, unsigned color, unsigned layer)
167{
168    // Type Depth FontSiz Height
169    // Just Pen Angle Length
170    // Color Font Flags X Y
171    printf("4 %u %d %d -1 %d %f %f 4 0.0 0.0 %d %d %s\\001\n",
172        align, color, layer, FONT_HELVETICA_BOLD,
173        pt(size), rot / 180.0 * M_PI, cx(x), cy(y), s);
174}
175
176
177static unsigned fig_text_width(void *ctx, const char *s, unsigned size)
178{
179    /*
180     * Note that we stretch the text size, so the ratio is larger than
181     * expressed here.
182     */
183    return strlen(s) * size * 1.0;
184}
185
186
187/* ----- FIG file header --------------------------------------------------- */
188
189
190static void fig_header(void)
191{
192    printf("#FIG 3.2\n");
193    printf("Landscape\n");
194    printf("Center\n");
195    printf("Metric\n");
196    printf("A4\n");
197    printf("100.00\n");
198    printf("Single\n");
199    printf("-2\n");
200    printf("1200 2\n");
201}
202
203
204static void fig_colors(void)
205{
206    unsigned i;
207
208    for (i = 32; i != n_color_rgb; i++)
209        printf("0 %d #%06x\n", i, color_rgb[i]);
210
211}
212
213
214static bool apply_vars(char *buf, int n_vars, const char **vars)
215{
216    char *p;
217    const char **var, *eq;
218    int var_len, value_len;
219
220    p = strchr(buf, '<');
221    if (!p)
222        return 0;
223    for (var = vars; var != vars + n_vars; var++) {
224        eq = strchr(*var, '=');
225        assert(eq);
226        var_len = eq - *var;
227        if (strncmp(p + 1, *var, var_len))
228            continue;
229        value_len = strlen(eq + 1);
230        memmove(p + value_len, p + var_len + 2,
231            strlen(p + var_len + 2) + 1);
232        memcpy(p, eq + 1, value_len);
233        return 1;
234    }
235    return 0;
236}
237
238
239
240static void *fig_init(int argc, char *const *argv)
241{
242    static char *buf = NULL;
243    static size_t n = 0;
244    const char *template = NULL;
245    const char **vars = NULL;
246    int n_vars = 0;
247    char c;
248    int arg;
249    FILE *file;
250    int lines_to_colors = 8;
251
252    while ((c = getopt(argc, argv, "t:")) != EOF)
253        switch (c) {
254        case 't':
255            template = optarg;
256            break;
257        default:
258            usage(*argv);
259        }
260
261    for (arg = optind; arg != argc; arg++) {
262        if (!strchr(argv[arg], '='))
263            usage(*argv);
264        n_vars++;
265        vars = realloc_type_n(vars, const char *, n_vars);
266        vars[n_vars - 1] = argv[arg];
267    }
268
269    if (!template) {
270        fig_header();
271        fig_colors();
272        return NULL;
273    }
274
275    file = fopen(template, "r");
276    if (!file)
277        diag_pfatal(template);
278    while (getline(&buf, &n, file) > 0) {
279        while (apply_vars(buf, n_vars, vars));
280        printf("%s", buf);
281        if (*buf == '#')
282            continue;
283        if (!--lines_to_colors)
284            fig_colors();
285        /*
286         * @@@ known bug: if the template is empty, we won't output
287         * color 32.
288         */
289    }
290    fclose(file);
291
292    return NULL;
293}
294
295
296/* ----- Operations -------------------------------------------------------- */
297
298
299const struct gfx_ops fig_ops = {
300    .name = "fig",
301    .line = fig_line,
302    .rect = fig_rect,
303    .poly = fig_poly,
304    .circ = fig_circ,
305    .arc = fig_arc,
306    .text = fig_text,
307    .tag = fig_tag,
308    .text_width = fig_text_width,
309    .init = fig_init,
310};
311

Archive Download this file

Branches:
master



interactive