mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-27 04:52:48 +02:00
sch2fig/: rename "layer" to "record", and use "layer" for layers in recordings
Clearing up massively confusing naming.
This commit is contained in:
parent
c50e7116cf
commit
a03e79de7c
@ -13,7 +13,7 @@
|
|||||||
NAME = sch2fig
|
NAME = sch2fig
|
||||||
OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.o \
|
OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.o \
|
||||||
file.o \
|
file.o \
|
||||||
style.o fig.o layer.o cairo.o gfx.o dwg.o text.o misc.o
|
style.o fig.o record.o cairo.o gfx.o dwg.o text.o misc.o
|
||||||
|
|
||||||
CFLAGS = -g -O -Wall -Wextra -Wno-unused-parameter -Wshadow \
|
CFLAGS = -g -O -Wall -Wextra -Wno-unused-parameter -Wshadow \
|
||||||
-Wmissing-prototypes -Wmissing-declarations \
|
-Wmissing-prototypes -Wmissing-declarations \
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "layer.h"
|
#include "record.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
|
|
||||||
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
|
|
||||||
struct cairo_ctx {
|
struct cairo_ctx {
|
||||||
struct layer layer; /* must be first */
|
struct record record; /* must be first */
|
||||||
|
|
||||||
int xo, yo;
|
int xo, yo;
|
||||||
float scale;
|
float scale;
|
||||||
@ -48,7 +48,7 @@ struct cairo_ctx {
|
|||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
cairo_surface_t *s;
|
cairo_surface_t *s;
|
||||||
|
|
||||||
struct layer *sheets; /* for PDF */
|
struct record *sheets; /* for PDF */
|
||||||
unsigned n_sheets;
|
unsigned n_sheets;
|
||||||
|
|
||||||
const char *output_name;
|
const char *output_name;
|
||||||
@ -266,7 +266,7 @@ static struct cairo_ctx *init_common(int argc, char *const *argv)
|
|||||||
usage(*argv);
|
usage(*argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
layer_init(&cc->layer, &real_cairo_ops, cc);
|
record_init(&cc->record, &real_cairo_ops, cc);
|
||||||
|
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
@ -309,7 +309,7 @@ static void end_common(struct cairo_ctx *cc, int *w, int *h)
|
|||||||
cairo_surface_destroy(cc->s);
|
cairo_surface_destroy(cc->s);
|
||||||
cairo_destroy(cc->cr);
|
cairo_destroy(cc->cr);
|
||||||
|
|
||||||
layer_bbox(&cc->layer, &x, &y, w, h);
|
record_bbox(&cc->record, &x, &y, w, h);
|
||||||
|
|
||||||
// fprintf(stderr, "%dx%d%+d%+d\n", *w, *h, x, y);
|
// fprintf(stderr, "%dx%d%+d%+d\n", *w, *h, x, y);
|
||||||
cc->xo = -cd(cc, x);
|
cc->xo = -cd(cc, x);
|
||||||
@ -337,8 +337,8 @@ static void cr_png_end(void *ctx)
|
|||||||
CAIRO_FONT_WEIGHT_BOLD);
|
CAIRO_FONT_WEIGHT_BOLD);
|
||||||
cairo_set_line_width(cc->cr, 2);
|
cairo_set_line_width(cc->cr, 2);
|
||||||
|
|
||||||
layer_replay(&cc->layer);
|
record_replay(&cc->record);
|
||||||
layer_destroy(&cc->layer);
|
record_destroy(&cc->record);
|
||||||
|
|
||||||
if (cc->output_name)
|
if (cc->output_name)
|
||||||
cairo_surface_write_to_png(cc->s, cc->output_name);
|
cairo_surface_write_to_png(cc->s, cc->output_name);
|
||||||
@ -350,13 +350,13 @@ static void cr_pdf_new_sheet(void *ctx)
|
|||||||
struct cairo_ctx *cc = ctx;
|
struct cairo_ctx *cc = ctx;
|
||||||
|
|
||||||
cc->n_sheets++;
|
cc->n_sheets++;
|
||||||
cc->sheets = realloc(cc->sheets, sizeof(struct layer) * cc->n_sheets);
|
cc->sheets = realloc(cc->sheets, sizeof(struct record) * cc->n_sheets);
|
||||||
if (!cc->sheets) {
|
if (!cc->sheets) {
|
||||||
perror("realloc");
|
perror("realloc");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
cc->sheets[cc->n_sheets - 1] = cc->layer;
|
cc->sheets[cc->n_sheets - 1] = cc->record;
|
||||||
layer_wipe(&cc->layer);
|
record_wipe(&cc->record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -379,14 +379,14 @@ static void cr_pdf_end(void *ctx)
|
|||||||
set_color(cc->cr, COLOR_WHITE);
|
set_color(cc->cr, COLOR_WHITE);
|
||||||
cairo_paint(cc->cr);
|
cairo_paint(cc->cr);
|
||||||
|
|
||||||
layer_replay(cc->sheets + i);
|
record_replay(cc->sheets + i);
|
||||||
layer_destroy(cc->sheets + i);
|
record_destroy(cc->sheets + i);
|
||||||
|
|
||||||
cairo_show_page(cc->cr);
|
cairo_show_page(cc->cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
layer_replay(&cc->layer);
|
record_replay(&cc->record);
|
||||||
layer_destroy(&cc->layer);
|
record_destroy(&cc->record);
|
||||||
|
|
||||||
cairo_show_page(cc->cr);
|
cairo_show_page(cc->cr);
|
||||||
|
|
||||||
@ -400,11 +400,11 @@ static void cr_pdf_end(void *ctx)
|
|||||||
|
|
||||||
const struct gfx_ops cairo_png_ops = {
|
const struct gfx_ops cairo_png_ops = {
|
||||||
.name = "png",
|
.name = "png",
|
||||||
.line = layer_line,
|
.line = record_line,
|
||||||
.poly = layer_poly,
|
.poly = record_poly,
|
||||||
.circ = layer_circ,
|
.circ = record_circ,
|
||||||
.arc = layer_arc,
|
.arc = record_arc,
|
||||||
.text = layer_text,
|
.text = record_text,
|
||||||
.text_width = cr_text_width,
|
.text_width = cr_text_width,
|
||||||
.init = cr_png_init,
|
.init = cr_png_init,
|
||||||
.end = cr_png_end,
|
.end = cr_png_end,
|
||||||
@ -412,11 +412,11 @@ const struct gfx_ops cairo_png_ops = {
|
|||||||
|
|
||||||
const struct gfx_ops cairo_pdf_ops = {
|
const struct gfx_ops cairo_pdf_ops = {
|
||||||
.name = "pdf",
|
.name = "pdf",
|
||||||
.line = layer_line,
|
.line = record_line,
|
||||||
.poly = layer_poly,
|
.poly = record_poly,
|
||||||
.circ = layer_circ,
|
.circ = record_circ,
|
||||||
.arc = layer_arc,
|
.arc = record_arc,
|
||||||
.text = layer_text,
|
.text = record_text,
|
||||||
.text_width = cr_text_width,
|
.text_width = cr_text_width,
|
||||||
.init = cr_pdf_init,
|
.init = cr_pdf_init,
|
||||||
.new_sheet = cr_pdf_new_sheet,
|
.new_sheet = cr_pdf_new_sheet,
|
||||||
|
336
sch2fig/layer.c
336
sch2fig/layer.c
@ -1,336 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
// @@@ figure this out later
|
|
||||||
return;
|
|
||||||
bb(layer, cos(a) * x + sin(a) * y, cos(a) * y - sin(a) * x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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, const int x[points], const 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_wipe(struct layer *layer)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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, const int x[points], const 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_wipe(struct layer *layer);
|
|
||||||
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 */
|
|
342
sch2fig/record.c
Normal file
342
sch2fig/record.c
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
/*
|
||||||
|
* record.c - Record 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 "record.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct record_obj {
|
||||||
|
enum ro_type {
|
||||||
|
ro_line,
|
||||||
|
ro_rect,
|
||||||
|
ro_poly,
|
||||||
|
ro_circ,
|
||||||
|
ro_arc,
|
||||||
|
ro_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 record_obj *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void bb(struct record *rec, int x, int y)
|
||||||
|
{
|
||||||
|
if (rec->xmin > x)
|
||||||
|
rec->xmin = x;
|
||||||
|
if (rec->ymin > y)
|
||||||
|
rec->ymin = y;
|
||||||
|
if (rec->xmax < x)
|
||||||
|
rec->xmax = x;
|
||||||
|
if (rec->ymax < y)
|
||||||
|
rec->ymax = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void bb_rot(struct record *rec, int x, int y, int rot)
|
||||||
|
{
|
||||||
|
double a = -rot / 180.0 * M_PI;
|
||||||
|
|
||||||
|
// @@@ figure this out later
|
||||||
|
return;
|
||||||
|
bb(rec, cos(a) * x + sin(a) * y, cos(a) * y - sin(a) * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct record_obj *new_obj(struct record *rec, enum ro_type type,
|
||||||
|
int color, int fill_color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record_layer **curr_layer;
|
||||||
|
struct record_layer *new_layer;
|
||||||
|
struct record_obj *new_obj;
|
||||||
|
|
||||||
|
for (curr_layer = &rec->layers; *curr_layer;
|
||||||
|
curr_layer= &(*curr_layer)->next) {
|
||||||
|
if ((*curr_layer)->layer == layer)
|
||||||
|
goto this_layer;
|
||||||
|
if ((*curr_layer)->layer < layer)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_layer = alloc_type(struct record_layer);
|
||||||
|
new_layer->layer = layer;
|
||||||
|
new_layer->objs = NULL;
|
||||||
|
new_layer->next_obj = &new_layer->objs;
|
||||||
|
new_layer->next = *curr_layer;
|
||||||
|
*curr_layer = new_layer;
|
||||||
|
|
||||||
|
this_layer:
|
||||||
|
new_obj = alloc_type(struct record_obj);
|
||||||
|
new_obj->type = type;
|
||||||
|
new_obj->color = color;
|
||||||
|
new_obj->fill_color = fill_color;
|
||||||
|
new_obj->next = NULL;
|
||||||
|
|
||||||
|
*(*curr_layer)->next_obj = new_obj;
|
||||||
|
(*curr_layer)->next_obj = &new_obj->next;
|
||||||
|
|
||||||
|
return new_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_line(void *ctx, int sx, int sy, int ex, int ey,
|
||||||
|
int color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record *rec = ctx;
|
||||||
|
struct record_obj *obj =
|
||||||
|
new_obj(rec, ro_line, color, COLOR_NONE, layer);
|
||||||
|
|
||||||
|
bb(rec, sx, sy);
|
||||||
|
bb(rec, ex, ey);
|
||||||
|
|
||||||
|
obj->x = sx;
|
||||||
|
obj->y = sy;
|
||||||
|
obj->u.line.ex = ex;
|
||||||
|
obj->u.line.ey = ey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_rect(void *ctx, int sx, int sy, int ex, int ey,
|
||||||
|
int color, int fill_color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record *rec = ctx;
|
||||||
|
struct record_obj *obj =
|
||||||
|
new_obj(rec, ro_rect, color, fill_color, layer);
|
||||||
|
|
||||||
|
bb(rec, sx, sy);
|
||||||
|
bb(rec, ex, ey);
|
||||||
|
|
||||||
|
obj->x = sx;
|
||||||
|
obj->y = sy;
|
||||||
|
obj->u.rect.ex = ex;
|
||||||
|
obj->u.rect.ey = ey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_poly(void *ctx,
|
||||||
|
int points, const int x[points], const int y[points],
|
||||||
|
int color, int fill_color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record *rec = ctx;
|
||||||
|
struct record_obj *obj =
|
||||||
|
new_obj(ctx, ro_poly, color, fill_color, layer);
|
||||||
|
int i;
|
||||||
|
unsigned size;
|
||||||
|
|
||||||
|
for (i = 0; i != points; i++)
|
||||||
|
bb(rec, 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 record_circ(void *ctx, int x, int y, int r,
|
||||||
|
int color, int fill_color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record *rec = ctx;
|
||||||
|
struct record_obj *obj =
|
||||||
|
new_obj(ctx, ro_circ, color, fill_color, layer);
|
||||||
|
|
||||||
|
bb(rec, x - r, y - r);
|
||||||
|
bb(rec, x + r, y + r);
|
||||||
|
|
||||||
|
obj->x = x;
|
||||||
|
obj->y = y;
|
||||||
|
obj->u.circ.r = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_arc(void *ctx, int x, int y, int r, int sa, int ea,
|
||||||
|
int color, int fill_color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record *rec = ctx;
|
||||||
|
struct record_obj *obj = new_obj(ctx, ro_arc, color, fill_color, layer);
|
||||||
|
|
||||||
|
bb(rec, x - r, y - r);
|
||||||
|
bb(rec, 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 record_text(void *ctx, int x, int y, const char *s, unsigned size,
|
||||||
|
enum text_align align, int rot, unsigned color, unsigned layer)
|
||||||
|
{
|
||||||
|
struct record *rec = ctx;
|
||||||
|
struct record_obj *obj =
|
||||||
|
new_obj(ctx, ro_text, color, COLOR_NONE, layer);
|
||||||
|
unsigned width = rec->ops->text_width(rec->user, s, size);
|
||||||
|
|
||||||
|
bb_rot(rec, x, y - size, rot);
|
||||||
|
bb_rot(rec, 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 record_init(struct record *rec, const struct gfx_ops *ops, void *user)
|
||||||
|
{
|
||||||
|
rec->ops = ops;
|
||||||
|
rec->user = user;
|
||||||
|
rec->xmin = rec->ymin = INT_MAX;
|
||||||
|
rec->xmax = rec->ymax = INT_MIN;
|
||||||
|
rec->layers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_wipe(struct record *rec)
|
||||||
|
{
|
||||||
|
rec->layers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_replay(const struct record *rec)
|
||||||
|
{
|
||||||
|
const struct gfx_ops *ops = rec->ops;
|
||||||
|
void *ctx = rec->user;
|
||||||
|
const struct record_layer *layer;
|
||||||
|
const struct record_obj *obj;
|
||||||
|
|
||||||
|
for (layer = rec->layers; layer; layer = layer->next)
|
||||||
|
for (obj = layer->objs; obj; obj = obj->next)
|
||||||
|
switch (obj->type) {
|
||||||
|
case ro_line:
|
||||||
|
ops->line(ctx, obj->x, obj->y,
|
||||||
|
obj->u.line.ex, obj->u.line.ey,
|
||||||
|
obj->color, layer->layer);
|
||||||
|
break;
|
||||||
|
case ro_rect:
|
||||||
|
ops->rect(ctx, obj->x, obj->y,
|
||||||
|
obj->u.rect.ex, obj->u.rect.ey,
|
||||||
|
obj->color, obj->fill_color, layer->layer);
|
||||||
|
break;
|
||||||
|
case ro_poly:
|
||||||
|
ops->poly(ctx, obj->u.poly.n,
|
||||||
|
obj->u.poly.vx, obj->u.poly.vy,
|
||||||
|
obj->color, obj->fill_color, layer->layer);
|
||||||
|
break;
|
||||||
|
case ro_circ:
|
||||||
|
ops->circ(ctx, obj->x, obj->y,
|
||||||
|
obj->u.circ.r,
|
||||||
|
obj->color, obj->fill_color, layer->layer);
|
||||||
|
break;
|
||||||
|
case ro_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, layer->layer);
|
||||||
|
break;
|
||||||
|
case ro_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, layer->layer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_bbox(const struct record *rec, int *x, int *y, int *w, int *h)
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
*x = rec->xmin;
|
||||||
|
if (y)
|
||||||
|
*y = rec->ymin;
|
||||||
|
if (w)
|
||||||
|
*w = rec->xmax - rec->xmin + 1;
|
||||||
|
if (h)
|
||||||
|
*h = rec->ymax - rec->ymin + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void record_obj_destroy(struct record_obj *obj)
|
||||||
|
{
|
||||||
|
switch (obj->type) {
|
||||||
|
case ro_poly:
|
||||||
|
free(obj->u.poly.vx);
|
||||||
|
free(obj->u.poly.vy);
|
||||||
|
break;
|
||||||
|
case ro_text:
|
||||||
|
free(obj->u.text.s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void record_destroy(struct record *rec)
|
||||||
|
{
|
||||||
|
struct record_layer *next_layer;
|
||||||
|
struct record_obj *next_obj;
|
||||||
|
|
||||||
|
while (rec->layers) {
|
||||||
|
next_layer = rec->layers->next;
|
||||||
|
while (rec->layers->objs) {
|
||||||
|
next_obj = rec->layers->objs->next;
|
||||||
|
record_obj_destroy(rec->layers->objs);
|
||||||
|
rec->layers->objs = next_obj;
|
||||||
|
}
|
||||||
|
free(rec->layers);
|
||||||
|
rec->layers = next_layer;
|
||||||
|
}
|
||||||
|
}
|
58
sch2fig/record.h
Normal file
58
sch2fig/record.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* record.h - Record 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 RECORD_H
|
||||||
|
#define RECORD_H
|
||||||
|
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct record_obj;
|
||||||
|
|
||||||
|
struct record_layer {
|
||||||
|
unsigned layer;
|
||||||
|
struct record_obj *objs;
|
||||||
|
struct record_obj **next_obj;
|
||||||
|
struct record_layer *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct record {
|
||||||
|
const struct gfx_ops *ops;
|
||||||
|
void *user;
|
||||||
|
int xmin, xmax;
|
||||||
|
int ymin, ymax;
|
||||||
|
struct record_layer *layers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void record_line(void *ctx, int sx, int sy, int ex, int ey,
|
||||||
|
int color, unsigned layer);
|
||||||
|
void record_rect(void *ctx, int sx, int sy, int ex, int ey,
|
||||||
|
int color, int fill_color, unsigned layer);
|
||||||
|
void record_poly(void *ctx,
|
||||||
|
int points, const int x[points], const int y[points],
|
||||||
|
int color, int fill_color, unsigned layer);
|
||||||
|
void record_circ(void *ctx, int x, int y, int r,
|
||||||
|
int color, int fill_color, unsigned layer);
|
||||||
|
void record_arc(void *ctx, int x, int y, int r, int sa, int ea,
|
||||||
|
int color, int fill_color, unsigned layer);
|
||||||
|
void record_text(void *ctx, int x, int y, const char *s, unsigned size,
|
||||||
|
enum text_align align, int rot, unsigned color, unsigned layer);
|
||||||
|
|
||||||
|
void record_init(struct record *rec, const struct gfx_ops *ops, void *user);
|
||||||
|
void record_wipe(struct record *rec);
|
||||||
|
void record_replay(const struct record *rec);
|
||||||
|
void record_bbox(const struct record *rec, int *x, int *y, int *w, int *h);
|
||||||
|
void record_destroy(struct record *rec);
|
||||||
|
|
||||||
|
#endif /* !RECORD_H */
|
Loading…
Reference in New Issue
Block a user