Root/
| 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 | |
| 37 | static inline int cx(int x) |
| 38 | { |
| 39 | return x * 1200 / 1000; |
| 40 | } |
| 41 | |
| 42 | |
| 43 | static inline int cy(int y) |
| 44 | { |
| 45 | return y * 1200 / 1000; |
| 46 | } |
| 47 | |
| 48 | |
| 49 | static inline float pt(int x) |
| 50 | { |
| 51 | return cx(x) * 72 * 1.5 / 1200.0; |
| 52 | } |
| 53 | |
| 54 | |
| 55 | /* ----- Schematics items -------------------------------------------------- */ |
| 56 | |
| 57 | |
| 58 | static 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 | |
| 73 | static 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 | |
| 88 | static 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 | |
| 109 | static 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 | |
| 123 | static 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 | |
| 131 | static 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 | |
| 139 | static 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 | |
| 157 | static 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 | |
| 165 | static 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 | |
| 177 | static 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 | |
| 190 | static 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 | |
| 204 | static 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 | |
| 214 | static 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 | |
| 240 | static 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 | |
| 299 | const 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 |
Branches:
master
