shithub: netgraph

ref: 59402bf42b8b199218f1f0d111aaf273a3c1806a
dir: /draw.c/

View raw version
#include <u.h>
#include <libc.h>
#include <String.h>
#include "dat.h"
#include "fns.h"

static int lineheight = 10;
static int charwidth = 6;
static int foldline = 32;

static int boxoffsetx = 2;
static int boxoffsety = 2;
static int borderoffset = 2;

static int labeloffset = 20;

void
dheader()
{
	print(
	"%%!PS\n"
	"%%%%Creator: netgraph\n"
	"%%%%Origin: 0 0\n"
	"%%%%BoundingBox: 0 0 %d %d\n"
	"%%%%Pages: 1\n"
	"/Courier 10 selectfont\n",
	pagewidth, pageheight
	);
}

void
dfooter()
{
	print("showpage\n%%%%EOF\n");
}

static void
drawtext(Pos p, int off, char *fmt, ...)
{
	va_list arg;
	
	print("%d %d moveto\n(", p.x, p.y - (off * lineheight));
	va_start(arg, fmt);
	vfprint(1, fmt, arg);
	va_end(arg);
	print(") show\n");
}

static void
drawbox(Block *b)
{
	Pos p1, p2;
	
	p1 = b->p;
	p1.y = pageheight - p1.y;
	p2 = p1;
	p1.x -= boxoffsetx;
	p1.y += boxoffsety - borderoffset;
	
	p2.x += boxoffsetx + b->width;
	p2.y -= boxoffsety + b->height + borderoffset;
	
	print("newpath\n"
	"%d %d moveto\n"
	"%d %d lineto\n"
	"%d %d lineto\n"
	"%d %d lineto\n"
	"closepath\n"
	"gsave\n"
	"1 setgray\n"
	"fill\n"
	"grestore\n"
	"1 setlinewidth\n"
	"0 setgray\n"
	"stroke\n",
	p1.x, p1.y,
	p2.x, p1.y,
	p2.x, p2.y,
	p1.x, p2.y);
}

static char*
strrnchr(char *str, int n, int c)
{
	char *s;
	s = &str[n];
	while (s > str) {
		if (*s == c)
			return s;
		s--;
	}
	return nil;
}

static int
isipnet(Tuple *t)
{
	return strcmp(t->key, Sipnet) == 0;
}

static void
drawtuple(Tuple *t, void *aux)
{
	Color c;
	Pos *p = aux;
	char *s, *s2;
	int n, fl;
	int ipnet = isipnet(t);
	
	if (!showipnet && t->ipnet && !ipnet)
		return;
	
	if (ipnet) {
		print("gsave\n");
		c = getipnetcolor(Sipnet, t->value);
		print("%f %f %f setrgbcolor\n", c.r, c.g, c.b);
	}
	
	fl = foldline - strlen(t->key) - 3;
	s = t->value;
	while (strlen(s) > fl) {
		s2 = strrnchr(s, fl, ',');
		if (!s2)
			s2 = &s[fl];
		n = s2 - s + 1;
		drawtext(*p, 1, "%s%s: %.*s", t->ipnet ? "*" : "", t->key, n, s);
		p->y -= lineheight;
		s = s2;
		if (*s == ',')
			s++;
		while (*s == ' ')
			s++;
	}
	if (strlen(s)) {
		drawtext(*p, 1, "%s%s: %s", t->ipnet ? "*" : "", t->key, s);
		p->y -= lineheight;
	}
	
	if (ipnet) {
		print("grestore\n");
	}
}

void
dblock(Block *b)
{
	Pos np;
	Pos p = b->p;
	p.y = pageheight - p.y;
	
	drawbox(b);
	np = p;
	fortuple(b, drawtuple, &np);
}

static void
tuplesize(Tuple *t, void *aux)
{
	Block *b = aux;
	char *s, *s2;
	int w, nw;
	int fl;
	
	if (!showipnet && t->ipnet && !isipnet(t))
		return;
	
	fl = foldline - strlen(t->key) - 3;
	w = 0;
	s = t->value;
	while (strlen(s) > fl) {
		s2 = strrnchr(s, fl, ',');
		if (!s2)
			s2 = &s[fl];
		nw = s2 - s + 1;
		if (nw > w) w = nw;
		b->height += lineheight;
		s = s2;
		if (*s == ',')
			s++;
		while (*s == ' ')
			s++;
	}
	if (strlen(s)) {
		nw = strlen(s);
		if (nw > w) w = nw;
		b->height += lineheight;
	}
	
	w = strlen(t->key) + w + 3;
	if (w > b->width)
		b->width = w;
}

void
setblocksize(Block *b)
{
	b->width = 0;
	fortuple(b, tuplesize, b);
	b->width *= charwidth;
}

static void
dlabel(Pos p, float angle, char *label)
{
	int n = charwidth * strlen(label) + 4;
	
	print("gsave\n");
	
	print(
	"%d %d translate\n"
	"%f rotate\n"
	"newpath\n"
	"-2 -5 moveto\n"
	"%d %d rlineto\n"
	"%d %d rlineto\n"
	"%d %d rlineto\n"
	"closepath\n"
	"gsave\n"
	"1 setgray\n"
	"fill\n"
	"grestore\n"
	"0 setgray\n"
	"0.5 setlinewidth\n"
	"stroke\n",
	p.x, p.y,
	angle,
	n, 0,
	0, lineheight+2,
	-n, 0
	);
	
	print(
	"newpath\n"
	"0 -2 moveto\n"
	"(%s) show\n",
	label);
	
	print("grestore\n");
}

void
dconn(Block *from, Block *to, char *label)
{
	Pos p1, p2, c, c2;
	float fx, fy, d;
	int m;
	
	p1 = from->p;
	p2 = to->p;
	p1.y = pageheight - p1.y;
	p2.y = pageheight - p2.y;
	
	p1.x += from->width/2;
	p1.y -= from->height/2;
	p2.x += from->width/2;
	p2.y -= from->height/2;
	
	c.x = pagewidth/2;
	c.y = pageheight/2;
	
	c2.x = p1.x + (p2.x - p1.x) / 2;
	c2.y = p1.y + (p2.y - p1.y) / 2;
	
	c.x = c2.x + (c.x - c2.x) / 2;
	c.y = c2.y + (c.y - c2.y) / 2;
	
	print("newpath\n"
	"%d %d moveto\n"
	"%d %d %d %d %d %d curveto\n"
	"1 setlinewidth\n"
	"stroke\n",
	p1.x, p1.y,
	c.x, c.y, c.x, c.y,
	p2.x, p2.y);
	
	m = from->width > from->height ? from->width : from->height;
	m /= 2;
	m += labeloffset;
	fx = c.x - p1.x;
	fy = c.y - p1.y;
	d = sqrt(fx*fx + fy*fy);
	fx /= d;
	fy /= d;
	p1.x += fx * m;
	p1.y += fy * m;
	
	fx = atan2(fy, fx) * 180./PI;
	dlabel(p1, fx, label);
}