shithub: microui

ref: b53399a1815178d6a221f580be4e5bce9614474d
dir: /demo/renderer_plan9.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include "common.h"
#include "atlas.inl"

enum
{
	Maxcolors = 64,
};

static u32int rgba[Maxcolors];
static u16int lastused[Maxcolors];
static Image *colors[Maxcolors];
static int numcolors = 0;
static u16int frame = 0;
static Image *atlasimage;

static Image *
getcolor(mu_Color color)
{
	u32int c;
	int i;
	u16int diff, leasti;

	diff = 0;
	leasti = 0;
	c = color.r<<24 | color.g<<16 | color.b<<8 | color.a;
	if (c == DBlack)
		return display->black;
	if (c == DWhite)
		return display->white;
	for (i = 0; i < numcolors; i++) {
		if (rgba[i] == c) {
			lastused[i] = frame;
			return colors[i];
		}
		if (diff < frame - lastused[i]) {
			diff = frame - lastused[i];
			leasti = i;
		}
	}
	if (i >= nelem(colors)) {
		freeimage(colors[leasti]);
		rgba[leasti] = c;
		colors[leasti] = allocimage(display, (Rectangle){ZP, (Point){1, 1}}, RGBA32, 1, c);
		lastused[leasti] = frame;
		return colors[leasti];
	}

	rgba[numcolors] = c;
	colors[numcolors] = allocimage(display, (Rectangle){ZP, (Point){1, 1}}, RGBA32, 1, c);
	return colors[numcolors++];
}

static Rectangle
screenrect(mu_Rect rect)
{
	Rectangle r;
	r.min = screen->r.min;
	r.min.x += rect.x;
	r.min.y += rect.y;
	r.max = r.min;
	r.max.x += rect.w;
	r.max.y += rect.h;
	return r;
}

void
r_init(void)
{
	u8int *b;
	Rectangle r = {ZP, (Point){ATLAS_WIDTH, ATLAS_HEIGHT}};
	int i;

	b = malloc(sizeof(atlas_texture)*4);
	for (i = 0; i < sizeof(atlas_texture); i++) {
		b[i*4+0] = atlas_texture[i];
		b[i*4+1] = atlas_texture[i];
		b[i*4+2] = atlas_texture[i];
		b[i*4+3] = atlas_texture[i];
	}
	atlasimage = allocimage(display, r, RGBA32, 1, DWhite);
	if (loadimage(atlasimage, r, b, sizeof(atlas_texture)*4) < 0)
		sysfatal("failed to load atlas");
}

void
r_draw_rect(mu_Rect rect, mu_Color color)
{
	draw(screen, screenrect(rect), getcolor(color), nil, ZP);
}

void
r_draw_text(mu_Font font, const char *text, mu_Vec2 pos, mu_Color color) {
	Point p;

	p = screen->r.min;
	p.x += pos.x;
	p.y += pos.y;
	string(screen, p, getcolor(color), ZP, font, text);
}

void
r_draw_icon(int id, mu_Rect rect, mu_Color color)
{
	Rectangle r;
	USED(color); /* FIXME no colors */
  	rect.x += (rect.w - atlas[id].w) / 2;
	rect.y += (rect.h - atlas[id].h) / 2;
	rect.w = atlas[id].w;
	rect.h = atlas[id].h;
	r = screenrect(rect);
	draw(screen, r, atlasimage, nil, (Point){atlas[id].x, atlas[id].y});
}

int
r_get_text_width(mu_Font font, const char *text, int len)
{
	if (len < 0)
		len = strlen(text);
	return stringnwidth(font, text, len);
}

int
r_get_text_height(mu_Font font)
{
	return ((Font*)font)->height;
}

void
r_set_clip_rect(mu_Rect rect)
{
	replclipr(screen, 0, screenrect(rect));
}

void
r_clear(mu_Color color)
{
	draw(screen, screen->r, getcolor(color), nil, ZP);
}

void
r_present(void)
{
	flushimage(display, 1);
	frame++;
}