mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-26 14:51:53 +02:00
sch2fig/: record drawing operations (for Cairo) and sort by layer
This commit is contained in:
parent
ae7924a01c
commit
dd1eb7ddc3
@ -13,7 +13,7 @@
|
||||
NAME = sch2fig
|
||||
OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.o \
|
||||
file.o \
|
||||
style.o fig.o cairo.o gfx.o dwg.o text.o misc.o
|
||||
style.o fig.o layer.o cairo.o gfx.o dwg.o text.o misc.o
|
||||
|
||||
CFLAGS = -g -O -Wall -Wextra -Wno-unused-parameter -Wshadow \
|
||||
-Wmissing-prototypes -Wmissing-declarations \
|
||||
|
@ -12,8 +12,6 @@
|
||||
- optionally display pin shapes
|
||||
- find libraries (e.g., from .pro)
|
||||
- PDF TOC
|
||||
- generic layering for cairo (and others ?), where primitives are first
|
||||
recorded in per layer lists, then replayed. Can also calculate BB.
|
||||
- let user set PNG size or zoom level
|
||||
- implement dashed lines in cairo.c
|
||||
- implement PDF output in cairo.o
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "style.h"
|
||||
#include "text.h"
|
||||
#include "gfx.h"
|
||||
#include "layer.h"
|
||||
#include "cairo.h"
|
||||
|
||||
#if 0
|
||||
@ -36,6 +37,7 @@
|
||||
|
||||
|
||||
struct cairo_ctx {
|
||||
struct layer layer; /* must be first */
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *s;
|
||||
};
|
||||
@ -200,11 +202,24 @@ static unsigned cr_text_width(void *ctx, const char *s, unsigned size)
|
||||
/* ----- Initializatio and termination ------------------------------------- */
|
||||
|
||||
|
||||
static const struct gfx_ops real_cairo_ops = {
|
||||
.name = "cairo",
|
||||
// .line = cr_line, @@@ later
|
||||
.poly = cr_poly,
|
||||
.circ = cr_circ,
|
||||
.arc = cr_arc,
|
||||
.text = cr_text,
|
||||
.text_width = cr_text_width,
|
||||
};
|
||||
|
||||
|
||||
static void *cr_init(int argc, char *const *argv)
|
||||
{
|
||||
struct cairo_ctx *cc;
|
||||
|
||||
cc = alloc_type(struct cairo_ctx);
|
||||
layer_init(&cc->layer, &real_cairo_ops, cc);
|
||||
|
||||
cc->s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 2000, 1414);
|
||||
cc->cr = cairo_create(cc->s);
|
||||
|
||||
@ -223,6 +238,9 @@ static void cr_end(void *ctx)
|
||||
{
|
||||
struct cairo_ctx *cc = ctx;
|
||||
|
||||
layer_replay(&cc->layer);
|
||||
layer_destroy(&cc->layer);
|
||||
|
||||
cairo_surface_write_to_png(cc->s, "test.png");
|
||||
cairo_surface_destroy(cc->s);
|
||||
}
|
||||
@ -234,10 +252,10 @@ static void cr_end(void *ctx)
|
||||
const struct gfx_ops cairo_ops = {
|
||||
.name = "cairo",
|
||||
// .line = cr_line, @@@ later
|
||||
.poly = cr_poly,
|
||||
.circ = cr_circ,
|
||||
.arc = cr_arc,
|
||||
.text = cr_text,
|
||||
.poly = layer_poly,
|
||||
.circ = layer_circ,
|
||||
.arc = layer_arc,
|
||||
.text = layer_text,
|
||||
.text_width = cr_text_width,
|
||||
.init = cr_init,
|
||||
.end = cr_end,
|
||||
|
327
sch2fig/layer.c
Normal file
327
sch2fig/layer.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* layer.h - Separate graphics operations by layers and replay
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "style.h"
|
||||
#include "gfx.h"
|
||||
#include "text.h"
|
||||
#include "layer.h"
|
||||
|
||||
|
||||
struct layer_obj {
|
||||
enum lo_type {
|
||||
lo_line,
|
||||
lo_rect,
|
||||
lo_poly,
|
||||
lo_circ,
|
||||
lo_arc,
|
||||
lo_text,
|
||||
} type;
|
||||
|
||||
int x, y;
|
||||
int color, fill_color;
|
||||
union {
|
||||
struct {
|
||||
int ex, ey;
|
||||
} line;
|
||||
struct {
|
||||
int ex, ey;
|
||||
} rect;
|
||||
struct {
|
||||
unsigned n;
|
||||
int *vx, *vy;
|
||||
} poly;
|
||||
struct {
|
||||
int r;
|
||||
} circ;
|
||||
struct {
|
||||
int r;
|
||||
int sa, ea;
|
||||
} arc;
|
||||
struct {
|
||||
char *s;
|
||||
unsigned size;
|
||||
enum text_align align;
|
||||
int rot;
|
||||
} text;
|
||||
} u;
|
||||
struct layer_obj *next;
|
||||
};
|
||||
|
||||
|
||||
static void bb(struct layer *layer, int x, int y)
|
||||
{
|
||||
if (layer->xmin > x)
|
||||
layer->xmin = x;
|
||||
if (layer->ymin > y)
|
||||
layer->ymin = y;
|
||||
if (layer->xmax < x)
|
||||
layer->xmax = x;
|
||||
if (layer->ymax < y)
|
||||
layer->ymax = y;
|
||||
}
|
||||
|
||||
|
||||
static void bb_rot(struct layer *layer, int x, int y, int rot)
|
||||
{
|
||||
double a = rot / 180.0 * M_PI;
|
||||
|
||||
bb(layer, cos(a) * x + sin(a) * y, cos(a) * y - sin(a) * y);
|
||||
}
|
||||
|
||||
|
||||
static struct layer_obj *new_obj(struct layer *lc, enum lo_type type,
|
||||
int color, int fill_color, unsigned layer)
|
||||
{
|
||||
struct layer_objs **objs;
|
||||
struct layer_objs *new_objs;
|
||||
struct layer_obj *new_obj;
|
||||
|
||||
for (objs = &lc->objs; *objs; objs = &(*objs)->next) {
|
||||
if ((*objs)->layer == layer)
|
||||
goto this_layer;
|
||||
if ((*objs)->layer < layer)
|
||||
break;
|
||||
}
|
||||
|
||||
new_objs = alloc_type(struct layer_objs);
|
||||
new_objs->layer = layer;
|
||||
new_objs->obj = NULL;
|
||||
new_objs->next_obj = &new_objs->obj;
|
||||
new_objs->next = *objs;
|
||||
*objs = new_objs;
|
||||
|
||||
this_layer:
|
||||
new_obj = alloc_type(struct layer_obj);
|
||||
new_obj->type = type;
|
||||
new_obj->color = color;
|
||||
new_obj->fill_color = fill_color;
|
||||
new_obj->next = NULL;
|
||||
|
||||
*(*objs)->next_obj = new_obj;
|
||||
(*objs)->next_obj = &new_obj->next;
|
||||
|
||||
return new_obj;
|
||||
}
|
||||
|
||||
|
||||
void layer_line(void *ctx, int sx, int sy, int ex, int ey,
|
||||
int color, unsigned layer)
|
||||
{
|
||||
struct layer *lc = ctx;
|
||||
struct layer_obj *obj = new_obj(ctx, lo_line, color, COLOR_NONE, layer);
|
||||
|
||||
bb(lc, sx, sy);
|
||||
bb(lc, ex, ey);
|
||||
|
||||
obj->x = sx;
|
||||
obj->y = sy;
|
||||
obj->u.line.ex = ex;
|
||||
obj->u.line.ey = ey;
|
||||
}
|
||||
|
||||
|
||||
void layer_rect(void *ctx, int sx, int sy, int ex, int ey,
|
||||
int color, int fill_color, unsigned layer)
|
||||
{
|
||||
struct layer *lc = ctx;
|
||||
struct layer_obj *obj = new_obj(ctx, lo_rect, color, fill_color, layer);
|
||||
|
||||
bb(lc, sx, sy);
|
||||
bb(lc, ex, ey);
|
||||
|
||||
obj->x = sx;
|
||||
obj->y = sy;
|
||||
obj->u.rect.ex = ex;
|
||||
obj->u.rect.ey = ey;
|
||||
}
|
||||
|
||||
|
||||
void layer_poly(void *ctx, int points, int x[points], int y[points],
|
||||
int color, int fill_color, unsigned layer)
|
||||
{
|
||||
struct layer *lc = ctx;
|
||||
struct layer_obj *obj = new_obj(ctx, lo_poly, color, fill_color, layer);
|
||||
int i;
|
||||
unsigned size;
|
||||
|
||||
for (i = 0; i != points; i++)
|
||||
bb(lc, x[i], y[i]);
|
||||
|
||||
obj->u.poly.n = points;
|
||||
size = sizeof(int) * points;
|
||||
obj->u.poly.vx = alloc_size(size);
|
||||
obj->u.poly.vy = alloc_size(size);
|
||||
memcpy(obj->u.poly.vx, x, size);
|
||||
memcpy(obj->u.poly.vy, y, size);
|
||||
}
|
||||
|
||||
|
||||
void layer_circ(void *ctx, int x, int y, int r,
|
||||
int color, int fill_color, unsigned layer)
|
||||
{
|
||||
struct layer *lc = ctx;
|
||||
struct layer_obj *obj = new_obj(ctx, lo_circ, color, fill_color, layer);
|
||||
|
||||
bb(lc, x - r, y - r);
|
||||
bb(lc, x + r, y + r);
|
||||
|
||||
obj->x = x;
|
||||
obj->y = y;
|
||||
obj->u.circ.r = r;
|
||||
}
|
||||
|
||||
|
||||
void layer_arc(void *ctx, int x, int y, int r, int sa, int ea,
|
||||
int color, int fill_color, unsigned layer)
|
||||
{
|
||||
struct layer *lc = ctx;
|
||||
struct layer_obj *obj = new_obj(ctx, lo_arc, color, fill_color, layer);
|
||||
|
||||
bb(lc, x - r, y - r);
|
||||
bb(lc, x + r, y + r);
|
||||
|
||||
obj->x = x;
|
||||
obj->y = y;
|
||||
obj->u.arc.r = r;
|
||||
obj->u.arc.sa = sa;
|
||||
obj->u.arc.ea = ea;
|
||||
}
|
||||
|
||||
|
||||
void layer_text(void *ctx, int x, int y, const char *s, unsigned size,
|
||||
enum text_align align, int rot, unsigned color, unsigned layer)
|
||||
{
|
||||
struct layer *lc = ctx;
|
||||
struct layer_obj *obj = new_obj(ctx, lo_text, color, COLOR_NONE, layer);
|
||||
unsigned width = lc->ops->text_width(lc->user, s, size);
|
||||
|
||||
bb_rot(lc, x, y - size, rot);
|
||||
bb_rot(lc, x + width, y, rot);
|
||||
|
||||
obj->x = x;
|
||||
obj->y = y;
|
||||
obj->u.text.s = stralloc(s);
|
||||
obj->u.text.size = size;
|
||||
obj->u.text.align = align;
|
||||
obj->u.text.rot = rot;
|
||||
}
|
||||
|
||||
|
||||
void layer_init(struct layer *layer, const struct gfx_ops *ops, void *user)
|
||||
{
|
||||
layer->ops = ops;
|
||||
layer->user = user;
|
||||
layer->xmin = layer->ymin = INT_MAX;
|
||||
layer->xmax = layer->ymax = INT_MIN;
|
||||
layer->objs = NULL;
|
||||
}
|
||||
|
||||
|
||||
void layer_replay(const struct layer *layer)
|
||||
{
|
||||
const struct gfx_ops *ops = layer->ops;
|
||||
void *ctx = layer->user;
|
||||
const struct layer_objs *objs;
|
||||
const struct layer_obj *obj;
|
||||
|
||||
for (objs = layer->objs; objs; objs = objs->next)
|
||||
for (obj = objs->obj; obj; obj = obj->next)
|
||||
switch (obj->type) {
|
||||
case lo_line:
|
||||
ops->line(ctx, obj->x, obj->y,
|
||||
obj->u.line.ex, obj->u.line.ey,
|
||||
obj->color, objs->layer);
|
||||
break;
|
||||
case lo_rect:
|
||||
ops->rect(ctx, obj->x, obj->y,
|
||||
obj->u.rect.ex, obj->u.rect.ey,
|
||||
obj->color, obj->fill_color, objs->layer);
|
||||
break;
|
||||
case lo_poly:
|
||||
ops->poly(ctx, obj->u.poly.n,
|
||||
obj->u.poly.vx, obj->u.poly.vy,
|
||||
obj->color, obj->fill_color, objs->layer);
|
||||
break;
|
||||
case lo_circ:
|
||||
ops->circ(ctx, obj->x, obj->y,
|
||||
obj->u.circ.r,
|
||||
obj->color, obj->fill_color, objs->layer);
|
||||
break;
|
||||
case lo_arc:
|
||||
ops->arc(ctx, obj->x, obj->y, obj->u.arc.r,
|
||||
obj->u.arc.sa, obj->u.arc.ea,
|
||||
obj->color, obj->fill_color, objs->layer);
|
||||
break;
|
||||
case lo_text:
|
||||
ops->text(ctx, obj->x, obj->y, obj->u.text.s,
|
||||
obj->u.text.size, obj->u.text.align,
|
||||
obj->u.text.rot,
|
||||
obj->color, objs->layer);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void layer_bbox(const struct layer *layer, int *x, int *y, int *w, int *h)
|
||||
{
|
||||
if (x)
|
||||
*x = layer->xmin;
|
||||
if (y)
|
||||
*y = layer->ymin;
|
||||
if (w)
|
||||
*w = layer->xmax - layer->xmin + 1;
|
||||
if (h)
|
||||
*h = layer->ymax - layer->ymin + 1;
|
||||
}
|
||||
|
||||
|
||||
static void layer_obj_destroy(struct layer_obj *obj)
|
||||
{
|
||||
switch (obj->type) {
|
||||
case lo_poly:
|
||||
free(obj->u.poly.vx);
|
||||
free(obj->u.poly.vy);
|
||||
break;
|
||||
case lo_text:
|
||||
free(obj->u.text.s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(obj);
|
||||
}
|
||||
|
||||
|
||||
void layer_destroy(struct layer *layer)
|
||||
{
|
||||
struct layer_objs *next_objs;
|
||||
struct layer_obj *next_obj;
|
||||
|
||||
while (layer->objs) {
|
||||
next_objs = layer->objs->next;
|
||||
while (layer->objs->obj) {
|
||||
next_obj = layer->objs->obj->next;
|
||||
layer_obj_destroy(layer->objs->obj);
|
||||
layer->objs->obj = next_obj;
|
||||
}
|
||||
free(layer->objs);
|
||||
layer->objs = next_objs;
|
||||
}
|
||||
}
|
56
sch2fig/layer.h
Normal file
56
sch2fig/layer.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* layer.h - Separate graphics operations by layers and replay
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LAYER_H
|
||||
#define LAYER_H
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
|
||||
struct layer_obj;
|
||||
|
||||
struct layer_objs {
|
||||
unsigned layer;
|
||||
struct layer_obj *obj;
|
||||
struct layer_obj **next_obj;
|
||||
struct layer_objs *next;
|
||||
};
|
||||
|
||||
struct layer {
|
||||
const struct gfx_ops *ops;
|
||||
void *user;
|
||||
int xmin, xmax;
|
||||
int ymin, ymax;
|
||||
struct layer_objs *objs;
|
||||
};
|
||||
|
||||
|
||||
void layer_line(void *ctx, int sx, int sy, int ex, int ey,
|
||||
int color, unsigned layer);
|
||||
void layer_rect(void *ctx, int sx, int sy, int ex, int ey,
|
||||
int color, int fill_color, unsigned layer);
|
||||
void layer_poly(void *ctx, int points, int x[points], int y[points],
|
||||
int color, int fill_color, unsigned layer);
|
||||
void layer_circ(void *ctx, int x, int y, int r,
|
||||
int color, int fill_color, unsigned layer);
|
||||
void layer_arc(void *ctx, int x, int y, int r, int sa, int ea,
|
||||
int color, int fill_color, unsigned layer);
|
||||
void layer_text(void *ctx, int x, int y, const char *s, unsigned size,
|
||||
enum text_align align, int rot, unsigned color, unsigned layer);
|
||||
|
||||
void layer_init(struct layer *layer, const struct gfx_ops *ops, void *user);
|
||||
void layer_replay(const struct layer *layer);
|
||||
void layer_bbox(const struct layer *layer, int *x, int *y, int *w, int *h);
|
||||
void layer_destroy(struct layer *layer);
|
||||
|
||||
#endif /* !LAYER_H */
|
Loading…
Reference in New Issue
Block a user