diff --git a/userspace/lib/shmemfonts.c b/userspace/lib/shmemfonts.c index 1c6739f4..bc261581 100644 --- a/userspace/lib/shmemfonts.c +++ b/userspace/lib/shmemfonts.c @@ -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); diff --git a/userspace/lib/shmemfonts.h b/userspace/lib/shmemfonts.h index efe8a1f4..b35597b4 100644 --- a/userspace/lib/shmemfonts.h +++ b/userspace/lib/shmemfonts.h @@ -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 diff --git a/userspace/lib/utf8decode.h b/userspace/lib/utf8decode.h index 1e5ad1a0..c69853f4 100644 --- a/userspace/lib/utf8decode.h +++ b/userspace/lib/utf8decode.h @@ -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 #define UTF8_ACCEPT 0 @@ -55,4 +58,4 @@ decode(uint32_t* state, uint32_t* codep, uint32_t byte) { return *state; } - +#endif diff --git a/userspace/panel.c b/userspace/panel.c index 0f6b09e9..648c1022 100644 --- a/userspace/panel.c +++ b/userspace/panel.c @@ -13,25 +13,13 @@ #define PANEL_HEIGHT 28 -#include "lib/utf8decode.h" - -#include -#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 */