prepare ffplot to read from stdin - ploot - simple plotting tools
(HTM) git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
(DIR) LICENSE
---
(DIR) commit 522bbe841ea86e232baf35ba638fe490cc763325
(DIR) parent df6b2deeefb42f4102a9bba819e7d06d15a3aebf
(HTM) Author: Josuah Demangeon <mail@josuah.net>
Date: Tue, 1 May 2018 20:00:10 +0200
prepare ffplot to read from stdin
Diffstat:
M Makefile | 4 ++--
M ffdraw.c | 19 ++++++++++++++++++-
D ffdraw.h | 39 -------------------------------
M ffplot.c | 241 +++++++++++++++++++++++++++++++
M font.h | 3 ++-
M main.c | 293 ++++---------------------------
A ploot.h | 44 +++++++++++++++++++++++++++++++
7 files changed, 342 insertions(+), 301 deletions(-)
---
(DIR) diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
CFLAGS = -Wall -Wextra -Werror -std=c89 -pedantic -D_POSIX_C_SOURCE=200809L
LDFLAGS = -static
-SRC = main.c ffdraw.c font_14x7.c
+SRC = main.c ffplot.c ffdraw.c font_14x7.c
OBJ = $(SRC:.c=.o)
LIB = -lm
@@ -19,4 +19,4 @@ clean:x
x:
-$(SRC): arg.h ffdraw.h font.h font_14x7.h
+$(SRC): arg.h ploot.h font.h font_14x7.h
(DIR) diff --git a/ffdraw.c b/ffdraw.c
@@ -6,11 +6,14 @@
* - (0,1) is above it. +--x
*/
+#include <arpa/inet.h>
+
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
-#include "ffdraw.h"
+#include "ploot.h"
/*
* Convert (x,y) coordinates to (row,col) for printing into the buffer.
@@ -144,3 +147,17 @@ ffdraw_fill(Canvas *can, Color *col)
can->x = x;
can->y = y;
}
+
+void
+ffdraw_print(Canvas *can)
+{
+ uint32_t w, h;
+
+ w = htonl(can->w);
+ h = htonl(can->h);
+
+ fputs("farbfeld", stdout);
+ fwrite(&w, sizeof(w), 1, stdout);
+ fwrite(&h, sizeof(h), 1, stdout);
+ fwrite(can->b, can->w * can->h, sizeof(*can->b), stdout);
+}
(DIR) diff --git a/ffdraw.h b/ffdraw.h
@@ -1,39 +0,0 @@
-#include <time.h>
-
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-
-typedef uint16_t Color[4];
-
-typedef struct {
- int w; /* width */
- int h; /* height */
- Color *b; /* buffer */
- int x; /* x offset */
- int y; /* x offset */
-} Canvas;
-
-typedef struct {
- int w; /* width */
- int h; /* height */
- char *b[128]; /* buffer */
-} Font;
-
-typedef struct {
- Color col; /* for drawing the curve and the legend */
-/* time_t *t; / * array of timestamps */
- double *v; /* array of values */
- int n; /* number of values */
- time_t step;
- char *name; /* for the legend */
-} Vlist;
-
-/* ffdraw.c */
-void ffdraw_pixel (Canvas *, Color *, int, int);
-void ffdraw_rectangle(Canvas *, Color *, int, int, int, int);
-void ffdraw_line (Canvas *, Color *, int, int, int, int);
-void ffdraw_char (Canvas *, Color *, char, Font *, int, int);
-void ffdraw_str_left(Canvas *, Color *, char *, Font *, int, int);
-void ffdraw_str_center(Canvas *, Color *, char *, Font *, int, int);
-void ffdraw_str_right(Canvas *, Color *, char *, Font *, int, int);
-void ffdraw_fill (Canvas *, Color *);
(DIR) diff --git a/ffplot.c b/ffplot.c
@@ -0,0 +1,241 @@
+/*
+ * Draw a plot
+ *
+ * Title (units)
+ * y ^ Legend
+ * label |- + - + - + - + -
+ * here |- + - + - + - + -
+ * +--+---+---+---+-->
+ * x label here
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "ploot.h" /* placed before for Font type declaration */
+#include "font_14x7.h"
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+#define MARGIN 4
+
+#define FONT_H 14
+#define FONT_W 7
+
+#define TITLE_X (IMAGE_H - TITLE_H)
+#define TITLE_Y (XLABEL_W)
+#define TITLE_H (FONT_H * 2)
+#define TITLE_W (PLOT_W)
+
+#define XLABEL_X (PLOT_X)
+#define XLABEL_Y (0)
+#define XLABEL_H (PLOT_H)
+#define XLABEL_W (FONT_W * 9 + MARGIN)
+
+#define YLABEL_X (0)
+#define YLABEL_Y (PLOT_Y)
+#define YLABEL_H (FONT_H * 2)
+#define YLABEL_W (PLOT_W)
+
+#define PLOT_X (YLABEL_H)
+#define PLOT_Y (XLABEL_W)
+#define PLOT_W 700
+#define PLOT_H 200
+
+#define LEGEND_X (YLABEL_H)
+#define LEGEND_Y (IMAGE_W - LEGEND_W)
+#define LEGEND_W (FONT_W + 150 + FONT_W)
+#define LEGEND_H (PLOT_H)
+
+#define IMAGE_H (TITLE_H + PLOT_H + YLABEL_H)
+#define IMAGE_W (XLABEL_W + PLOT_W + LEGEND_W)
+
+Color buffer[IMAGE_W * IMAGE_H];
+
+Color c_axis = { 0xffff, 0xffff, 0xffff, 0xfff };
+Font *font = &font_14x7;
+
+static int
+t2y(time_t t, time_t tmin, time_t tmax)
+{
+ return (t - tmin) * PLOT_W / (tmax - tmin);
+}
+
+static int
+v2x(double v, double vmin, double vmax)
+{
+ return (v - vmin) * PLOT_H / (vmax - vmin);
+}
+
+/*
+ * Set 'str' to a human-readable form of 'num' with always a width of 8 (+ 1
+ * the '\0' terminator). Buffer overflow is ensured not to happen due to the
+ * max size of a double. Return the exponent.
+ */
+static int
+humanize(char *str, double val)
+{
+ int exp, precision;
+ char label[] = { '\0', 'M', 'G', 'T', 'E' };
+
+ for (exp = 0; ABS(val) > 1000; exp++)
+ val /= 1000;
+
+ precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
+ precision += (exp == 0);
+
+ snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
+ str[8] = '\0';
+ if (val >= 0)
+ str[0] = ' ';
+
+ return exp * 3;
+}
+
+static void
+xaxis(Canvas *can, Color *label, Color *grid,
+ double vmin, double vmax, double vstep)
+{
+ double v;
+ int x;
+ char str[8 + 1];
+
+ for (v = vmax - fmod(vmax, vstep); v >= vmin; v -= vstep) {
+ x = v2x(v, vmin, vmax);
+
+ ffdraw_line(can, grid,
+ x, XLABEL_W,
+ x, XLABEL_W + PLOT_W);
+
+ humanize(str, v);
+ ffdraw_str_right(can, label, str, font,
+ x, XLABEL_W - MARGIN);
+ }
+}
+
+static void
+yaxis(Canvas *can, Color *label, Color *grid,
+ time_t tmin, time_t tmax, time_t tstep)
+{
+ time_t t;
+ int y;
+ char str[sizeof("YYYY/MM/DD")], *fmt;
+
+ fmt = (tstep < 3600 * 24) ? " %H:%M:%S " : " %Y/%m/%d ";
+
+ for (t = tmax - tmax % tstep; t >= tmin; t -= tstep) {
+ y = t2y(t, tmin, tmax);
+
+ ffdraw_line(can, grid,
+ YLABEL_H, y,
+ YLABEL_H + PLOT_H, y);
+
+ strftime(str, sizeof(str), fmt, localtime(&t));
+ ffdraw_str_center(can, label, str, font,
+ YLABEL_H / 2, y);
+ }
+}
+
+static void
+title(Canvas *can,
+ Color *ct, char *title,
+ Color *cu, char *unit)
+{
+ ffdraw_str_left(can, ct, title, font,
+ TITLE_H / 2, 0);
+ ffdraw_str_right(can, cu, unit, font,
+ TITLE_H / 2, TITLE_W);
+}
+
+static void
+graph(Canvas *can, Vlist *v,
+ double vmin, double vmax,
+ time_t tmin, time_t tmax)
+{
+ time_t *tp;
+ double *vp;
+ int x, y, n, xlast, ylast, first;
+
+ first = 1;
+ for (tp = v->t, vp = v->v, n = v->n; n-- > 0; n--, vp++, tp++) {
+ x = v2x(*vp, vmin, vmax);
+ y = t2y(*tp, tmin, tmax);
+
+ if (!first)
+ ffdraw_line(can, &v->col, xlast, ylast, x, y);
+
+ xlast = x;
+ ylast = y;
+ first = 0;
+ }
+}
+
+static void
+plot(Canvas *can, Vlist *v, int n,
+ double vmin, double vmax,
+ time_t tmin, time_t tmax)
+{
+ for (; n > 0; n--, v++)
+ graph(can, v, vmin, vmax, tmin, tmax);
+}
+
+static void
+legend(Canvas *can, Color *label_fg, Vlist *v, int n)
+{
+ int i, x, y;
+
+ for (i = 0; i < n; i++, v++) {
+ x = LEGEND_H - n * (FONT_H + MARGIN) - FONT_H / 2;
+
+ y = MARGIN + FONT_W;
+ ffdraw_str_left(can, &v->col, "\1", font, x, y);
+
+ y += FONT_W * 2;
+ ffdraw_str_left(can, label_fg, v->name, font, x, y);
+ }
+}
+
+void
+ffdraw(char *name, char *units, Vlist *v, int n,
+ double vmin, double vmax, double vstep,
+ time_t tmin, time_t tmax, time_t tstep)
+{
+ Canvas can = { IMAGE_W, IMAGE_H, buffer, 0, 0 };
+ Color plot_bg = { 0x2222, 0x2222, 0x2222, 0xffff };
+ Color grid_bg = { 0x2929, 0x2929, 0x2929, 0xffff };
+ Color grid_fg = { 0x3737, 0x3737, 0x3737, 0xffff };
+ Color label_fg = { 0x8888, 0x8888, 0x8888, 0xffff };
+ Color title_fg = { 0xdddd, 0xdddd, 0xdddd, 0xffff };
+
+ can.x = 0;
+ can.y = 0;
+ ffdraw_fill(&can, &plot_bg);
+
+ can.x = PLOT_X;
+ can.y = PLOT_Y;
+ ffdraw_rectangle(&can, &grid_bg, 0, 0, PLOT_H, PLOT_W);
+
+ can.x = YLABEL_X;
+ can.y = YLABEL_Y;
+ yaxis(&can, &label_fg, &grid_fg, tmin, tmax, tstep);
+
+ can.x = XLABEL_X;
+ can.y = XLABEL_Y;
+ xaxis(&can, &label_fg, &grid_fg, vmin, vmax, vstep);
+
+ can.x = TITLE_X;
+ can.y = TITLE_Y;
+ title(&can, &title_fg, name, &label_fg, units);
+
+ can.x = PLOT_X;
+ can.y = PLOT_Y;
+ plot(&can, v, n, vmin, vmax, tmin, tmax);
+
+ can.x = LEGEND_X;
+ can.y = LEGEND_Y;
+ legend(&can, &label_fg, v, n);
+
+ ffdraw_print(&can);
+}
(DIR) diff --git a/font.h b/font.h
@@ -1,6 +1,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "ffdraw.h"
+
+#include "ploot.h"
/*
* Macros to make the fonts header file more readable.
(DIR) diff --git a/main.c b/main.c
@@ -1,289 +1,66 @@
-#include <arpa/inet.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
-#include <math.h>
-
-#include "ffdraw.h"
-#include "font_14x7.h"
+#include "arg.h"
+#include "ploot.h"
-#define ABS(x) ((x) < 0 ? -(x) : (x))
#define LEN(x) (sizeof(x) / sizeof(*x))
-/*
- * Sizes and positions:
- *
- * Title on the first row legend
- * y ^ here
- * label |- + - + - + - + - with
- * here |- + - + - + - + - the
- * +--+---+---+---+--> full
- * x label here height
- */
-
-#define MARGIN 4
-
-#define FONT_H 14
-#define FONT_W 7
-
-#define TITLE_X (IMAGE_H - TITLE_H)
-#define TITLE_Y (XLABEL_W)
-#define TITLE_H (FONT_H * 2)
-#define TITLE_W (PLOT_W)
-
-#define XLABEL_X (PLOT_X)
-#define XLABEL_Y (0)
-#define XLABEL_H (PLOT_H)
-#define XLABEL_W (FONT_W * 9 + MARGIN)
+char *argv0;
+char *tflag = "";
+char *uflag = "";
-#define YLABEL_X (0)
-#define YLABEL_Y (PLOT_Y)
-#define YLABEL_H (FONT_H * 2)
-#define YLABEL_W (PLOT_W)
-
-#define PLOT_X (YLABEL_H)
-#define PLOT_Y (XLABEL_W)
-#define PLOT_W 700
-#define PLOT_H 200
-
-#define LEGEND_X (YLABEL_H)
-#define LEGEND_Y (IMAGE_W - LEGEND_W)
-#define LEGEND_W (FONT_W + 150 + FONT_W)
-#define LEGEND_H (PLOT_H)
-
-#define IMAGE_H (TITLE_H + PLOT_H + YLABEL_H)
-#define IMAGE_W (XLABEL_W + PLOT_W + LEGEND_W)
-
-Color buffer[IMAGE_W * IMAGE_H];
-
-Color c_axis = { 0xffff, 0xffff, 0xffff, 0xfff };
-Font *font = &font_14x7;
-
-int
-ffplot_t2y(time_t t, time_t tmin, time_t tmax)
+static void
+usage(void)
{
- return (t - tmin) * PLOT_W / (tmax - tmin);
-}
-
-int
-ffplot_v2x(double v, double vmin, double vmax)
-{
- return (v - vmin) * PLOT_H / (vmax - vmin);
-}
-
-/*
- * Set 'str' to a human-readable form of 'num' with always a width of 8 (+ 1
- * the '\0' terminator). Buffer overflow is ensured not to happen due to the
- * max size of a double. Return the exponent.
- */
-int
-humanize(char *str, double val)
-{
- int exp, precision;
- char label[] = { '\0', 'M', 'G', 'T', 'E' };
-
- for (exp = 0; ABS(val) > 1000; exp++)
- val /= 1000;
-
- precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
- precision += (exp == 0);
-
- snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
- str[8] = '\0';
- if (val >= 0)
- str[0] = ' ';
-
- return exp * 3;
+ fprintf(stderr, "usage: %s [-t title] [-u unit] label:color...\n", argv0);
+ exit(1);
}
void
-ffplot_xaxis(Canvas *can, Color *label, Color *grid,
- double vmin, double vmax, double vstep)
+read_labels(Vlist *v, int n)
{
- double v;
- int x;
- char str[8 + 1];
-
- for (v = vmax - fmod(vmax, vstep); v >= vmin; v -= vstep) {
- x = ffplot_v2x(v, vmin, vmax);
-
- ffdraw_line(can, grid,
- x, XLABEL_W,
- x, XLABEL_W + PLOT_W);
-
- humanize(str, v);
- ffdraw_str_right(can, label, str, font,
- x, XLABEL_W - MARGIN);
- }
+ (void)v;
+ (void)n;
}
void
-ffplot_yaxis(Canvas *can, Color *label, Color *grid,
- time_t tmin, time_t tmax, time_t tstep)
+read_values(Vlist *v, int n)
{
- time_t t;
- int y;
- char str[sizeof("YYYY/MM/DD")], *fmt;
-
- fmt = (tstep < 3600 * 24) ? " %H:%M:%S " : " %Y/%m/%d ";
-
- for (t = tmax - tmax % tstep; t >= tmin; t -= tstep) {
- y = ffplot_t2y(t, tmin, tmax);
-
- ffdraw_line(can, grid,
- YLABEL_H, y,
- YLABEL_H + PLOT_H, y);
-
- strftime(str, sizeof(str), fmt, localtime(&t));
- ffdraw_str_center(can, label, str, font,
- YLABEL_H / 2, y);
- }
-}
-
-void
-ffplot_title(Canvas *can,
- Color *ct, char *title,
- Color *cu, char *unit)
-{
- ffdraw_str_left(can, ct, title, font,
- TITLE_H / 2, 0);
- ffdraw_str_right(can, cu, unit, font,
- TITLE_H / 2, TITLE_W);
-}
-
-void
-ffplot_graph(Canvas *can, Vlist *v,
- double vmin, double vmax,
- time_t tmin, time_t tmax)
-{
- time_t t;
- double *vp;
- int x, y, n, xlast, ylast, first;
-
- first = 1;
- t = tmin;
- for (vp = v->v, n = v->n; n-- > 0; n--, vp++) {
- x = ffplot_v2x(*vp, vmin, vmax);
- y = ffplot_t2y(t, tmin, tmax);
-
- if (!first)
- ffdraw_line(can, &v->col, xlast, ylast, x, y);
-
- xlast = x;
- ylast = y;
- t += v->step;
- first = 0;
- }
-}
-
-void
-ffplot_plot(Canvas *can, Vlist **v,
- double vmin, double vmax,
- time_t tmin, time_t tmax)
-{
- for (; *v != NULL; v++)
- ffplot_graph(can, *v, vmin, vmax, tmin, tmax);
-}
-
-void
-ffplot_legend(Canvas *can, Color *label_fg, Vlist **v)
-{
- int n, x, y;
-
- for (n = 0; *v != NULL; v++, n++) {
- x = LEGEND_H - n * (FONT_H + MARGIN) - FONT_H / 2;
-
- y = MARGIN + FONT_W;
- ffdraw_str_left(can, &(*v)->col, "\1", font, x, y);
-
- y += FONT_W * 2;
- ffdraw_str_left(can, label_fg, (*v)->name, font, x, y);
- }
-}
-
-void
-ffdraw(Canvas *can, char *title, char *units, Vlist **vlistv,
- double vmin, double vmax, double vstep,
- time_t tmin, time_t tmax, time_t tstep)
-{
- Color plot_bg = { 0x2222, 0x2222, 0x2222, 0xffff };
- Color grid_bg = { 0x2929, 0x2929, 0x2929, 0xffff };
- Color grid_fg = { 0x3737, 0x3737, 0x3737, 0xffff };
- Color label_fg = { 0x8888, 0x8888, 0x8888, 0xffff };
- Color title_fg = { 0xdddd, 0xdddd, 0xdddd, 0xffff };
-
- can->x = 0;
- can->y = 0;
- ffdraw_fill(can, &plot_bg);
-
- can->x = PLOT_X;
- can->y = PLOT_Y;
- ffdraw_rectangle(can, &grid_bg, 0, 0, PLOT_H, PLOT_W);
-
- can->x = YLABEL_X;
- can->y = YLABEL_Y;
- ffplot_yaxis(can, &label_fg, &grid_fg, tmin, tmax, tstep);
-
- can->x = XLABEL_X;
- can->y = XLABEL_Y;
- ffplot_xaxis(can, &label_fg, &grid_fg, vmin, vmax, vstep);
-
- can->x = TITLE_X;
- can->y = TITLE_Y;
- ffplot_title(can, &title_fg, title, &label_fg, units);
-
- can->x = PLOT_X;
- can->y = PLOT_Y;
- ffplot_plot(can, vlistv, vmin, vmax, tmin, tmax);
-
- can->x = LEGEND_X;
- can->y = LEGEND_Y;
- ffplot_legend(can, &label_fg, vlistv);
+ (void)v;
+ (void)n;
}
int
-main(void)
+main(int argc, char **argv)
{
- Canvas can = { IMAGE_W, IMAGE_H, buffer, 0, 0 };
- double v1[] = { 0.1, 30, -3, 42, 559, 343, 10, 345, 0 };
- double v2[] = { 30, -3, 42, 559, 343, 10, 345, 0, 0.3 };
- double v3[] = { 0, 0.3, 30, -3, 42, 5, 43, 345, 0, 10,
- 0.3, 30, -3, 42, 59, 33, 35, 0, 40, 0.3, 30,
- 0.3, 30, -3, 42, 55, 3, 5, 0, 100, 0.3, 30,
- 95, 43, 45, 0, 40, 0.3, 30, 0.3, 30, -3, 42,
- 0.3, 30, -3, 42, 5, 43, 3, 0, 100, 0.3, 30,
- 0.3, 30, -3, 42, 59, 43, 45, 0, 4, 0.3, 30,
- -3, 42, 559, 343, 45, 0, 10 };
- Vlist vl1 = { { 0x0000, 0xffff, 0xdddd, 0xffff }, NULL, LEN(v1), 500, "available ravens" };
- Vlist vl2 = { { 0xffff, 0x9999, 0x4444, 0xffff }, NULL, LEN(v2), 500, "used ravens" };
- Vlist vl3 = { { 0x1111, 0xffff, 0x5555, 0xffff }, NULL, LEN(v3), 57, "free ravens" };
- Vlist *vlistv[] = { NULL, NULL, NULL, NULL };
+ Vlist *v;
double vmin, vmax, vstep;
time_t tmin, tmax, tstep;
- uint32_t w, h;
- vlistv[0] = &vl1; vl1.v = v1;
- vlistv[1] = &vl2; vl2.v = v2;
- vlistv[2] = &vl3; vl3.v = v3;
- vlistv[3] = NULL;
+ ARGBEGIN {
+ case 't':
+ tflag = EARGF(usage());
+ break;
+ case 'u':
+ uflag = EARGF(usage());
+ break;
+ } ARGEND;
+
+ if ((v = calloc(argc, sizeof(*v))) == NULL)
+ perror("calloc value list"), exit(1);
vmin = -30; vmax = 700; vstep = 120;
tmin = 0; tmax = 2000; tstep = 300;
- ffdraw(&can, "Council of the ravens", "(feather per second)", vlistv,
+ read_labels(v, argc);
+ read_values(v, argc);
+
+ ffdraw(tflag, uflag, v, argc,
vmin, vmax, vstep,
tmin, tmax, tstep);
- w = htonl(IMAGE_W);
- h = htonl(IMAGE_H);
-
- fputs("farbfeld", stdout);
- fwrite(&w, sizeof(w), 1, stdout);
- fwrite(&h, sizeof(h), 1, stdout);
- fwrite(can.b, IMAGE_W * IMAGE_H, sizeof(*can.b), stdout);
-
return 0;
}
(DIR) diff --git a/ploot.h b/ploot.h
@@ -0,0 +1,44 @@
+#include <time.h>
+#include <stdint.h>
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+typedef uint16_t Color[4];
+
+typedef struct {
+ int w; /* width */
+ int h; /* height */
+ Color *b; /* buffer */
+ int x; /* x offset */
+ int y; /* x offset */
+} Canvas;
+
+typedef struct {
+ int w; /* width */
+ int h; /* height */
+ char *b[128]; /* buffer */
+} Font;
+
+typedef struct {
+ Color col; /* for drawing the curve and the legend */
+ time_t *t; /* array of timestamps */
+ double *v; /* array of values */
+ int n; /* number of values */
+ char *name; /* for the legend */
+} Vlist;
+
+/* ffdraw.c */
+void ffdraw_pixel (Canvas *, Color *, int, int);
+void ffdraw_rectangle(Canvas *, Color *, int, int, int, int);
+void ffdraw_line (Canvas *, Color *, int, int, int, int);
+void ffdraw_char (Canvas *, Color *, char, Font *, int, int);
+void ffdraw_str_left(Canvas *, Color *, char *, Font *, int, int);
+void ffdraw_str_center(Canvas *, Color *, char *, Font *, int, int);
+void ffdraw_str_right(Canvas *, Color *, char *, Font *, int, int);
+void ffdraw_fill (Canvas *, Color *);
+void ffdraw_print (Canvas *);
+
+/* ffplot.c */
+void ffdraw (char *, char *, Vlist *, int, double, double,
+ double, time_t, time_t, time_t);