Support UTF-8 in shmemfonts w/ fallbacks
This commit is contained in:
parent
7b7697698e
commit
25f418e887
@ -12,6 +12,7 @@
|
||||
|
||||
#include "graphics.h"
|
||||
#include "shmemfonts.h"
|
||||
#include "utf8decode.h"
|
||||
|
||||
static FT_Library library;
|
||||
static FT_Face faces[FONTS_TOTAL]; /* perhaps make this an array ? */
|
||||
@ -25,6 +26,8 @@ static int selected_face = 0;
|
||||
#define SGFX(CTX,x,y,WIDTH) *((uint32_t *)&CTX[((WIDTH) * (y) + (x)) * 4])
|
||||
#define FONT_SIZE 12
|
||||
|
||||
#define FALLBACK FONT_JAPANESE
|
||||
|
||||
/*
|
||||
* XXX: take font name as an argument / allow multiple fonts
|
||||
*/
|
||||
@ -37,6 +40,12 @@ static void _load_font(int i, char * name) {
|
||||
error = FT_Set_Pixel_Sizes(faces[i], FONT_SIZE, FONT_SIZE);
|
||||
}
|
||||
|
||||
static void _load_font_f(int i, char * path) {
|
||||
int error;
|
||||
error = FT_New_Face(library, path, 0, &faces[i]);
|
||||
error = FT_Set_Pixel_Sizes(faces[i], FONT_SIZE, FONT_SIZE);
|
||||
}
|
||||
|
||||
static void _load_fonts() {
|
||||
_load_font(FONT_SANS_SERIF, WINS_SERVER_IDENTIFIER ".fonts.sans-serif");
|
||||
_load_font(FONT_SANS_SERIF_BOLD, WINS_SERVER_IDENTIFIER ".fonts.sans-serif.bold");
|
||||
@ -46,6 +55,7 @@ static void _load_fonts() {
|
||||
_load_font(FONT_MONOSPACE_BOLD, WINS_SERVER_IDENTIFIER ".fonts.monospace.bold");
|
||||
_load_font(FONT_MONOSPACE_ITALIC, WINS_SERVER_IDENTIFIER ".fonts.monospace.italic");
|
||||
_load_font(FONT_MONOSPACE_BOLD_ITALIC, WINS_SERVER_IDENTIFIER ".fonts.monospace.bolditalic");
|
||||
_load_font_f(FONT_JAPANESE, "/usr/share/fonts/VLGothic.ttf");
|
||||
}
|
||||
|
||||
void init_shmemfonts() {
|
||||
@ -58,8 +68,9 @@ void init_shmemfonts() {
|
||||
}
|
||||
|
||||
void set_font_size(int size) {
|
||||
_font_size = size;
|
||||
FT_Set_Pixel_Sizes(faces[selected_face], size, size);
|
||||
for (int i = 0; i < FONTS_TOTAL; ++i) {
|
||||
FT_Set_Pixel_Sizes(faces[i], size, size);
|
||||
}
|
||||
}
|
||||
|
||||
void set_text_opacity(float new_opacity) {
|
||||
@ -87,19 +98,48 @@ static void draw_char(FT_Bitmap * bitmap, int x, int y, uint32_t fg, gfx_context
|
||||
uint32_t draw_string_width(char * string) {
|
||||
slot = faces[selected_face]->glyph;
|
||||
int pen_x = 0, i = 0;
|
||||
int len = strlen(string);
|
||||
int error;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
uint8_t * s = string;
|
||||
|
||||
uint32_t codepoint;
|
||||
uint32_t state = 0;
|
||||
|
||||
while (*s) {
|
||||
uint16_t o = 0;
|
||||
while (*s) {
|
||||
if (!decode(&state, &codepoint, *s)) {
|
||||
o = (uint16_t)codepoint;
|
||||
s++;
|
||||
goto finished_width;
|
||||
} else if (state == UTF8_REJECT) {
|
||||
state = 0;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
finished_width:
|
||||
if (!o) continue;
|
||||
|
||||
FT_UInt glyph_index;
|
||||
|
||||
glyph_index = FT_Get_Char_Index( faces[selected_face], string[i]);
|
||||
error = FT_Load_Glyph(faces[selected_face], glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("Error loading glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
glyph_index = FT_Get_Char_Index( faces[selected_face], o);
|
||||
if (glyph_index) {
|
||||
error = FT_Load_Glyph(faces[selected_face], glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error loading glyph for '%d'\n", o);
|
||||
continue;
|
||||
}
|
||||
slot = (faces[selected_face])->glyph;
|
||||
} else {
|
||||
glyph_index = FT_Get_Char_Index( faces[FALLBACK], o);
|
||||
error = FT_Load_Glyph(faces[FALLBACK], glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error loading glyph for '%d'\n", o);
|
||||
continue;
|
||||
}
|
||||
slot = (faces[FALLBACK])->glyph;
|
||||
}
|
||||
slot = (faces[selected_face])->glyph;
|
||||
pen_x += slot->advance.x >> 6;
|
||||
}
|
||||
return pen_x;
|
||||
@ -108,25 +148,62 @@ uint32_t draw_string_width(char * string) {
|
||||
void draw_string(gfx_context_t * ctx, int x, int y, uint32_t fg, char * string) {
|
||||
slot = faces[selected_face]->glyph;
|
||||
int pen_x = x, pen_y = y, i = 0;
|
||||
int len = strlen(string);
|
||||
int error;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
uint8_t * s = string;
|
||||
|
||||
uint32_t codepoint;
|
||||
uint32_t state = 0;
|
||||
|
||||
while (*s) {
|
||||
uint16_t o = 0;
|
||||
while (*s) {
|
||||
if (!decode(&state, &codepoint, *s)) {
|
||||
o = (uint16_t)codepoint;
|
||||
s++;
|
||||
goto finished;
|
||||
} else if (state == UTF8_REJECT) {
|
||||
state = 0;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
finished:
|
||||
if (!o) continue;
|
||||
|
||||
FT_UInt glyph_index;
|
||||
|
||||
glyph_index = FT_Get_Char_Index( faces[selected_face], string[i]);
|
||||
error = FT_Load_Glyph(faces[selected_face], glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("Error loading glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
slot = (faces[selected_face])->glyph;
|
||||
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
error = FT_Render_Glyph((faces[selected_face])->glyph, FT_RENDER_MODE_NORMAL);
|
||||
glyph_index = FT_Get_Char_Index( faces[selected_face], o);
|
||||
if (glyph_index) {
|
||||
error = FT_Load_Glyph(faces[selected_face], glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("Error rendering glyph for '%c'\n", string[i]);
|
||||
fprintf(stderr, "Error loading glyph for '%d'\n", o);
|
||||
continue;
|
||||
}
|
||||
slot = (faces[selected_face])->glyph;
|
||||
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
error = FT_Render_Glyph((faces[selected_face])->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error rendering glyph for '%d'\n", o);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
glyph_index = FT_Get_Char_Index( faces[FALLBACK], o);
|
||||
error = FT_Load_Glyph(faces[FALLBACK], glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error loading glyph for '%d'\n", o);
|
||||
continue;
|
||||
}
|
||||
slot = (faces[FALLBACK])->glyph;
|
||||
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
error = FT_Render_Glyph((faces[FALLBACK])->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error rendering glyph for '%d'\n", o);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
draw_char(&slot->bitmap, pen_x + slot->bitmap_left, pen_y - slot->bitmap_top, fg, ctx);
|
||||
|
@ -20,7 +20,8 @@ void set_font_face(int face_num);
|
||||
#define FONT_MONOSPACE_BOLD 5
|
||||
#define FONT_MONOSPACE_ITALIC 6
|
||||
#define FONT_MONOSPACE_BOLD_ITALIC 7
|
||||
#define FONT_JAPANESE 8
|
||||
|
||||
#define FONTS_TOTAL 8
|
||||
#define FONTS_TOTAL 9
|
||||
|
||||
#endif
|
||||
|
@ -21,6 +21,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef UTF_DECODER_H
|
||||
#define UTF_DECODER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define UTF8_ACCEPT 0
|
||||
@ -55,4 +58,4 @@ decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
|
||||
return *state;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -13,25 +13,13 @@
|
||||
|
||||
#define PANEL_HEIGHT 28
|
||||
|
||||
#include "lib/utf8decode.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_CACHE_H
|
||||
|
||||
#include "lib/window.h"
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/shmemfonts.h"
|
||||
|
||||
sprite_t * sprites[128];
|
||||
sprite_t alpha_tmp;
|
||||
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Face face_extra;
|
||||
FT_GlyphSlot slot;
|
||||
FT_UInt glyph_index;
|
||||
|
||||
|
||||
uint16_t win_width;
|
||||
uint16_t win_height;
|
||||
gfx_context_t * ctx;
|
||||
@ -61,120 +49,8 @@ void init_sprite_png(int i, char * filename) {
|
||||
load_sprite_png(sprites[i], filename);
|
||||
}
|
||||
|
||||
void draw_char(FT_Bitmap * bitmap, int x, int y, uint32_t fg) {
|
||||
int i, j, p, q;
|
||||
int x_max = x + bitmap->width;
|
||||
int y_max = y + bitmap->rows;
|
||||
for (j = y, q = 0; j < y_max; j++, q++) {
|
||||
for ( i = x, p = 0; i < x_max; i++, p++) {
|
||||
GFX(ctx, i,j) = alpha_blend(GFX(ctx, i,j),fg,rgb(bitmap->buffer[q * bitmap->width + p],0,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_string(int x, int y, uint32_t fg, char * string) {
|
||||
slot = face->glyph;
|
||||
int pen_x = x, pen_y = y, i = 0;
|
||||
int len = strlen(string);
|
||||
int error;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
FT_UInt glyph_index;
|
||||
|
||||
glyph_index = FT_Get_Char_Index( face, string[i]);
|
||||
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("Error loading glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
slot = (face)->glyph;
|
||||
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
error = FT_Render_Glyph((face)->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error) {
|
||||
printf("Error rendering glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
draw_char(&slot->bitmap, pen_x + slot->bitmap_left, pen_y - slot->bitmap_top, fg);
|
||||
pen_x += slot->advance.x >> 6;
|
||||
pen_y += slot->advance.y >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
int wstrlen(uint16_t * s) {
|
||||
int i = 0;
|
||||
while (s[i] != 0) {
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void draw_string_wide(int x, int y, uint32_t fg, uint16_t * string) {
|
||||
slot = face->glyph;
|
||||
int pen_x = x, pen_y = y, i = 0;
|
||||
int len = wstrlen(string);
|
||||
int error;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
FT_UInt glyph_index;
|
||||
|
||||
glyph_index = FT_Get_Char_Index( face, string[i]);
|
||||
|
||||
if (glyph_index) {
|
||||
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("Error loading glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
slot = (face)->glyph;
|
||||
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
error = FT_Render_Glyph((face)->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error) {
|
||||
printf("Error rendering glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
glyph_index = FT_Get_Char_Index( face_extra, string[i]);
|
||||
error = FT_Load_Glyph(face_extra, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("Error loading glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
slot = (face_extra)->glyph;
|
||||
if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||
error = FT_Render_Glyph((face_extra)->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error) {
|
||||
printf("Error rendering glyph for '%c'\n", string[i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_char(&slot->bitmap, pen_x + slot->bitmap_left, pen_y - slot->bitmap_top, fg);
|
||||
pen_x += slot->advance.x >> 6;
|
||||
pen_y += slot->advance.y >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
#define FONT_SIZE 14
|
||||
|
||||
void _loadDejavu() {
|
||||
char * font;
|
||||
size_t s = 0;
|
||||
int error;
|
||||
font = (char *)syscall_shm_obtain(WINS_SERVER_IDENTIFIER ".fonts.sans-serif", &s);
|
||||
error = FT_New_Memory_Face(library, font, s, 0, &face);
|
||||
error = FT_Set_Pixel_Sizes(face, FONT_SIZE, FONT_SIZE);
|
||||
}
|
||||
|
||||
void _loadVlgothic() {
|
||||
int error;
|
||||
error = FT_New_Face(library, "/usr/share/fonts/VLGothic.ttf", 0, &face_extra);
|
||||
error = FT_Set_Pixel_Sizes(face_extra, FONT_SIZE, FONT_SIZE);
|
||||
}
|
||||
|
||||
volatile int _continue = 1;
|
||||
|
||||
void sig_int(int sig) {
|
||||
@ -201,10 +77,8 @@ int main (int argc, char ** argv) {
|
||||
win_width = width;
|
||||
win_height = height;
|
||||
|
||||
|
||||
FT_Init_FreeType(&library);
|
||||
_loadDejavu();
|
||||
_loadVlgothic();
|
||||
init_shmemfonts();
|
||||
set_font_size(14);
|
||||
|
||||
/* Create the panel */
|
||||
window_t * panel = window_create(0, 0, width, PANEL_HEIGHT);
|
||||
@ -241,30 +115,9 @@ int main (int argc, char ** argv) {
|
||||
|
||||
/* UTF-8 Strings FTW! */
|
||||
uint8_t * os_name_ = "とあるOS";
|
||||
|
||||
uint8_t final[512];
|
||||
|
||||
uint32_t l = snprintf(final, 512, "%s %s", os_name_, os_version);
|
||||
|
||||
uint8_t *s = final;
|
||||
uint16_t os_name[256] = {0};
|
||||
uint16_t *o = os_name;
|
||||
|
||||
uint32_t codepoint;
|
||||
uint32_t state = 0;
|
||||
|
||||
/* TODO: This should be part of the graphics library (combined with generic text rendering) */
|
||||
while (*s) {
|
||||
if (!decode(&state, &codepoint, *s)) {
|
||||
*o = (uint16_t)codepoint;
|
||||
o++;
|
||||
} else if (state == UTF8_REJECT) {
|
||||
state = 0;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
o = 0;
|
||||
|
||||
syscall_signal(2, sig_int);
|
||||
|
||||
/* Enable mouse */
|
||||
@ -280,8 +133,8 @@ int main (int argc, char ** argv) {
|
||||
timeinfo = localtime((time_t *)&now.tv_sec);
|
||||
strftime(buffer, 80, "%I:%M:%S %p", timeinfo);
|
||||
|
||||
draw_string(width - 120, 17, rgb(255,255,255), buffer);
|
||||
draw_string_wide(10, 17, rgb(255,255,255), os_name);
|
||||
draw_string(ctx, width - 120, 17, rgb(255,255,255), buffer);
|
||||
draw_string(ctx, 10, 17, rgb(255,255,255), final);
|
||||
|
||||
draw_sprite(ctx, sprites[1], win_width - 23, 1); /* Logout button */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user