Mercurial > repos > blastem
comparison nuklear_ui/font.c @ 2480:369a52e302e2
Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 30 Mar 2024 14:26:48 -0700 |
parents | 3dd9c68472fb |
children | 48ab1e3e5df5 |
comparison
equal
deleted
inserted
replaced
2479:29baf8d5a579 | 2480:369a52e302e2 |
---|---|
3 #include <stdint.h> | 3 #include <stdint.h> |
4 #include <string.h> | 4 #include <string.h> |
5 #include "../util.h" | 5 #include "../util.h" |
6 #include "sfnt.h" | 6 #include "sfnt.h" |
7 | 7 |
8 char *default_font_path(void) | 8 char **preferred_font_paths(uint32_t *num_out) |
9 { | 9 { |
10 char ** ret; | |
10 #ifdef FONT_PATH | 11 #ifdef FONT_PATH |
11 FILE *f = fopen(FONT_PATH, "rb"); | 12 FILE *f = fopen(FONT_PATH, "rb"); |
12 if (f) { | 13 if (f) { |
13 fclose(f); | 14 fclose(f); |
14 return strdup(FONT_PATH); | 15 ret = calloc(1, sizeof(char*)); |
16 ret[0] = strdup(FONT_PATH); | |
17 *num_out = 1; | |
18 return ret; | |
15 } | 19 } |
16 #endif | 20 #endif |
17 //TODO: specify language dynamically once BlastEm is localized | 21 //TODO: specify language dynamically once BlastEm is localized |
18 FILE *fc_pipe = popen("fc-match :lang=en -f '%{file}'", "r"); | 22 FILE *fc_pipe = popen("fc-match -s -f '%{file}\n' :lang=en", "r"); |
19 if (!fc_pipe) { | 23 if (!fc_pipe) { |
20 return NULL; | 24 return NULL; |
21 } | 25 } |
22 size_t buf_size = 128; | 26 size_t buf_size = 4096; |
23 char *buffer = NULL; | 27 char *buffer = NULL; |
24 size_t total = 0, read = 0; | 28 size_t total = 0, read = 0; |
25 do { | 29 do { |
26 total += read; | 30 total += read; |
27 buf_size *= 2; | 31 buf_size *= 2; |
31 } | 35 } |
32 read = fread(buffer, 1, buf_size - total, fc_pipe); | 36 read = fread(buffer, 1, buf_size - total, fc_pipe); |
33 } while (read == (buf_size - total)); | 37 } while (read == (buf_size - total)); |
34 total += read; | 38 total += read; |
35 buffer[total] = 0; | 39 buffer[total] = 0; |
36 | 40 *num_out = 0; |
37 return buffer; | 41 for (size_t i = 0; i < total; i++) |
42 { | |
43 if (buffer[i] == '\n') { | |
44 buffer[i] = 0; | |
45 if (i + 1 != total) { | |
46 (*num_out)++; | |
47 } | |
48 } | |
49 } | |
50 ret = calloc(*num_out, sizeof(char*)); | |
51 size_t entry = 0; | |
52 ret[entry++] = buffer; | |
53 for (size_t i = 0; i < total - 1 && entry < *num_out; i++) | |
54 { | |
55 if (!buffer[i]) { | |
56 ret[entry++] = buffer + i + 1; | |
57 } | |
58 } | |
59 return ret; | |
38 } | 60 } |
39 | 61 |
40 uint8_t *default_font(uint32_t *size_out) | 62 uint8_t *default_font(uint32_t *size_out) |
41 { | 63 { |
42 char *path = default_font_path(); | 64 uint8_t *ret = NULL; |
43 if (!path) { | 65 uint32_t num_fonts; |
66 char **paths = preferred_font_paths(&num_fonts); | |
67 if (!paths) { | |
44 goto error; | 68 goto error; |
45 } | 69 } |
46 FILE *f = fopen(path, "rb"); | 70 for (uint32_t i = 0; i < num_fonts && !ret; i++) |
47 free(path); | 71 { |
48 if (!f) { | 72 FILE *f = fopen(paths[i], "rb"); |
49 goto error; | 73 if (!f) { |
74 fprintf(stderr, "Failed to open font file %s\n", paths[i]); | |
75 continue; | |
76 } | |
77 long size = file_size(f); | |
78 uint8_t *buffer = malloc(size); | |
79 if (size != fread(buffer, 1, size, f)) { | |
80 fprintf(stderr, "Failed to read font file %s\n", paths[i]); | |
81 fclose(f); | |
82 continue; | |
83 } | |
84 fclose(f); | |
85 sfnt_container *sfnt = load_sfnt(buffer, size); | |
86 if (!sfnt) { | |
87 fprintf(stderr, "File %s does not contain SFNT resources\n", paths[i]); | |
88 free(buffer); | |
89 continue; | |
90 } | |
91 for (uint8_t j = 0; j < sfnt->num_fonts; j++) | |
92 { | |
93 if (sfnt_has_truetype_glyphs(sfnt->tables + j)) { | |
94 ret = sfnt_flatten(sfnt->tables + j, size_out); | |
95 sfnt = NULL; | |
96 break; | |
97 } | |
98 fprintf(stderr, "Font %s in file %s doesn't have TrueType glyphs\n", sfnt_name(sfnt->tables + j, SFNT_POSTSCRIPT), paths[i]); | |
99 } | |
100 if (sfnt) { | |
101 sfnt_free(sfnt); | |
102 } | |
50 } | 103 } |
51 long size = file_size(f); | 104 free(paths[0]); |
52 uint8_t *buffer = malloc(size); | 105 free(paths); |
53 if (size != fread(buffer, 1, size, f)) { | |
54 fclose(f); | |
55 goto error; | |
56 } | |
57 fclose(f); | |
58 sfnt_container *sfnt = load_sfnt(buffer, size); | |
59 if (!sfnt) { | |
60 free(buffer); | |
61 goto error; | |
62 } | |
63 return sfnt_flatten(sfnt->tables, size_out); | |
64 error: | 106 error: |
65 //TODO: try to find a suitable font in /usr/share/fonts as a fallback | 107 //TODO: try to find a suitable font in /usr/share/fonts as a fallback |
66 return NULL; | 108 return ret; |
67 } | 109 } |