text: purge the SDF renderer, RIP

This commit is contained in:
K. Lange 2021-07-06 13:22:59 +09:00
parent 9a34ba2e44
commit 02b9a5233a
23 changed files with 89 additions and 610 deletions

View File

@ -2123,56 +2123,6 @@ int main(int argc, char * argv[]) {
TRACE("pex bound? %d", server);
yg->server = server;
TRACE("Loading fonts...");
{
#define FONT_COUNT 8
sprite_t _font_data[FONT_COUNT];
load_sprite(&_font_data[0], "/usr/share/fonts/sdf_thin.sdf");
load_sprite(&_font_data[1], "/usr/share/fonts/sdf_bold.sdf");
load_sprite(&_font_data[2], "/usr/share/fonts/sdf_mono.sdf");
load_sprite(&_font_data[3], "/usr/share/fonts/sdf_mono_bold.sdf");
load_sprite(&_font_data[4], "/usr/share/fonts/sdf_mono_oblique.sdf");
load_sprite(&_font_data[5], "/usr/share/fonts/sdf_mono_bold_oblique.sdf");
load_sprite(&_font_data[6], "/usr/share/fonts/sdf_oblique.sdf");
load_sprite(&_font_data[7], "/usr/share/fonts/sdf_bold_oblique.sdf");
TRACE(" Data loaded...");
size_t font_data_size = sizeof(unsigned int) * (1 + FONT_COUNT * 3);
for (int i = 0; i < FONT_COUNT; ++i) {
font_data_size += 4 * _font_data[i].width * _font_data[i].height;
}
TRACE(" Size calculated: %d", font_data_size);
char tmp[100];
sprintf(tmp, "sys.%s.fonts", yg->server_ident);
size_t s = font_data_size;
char * font = shm_obtain(tmp, &s);
assert((s >= font_data_size) && "Font server failure.");
uint32_t * data = (uint32_t *)font;
data[0] = FONT_COUNT;
data[1] = _font_data[0].width;
data[2] = _font_data[0].height;
data[3] = (FONT_COUNT * 3 + 1) * sizeof(unsigned int);
memcpy(&font[data[3]], _font_data[0].bitmap, _font_data[0].width * _font_data[0].height * 4);
free(_font_data[0].bitmap);
for (int i = 1; i < FONT_COUNT; ++i) {
TRACE(" Loaded %d font(s)... %d %d %d", i, data[(i - 1) * 3 + 2], data[(i - 1) * 3 + 1], data[(i - 1) * 3 + 3]);
data[i * 3 + 1] = _font_data[i].width;
data[i * 3 + 2] = _font_data[i].height;
data[i * 3 + 3] = data[(i - 1) * 3 + 3] + data[(i - 1) * 3 + 2] * data[(i - 1) * 3 + 1] * 4;
memcpy(&font[data[i * 3 + 3]], _font_data[i].bitmap, _font_data[i].width * _font_data[i].height * 4);
free(_font_data[i].bitmap);
}
TRACE("Done loading fonts.");
}
TRACE("Loading sprites...");
#define MOUSE_DIR "/usr/share/cursor/"
load_sprite(&yg->mouse_sprite, MOUSE_DIR "normal.png");

View File

@ -24,7 +24,7 @@
#include <toaru/yutani.h>
#include <toaru/auth.h>
#include <toaru/confreader.h>
#include <toaru/sdf.h>
#include <toaru/text.h>
#include <toaru/trace.h>
#define TRACE_APP_NAME "glogin-provider"
@ -57,6 +57,8 @@ static int BOX_COLOR_B=0;
static int BOX_COLOR_A=127;
static char * WALLPAPER = "/usr/share/wallpaper.jpg";
static char * LOGO = "/usr/share/logo_login.png";
static struct TT_Font * tt_font_thin = NULL;
static struct TT_Font * tt_font_bold = NULL;
#define TEXTBOX_INTERIOR_LEFT 4
#define EXTRA_TEXT_OFFSET 15
@ -145,15 +147,16 @@ void draw_text_box(gfx_context_t * ctx, struct text_box * tb) {
} else if (tb->is_password) {
strcpy(password_circles, "");
for (unsigned int i = 0; i < strlen(tb->buffer); ++i) {
strcat(password_circles, "\007");
strcat(password_circles, "");
}
text = password_circles;
}
draw_sdf_string(ctx, x + TEXTBOX_INTERIOR_LEFT, y + text_offset - 12, text, 15, color, SDF_FONT_THIN);
tt_set_size(tt_font_thin, 13);
tt_draw_string(ctx, tt_font_thin, x + TEXTBOX_INTERIOR_LEFT, y + text_offset + 1, text, color);
if (tb->is_focused) {
int width = draw_sdf_string_width(text, 15, SDF_FONT_THIN) + 2;
int width = tt_string_width(tt_font_thin, text);
draw_line(ctx, x + TEXTBOX_INTERIOR_LEFT + width, x + TEXTBOX_INTERIOR_LEFT + width, y + 2, y + text_offset + 1, tb->text_color);
}
@ -168,10 +171,8 @@ void draw_login_container(gfx_context_t * ctx, struct login_container * lc) {
/* Draw labels */
if (lc->show_error) {
char * error_message = "Incorrect username or password.";
//set_font_size(11);
//draw_string(ctx, lc->x + (lc->width - draw_string_width(error_message)) / 2, lc->y + 6 + EXTRA_TEXT_OFFSET, rgb(240, 20, 20), error_message);
draw_sdf_string(ctx, lc->x + (lc->width - draw_sdf_string_width(error_message, 14, SDF_FONT_THIN)) / 2, lc->y + 6 + EXTRA_TEXT_OFFSET - 14, error_message, 14, rgb(240,20,20), SDF_FONT_THIN);
tt_set_size(tt_font_thin, 13);
tt_draw_string(ctx, tt_font_thin, lc->x + (lc->width - tt_string_width(tt_font_thin, error_message)) / 2, lc->y + 6 + EXTRA_TEXT_OFFSET - 1, error_message, rgb(240,20,20));
}
draw_text_box(ctx, lc->username_box);
@ -201,19 +202,6 @@ static void get_updated_hostname_with_time_info(char hostname[]) {
sprintf(hostname, "%s // %s", _hostname, _date);
}
static void draw_sdf_string_shadow(gfx_context_t * ctx, char * string, int font_size, int left, int top, uint32_t text_color, uint32_t shadow_color, int blur, int font) {
int w = draw_sdf_string_width(string, font_size, font);
sprite_t * _tmp_s = create_sprite(w + blur * 2, font_size + blur * 2, ALPHA_EMBEDDED);
gfx_context_t * _tmp = init_graphics_sprite(_tmp_s);
draw_fill(_tmp, rgba(0,0,0,0));
draw_sdf_string(_tmp, blur, blur, string, font_size, shadow_color, font);
blur_context_box(_tmp, blur);
free(_tmp);
draw_sprite(ctx, _tmp_s, left - blur, top - blur);
sprite_free(_tmp_s);
draw_sdf_string(ctx, left, top, string, 14, text_color, font);
}
int main (int argc, char ** argv) {
if (getuid() != 0) {
return 1;
@ -279,6 +267,8 @@ int main (int argc, char ** argv) {
yutani_flip(y, wina);
TRACE("... done.");
tt_font_thin = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf");
tt_font_bold = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf");
redo_everything:
win_width = width;
@ -402,8 +392,8 @@ redo_everything:
int focus = 0;
//set_font_size(11);
int hostname_label_left = width - 10 - draw_sdf_string_width(hostname, 14, SDF_FONT_BOLD);
tt_set_size(tt_font_thin, 13);
int hostname_label_left = width - 10 - tt_string_width(tt_font_thin, hostname);
int kernel_v_label_left = 10;
struct text_box username_box = { (BOX_WIDTH - 170) / 2, 30, 170, 20, rgb(0,0,0), NULL, 0, 0, 0, username, "Username" };
@ -427,8 +417,8 @@ redo_everything:
memcpy(ctx->backbuffer, foo, sizeof(uint32_t) * width * height);
draw_sprite(ctx, &logo, center_x(logo.width), center_y(logo.height) - LOGO_FINAL_OFFSET);
draw_sdf_string_shadow(ctx, hostname, 14, hostname_label_left, height - 22, rgb(255,255,255), rgb(0,0,0), 4, SDF_FONT_BOLD);
draw_sdf_string_shadow(ctx, kernel_v, 14, kernel_v_label_left, height - 22, rgb(255,255,255), rgb(0,0,0), 4, SDF_FONT_BOLD);
tt_draw_string_shadow(ctx, tt_font_bold, hostname, 12, hostname_label_left, height - 22, rgb(255,255,255), rgb(0,0,0), 4);
tt_draw_string_shadow(ctx, tt_font_bold, kernel_v, 12, kernel_v_label_left, height - 22, rgb(255,255,255), rgb(0,0,0), 4);
if (focus == USERNAME_BOX) {
username_box.is_focused = 1;

View File

@ -19,16 +19,16 @@
#include <toaru/auth.h>
#include <toaru/yutani.h>
#include <toaru/graphics.h>
#include <toaru/sdf.h>
#include <toaru/text.h>
#include <toaru/button.h>
#define main __main_unused
#include "sudo.c"
#undef main
#define FONT_SIZE_TITLE 20
#define FONT_SIZE_MAIN 16
#define FONT_SIZE_PASSWD 25
#define FONT_SIZE_TITLE 18
#define FONT_SIZE_MAIN 13
#define FONT_SIZE_PASSWD 22
#define FONT_COLOR (rgb(0,0,0))
#define FONT_RED (rgb(250,0,0))
#define BUTTON_HEIGHT 28
@ -38,6 +38,7 @@
static yutani_t * yctx;
static gfx_context_t * ctx;
static yutani_window_t * window;
static struct TT_Font * tt_font_thin;
struct TTKButton _button_cancel = {
0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "Cancel", 0
@ -85,17 +86,19 @@ static void redraw(char * username, char * password, int fails, char * argv[]) {
draw_rounded_rectangle(myctx, 10, 10, prompt->width - 20, prompt->height - 20, 10, rgb(239,238,232));
/* Draw prompt messages */
draw_sdf_string(myctx, 30, 30, "Authentication Required", FONT_SIZE_TITLE, FONT_COLOR, SDF_FONT_THIN);
draw_sdf_string(myctx, 30, 54, "Authentication is required to run the application", FONT_SIZE_MAIN, FONT_COLOR, SDF_FONT_THIN);
draw_sdf_string(myctx, 30, 72, argv[1], FONT_SIZE_MAIN, FONT_COLOR, SDF_FONT_THIN);
tt_set_size(tt_font_thin, FONT_SIZE_TITLE);
tt_draw_string(myctx, tt_font_thin, 30, 30 + FONT_SIZE_TITLE, "Authentication Required", FONT_COLOR);
tt_set_size(tt_font_thin, FONT_SIZE_MAIN);
tt_draw_string(myctx, tt_font_thin, 30, 54 + FONT_SIZE_MAIN, "Authentication is required to run the application", FONT_COLOR);
tt_draw_string(myctx, tt_font_thin, 30, 72 + FONT_SIZE_MAIN, argv[1], FONT_COLOR);
char prompt_message[512];
sprintf(prompt_message, "Enter password for '%s'", username);
draw_sdf_string(myctx, 30, 100, prompt_message, FONT_SIZE_MAIN, FONT_COLOR, SDF_FONT_THIN);
tt_draw_string(myctx, tt_font_thin, 30, 100 + FONT_SIZE_MAIN, prompt_message, FONT_COLOR);
if (fails) {
sprintf(prompt_message, "Try again. %d failures.", fails);
draw_sdf_string(myctx, 30, 146, prompt_message, FONT_SIZE_MAIN, FONT_RED, SDF_FONT_THIN);
tt_draw_string(myctx, tt_font_thin, 30, 146 + FONT_SIZE_MAIN, prompt_message, FONT_RED);
}
struct gradient_definition edge = {30, 114, rgb(0,120,220), rgb(0,120,220)};
@ -105,9 +108,10 @@ static void redraw(char * username, char * password, int fails, char * argv[]) {
char password_circles[512] = {0};;
strcpy(password_circles, "");
for (unsigned int i = 0; i < strlen(password) && i < 512/4; ++i) {
strcat(password_circles, "\007");
strcat(password_circles, "");
}
draw_sdf_string(myctx, 33, 118, password_circles, FONT_SIZE_PASSWD, FONT_COLOR, SDF_FONT_THIN);
tt_set_size(tt_font_thin, FONT_SIZE_PASSWD);
tt_draw_string(myctx, tt_font_thin, 33, 118 + FONT_SIZE_PASSWD, password_circles, FONT_COLOR);
draw_fill(ctx, rgba(0,0,0,200));
draw_sprite(ctx, prompt, (ctx->width - prompt->width) / 2, (ctx->height - prompt->height) / 2);
@ -226,6 +230,7 @@ int main(int argc, char ** argv) {
window = yutani_window_create(yctx, width, height);
yutani_window_move(yctx, window, 0, 0);
yutani_window_advertise(yctx, window, "gsudo");
tt_font_thin = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf");
ctx = init_graphics_yutani_double_buffer(window);

View File

@ -18,7 +18,7 @@
#include <toaru/graphics.h>
#include <toaru/decorations.h>
#include <toaru/menu.h>
#include <toaru/sdf.h>
#include <toaru/text.h>
#include <toaru/markup.h>
#define APPLICATION_TITLE "Help Browser"
@ -47,6 +47,11 @@ static int cursor_x = 0;
static list_t * state = NULL;
static int current_state = 0;
static struct TT_Font * tt_font_thin = NULL;
static struct TT_Font * tt_font_bold = NULL;
static struct TT_Font * tt_font_oblique = NULL;
static struct TT_Font * tt_font_bold_oblique = NULL;
struct Char {
char c; /* TODO: unicode */
char state;
@ -55,23 +60,23 @@ struct Char {
//static list_t * lines = NULL;
static list_t * buffer = NULL;
static int state_to_font(int current_state) {
static struct TT_Font * state_to_font(int current_state) {
if (current_state & (1 << 0)) {
if (current_state & (1 << 1)) {
return SDF_FONT_BOLD_OBLIQUE;
return tt_font_bold_oblique;
}
return SDF_FONT_BOLD;
return tt_font_bold;
} else if (current_state & (1 << 1)) {
return SDF_FONT_OBLIQUE;
return tt_font_oblique;
}
return SDF_FONT_THIN;
return tt_font_thin;
}
static int current_size(void) {
if (current_state & (1 << 2)) {
return 24;
return 22;
}
return 16;
return 13;
}
static int buffer_width(list_t * buffer) {
@ -81,7 +86,8 @@ static int buffer_width(list_t * buffer) {
char tmp[2] = {c->c, '\0'};
out += draw_sdf_string_width(tmp, current_size(), state_to_font(c->state));
tt_set_size(state_to_font(c->state), current_size());
out += tt_string_width(state_to_font(c->state), tmp);
}
return out;
}
@ -92,7 +98,8 @@ static int draw_buffer(list_t * buffer) {
node_t * node = list_dequeue(buffer);
struct Char * c = node->value;
char tmp[2] = { c->c, '\0' };
x += draw_sdf_string(nctx, cursor_x + x, cursor_y, tmp, current_size(), 0xFF000000, state_to_font(c->state));
tt_set_size(state_to_font(c->state), current_size());
x += tt_draw_string(nctx, state_to_font(c->state), cursor_x + x, cursor_y + current_size(), tmp, 0xFF000000);
free(c);
free(node);
}
@ -342,6 +349,11 @@ int main(int argc, char * argv[]) {
yutani_window_move(yctx, main_window, yctx->display_width / 2 - main_window->width / 2, yctx->display_height / 2 - main_window->height / 2);
ctx = init_graphics_yutani_double_buffer(main_window);
tt_font_thin = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf");
tt_font_bold = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf");
tt_font_oblique = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf");
tt_font_bold_oblique = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans-BoldOblique.ttf");
yutani_window_advertise_icon(yctx, main_window, APPLICATION_TITLE, "help");
menu_bar.entries = menu_entries;

View File

@ -16,7 +16,7 @@
#include <toaru/graphics.h>
#include <toaru/decorations.h>
#include <toaru/menu.h>
#include <toaru/sdf.h>
#include <toaru/text.h>
#include <toaru/confreader.h>
#include <toaru/icon_cache.h>
@ -39,6 +39,9 @@ static int hilighted_offset = -1; /* Which file is hovered by the mouse */
static uint64_t last_click = 0; /* For double click */
static int last_click_offset = -1; /* So that clicking two different things quickly doesn't count as a double click */
struct TT_Font * tt_font_thin = NULL;
struct TT_Font * tt_font_bold = NULL;
struct Package {
char name[256];
char friendly_name[256];
@ -130,10 +133,12 @@ static void draw_package(struct Package * package, int index) {
char tmp[2048];
sprintf(tmp, "%s - %s", package->friendly_name, package->version);
draw_sdf_string(contents, 64, offset_y + 4, tmp, 20, text_color, SDF_FONT_BOLD);
tt_set_size(tt_font_bold, 18);
tt_draw_string(contents, tt_font_bold, 64, offset_y + 4 + 18, tmp, text_color);
sprintf(tmp, "%s - %s", package->name, package->description);
int x = draw_sdf_string(contents, 65, offset_y + 24, package->name, 16, rgb(150,150,150), SDF_FONT_THIN);
draw_sdf_string(contents, 64 + x + 4, offset_y + 24, package->description, 16, text_color, SDF_FONT_THIN);
tt_set_size(tt_font_thin, 13);
int x = tt_draw_string(contents, tt_font_thin, 65, offset_y + 24 + 13, package->name, rgb(150,150,150));
tt_draw_string(contents, tt_font_thin, 64 + x + 4, offset_y + 24 + 13, package->description, text_color);
}
@ -457,6 +462,9 @@ int main(int argc, char * argv[]) {
yutani_window_move(yctx, main_window, yctx->display_width / 2 - main_window->width / 2, yctx->display_height / 2 - main_window->height / 2);
ctx = init_graphics_yutani_double_buffer(main_window);
tt_font_thin = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf");
tt_font_bold = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf");
yutani_window_advertise_icon(yctx, main_window, APPLICATION_TITLE, "package");
menu_bar.entries = menu_entries;

View File

@ -47,7 +47,6 @@
#include <toaru/spinlock.h>
#include <toaru/list.h>
#include <toaru/menu.h>
#include <toaru/sdf.h>
#include <toaru/text.h>
/* 16- and 256-color palette */
@ -84,7 +83,7 @@ static int scale_fonts = 0; /* Whether fonts should be scaled */
static float font_scaling = 1.0; /* How much they should be scaled by */
static uint16_t term_width = 0; /* Width of the terminal (in cells) */
static uint16_t term_height = 0; /* Height of the terminal (in cells) */
static uint16_t font_size = 16; /* Font size according to SDF library */
static uint16_t font_size = 16; /* Font size according to tt library */
static uint16_t char_width = 9; /* Width of a cell in pixels */
static uint16_t char_height = 17; /* Height of a cell in pixels */
static uint16_t char_offset = 0; /* Offset of the font within the cell */
@ -2128,7 +2127,7 @@ static void _menu_action_hide_borders(struct MenuEntry * self) {
reinit();
}
static void _menu_action_toggle_sdf(struct MenuEntry * self) {
static void _menu_action_toggle_tt(struct MenuEntry * self) {
_use_aa = !(_use_aa);
menu_update_title(self, _use_aa ? "Bitmap font" : "Anti-aliased font");
reinit();
@ -2323,7 +2322,7 @@ int main(int argc, char ** argv) {
_menu_toggle_borders_bar = menu_create_normal(NULL, NULL, _no_frame ? "Show borders" : "Hide borders", _menu_action_hide_borders);
menu_insert(m, _menu_toggle_borders_bar);
menu_insert(m, menu_create_submenu(NULL,"zoom","Set zoom..."));
menu_insert(m, menu_create_normal(NULL, NULL, _use_aa ? "Bitmap font" : "Anti-aliased font", _menu_action_toggle_sdf));
menu_insert(m, menu_create_normal(NULL, NULL, _use_aa ? "Bitmap font" : "Anti-aliased font", _menu_action_toggle_tt));
menu_insert(m, menu_create_normal(NULL, NULL, _free_size ? "Snap to Cell Size" : "Freely Resize", _menu_action_toggle_free_size));
menu_insert(m, menu_create_separator());
menu_insert(m, menu_create_normal(NULL, NULL, "Redraw", _menu_action_redraw));

View File

@ -10,7 +10,7 @@
#include <toaru/yutani.h>
#include <toaru/graphics.h>
#include <toaru/decorations.h>
#include <toaru/sdf.h>
#include <toaru/text.h>
#include <toaru/menu.h>
#include <toaru/button.h>
#include <toaru/list.h>
@ -25,6 +25,7 @@ static yutani_t * yctx;
static yutani_window_t * window = NULL;
static gfx_context_t * ctx = NULL;
static sprite_t wallpaper = { 0 };
static struct TT_Font * tt_font = NULL;
static int32_t width = 640;
static int32_t height = 300;
@ -70,10 +71,11 @@ static void redraw(void) {
}
/* Draws the path for the selected wallpaper in white, centered, with a drop shadow */
int str_width = draw_sdf_string_width(wallpaper_path, 16, SDF_FONT_THIN);
tt_set_size(tt_font, 13);
int str_width = tt_string_width(tt_font, wallpaper_path);
int center_x_text = (window->width - bounds.width - str_width) / 2;
draw_sdf_string_stroke(ctx, center_x_text + 1, bounds.top_height + 10 + 1, wallpaper_path, 16, rgba(0,0,0,120), SDF_FONT_THIN, 1.7, 0.5);
draw_sdf_string(ctx, center_x_text, bounds.top_height + 10, wallpaper_path, 16, rgb(255,255,255), SDF_FONT_THIN);
tt_draw_string_shadow(ctx, tt_font, wallpaper_path, 13, center_x_text + 1, bounds.top_height + 10 + 1, rgba(0,0,0,0), rgb(0,0,0), 4);
tt_draw_string_shadow(ctx, tt_font, wallpaper_path, 13, center_x_text + 1, bounds.top_height + 10 + 1, rgb(255,255,255), rgb(0,0,0), 4);
/* Draw the buttons */
ttk_button_draw(ctx, &_set);
@ -292,6 +294,8 @@ int main(int argc, char * argv[]) {
req_center_x = yctx->display_width / 2;
req_center_y = yctx->display_height / 2;
tt_font = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf");
get_default_wallpaper();
read_wallpapers();

View File

@ -1,24 +0,0 @@
#pragma once
#include <_cheader.h>
#include <stdint.h>
#include <toaru/graphics.h>
_Begin_C_Header
enum sdf_font {
SDF_FONT_THIN,
SDF_FONT_BOLD,
SDF_FONT_MONO,
SDF_FONT_MONO_BOLD,
SDF_FONT_MONO_OBLIQUE,
SDF_FONT_MONO_BOLD_OBLIQUE,
SDF_FONT_OBLIQUE,
SDF_FONT_BOLD_OBLIQUE,
};
extern int draw_sdf_string(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, int size, uint32_t color, int font);
extern int draw_sdf_string_width(const char * str, int size, int font);
extern int draw_sdf_string_gamma(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, int size, uint32_t color, int font, double _gamma);
extern int draw_sdf_string_stroke(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, int size, uint32_t color, int font, double _gamma, double stroke);
_End_C_Header

View File

@ -1,92 +0,0 @@
#pragma once
#include <_cheader.h>
#include <stdint.h>
#include <stdbool.h>
#include <toaru/hashmap.h>
#include <toaru/graphics.h>
_Begin_C_Header
struct TR_Font {
int typeface; /* Should probably be more flexible than int, but tough luck for now. */
int size;
uint32_t color;
/* TODO shadow - we had built-in support for this in the old setup, not sure I want to do it here */
};
/* TODO This should probably all use wchar_t, but the font library needs to support that as well. */
extern int tr_font_get_width(struct TR_Font * font, char * string);
extern int tr_font_write(struct TR_Font * font, gfx_context_t * ctx, int x, int y, char * string);
struct TR_TextUnit {
char * string;
int unit_type;
int width; /* calculated on creation */
struct TR_Font * font; /* not a pointer */
hashmap_t * extra; /* extra properties in hashmap if present */
list_t * tag_group; /* tag group membership if present */
};
extern void tr_textunit_set_tag_group(struct TR_TextUnit * self, list_t * tag_group);
extern void tr_textunit_set_font(struct TR_TextUnit * self, struct TR_Font * font);
extern void tr_textunit_set_extra(struct TR_TextUnit * self, char * key, void * data);
struct TR_TextRegion {
int x;
int y;
int width;
int height;
struct TR_Font * font;
char * text;
list_t * lines;
int align;
int valign;
int line_height; /* TODO should be property of lines */
struct TR_TextUnit * text_units; /* array */
int scroll;
char * ellipsis; /* blank by default */
bool one_line; /* False by default */
char * base_dir; /* Used for links and images */
bool break_all; /* False by default */
char * title; /* blank by default */
int max_lines; /* 0 is None */
};
struct TR_Offset {
struct TR_TextUnit * unit;
int line;
int left;
int right;
int index;
};
extern void tr_textregion_set_alignment(struct TR_TextRegion * self, int align);
extern void tr_textregion_set_valignment(struct TR_TextRegion * self, int align);
extern void tr_textregion_set_max_lines(struct TR_TextRegion * self, int max_lines);
extern int tr_textregion_get_visible_lines(struct TR_TextRegion * self); /* height / line_height */
extern void tr_textregion_reflow(struct TR_TextRegion * self);
extern list_t * tr_textregion_units_from_text(struct TR_TextRegion * self, char * text, struct TR_Font * font, bool whitespace);
extern void tr_textregion_set_one_line(struct TR_TextRegion * self, bool one_line);
extern void tr_textregion_set_ellipsis(struct TR_TextRegion * self, char * ellipsis);
extern void tr_textregion_set_text(struct TR_TextRegion* self, char * text);
extern void tr_textregion_set_font(struct TR_TextRegion* self, struct TR_Font * font);
extern void tr_textregion_set_line_height(struct TR_TextRegion * self, int line_height);
extern void tr_textregion_resize(struct TR_TextRegion * self, int width, int height);
extern void tr_textregion_move(struct TR_TextRegion * self, int x, int y);
extern void tr_textregion_get_offset_at_index(struct TR_TextRegion* self, int index, struct TR_Offset * out);
extern void tr_textregion_pick(struct TR_TextRegion * self, int x, int y, struct TR_Offset * out);
extern struct TR_TextUnit * tr_textregion_click(struct TR_TextRegion * self, int x, int y);
extern void tr_textregion_draw(struct TR_TextRegion * self, gfx_context_t * ctx);
_End_C_Header

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

View File

@ -62,18 +62,10 @@ Replacement for `readline`. Mostly deprecated in favor of `rline_exp`.
Replacement for `readline`, with support for syntax highlighting.
## `toaru_sdf`
Signed Distance Field text rendering library.
## `toaru_termemu`
Terminal ANSI escape processor.
## `toaru_textregion`
WIP library for providing multiline wrapping label widgets with rich text support.
## `toaru_tree`
Generic tree implementation. Also used by the kernel.

View File

@ -13,8 +13,8 @@
#include <toaru/graphics.h>
#include <toaru/yutani.h>
#include <toaru/decorations.h>
#include <toaru/sdf.h>
#include <toaru/menu.h>
#include <toaru/text.h>
#define TEXT_OFFSET_X 10
#define TEXT_OFFSET_Y 3
@ -37,6 +37,8 @@ static int close_enough(struct yutani_msg_window_mouse_event * me) {
sqrt(pow(me->new_x - me->old_x, 2.0) + pow(me->new_y - me->old_y, 2.0)) < 10.0);
}
static struct TT_Font * tt_font = NULL;
static void render_decorations_simple(yutani_window_t * window, gfx_context_t * ctx, char * title, int decors_active) {
uint32_t color = BORDERCOLOR;
@ -56,13 +58,10 @@ static void render_decorations_simple(yutani_window_t * window, gfx_context_t *
}
}
if (decors_active == DECOR_INACTIVE) {
draw_sdf_string(ctx, TEXT_OFFSET_X, TEXT_OFFSET_Y, title, 14, TEXTCOLOR_INACTIVE, SDF_FONT_THIN);
draw_sdf_string(ctx, window->width - 20, TEXT_OFFSET_Y, "x", 14, TEXTCOLOR_INACTIVE, SDF_FONT_THIN);
} else {
draw_sdf_string(ctx, TEXT_OFFSET_X, TEXT_OFFSET_Y, title, 14, TEXTCOLOR, SDF_FONT_THIN);
draw_sdf_string(ctx, window->width - 20, TEXT_OFFSET_Y, "x", 14, TEXTCOLOR, SDF_FONT_THIN);
}
tt_set_size(tt_font, 12);
uint32_t textcolor = (decors_active == DECOR_INACTIVE) ? TEXTCOLOR_INACTIVE : TEXTCOLOR;
tt_draw_string(ctx, tt_font, TEXT_OFFSET_X, TEXT_OFFSET_Y + 12, title, textcolor);
tt_draw_string(ctx, tt_font, window->width - 20, TEXT_OFFSET_Y + 12, "x", textcolor);
for (uint32_t i = 0; i < window->width; ++i) {
GFX(ctx, i, 0) = color;
@ -96,6 +95,7 @@ static void initialize_simple() {
decor_render_decorations = render_decorations_simple;
decor_check_button_press = check_button_press_simple;
decor_get_bounds = get_bounds_simple;
tt_font = tt_font_from_file("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf");
}
void render_decorations(yutani_window_t * window, gfx_context_t * ctx, char * title) {

View File

@ -2,7 +2,6 @@
#include <assert.h>
#include <toaru/yutani.h>
#include <toaru/decorations.h>
#include <toaru/sdf.h>
#include <toaru/menu.h>
#include <kuroko/kuroko.h>
#include <kuroko/vm.h>
@ -925,7 +924,7 @@ static KrkValue _font_draw_string(int argc, KrkValue argv[], int hasKw) {
int32_t x = AS_INTEGER(argv[3]);
int32_t y = AS_INTEGER(argv[4]);
return INTEGER_VAL(draw_sdf_string_stroke(ctx,x,y,str,self->fontSize,self->fontColor,self->fontType,self->fontGamma,self->fontStroke));
return INTEGER_VAL(-1);
}
static KrkValue _font_width(int argc, KrkValue argv[], int hasKw) {
@ -934,7 +933,7 @@ static KrkValue _font_width(int argc, KrkValue argv[], int hasKw) {
return krk_runtimeError(vm.exceptions->typeError, "expected str");
const char * str = AS_CSTRING(argv[1]);
return INTEGER_VAL(draw_sdf_string_width(str, self->fontSize, self->fontType));
return INTEGER_VAL(-1);
}
static void _MenuBar_gcsweep(KrkInstance * _self) {
@ -1346,16 +1345,6 @@ KrkValue krk_module_onload__yutani(void) {
"Font.width(string)\n"
" Calculate the rendered width of the given string when drawn with this font.";
krk_defineNative(&YutaniFont->methods, "size", _font_size)->flags |= KRK_NATIVE_FLAGS_IS_DYNAMIC_PROPERTY;
/* Some static values */
#define ATTACH_FONT(name) krk_attachNamedValue(&YutaniFont->methods, #name, INTEGER_VAL(SDF_ ## name))
ATTACH_FONT(FONT_THIN);
ATTACH_FONT(FONT_BOLD);
ATTACH_FONT(FONT_MONO);
ATTACH_FONT(FONT_MONO_BOLD);
ATTACH_FONT(FONT_MONO_OBLIQUE);
ATTACH_FONT(FONT_MONO_BOLD_OBLIQUE);
ATTACH_FONT(FONT_OBLIQUE);
ATTACH_FONT(FONT_BOLD_OBLIQUE);
krk_finalizeClass(YutaniFont);
MenuBarClass = krk_createClass(module, "MenuBar", NULL);

267
lib/sdf.c
View File

@ -1,267 +0,0 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2018 K. Lange
*
* Signed Distance Field text rasterization library
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <toaru/graphics.h>
#include <toaru/hashmap.h>
#include <toaru/sdf.h>
#include <toaru/spinlock.h>
#include <toaru/decodeutf8.h>
#include "apps/ununicode.h"
#define BASE_WIDTH 50
#define BASE_HEIGHT 50
static sprite_t _font_data_thin;
static sprite_t _font_data_bold;
static sprite_t _font_data_oblique;
static sprite_t _font_data_bold_oblique;
static sprite_t _font_data_mono;
static sprite_t _font_data_mono_bold;
static sprite_t _font_data_mono_oblique;
static sprite_t _font_data_mono_bold_oblique;
static hashmap_t * _font_cache;
static volatile int _sdf_lock = 0;
static double gamma = 1.7;
struct CharData{
char code;
size_t width_bold;
size_t width_thin;
size_t width_mono;
} _char_data[256];
static int loaded = 0;
static int offset(int ch) {
/* Calculate offset into table above */
return ch;
}
static char * _font_data = NULL;
static size_t _font_data_size = 0;
static void load_font(sprite_t * sprite, int font) {
uint32_t * _font_data_i = (uint32_t*)_font_data;
sprite->width = _font_data_i[font * 3 + 1];
sprite->height = _font_data_i[font * 3 + 2];
int offset = _font_data_i[font * 3 + 3];
sprite->bitmap = (uint32_t *)&_font_data[offset];
sprite->alpha = 0;
sprite->masks = NULL;
sprite->blank = 0;
}
__attribute__((constructor))
static void _init_sdf(void) {
/* Load the font. */
_font_cache = hashmap_create_int(10);
{
char tmp[100];
char * display = getenv("DISPLAY");
if (!display) display = "compositor";
sprintf(tmp, "sys.%s.fonts", display);
_font_data = shm_obtain(tmp, &_font_data_size);
}
if (!_font_data_size) return;
load_font(&_font_data_thin, SDF_FONT_THIN);
load_font(&_font_data_bold, SDF_FONT_BOLD);
load_font(&_font_data_oblique, SDF_FONT_OBLIQUE);
load_font(&_font_data_bold_oblique, SDF_FONT_BOLD_OBLIQUE);
load_font(&_font_data_mono, SDF_FONT_MONO);
load_font(&_font_data_mono_bold, SDF_FONT_MONO_BOLD);
load_font(&_font_data_mono_oblique, SDF_FONT_MONO_OBLIQUE);
load_font(&_font_data_mono_bold_oblique, SDF_FONT_MONO_BOLD_OBLIQUE);
FILE * fi = fopen("/etc/sdf.conf", "r");
char tmp[1024];
char * s = tmp;
for (int i = 0; i < 256; ++i) {
_char_data[i].code = i;
_char_data[i].width_bold = 25;
_char_data[i].width_thin = 20;
_char_data[i].width_mono = 25;
}
while ((s = fgets(tmp, 1024, fi))) {
if (strlen(s) < 1) continue;
int i = offset(*s);
s++; s++;
char t = *s;
s++; s++;
int o = atoi(s);
if (t == 'b') {
_char_data[i].width_bold = o;
} else if (t == 't') {
_char_data[i].width_thin = o;
} else if (t == 'm') {
_char_data[i].width_mono = o;
}
}
fclose(fi);
loaded = 1;
}
static sprite_t * _select_font(int font) {
switch (font) {
case SDF_FONT_BOLD:
return &_font_data_bold;
case SDF_FONT_MONO:
return &_font_data_mono;
case SDF_FONT_MONO_BOLD:
return &_font_data_mono_bold;
case SDF_FONT_MONO_OBLIQUE:
return &_font_data_mono_oblique;
case SDF_FONT_MONO_BOLD_OBLIQUE:
return &_font_data_mono_bold_oblique;
case SDF_FONT_OBLIQUE:
return &_font_data_oblique;
case SDF_FONT_BOLD_OBLIQUE:
return &_font_data_bold_oblique;
case SDF_FONT_THIN:
default:
return &_font_data_thin;
}
}
static int _select_width(int _ch, int font) {
int ch = (_ch >= 0 && _ch <= 128) ? _ch : (int)ununicode(_ch);
switch (font) {
case SDF_FONT_BOLD:
case SDF_FONT_BOLD_OBLIQUE:
return _char_data[ch].width_bold;
case SDF_FONT_MONO:
case SDF_FONT_MONO_BOLD:
case SDF_FONT_MONO_OBLIQUE:
case SDF_FONT_MONO_BOLD_OBLIQUE:
return _char_data[ch].width_mono;
case SDF_FONT_OBLIQUE:
case SDF_FONT_THIN:
default:
return _char_data[ch].width_thin;
}
}
static int draw_sdf_character(gfx_context_t * ctx, int32_t x, int32_t y, int _ch, int size, uint32_t color, sprite_t * tmp, int font, sprite_t * _font_data, double buffer) {
int ch = (_ch >= 0 && _ch <= 128) ? _ch : (int)ununicode(_ch);
double scale = (double)size / 50.0;
int width = _select_width(ch, font) * 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);
/* ignore size */
for (int j = 0; j < height; ++j) {
if (y + j < 0) continue;
if (y + j >= ctx->height) continue;
if (fy+j >= tmp->height) continue;
for (int i = 0; i < size; ++i) {
/* TODO needs to do bilinear filter */
if (fx+i >= tmp->width) continue;
if (x + i < 0) continue;
if (x + i >= ctx->width) continue;
uint32_t c = SPRITE((tmp), fx+i, fy+j);
double dist = (double)_RED(c) / 255.0;
double edge0 = buffer - gamma * 1.4142 / (double)size;
double edge1 = buffer + gamma * 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);
uint32_t f_color = premultiply((color & 0xFFFFFF) | ((uint32_t)(255 * a) << 24));
f_color = (f_color & 0xFFFFFF) | ((uint32_t)(a * _ALP(color)) << 24);
GFX(ctx,x+i,y+j) = alpha_blend_rgba(GFX(ctx,x+i,y+j), f_color);
}
}
return width;
}
int draw_sdf_string_stroke(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, int size, uint32_t color, int font, double _gamma, double stroke) {
sprite_t * _font_data = _select_font(font);
if (!loaded) return 0;
double scale = (double)size / 50.0;
int scale_height = scale * _font_data->height;
sprite_t * tmp;
spin_lock(&_sdf_lock);
if (!hashmap_has(_font_cache, (void *)(uintptr_t)(scale_height | (font << 16)))) {
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);
free(t);
hashmap_set(_font_cache, (void *)(uintptr_t)(scale_height | (font << 16)), tmp);
} else {
tmp = hashmap_get(_font_cache, (void *)(uintptr_t)(scale_height | (font << 16)));
}
uint32_t state = 0;
uint32_t c = 0;
int32_t out_width = 0;
gamma = _gamma;
while (*str) {
if (!decode(&state, &c, (unsigned char)*str)) {
int w = draw_sdf_character(ctx,x,y,c,size,color,tmp,font,_font_data, stroke);
out_width += w;
x += w;
}
str++;
}
spin_unlock(&_sdf_lock);
return out_width;
}
int draw_sdf_string_gamma(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, int size, uint32_t color, int font, double _gamma) {
return draw_sdf_string_stroke(ctx,x,y,str,size,color,font,gamma,0.75);
}
int draw_sdf_string(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, int size, uint32_t color, int font) {
return draw_sdf_string_stroke(ctx,x,y,str,size,color,font,1.7, 0.75);
}
static int char_width(int ch, int font) {
return _select_width(ch, font);
}
int draw_sdf_string_width(const char * str, int size, int font) {
double scale = (double)size / 50.0;
uint32_t state = 0;
uint32_t c = 0;
int32_t out_width = 0;
while (*str) {
if (!decode(&state, &c, (unsigned char)*str)) {
int w = char_width(c,font) * scale;
out_width += w;
} else if (state == UTF8_REJECT) {
state = 0;
}
str++;
}
return out_width;
}

View File

@ -1,85 +0,0 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2018 K. Lange
*
* TODO: This is a work in progress
*
* Port of the original ToaruOS Python text_region library to C.
*
* Allows for the display of rich text with multiple varied formats,
* as well as carat positioning, reflow, links, images, and so on.
*/
#include <stdio.h>
#include <toaru/textregion.h>
#include <toaru/sdf.h>
int tr_font_get_width(struct TR_Font * font, char * string) {
return draw_sdf_string_width(string, font->size, font->typeface);
}
int tr_font_write(struct TR_Font * font, gfx_context_t * ctx, int x, int y, char * string) {
return draw_sdf_string(ctx, x, y, string, font->size, font->color, font->typeface);
}
void tr_textunit_set_tag_group(struct TR_TextUnit * self, list_t * tag_group) {
if (!self->tag_group) {
self->tag_group = tag_group;
list_insert(tag_group, self);
} else {
/* Already in a tag group, this is wrong */
}
}
void tr_textunit_set_font(struct TR_TextUnit * self, struct TR_Font * font) {
self->font = font;
self->width = tr_font_get_width(font, self->string);
}
void tr_textunit_set_extra(struct TR_TextUnit * self, char * key, void * data) {
if (!self->extra) {
self->extra = hashmap_create(10);
}
hashmap_set(self->extra, key, data);
}
void tr_textregion_set_alignment(struct TR_TextRegion * self, int align) {
self->align = align;
}
void tr_textregion_set_valignment(struct TR_TextRegion * self, int align) {
self->valign = align;
}
void tr_textregion_set_max_lines(struct TR_TextRegion * self, int max_lines) {
self->max_lines = max_lines;
tr_textregion_reflow(self);
}
int tr_textregion_get_visible_lines(struct TR_TextRegion * self) {
return self->height / self->line_height;
}
void tr_textregion_reflow(struct TR_TextRegion * self) {
if (self->lines) {
fprintf(stderr, "Need to clean out lines\n");
#if 0
list_destroy(self->lines);
list_free(self->lines);
free(self->lines);
#endif
}
#if 0
self->lines = list_create();
int current_width = 0;
list_t * current_units = list_create();
struct TR_TextUnit * leftover = NULL;
int i = 0;
while (i < self->text_units
#endif
}

View File

@ -25,13 +25,11 @@ class Classifier:
'<toaru/markup.h>': (None, '-ltoaru_markup', ['<toaru/hashmap.h>']),
'<toaru/json.h>': (None, '-ltoaru_json', ['<toaru/hashmap.h>']),
'<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/menu.h>', '<toaru/sdf.h>', '<toaru/graphics.h>', '<toaru/yutani.h>']),
'<toaru/decorations.h>': (None, '-ltoaru_decorations', ['<toaru/menu.h>', '<toaru/text.h>', '<toaru/graphics.h>', '<toaru/yutani.h>']),
'<toaru/termemu.h>': (None, '-ltoaru_termemu', ['<toaru/graphics.h>']),
'<toaru/sdf.h>': (None, '-ltoaru_sdf', ['<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/icon_cache.h>': (None, '-ltoaru_icon_cache', ['<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/menu.h>': (None, '-ltoaru_menu', ['<toaru/sdf.h>', '<toaru/yutani.h>', '<toaru/icon_cache.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/textregion.h>': (None, '-ltoaru_textregion', ['<toaru/sdf.h>', '<toaru/yutani.h>','<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/button.h>': (None, '-ltoaru_button', ['<toaru/graphics.h>','<toaru/sdf.h>', '<toaru/icon_cache.h>']),
'<toaru/menu.h>': (None, '-ltoaru_menu', ['<toaru/yutani.h>', '<toaru/icon_cache.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
'<toaru/button.h>': (None, '-ltoaru_button', ['<toaru/graphics.h>','<toaru/text.h>', '<toaru/icon_cache.h>']),
'<toaru/text.h>': (None, '-ltoaru_text', ['<toaru/graphics.h>', '<toaru/hashmap.h>']),
# Kuroko
'<kuroko/kuroko.h>': ('../../../kuroko/src', '-lkuroko', []),