1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-12-23 00:48:39 +02:00

- fpd.y: fixed check for empty part name

- added new-style measurements (experimental)



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5400 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2009-08-07 13:37:51 +00:00
parent 63b4cb912e
commit d046f9306c
13 changed files with 511 additions and 35 deletions

View File

@ -11,7 +11,7 @@
#
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
unparse.o dump.o \
unparse.o dump.o meas.o \
cpp.o lex.yy.o y.tab.o \
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
gui_tools.o

42
README
View File

@ -427,3 +427,45 @@ To delete an object, select it and press Delete. Deleted objects can
be undeleted by pressing "u". If any other changes have been made
since deletion, fped may misbehave. If deleting a vector, all items
that reference it are deleted.
Experimental: new-style measurements
------------------------------------
New-style measurements can measure the distance between various pairs
of points, not only between points in the same instance and the same
frame. They operate on the set of points produced during instantiation.
New-style measurements are placed in the root frame after all other
items.
Known issues:
- they are currently not dumped and they can't be entered or edited
through the GUI
-
Syntax:
<type> <from> <op> <to> <offset>
Types:
- measxy: measure diagonally
- measx: measure along the X axis
- measy: measure along the y axis
Note that the type also affects the selection of the points. E.g.,
measx will select maximum x values.
Operators:
- A -> B: smallest value of A and smallest B greater than A
- A <- B: like A -> B, but normal (for offset and text) is inverted
- A >> B: smallest value of A and greatest value of B
- A << B: like A -> B, but normal (for offset and text) is inverted
Operands are qualified vector names. Vectors in the root frame are
referenced by their name. Vectors in other frames are prefixed with
the name of the frame followed by a dot.
Example:
measx pad.sw -> pad.se 1mm

12
fpd.l
View File

@ -18,6 +18,7 @@
#include "coord.h"
#include "expr.h"
#include "error.h"
#include "meas.h"
#include "y.tab.h"
@ -94,6 +95,12 @@ SP [\t ]*
return TOK_ARC; }
<INITIAL>"meas" { BEGIN(NOKEYWORD);
return TOK_MEAS; }
<INITIAL>"measxy" { BEGIN(NOKEYWORD);
return TOK_MEASXY; }
<INITIAL>"measx" { BEGIN(NOKEYWORD);
return TOK_MEASX; }
<INITIAL>"measy" { BEGIN(NOKEYWORD);
return TOK_MEASY; }
<INITIAL>[a-zA-Z_][a-zA-Z_0-9]*: { *strchr(yytext, ':') = 0;
yylval.id = unique(yytext);
@ -118,6 +125,11 @@ SP [\t ]*
yylval.str = stralloc(yytext+1);
return STRING; }
"->" return TOK_NEXT;
"<-" return TOK_NEXT_INVERTED;
">>" return TOK_MAX;
"<<" return TOK_MAX_INVERTED;
{SP} ;
\n { if (!disable_keywords)
BEGIN(INITIAL);

127
fpd.y
View File

@ -18,6 +18,7 @@
#include "error.h"
#include "expr.h"
#include "obj.h"
#include "meas.h"
extern struct expr *expr_result;
@ -48,11 +49,11 @@ static struct frame *find_frame(const char *name)
}
static struct vec *find_vec(const char *name)
static struct vec *find_vec(const struct frame *frame, const char *name)
{
struct vec *v;
for (v = curr_frame->vecs; v; v = v->next)
for (v = frame->vecs; v; v = v->next)
if (v->name == name)
return v;
return NULL;
@ -140,12 +141,20 @@ static struct obj *new_obj(enum obj_type type)
struct value *value;
struct vec *vec;
struct obj *obj;
struct meas *meas;
enum meas_type mt;
struct {
int inverted;
int max;
} mo;
};
%token START_FPD START_EXPR
%token TOK_SET TOK_LOOP TOK_PART TOK_FRAME TOK_TABLE TOK_VEC
%token TOK_PAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC TOK_MEAS
%token TOK_PAD TOK_RECT TOK_LINE TOK_CIRC TOK_ARC
%token TOK_MEAS TOK_MEASXY TOK_MEASX TOK_MEASY
%token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED
%token <num> NUMBER
%token <str> STRING
@ -155,9 +164,13 @@ static struct obj *new_obj(enum obj_type type)
%type <var> vars var
%type <row> rows
%type <value> row value
%type <vec> vec base
%type <vec> vec base qbase
%type <obj> obj
%type <expr> expr opt_expr add_expr mult_expr unary_expr primary_expr
%type <meas> measurements meas
%type <str> opt_string
%type <mt> meas_type
%type <mo> meas_op
%%
@ -191,7 +204,7 @@ part_name:
{
const char *p;
if (!*p) {
if (!*$2) {
yyerrorf("invalid part name");
YYABORT;
}
@ -232,6 +245,10 @@ frame_def:
;
frame_items:
measurements
{
measurements = $1;
}
| frame_item frame_items
;
@ -248,7 +265,7 @@ frame_item:
| vec
| LABEL vec
{
if (find_vec($1)) {
if (find_vec(curr_frame, $1)) {
yyerrorf("duplicate vector \"%s\"", $1);
YYABORT;
}
@ -370,6 +387,7 @@ vec:
$$->y = $6;
$$->frame = curr_frame;
$$->next = NULL;
$$->samples = NULL;
last_vec = $$;
*next_vec = $$;
next_vec = &$$->next;
@ -391,7 +409,7 @@ base:
}
| ID
{
$$ = find_vec($1);
$$ = find_vec(curr_frame, $1);
if (!$$) {
yyerrorf("unknown vector \"%s\"", $1);
YYABORT;
@ -463,6 +481,101 @@ obj:
}
;
measurements:
{
$$ = NULL;
}
| meas measurements
{
$$ = $1;
$$->next = $2;
}
;
meas:
meas_type opt_string qbase meas_op qbase expr
{
$$ = alloc_type(struct meas);
$$->type = $4.max ? $1+3 : $1;
$$->label = $2;
$$->low = $3;
$$->inverted = $4.inverted;
$$->high = $5;
$$->offset = $6;
$$->next = NULL;
}
;
qbase:
ID
{
$$ = find_vec(root_frame, $1);
if (!$$) {
yyerrorf("unknown vector \"%s\"", $1);
YYABORT;
}
}
| ID '.' ID
{
const struct frame *frame;
frame = find_frame($1);
$$ = frame ? find_vec(frame, $3) : NULL;
if (!$$) {
yyerrorf("unknown vector \"%s.%s\"", $1, $3);
YYABORT;
}
}
;
meas_type:
TOK_MEASXY
{
$$ = mt_xy_next;
}
| TOK_MEASX
{
$$ = mt_x_next;
}
| TOK_MEASY
{
$$ = mt_y_next;
}
;
meas_op:
TOK_NEXT
{
$$.max = 0;
$$.inverted = 0;
}
| TOK_NEXT_INVERTED
{
$$.max = 0;
$$.inverted = 1;
}
| TOK_MAX
{
$$.max = 1;
$$.inverted = 0;
}
| TOK_MAX_INVERTED
{
$$.max = 1;
$$.inverted = 1;
}
;
opt_string:
{
$$ = NULL;
}
| STRING
{
$$ = $1;
}
;
opt_expr:
{
$$ = NULL;

View File

@ -16,6 +16,7 @@
#include <gtk/gtk.h>
#include "util.h"
#include "coord.h"
#include "inst.h"
#include "gui.h"
#include "gui_util.h"
@ -329,13 +330,12 @@ void gui_draw_arc(struct inst *self, struct draw_ctx *ctx)
/* ----- meas -------------------------------------------------------------- */
static struct coord offset_vec(const struct inst *self)
static struct coord offset_vec(struct coord a, struct coord b,
const struct inst *self)
{
struct coord a, b, res;
struct coord res;
double f;
a = self->base;
b = self->u.meas.end;
res.x = a.y-b.y;
res.y = b.x-a.x;
if (res.x == 0 && res.y == 0)
@ -352,7 +352,7 @@ unit_type gui_dist_meas(struct inst *self, struct coord pos, unit_type scale)
struct coord a, b, off;
unit_type d;
off = offset_vec(self);
off = offset_vec(self->base, self->u.meas.end, self);
a = add_vec(self->base, off);
b = add_vec(self->u.meas.end, off);
d = dist_line(pos, a, b)/scale;
@ -364,13 +364,34 @@ void gui_draw_meas(struct inst *self, struct draw_ctx *ctx)
{
struct coord a0, b0, a1, b1, off, c, d;
GdkGC *gc;
double len;
const char *label = self->u.meas.meas ?
self->u.meas.meas->label ? self->u.meas.meas->label : "" : "";
char *s;
off = offset_vec(self);
a0 = translate(ctx, self->base);
b0 = translate(ctx, self->u.meas.end);
a1 = translate(ctx, add_vec(self->base, off));
b1 = translate(ctx, add_vec(self->u.meas.end, off));
a1 = self->base;
b1 = self->u.meas.end;
switch (self->u.meas.meas ? self->u.meas.meas->type : mt_xy_next) {
case mt_xy_next:
case mt_xy_max:
break;
case mt_x_next:
case mt_x_max:
b1.y = a1.y;
break;
case mt_y_next:
case mt_y_max:
b1.x = a1.x;
break;
default:
abort();
}
off = offset_vec(a1, b1, self);
len = units_to_mm(dist_point(a1, b1));
a1 = translate(ctx, add_vec(a1, off));
b1 = translate(ctx, add_vec(b1, off));
gc = gc_meas[get_mode(self)];
gdk_draw_line(DA, gc, a0.x, a0.y, a1.x, a1.y);
gdk_draw_line(DA, gc, b0.x, b0.y, b1.x, b1.y);
@ -379,9 +400,8 @@ void gui_draw_meas(struct inst *self, struct draw_ctx *ctx)
draw_arrow(ctx, gc, FALSE, b1, a1, MEAS_ARROW_LEN, MEAS_ARROW_ANGLE);
c = add_vec(a1, b1);
d = sub_vec(b0, a0);
s = stralloc_printf("%lgmm",
units_to_mm(dist_point(self->base, self->u.meas.end)));
d = sub_vec(b1, a1);
s = stralloc_printf("%s%lgmm", label, len);
render_text(DA, gc, c.x/2, c.y/2, -atan2(d.y, d.x)/M_PI*180, s,
MEAS_FONT, 0.5, -MEAS_BASELINE_OFFSET,
dist_point(a1, b1)-1.5*MEAS_ARROW_LEN, 0);

18
inst.c
View File

@ -291,8 +291,11 @@ static void update_bbox(struct bbox *bbox, struct coord coord)
static void propagate_bbox(const struct inst *inst)
{
update_bbox(&curr_frame->bbox, inst->bbox.min);
update_bbox(&curr_frame->bbox, inst->bbox.max);
/* @@@ for new-style measurements */
struct inst *frame = curr_frame ? curr_frame : insts[ip_frame];
update_bbox(&frame->bbox, inst->bbox.min);
update_bbox(&frame->bbox, inst->bbox.max);
}
@ -640,6 +643,8 @@ static void meas_op_select(struct inst *self)
rect_status(self->bbox.min, self->bbox.max, -1);
status_set_type_entry("offset =");
status_set_name("%5.2f mm", units_to_mm(self->u.meas.offset));
if (!self->obj)
return; /* @@@ new-style measurements */
edit_expr(&self->obj->u.meas.offset, 0);
}
@ -648,6 +653,8 @@ static int meas_op_anchors(struct inst *inst, struct vec ***anchors)
{
struct obj *obj = inst->obj;
if (!inst->obj)
return 0; /* @@@ new-style measurements */
anchors[0] = &obj->base;
anchors[1] = &obj->u.meas.other;
return 2;
@ -664,8 +671,8 @@ static struct inst_ops meas_ops = {
};
int inst_meas(struct obj *obj, struct coord from, struct coord to,
unit_type offset)
int inst_meas(struct obj *obj, struct meas *meas,
struct coord from, struct coord to, unit_type offset)
{
struct inst *inst;
@ -673,6 +680,9 @@ int inst_meas(struct obj *obj, struct coord from, struct coord to,
inst->obj = obj;
inst->u.meas.end = to;
inst->u.meas.offset = offset;
inst->u.meas.meas = meas;
if (!obj)
inst->active = 1; /* @@@ new-style measurements */
/* @@@ our bbox is actually a bit more complex than this */
update_bbox(&inst->bbox, to);
propagate_bbox(inst);

6
inst.h
View File

@ -18,6 +18,7 @@
#include "coord.h"
#include "obj.h"
#include "meas.h"
enum mode {
@ -70,6 +71,7 @@ struct inst {
struct {
struct coord end;
double offset;
struct meas *meas; /* new-style measurement */
} meas;
} u;
struct inst *next;
@ -95,8 +97,8 @@ int inst_rect(struct obj *obj, struct coord a, struct coord b, unit_type width);
int inst_pad(struct obj *obj, const char *name, struct coord a, struct coord b);
int inst_arc(struct obj *obj, struct coord center, struct coord start,
struct coord stop, unit_type width);
int inst_meas(struct obj *obj, struct coord from, struct coord to,
unit_type offset);
int inst_meas(struct obj *obj, struct meas *meas,
struct coord from, struct coord to, unit_type offset);
void inst_begin_active(int active);
void inst_end_active(void);

193
meas.c Normal file
View File

@ -0,0 +1,193 @@
/*
* meas.c - Measurements
*
* Written 2009 by Werner Almesberger
* Copyright 2009 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 <stdlib.h>
#include "util.h"
#include "coord.h"
#include "expr.h"
#include "obj.h"
#include "inst.h"
#include "meas.h"
struct num eval_unit(const struct expr *expr, const struct frame *frame);
struct sample {
struct coord pos;
struct sample *next;
};
struct meas *measurements = NULL;
static void reset_samples(struct sample **samples)
{
struct sample *next;
while (*samples) {
next = (*samples)->next;
free(*samples);
*samples = next;
}
}
void meas_start(void)
{
struct frame *frame;
struct vec *vec;
for (frame = frames; frame; frame = frame->next)
for (vec = frame->vecs; vec; vec = vec->next)
reset_samples(&vec->samples);
}
void meas_post(struct vec *vec, struct coord pos)
{
struct sample **walk, *new;
for (walk = &vec->samples; *walk; walk = &(*walk)->next) {
if (pos.y < (*walk)->pos.y)
break;
if (pos.y > (*walk)->pos.y)
continue;
if (pos.x < (*walk)->pos.x)
break;
if (pos.x == (*walk)->pos.x)
return;
}
new = alloc_type(struct sample);
new->pos = pos;
new->next = *walk;
*walk = new;
}
static int lt_x(struct coord a, struct coord b)
{
return a.x < b.x;
}
static int lt_y(struct coord a, struct coord b)
{
return a.y < b.y;
}
static int lt_xy(struct coord a, struct coord b)
{
return a.y < b.y || (a.y == b.y && a.x < b.x);
}
static int (*lt_op[mt_n])(struct coord a, struct coord b) = {
lt_xy,
lt_x,
lt_y,
lt_xy,
lt_x,
lt_y
};
static int is_next[mt_n] = {
1, 1, 1,
0, 0, 0
};
static int better_next(int (*lt)(struct coord a, struct coord b),
struct coord a0, struct coord b0, struct coord b)
{
/* if we don't have any suitable point A0 < B0 yet, use this one */
if (!lt(a0, b0))
return 1;
/* B must be strictly greater than A0 */
if (!lt(a0, b))
return 0;
/* if we can get closer to A0, do so */
if (lt(b, b0))
return 1;
/* reject B > B0 */
if (lt(b0, b))
return 0;
/*
* B == B0 along the coordinate we measure. Now give the other
* coordinate a chance. This gives us a stable sort order and it
* makes meas/measx/measy usually select the same point.
*/
if (lt == lt_xy)
return 0;
if (lt == lt_x)
return better_next(lt_y, a0, b0, b);
if (lt == lt_y)
return better_next(lt_x, a0, b0, b);
abort();
}
int instantiate_meas(void)
{
struct meas *meas;
struct coord a0, b0;
const struct sample *a, *b;
int (*lt)(struct coord a, struct coord b);
struct num offset;
for (meas = measurements; meas; meas = meas->next) {
if (!meas->low->samples || !meas->high->samples)
continue;
lt = lt_op[meas->type];
/*
* In order to obtain a stable order, we sort points equal on
* the measured coordinate also by xy:
*
* if (*a < a0) use *a
* else if (*a == a0 && *a <xy a0) use *a
*/
a0 = meas->low->samples->pos;
for (a = meas->low->samples; a; a = a->next)
if (lt(a->pos, a0) ||
(!lt(a0, a->pos) && lt_xy(a->pos, a0)))
a0 = a->pos;
b0 = meas->high->samples->pos;
for (b = meas->high->samples; b; b = b->next) {
if (is_next[meas->type]) {
if (better_next(lt, a0, b0, b->pos))
b0 = b->pos;
} else {
if (lt(b0, b->pos) ||
(!lt(b->pos, b0) && lt_xy(b0, b->pos)))
b0 = b->pos;
}
}
offset = eval_unit(meas->offset, root_frame);
if (is_undef(offset))
return 0;
inst_meas(NULL, meas,
meas->inverted ? b0 : a0, meas->inverted ? a0 : b0,
offset.n);
}
return 1;
}

24
meas.fpd Normal file
View File

@ -0,0 +1,24 @@
/*
* new-style measurements demo
*/
part "measurements"
loop x = -2, 2
A: vec @(0mm, 0mm)
B: vec @(x*2mm, 2mm)
C: vec @(0mm, 4mm)
/*
* If we measure (x, y), y trumps x
*/
measxy "A -> B = " A -> B 0.2mm
measxy "A <- B = " A <- B 0.5mm
measxy "A >> B = " A >> B 1.5mm
measx "x(A -> B) = " A -> B -0.5mm
measx "x(A >> B) = " A >> B -1mm
measy "y(A -> B) = " A -> B -2mm
measy "y(A >> B) = " A >> B -4.5mm
measxy "B -> C = " B -> C 0.5mm

46
meas.h Normal file
View File

@ -0,0 +1,46 @@
/*
* meas.h - Measurements
*
* Written 2009 by Werner Almesberger
* Copyright 2009 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.
*/
#ifndef MEAS_H
#define MEAS_H
#include "obj.h"
struct meas {
enum meas_type {
mt_xy_next,
mt_x_next,
mt_y_next,
mt_xy_max,
mt_x_max,
mt_y_max,
mt_n
} type;
char *label; /* or NULL */
int inverted;
struct vec *low;
struct vec *high;
struct expr *offset;
struct meas *next;
};
extern struct meas *measurements;
void meas_start(void);
void meas_post(struct vec *vec, struct coord pos);
int instantiate_meas(void);
#endif /* !MEAS_H */

11
obj.c
View File

@ -18,6 +18,7 @@
#include "util.h"
#include "error.h"
#include "expr.h"
#include "meas.h"
#include "inst.h"
#include "obj.h"
@ -37,7 +38,8 @@ static int generate_frame(struct frame *frame, struct coord base,
const struct frame *parent, struct obj *frame_ref, int active);
static struct num eval_unit(const struct expr *expr, const struct frame *frame)
struct num eval_unit(const struct expr *expr, const struct frame *frame);
/*static*/ struct num eval_unit(const struct expr *expr, const struct frame *frame)
{
struct num d;
@ -78,6 +80,7 @@ static int generate_vecs(struct frame *frame, struct coord base)
vec->pos.y += y.n;
if (!inst_vec(vec, vec_base))
return 0;
meas_post(vec, vec->pos);
}
return 1;
}
@ -144,7 +147,8 @@ static int generate_objs(struct frame *frame, struct coord base, int active)
offset = eval_unit(obj->u.meas.offset, frame);
if (is_undef(offset))
return 0;
if (!inst_meas(obj, obj->base ? obj->base->pos : base,
if (!inst_meas(obj, NULL,
obj->base ? obj->base->pos : base,
obj->u.meas.other ? obj->u.meas.other->pos : base,
offset.n))
return 0;
@ -261,7 +265,10 @@ int instantiate(void)
int ok;
inst_start();
meas_start();
ok = generate_frame(root_frame, zero, NULL, NULL, 1);
if (ok)
ok = instantiate_meas();
if (ok)
inst_commit();
else

9
obj.h
View File

@ -84,6 +84,8 @@ struct loop {
int initialized;
};
struct sample;
struct vec {
const char *name; /* NULL if anonymous */
struct expr *x;
@ -96,6 +98,9 @@ struct vec {
/* used when editing */
struct frame *frame;
/* samples for measurements */
struct sample *samples;
};
struct frame {
@ -147,7 +152,7 @@ struct arc {
struct expr *width;
};
struct meas {
struct old_meas {
struct vec *other; /* NULL if frame origin */
struct expr *offset;
};
@ -160,7 +165,7 @@ struct obj {
struct rect line;
struct pad pad;
struct arc arc;
struct meas meas;
struct old_meas meas;
} u;
struct frame *frame;
struct vec *base;

View File

@ -1,12 +1,12 @@
/* MACHINE-GENERATED ! */
frame pad {
_pad_0: vec @(-Px/2, -Py/2)
_pad_1: vec .(Px, 0mm)
_pad_2: vec _pad_0(0mm, Py)
pad "$pad" _pad_1 _pad_2
meas _pad_0 _pad_1 -0.1mm
meas _pad_0 _pad_2 0.1mm
sw: vec @(-Px/2, -Py/2)
se: vec sw(Px, 0mm)
nw: vec sw(0mm, Py)
pad "$pad" se nw
// meas sw se -0.1mm
// meas sw nw 0.1mm
}
frame pad_ne {
@ -41,3 +41,5 @@ __2: vec @(Gx/2, -Gy/2)
frame pad_sc __0
frame pad_nw __1
frame pad_ne __2
measx pad.sw -> pad.se 1mm