Root/eeshow/kicad/pl-render.c

1/*
2 * kicad/pl-render.c - RenderKiCad page layout
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#define _GNU_SOURCE /* for asprintf */
14#include <stdbool.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <ctype.h>
19
20#include "misc/util.h"
21#include "misc/diag.h"
22#include "gfx/style.h"
23#include "gfx/text.h"
24#include "gfx/gfx.h"
25#include "kicad/sch.h"
26#include "kicad/pl-common.h"
27#include "kicad/pl.h"
28
29
30/*
31 * Eeschema works in mil
32 * Page layouts are in mm
33 */
34
35
36static int mil(float mm)
37{
38    return mm / 25.4 * 1000;
39}
40
41
42static int coord(int v, int d, int o, int e)
43{
44    return d >= 0 ? o + v : e - v;
45}
46
47
48static char *expand(const struct pl_ctx *pl, const char *s,
49    const struct sheet *sheets, const struct sheet *sheet)
50{
51    const struct sheet *sch;
52    char *res = NULL;
53    const char *p;
54    unsigned size = 0;
55    unsigned len;
56    char *x;
57    unsigned n;
58
59    while (1) {
60        p = strchr(s, '%');
61        if (!p)
62            break;
63        switch (p[1]) {
64        case '%':
65            x = "%";
66            break;
67        case 'C':
68            x = "%C"; // comment #n
69            break;
70        case 'D':
71            x = "%D"; // date
72            break;
73        case 'F':
74            x = "%F"; // file name
75            break;
76        case 'K':
77            x = "%K"; // KiCad version
78            break;
79        case 'N':
80            n = 0;
81            for (sch = sheets; sch; sch = sch->next)
82                n++;
83            if (asprintf(&x, "%u", n)) {}
84            break;
85        case 'P':
86            x = "%P"; // sheet path
87            break;
88        case 'R':
89            x = "%R"; // revision
90            break;
91        case 'S':
92            n = 1;
93            for (sch = sheets; sch != sheet;
94                sch = sch->next)
95                n++;
96            if (asprintf(&x, "%u", n)) {}
97            break;
98        case 'T':
99            x = (char *) sheet->title;
100            break;
101        case 'Y':
102            x = "%Y"; // company name
103            break;
104        case 'Z':
105            x = "%Z"; // paper format
106            break;
107        default:
108            x = "???";
109            break;
110        }
111        len = strlen(x);
112        res = realloc_size(res, size + p - s + len);
113        memcpy(res + size, s, p - s);
114        size += p - s;
115        s = p + 2;
116        memcpy(res + size, x, len);
117        size += len;
118    }
119
120    len = strlen(s);
121    res = realloc_size(res, size + len + 1);
122    memcpy(res + size, s, len + 1);
123    return res;
124}
125
126
127static char *increment(char *s, int inc, const char *range)
128{
129    char *t;
130    unsigned len = strlen(s);
131    int base, n;
132
133    t = realloc_size(s, len + 2);
134    t[len + 1] = 0;
135
136    base = range[1] - range[0] + 1;
137    n = t[len - 1] - range[0] + inc;
138    t[len - 1] = n / base + range[0];
139    t[len] = n % base + range[0];
140    return t;
141}
142
143
144static void render_text(const struct pl_ctx *pl, const struct pl_obj *obj,
145    int x, int y, int inc,
146    const struct sheet *sheets, const struct sheet *sheet)
147{
148    char *s = expand(pl, obj->s, sheets, sheet);
149    struct text txt = {
150        .size = mil(obj->ey ? obj->ey : pl->ty),
151        .x = x,
152        .y = y,
153        .rot = 0,
154        .hor = obj->hor,
155        .vert = obj->vert,
156    };
157
158    if (inc && *s) {
159        char *end = strchr(s, 0) - 1;
160        const char *range = NULL;
161
162        if (isdigit(*end))
163            range = "09";
164        else if (isupper(*end))
165            range = "AZ";
166        else if (islower(*end))
167            range = "az";
168        if (range) {
169             if (*end + inc <= range[1])
170                *end += inc;
171            else
172                s = increment(s, inc, range);
173        }
174    }
175    txt.s = s;
176    text_fig(&txt, COLOR_COMP_DWG, LAYER_COMP_DWG);
177    free(s);
178}
179
180
181static void render_obj(const struct pl_ctx *pl, const struct pl_obj *obj,
182    unsigned inc,
183    const struct sheet *sheets, const struct sheet *sheet)
184{
185    int w = sheet->w;
186    int h = sheet->h;
187    int xo = mil(pl->l);
188    int yo = mil(pl->r);
189    int xe = w - mil(pl->t);
190    int ye = h - mil(pl->b);
191    int x = mil(obj->x + inc * obj->incrx);
192    int y = mil(obj->y + inc * obj->incry);
193    int ex = mil(obj->ex + inc * obj->incrx);
194    int ey = mil(obj->ey + inc * obj->incry);
195    int ww = xe - xo;
196    int hh = ye - yo;
197
198    if (x < 0 || y < 0 || ex < 0 || ey < 0)
199        return;
200    if (x > ww || y > hh || ex > ww || ey > hh)
201        return;
202
203    x = coord(x, obj->dx, xo, xe);
204    y = coord(y, obj->dy, yo, ye);
205    ex = coord(ex, obj->edx, xo, xe);
206    ey = coord(ey, obj->edy, yo, ye);
207
208    switch (obj->type) {
209    case pl_obj_rect:
210        gfx_rect(x, y, ex, ey,
211            COLOR_COMP_DWG, COLOR_NONE, LAYER_COMP_DWG);
212        break;
213    case pl_obj_line: {
214            int vx[] = { x, ex };
215            int vy[] = { y, ey };
216
217            gfx_poly(2, vx, vy,
218                COLOR_COMP_DWG, COLOR_NONE, LAYER_COMP_DWG);
219        }
220        break;
221    case pl_obj_text:
222        render_text(pl, obj, x, y, inc, sheets, sheet);
223        break;
224    default:
225        break;
226    }
227}
228
229
230void pl_render(struct pl_ctx *pl, const struct sheet *sheets,
231    const struct sheet *sheet)
232{
233    const struct pl_obj *obj;
234    int i;
235
236    for (obj = pl->objs; obj; obj = obj->next)
237        for (i = 0; i != obj->repeat; i++)
238            render_obj(pl, obj, i, sheets, sheet);
239}
240

Archive Download this file

Branches:
master



interactive