wip sdf font renderer
This commit is contained in:
parent
9f14275bbc
commit
4ebeee76db
157
apps/sdf-demo.c
Normal file
157
apps/sdf-demo.c
Normal file
@ -0,0 +1,157 @@
|
||||
/* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2013-2014 Kevin Lange
|
||||
*/
|
||||
/*
|
||||
* Julia Fractal Generator
|
||||
*
|
||||
* This is the updated windowed version of the
|
||||
* julia fractal generator demo.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <toaru/yutani.h>
|
||||
#include <toaru/graphics.h>
|
||||
#include <toaru/decorations.h>
|
||||
#include <toaru/sdf.h>
|
||||
|
||||
#define DIRECT_OFFSET(x,y) ((x) + (y) * window->width)
|
||||
|
||||
/*
|
||||
* Macros make verything easier.
|
||||
*/
|
||||
#define SPRITE(sprite,x,y) sprite->bitmap[sprite->width * (y) + (x)]
|
||||
|
||||
#define GFX_(xpt, ypt) ((uint32_t *)window->buffer)[DIRECT_OFFSET(xpt+decor_left_width,ypt+decor_top_height)]
|
||||
|
||||
/* Pointer to graphics memory */
|
||||
static yutani_t * yctx;
|
||||
static yutani_window_t * window = NULL;
|
||||
static gfx_context_t * ctx = NULL;
|
||||
|
||||
static int width = 500;
|
||||
static int height = 500;
|
||||
|
||||
static int left = 200;
|
||||
static int top = 200;
|
||||
|
||||
static int size = 30;
|
||||
|
||||
static void decors() {
|
||||
render_decorations(window, ctx, "SDF Demo");
|
||||
}
|
||||
|
||||
void redraw() {
|
||||
draw_fill(ctx, rgb(255,255,255));
|
||||
|
||||
decors();
|
||||
|
||||
draw_sdf_string(ctx, 30, 30, "Hello, world!", size, rgb(0,0,0));
|
||||
}
|
||||
|
||||
void resize_finish(int w, int h) {
|
||||
yutani_window_resize_accept(yctx, window, w, h);
|
||||
reinit_graphics_yutani(ctx, window);
|
||||
|
||||
width = w - decor_left_width - decor_right_width;
|
||||
height = h - decor_top_height - decor_bottom_height;
|
||||
|
||||
redraw();
|
||||
|
||||
yutani_window_resize_done(yctx, window);
|
||||
yutani_flip(yctx, window);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
|
||||
yctx = yutani_init();
|
||||
init_decorations();
|
||||
|
||||
window = yutani_window_create(yctx, width + decor_width(), height + decor_height());
|
||||
yutani_window_move(yctx, window, left, top);
|
||||
|
||||
yutani_window_advertise_icon(yctx, window, "SDF Demo", "sdf");
|
||||
|
||||
ctx = init_graphics_yutani(window);
|
||||
|
||||
redraw();
|
||||
yutani_flip(yctx, window);
|
||||
|
||||
int playing = 1;
|
||||
while (playing) {
|
||||
yutani_msg_t * m = yutani_poll(yctx);
|
||||
if (m) {
|
||||
switch (m->type) {
|
||||
case YUTANI_MSG_KEY_EVENT:
|
||||
{
|
||||
struct yutani_msg_key_event * ke = (void*)m->data;
|
||||
if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
|
||||
playing = 0;
|
||||
} else if (ke->event.action == KEY_ACTION_DOWN) {
|
||||
if (size <= 20) {
|
||||
size += 1;
|
||||
} else if (size > 20) {
|
||||
size += 5;
|
||||
}
|
||||
if (size > 100) {
|
||||
size = 1;
|
||||
}
|
||||
redraw();
|
||||
yutani_flip(yctx,window);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
|
||||
{
|
||||
struct yutani_msg_window_focus_change * wf = (void*)m->data;
|
||||
yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
|
||||
if (win) {
|
||||
win->focused = wf->focused;
|
||||
decors();
|
||||
yutani_flip(yctx, window);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_RESIZE_OFFER:
|
||||
{
|
||||
struct yutani_msg_window_resize * wr = (void*)m->data;
|
||||
resize_finish(wr->width, wr->height);
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
|
||||
{
|
||||
int result = decor_handle_event(yctx, m);
|
||||
switch (result) {
|
||||
case DECOR_CLOSE:
|
||||
playing = 0;
|
||||
break;
|
||||
default:
|
||||
/* Other actions */
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YUTANI_MSG_SESSION_END:
|
||||
playing = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(m);
|
||||
}
|
||||
|
||||
yutani_close(yctx, window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -88,3 +88,5 @@ extern uint32_t premultiply(uint32_t color);
|
||||
extern void gfx_add_clip(gfx_context_t * ctx, int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
extern void gfx_clear_clip(gfx_context_t * ctx);
|
||||
|
||||
extern uint32_t getBilinearFilteredPixelColor(sprite_t * tex, double u, double v);
|
||||
|
||||
|
4
base/usr/include/toaru/sdf.h
Normal file
4
base/usr/include/toaru/sdf.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
extern int draw_sdf_character(gfx_context_t * ctx, int32_t x, int32_t y, int ch, int size, uint32_t color);
|
||||
extern int draw_sdf_string(gfx_context_t * ctx, int32_t x, int32_t y, char * str, int size, uint32_t color);
|
BIN
base/usr/share/sdf.bmp
Normal file
BIN
base/usr/share/sdf.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 732 KiB |
182
lib/sdf.c
Normal file
182
lib/sdf.c
Normal file
@ -0,0 +1,182 @@
|
||||
/* vim: ts=4 sw=4 noexpandtab
|
||||
*
|
||||
* Signed Distance Field Text Library
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <toaru/graphics.h>
|
||||
|
||||
#define BASE_WIDTH 50
|
||||
#define BASE_HEIGHT 50
|
||||
|
||||
static sprite_t _font_data;
|
||||
|
||||
struct {
|
||||
char code;
|
||||
size_t width;
|
||||
} _char_data[] = {
|
||||
{'!', 20},
|
||||
{'"', 35},
|
||||
{'#', 40},
|
||||
{'$', 35},
|
||||
{'%', 35},
|
||||
{'&', 35},
|
||||
{'\'', 35},
|
||||
{'(', 35},
|
||||
{')', 35},
|
||||
{'*', 35},
|
||||
{'+', 35},
|
||||
{',', 35},
|
||||
{'-', 35},
|
||||
{'.', 35},
|
||||
{'/', 35},
|
||||
{'0', 35},
|
||||
{'1', 35},
|
||||
{'2', 35},
|
||||
{'3', 35},
|
||||
{'4', 35},
|
||||
{'5', 35},
|
||||
{'6', 35},
|
||||
{'7', 35},
|
||||
{'8', 35},
|
||||
{'9', 35},
|
||||
{':', 35},
|
||||
{';', 35},
|
||||
{'<', 35},
|
||||
{'=', 35},
|
||||
{'>', 35},
|
||||
{'?', 35},
|
||||
{'@', 50},
|
||||
{'A', 35},
|
||||
{'B', 35},
|
||||
{'C', 35},
|
||||
{'D', 35},
|
||||
{'E', 35},
|
||||
{'F', 35},
|
||||
{'G', 35},
|
||||
{'H', 35},
|
||||
{'I', 35},
|
||||
{'J', 35},
|
||||
{'K', 35},
|
||||
{'L', 35},
|
||||
{'M', 40},
|
||||
{'N', 35},
|
||||
{'O', 35},
|
||||
{'P', 35},
|
||||
{'Q', 35},
|
||||
{'R', 35},
|
||||
{'S', 35},
|
||||
{'T', 35},
|
||||
{'U', 35},
|
||||
{'V', 35},
|
||||
{'W', 35},
|
||||
{'X', 35},
|
||||
{'Y', 35},
|
||||
{'Z', 35},
|
||||
{'[', 35},
|
||||
{'\\', 35},
|
||||
{']', 35},
|
||||
{'^', 35},
|
||||
{'_', 35},
|
||||
{'`', 35},
|
||||
{'a', 35},
|
||||
{'b', 35},
|
||||
{'c', 35},
|
||||
{'d', 32},
|
||||
{'e', 32},
|
||||
{'f', 35},
|
||||
{'g', 35},
|
||||
{'h', 35},
|
||||
{'i', 16},
|
||||
{'j', 16},
|
||||
{'k', 30},
|
||||
{'l', 16},
|
||||
{'m', 50},
|
||||
{'n', 50},
|
||||
{'o', 32},
|
||||
{'p', 35},
|
||||
{'q', 35},
|
||||
{'r', 25},
|
||||
{'s', 35},
|
||||
{'t', 35},
|
||||
{'u', 35},
|
||||
{'v', 35},
|
||||
{'w', 42},
|
||||
{'x', 35},
|
||||
{'y', 35},
|
||||
{'z', 35},
|
||||
{'{', 35},
|
||||
{'|', 35},
|
||||
{'}', 35},
|
||||
{'~', 35},
|
||||
{' ', 20},
|
||||
{0,0},
|
||||
};
|
||||
|
||||
__attribute__((constructor))
|
||||
static void _init_sdf(void) {
|
||||
/* Load the font. */
|
||||
load_sprite(&_font_data, "/usr/share/sdf.bmp");
|
||||
}
|
||||
|
||||
int draw_sdf_character(gfx_context_t * ctx, int32_t x, int32_t y, int ch, int size, uint32_t color) {
|
||||
if (ch != ' ' && ch < '!' || ch > '~') {
|
||||
/* TODO: Draw missing symbol? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate offset into table above */
|
||||
if (ch == ' ') {
|
||||
ch = '~' + 1 - '!';
|
||||
} else {
|
||||
ch -= '!';
|
||||
}
|
||||
|
||||
double scale = (double)size / 50.0;
|
||||
size_t width = _char_data[ch].width * scale;
|
||||
int fx = ((BASE_WIDTH * ch) % _font_data.width) * scale;
|
||||
int fy = (((BASE_WIDTH * ch) / _font_data.width) * BASE_HEIGHT) * scale;
|
||||
|
||||
int height = BASE_HEIGHT * ((double)size / 50.0);
|
||||
|
||||
sprite_t * tmp = create_sprite(scale * _font_data.width, scale * _font_data.height, ALPHA_OPAQUE);
|
||||
gfx_context_t * t = init_graphics_sprite(tmp);
|
||||
draw_sprite_scaled(t, &_font_data, 0, 0, tmp->width, tmp->height);
|
||||
|
||||
/* ignore size */
|
||||
for (int j = 0; j < height; ++j) {
|
||||
for (int i = 0; i < width; ++i) {
|
||||
/* TODO needs to do bilinear filter */
|
||||
if (fx+i > tmp->width) continue;
|
||||
if (fy+j > tmp->height) continue;
|
||||
uint32_t c = SPRITE((tmp), fx+i, fy+j);
|
||||
double dist = (double)_RED(c) / 255.0;
|
||||
double edge0 = 0.75 - 2.0 * 1.4142 / (double)size;
|
||||
double edge1 = 0.75 + 2.0 * 1.4142 / (double)size;
|
||||
double a = (dist - edge0) / (edge1 - edge0);
|
||||
if (a < 0.0) a = 0.0;
|
||||
if (a > 1.0) a = 1.0;
|
||||
a = a * a * (3 - 2 * a);
|
||||
GFX(ctx,x+i,y+j) = alpha_blend(GFX(ctx,x+i,y+j), color, rgb(255*a,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
sprite_free(tmp);
|
||||
free(t);
|
||||
|
||||
return width;
|
||||
|
||||
}
|
||||
|
||||
int draw_sdf_string(gfx_context_t * ctx, int32_t x, int32_t y, char * str, int size, uint32_t color) {
|
||||
int32_t out_width = 0;
|
||||
while (*str) {
|
||||
int w = draw_sdf_character(ctx,x,y,*str,size,color);
|
||||
out_width += w;
|
||||
x += w;
|
||||
str++;
|
||||
}
|
||||
return out_width;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ class Classifier(object):
|
||||
'<toaru/yutani.h>': (None, '-ltoaru_yutani', ['<toaru/kbd.h>', '<toaru/list.h>', '<toaru/pex.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
||||
'<toaru/decorations.h>': (None, '-ltoaru_decorations', ['<toaru/graphics.h>', '<toaru/yutani.h>','<toaru/dlfcn.h>']),
|
||||
'<toaru/termemu.h>': (None, '-ltoaru_termemu', ['<toaru/graphics.h>']),
|
||||
'<toaru/sdf.h>': (None, '-ltoaru_sdf', ['<toaru/graphics.h>']),
|
||||
}
|
||||
|
||||
def __init__(self, filename):
|
||||
|
Loading…
Reference in New Issue
Block a user