# HG changeset patch # User Michael Pavone # Date 1711834008 25200 # Node ID 369a52e302e28cf01a9bb2662098df6ded468386 # Parent 29baf8d5a579502a26a6d1e36c55d364bc96e77e Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable diff -r 29baf8d5a579 -r 369a52e302e2 nuklear_ui/font.c --- a/nuklear_ui/font.c Fri Mar 08 23:14:08 2024 -0800 +++ b/nuklear_ui/font.c Sat Mar 30 14:26:48 2024 -0700 @@ -5,21 +5,25 @@ #include "../util.h" #include "sfnt.h" -char *default_font_path(void) +char **preferred_font_paths(uint32_t *num_out) { + char ** ret; #ifdef FONT_PATH FILE *f = fopen(FONT_PATH, "rb"); if (f) { fclose(f); - return strdup(FONT_PATH); + ret = calloc(1, sizeof(char*)); + ret[0] = strdup(FONT_PATH); + *num_out = 1; + return ret; } #endif //TODO: specify language dynamically once BlastEm is localized - FILE *fc_pipe = popen("fc-match :lang=en -f '%{file}'", "r"); + FILE *fc_pipe = popen("fc-match -s -f '%{file}\n' :lang=en", "r"); if (!fc_pipe) { return NULL; } - size_t buf_size = 128; + size_t buf_size = 4096; char *buffer = NULL; size_t total = 0, read = 0; do { @@ -33,35 +37,73 @@ } while (read == (buf_size - total)); total += read; buffer[total] = 0; - - return buffer; + *num_out = 0; + for (size_t i = 0; i < total; i++) + { + if (buffer[i] == '\n') { + buffer[i] = 0; + if (i + 1 != total) { + (*num_out)++; + } + } + } + ret = calloc(*num_out, sizeof(char*)); + size_t entry = 0; + ret[entry++] = buffer; + for (size_t i = 0; i < total - 1 && entry < *num_out; i++) + { + if (!buffer[i]) { + ret[entry++] = buffer + i + 1; + } + } + return ret; } uint8_t *default_font(uint32_t *size_out) { - char *path = default_font_path(); - if (!path) { - goto error; - } - FILE *f = fopen(path, "rb"); - free(path); - if (!f) { + uint8_t *ret = NULL; + uint32_t num_fonts; + char **paths = preferred_font_paths(&num_fonts); + if (!paths) { goto error; } - long size = file_size(f); - uint8_t *buffer = malloc(size); - if (size != fread(buffer, 1, size, f)) { + for (uint32_t i = 0; i < num_fonts && !ret; i++) + { + FILE *f = fopen(paths[i], "rb"); + if (!f) { + fprintf(stderr, "Failed to open font file %s\n", paths[i]); + continue; + } + long size = file_size(f); + uint8_t *buffer = malloc(size); + if (size != fread(buffer, 1, size, f)) { + fprintf(stderr, "Failed to read font file %s\n", paths[i]); + fclose(f); + continue; + } fclose(f); - goto error; + sfnt_container *sfnt = load_sfnt(buffer, size); + if (!sfnt) { + fprintf(stderr, "File %s does not contain SFNT resources\n", paths[i]); + free(buffer); + continue; + } + for (uint8_t j = 0; j < sfnt->num_fonts; j++) + { + if (sfnt_has_truetype_glyphs(sfnt->tables + j)) { + ret = sfnt_flatten(sfnt->tables + j, size_out); + sfnt = NULL; + break; + } + fprintf(stderr, "Font %s in file %s doesn't have TrueType glyphs\n", sfnt_name(sfnt->tables + j, SFNT_POSTSCRIPT), paths[i]); + } + if (sfnt) { + sfnt_free(sfnt); + } } - fclose(f); - sfnt_container *sfnt = load_sfnt(buffer, size); - if (!sfnt) { - free(buffer); - goto error; - } - return sfnt_flatten(sfnt->tables, size_out); + free(paths[0]); + free(paths); error: //TODO: try to find a suitable font in /usr/share/fonts as a fallback - return NULL; + return ret; } \ No newline at end of file diff -r 29baf8d5a579 -r 369a52e302e2 nuklear_ui/sfnt.c --- a/nuklear_ui/sfnt.c Fri Mar 08 23:14:08 2024 -0800 +++ b/nuklear_ui/sfnt.c Sat Mar 30 14:26:48 2024 -0700 @@ -209,6 +209,18 @@ } } +uint8_t sfnt_has_truetype_glyphs(sfnt_table *sfnt) +{ + uint32_t table_size; + uint8_t *table = sfnt_find_table(sfnt, "glyf", &table_size); + if (!table) { + return 0; + } + table = sfnt_find_table(sfnt, "loca", &table_size); + return table != NULL; + +} + uint8_t *sfnt_flatten(sfnt_table *sfnt, uint32_t *size_out) { uint8_t *ret = NULL;; diff -r 29baf8d5a579 -r 369a52e302e2 nuklear_ui/sfnt.h --- a/nuklear_ui/sfnt.h Fri Mar 08 23:14:08 2024 -0800 +++ b/nuklear_ui/sfnt.h Sat Mar 30 14:26:48 2024 -0700 @@ -37,6 +37,7 @@ sfnt_container *load_sfnt(uint8_t *buffer, uint32_t size); char *sfnt_name(sfnt_table *sfnt, uint16_t name_type); +uint8_t sfnt_has_truetype_glyphs(sfnt_table *sfnt); uint8_t *sfnt_flatten(sfnt_table *sfnt, uint32_t *size_out); sfnt_table *sfnt_subfamily_by_names(sfnt_container *sfnt, const char **names); void sfnt_free(sfnt_container *sfnt);