summaryrefslogtreecommitdiff
path: root/meme/marker.c
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2016-02-14 03:54:57 (GMT)
committerWerner Almesberger <werner@almesberger.net>2016-02-14 03:55:32 (GMT)
commitd5afcf56635da6a906dc7343fed6576720b809ba (patch)
tree7bf699aadec0e766347b175f8dd3510c10c82293 /meme/marker.c
parent72e6384adec350a300e7c508ee027f3ec8b5857c (diff)
downloadmisc-d5afcf56635da6a906dc7343fed6576720b809ba.zip
misc-d5afcf56635da6a906dc7343fed6576720b809ba.tar.gz
misc-d5afcf56635da6a906dc7343fed6576720b809ba.tar.bz2
meme/: add marker system (for documentation); option -m marker.gp to add markers
Diffstat (limited to 'meme/marker.c')
-rw-r--r--meme/marker.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/meme/marker.c b/meme/marker.c
new file mode 100644
index 0000000..bedb638
--- /dev/null
+++ b/meme/marker.c
@@ -0,0 +1,158 @@
+/*
+ * marker.c - Markers
+ *
+ * Written 2016 by Werner Almesberger
+ * Copyright 2016 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "util.h"
+#include "marker.h"
+
+
+struct mark {
+ float xa, ya, xb, yb;
+ const char *s;
+ struct mark *next;
+};
+
+
+void marker_draw(const struct marker *marker,
+ void (*line)(void *user, int xa, int ya, int xb, int yb),
+ void (*text)(void *user, int x, int y, float nx, float ny, const char *txt),
+ void *user)
+{
+ const struct mark *mark;
+ float dx, dy, x, y;
+ float d;
+
+ for (mark = marker->markers; mark; mark = mark->next) {
+ if (mark->xa == mark->xb && mark->ya == mark->yb) {
+ text(user, mark->xa, mark->ya, 0, 0, mark->s);
+ continue;
+ }
+ dx = mark->xb - mark->xa;
+ dy = mark->yb - mark->ya;
+ d = hypotf(dx, dy);
+ x = (mark->xa + mark->xb) / 2.0;
+ y = (mark->ya + mark->yb) / 2.0;
+ line(user, mark->xa, mark->ya, mark->xb, mark->yb);
+ text(user, x, y, dy / d, -dx / d, mark->s);
+ }
+}
+
+
+static void marker_load_file(struct marker *marker, FILE *file,
+ void (*xform)(float x, float y, float *res_x, float *res_y))
+{
+ int lineno = 0;
+ char buf[1024];
+ int n;
+ double xa, ya, xb, yb;
+ char *s;
+ struct mark *mark;
+
+ marker->markers = NULL;
+ while (fgets(buf, sizeof(buf), file)) {
+ lineno++;
+ if (*buf == '#')
+ continue;
+ n = sscanf(buf, "%lf %lf %lf %lf %ms\n",
+ &xa, &ya, &xb, &yb, &s);
+ if (n != 5)
+ n = sscanf(buf, "%lf %lf %ms\n", &xa, &ya, &s);
+ switch (n) {
+ case -1:
+ continue;
+ case 3:
+ case 5:
+ break;
+ default:
+ fprintf(stderr, "invalid data at line %d\n", lineno);
+ exit(1);
+ }
+
+ mark = alloc_type(struct mark);
+ mark->next = marker->markers;
+ if (xform) {
+ xform(xa, ya, &mark->xa, &mark->ya);
+ } else {
+ mark->xa = xa;
+ mark->ya = ya;
+ }
+ mark->s = s;
+
+ if (n == 3) {
+ mark->xb = mark->xa;
+ mark->yb = mark->ya;
+ } else {
+ if (xform) {
+ xform(xb, yb, &mark->xb, &mark->yb);
+ } else {
+ mark->xb = xb;
+ mark->yb = yb;
+ }
+ }
+ marker->markers = mark;
+ }
+}
+
+
+static void marker_do_load(struct marker *marker)
+{
+ FILE *file;
+
+ file = fopen(marker->name, "r");
+ if (!file) {
+ perror(marker->name);
+ exit(1);
+ }
+ marker_load_file(marker, file, marker->xform);
+ fclose(file);
+}
+
+
+static void free_marker(struct marker *marker)
+{
+ struct mark *mark, *next;
+
+ while (marker->markers) {
+ mark = marker->markers;
+ next = mark->next;
+ free((void *) mark->s);
+ free(mark);
+ marker->markers = next;
+ }
+}
+
+
+void marker_reload(struct marker *marker)
+{
+ if (!marker->name)
+ return;
+ free_marker(marker);
+ marker_do_load(marker);
+}
+
+
+void marker_load(struct marker *marker, const char *name,
+ void (*xform)(float x, float y, float *res_x, float *res_y))
+{
+ marker->name = strdup(name);
+ if (!marker->name) {
+ perror("strdup");
+ exit(1);
+ }
+ marker->xform = xform;
+ marker_do_load(marker);
+}