shithub: neindaw

ref: 49765cee0852763c1703d04ea5a867ea7f880bf2
dir: /cfg/nk.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>

static char *
dtoa(char *s, double n)
{
	sprint(s, "%g", n);
	return s;
}

#define NK_IMPLEMENTATION
#include "nk.h"

static ulong rgba[32];
static Image *colors[32];
static int numcolors = 0;
static void *oldcmds = nil;
static int oldcmdslen = 0, oldcmdsmax = 0;

static void*
nk_alloc_p9(nk_handle handle, void *old, nk_size size)
{
	USED(handle);
	return realloc(old, size);
}

static void
nk_free_p9(nk_handle handle, void *old)
{
	USED(handle);
	free(old);
}

static float
nk_text_width_p9(nk_handle handle, float height, const char *text, int len)
{
	USED(height);
	return stringnwidth(handle.ptr, text, len);
}

static struct nk_allocator nkallocp9 = {
	.alloc = nk_alloc_p9,
	.free = nk_free_p9,
};

static struct nk_user_font nkfontp9 = {
	.width = nk_text_width_p9,
};

int
nk_init_p9(struct nk_context *ctx)
{
	nkfontp9.userdata.ptr = display->defaultfont;
	nkfontp9.height = display->defaultfont->height;

	return nk_init(ctx, &nkallocp9, &nkfontp9);
}

static Image *
nk_color_p9(struct nk_color c)
{
	ulong x;
	int i;

	x = c.r<<24 | c.g<<16 | c.b<<8 | c.a;
	for (i = 0; i < numcolors; i++) {
		if (rgba[i] == x)
			return colors[i];
	}
	if (i >= nelem(colors))
		return display->black;

	rgba[numcolors] = x;
	colors[numcolors] = allocimagemix(display, x, x);
	return colors[numcolors++];
}

#define THICK(x) ((x)/2-1)

void
nk_redraw_p9(struct nk_context *ctx, Image *screen)
{
	Point p, sp;
	Rectangle rect;
	const struct nk_command *cmd;
	void *cmds;

	/* check if there is anything changed, return if nothing */
	cmds = nk_buffer_memory(&ctx->memory);
	if (ctx->memory.allocated == oldcmdslen && memcmp(oldcmds, cmds, oldcmdslen) == 0)
		return;

	if (ctx->memory.allocated > oldcmdsmax) {
		oldcmdsmax = ctx->memory.allocated;
		oldcmds = realloc(oldcmds, oldcmdsmax);
	}
	oldcmdslen = ctx->memory.allocated;
	memmove(oldcmds, cmds, oldcmdslen);

	nk_foreach(cmd, ctx) {
		rect.min = screen->r.min;
		p = rect.min;
		sp = p;

		switch (cmd->type) {
		case NK_COMMAND_NOP:
			break;
		case NK_COMMAND_SCISSOR:
			{
				const struct nk_command_scissor *s = (void*)cmd;
				rect.min.x += s->x;
				rect.min.y += s->y;
				rect.max = rect.min;
				rect.max.x += s->w;
				rect.max.y += s->h;
				replclipr(screen, 0, rect);
			}
			break;
		case NK_COMMAND_LINE:
			{
				const struct nk_command_line *l = (void*)cmd;
				p.x += l->begin.x;
				p.y += l->begin.y;
				sp.x += l->end.x;
				sp.y += l->end.y;
				line(screen, p, sp, Endsquare, Endsquare, THICK(l->line_thickness), nk_color_p9(l->color), ZP);
			}
			break;
		case NK_COMMAND_CURVE:
			fprint(2, "NK_COMMAND_CURVE\n");
			break;
		case NK_COMMAND_RECT:
			{
				const struct nk_command_rect *r = (void*)cmd;
				rect.min.x += r->x;
				rect.min.y += r->y;
				rect.max = rect.min;
				rect.max.x += r->w;
				rect.max.y += r->h;
				border(screen, rect, THICK(r->line_thickness), nk_color_p9(r->color), ZP);
			}
			break;
		case NK_COMMAND_RECT_FILLED:
			{
				const struct nk_command_rect_filled *r = (void*)cmd;
				rect.min.x += r->x;
				rect.min.y += r->y;
				rect.max = rect.min;
				rect.max.x += r->w;
				rect.max.y += r->h;
				draw(screen, rect, nk_color_p9(r->color), nil, ZP);
			}
			break;
		case NK_COMMAND_RECT_MULTI_COLOR:
			fprint(2, "NK_COMMAND_RECT_MULTI_COLOR\n");
			break;
		case NK_COMMAND_CIRCLE:
			{
				const struct nk_command_circle *c = (void*)cmd;
				p.x += c->x + c->w/2;
				p.y += c->y + c->h/2;
				ellipse(screen, p, c->w/2, c->h/2, THICK(c->line_thickness), nk_color_p9(c->color), ZP);
			}
			break;
		case NK_COMMAND_CIRCLE_FILLED:
			{
				const struct nk_command_circle_filled *c = (void*)cmd;
				p.x += c->x + c->w/2;
				p.y += c->y + c->h/2;
				fillellipse(screen, p, c->w/2, c->h/2, nk_color_p9(c->color), ZP);
			}
			break;
		case NK_COMMAND_ARC:
			fprint(2, "NK_COMMAND_ARC\n");
			break;
		case NK_COMMAND_ARC_FILLED:
			fprint(2, "NK_COMMAND_ARC_FILLED\n");
			break;
		case NK_COMMAND_TRIANGLE:
			fprint(2, "NK_COMMAND_TRIANGLE\n");
			break;
		case NK_COMMAND_TRIANGLE_FILLED:
			fprint(2, "NK_COMMAND_TRIANGLE_FILLED\n");
			break;
		case NK_COMMAND_POLYGON:
			fprint(2, "NK_COMMAND_POLYGON\n");
			break;
		case NK_COMMAND_POLYGON_FILLED:
			fprint(2, "NK_COMMAND_POLYGON_FILLED\n");
			break;
		case NK_COMMAND_POLYLINE:
			fprint(2, "NK_COMMAND_POLYLINE\n");
			break;
		case NK_COMMAND_TEXT:
			{
				const struct nk_command_text *t = (void*)cmd;
				p.x += t->x;
				p.y += t->y;
				sp = p;
				sp.x += t->w;
				sp.y += t->h;
				stringn(screen, p, nk_color_p9(t->foreground), sp, nkfontp9.userdata.ptr, t->string, t->length);
			}
			break;
		case NK_COMMAND_IMAGE:
			fprint(2, "NK_COMMAND_IMAGE\n");
			break;
		case NK_COMMAND_CUSTOM:
			fprint(2, "NK_COMMAND_CUSTOM\n");
			break;
		}
	}

	flushimage(display, 1);
}