annotate nuklear_ui/font.c @ 2496:187bc857a76a default tip

Fix bug in MED mapper protection bit implementation
author Michael Pavone <pavone@retrodev.com>
date Sun, 28 Apr 2024 23:33:11 -0700
parents 48ab1e3e5df5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
1 #include <stdio.h>
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
2 #include <stdlib.h>
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
3 #include <stdint.h>
1934
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
4 #include <string.h>
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
5 #include "../util.h"
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
6 #include "sfnt.h"
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
7
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
8 char **preferred_font_paths(uint32_t *num_out)
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
9 {
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
10 char ** ret;
1934
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
11 #ifdef FONT_PATH
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
12 FILE *f = fopen(FONT_PATH, "rb");
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
13 if (f) {
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
14 fclose(f);
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
15 ret = calloc(1, sizeof(char*));
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
16 ret[0] = strdup(FONT_PATH);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
17 *num_out = 1;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
18 return ret;
1934
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
19 }
253c62b7144e Allow specifying a default font path at build time
Michael Pavone <pavone@retrodev.com>
parents: 1593
diff changeset
20 #endif
1976
3dd9c68472fb Specify desired language when invoking fc-match to find an appropriate font on Linux
Michael Pavone <pavone@retrodev.com>
parents: 1934
diff changeset
21 //TODO: specify language dynamically once BlastEm is localized
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
22 FILE *fc_pipe = popen("fc-match -s -f '%{file}\n' :lang=en", "r");
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
23 if (!fc_pipe) {
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
24 return NULL;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
25 }
2483
48ab1e3e5df5 Fix Linux font selection regression
Michael Pavone <pavone@retrodev.com>
parents: 2480
diff changeset
26 size_t buf_size = 2048;
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
27 char *buffer = NULL;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
28 size_t total = 0, read = 0;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
29 do {
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
30 total += read;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
31 buf_size *= 2;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
32 buffer = realloc(buffer, buf_size);
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
33 if (!buffer) {
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
34 return NULL;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
35 }
2483
48ab1e3e5df5 Fix Linux font selection regression
Michael Pavone <pavone@retrodev.com>
parents: 2480
diff changeset
36 read = fread(buffer + total, 1, buf_size - total, fc_pipe);
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
37 } while (read == (buf_size - total));
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
38 total += read;
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
39 buffer[total] = 0;
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
40 *num_out = 0;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
41 for (size_t i = 0; i < total; i++)
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
42 {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
43 if (buffer[i] == '\n') {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
44 buffer[i] = 0;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
45 if (i + 1 != total) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
46 (*num_out)++;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
47 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
48 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
49 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
50 ret = calloc(*num_out, sizeof(char*));
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
51 size_t entry = 0;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
52 ret[entry++] = buffer;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
53 for (size_t i = 0; i < total - 1 && entry < *num_out; i++)
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
54 {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
55 if (!buffer[i]) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
56 ret[entry++] = buffer + i + 1;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
57 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
58 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
59 return ret;
1474
c5c022c7aa54 Initial work on Nuklear-based UI
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
60 }
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
61
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
62 uint8_t *default_font(uint32_t *size_out)
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
63 {
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
64 uint8_t *ret = NULL;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
65 uint32_t num_fonts;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
66 char **paths = preferred_font_paths(&num_fonts);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
67 if (!paths) {
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
68 goto error;
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
69 }
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
70 for (uint32_t i = 0; i < num_fonts && !ret; i++)
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
71 {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
72 FILE *f = fopen(paths[i], "rb");
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
73 if (!f) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
74 fprintf(stderr, "Failed to open font file %s\n", paths[i]);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
75 continue;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
76 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
77 long size = file_size(f);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
78 uint8_t *buffer = malloc(size);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
79 if (size != fread(buffer, 1, size, f)) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
80 fprintf(stderr, "Failed to read font file %s\n", paths[i]);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
81 fclose(f);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
82 continue;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
83 }
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
84 fclose(f);
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
85 sfnt_container *sfnt = load_sfnt(buffer, size);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
86 if (!sfnt) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
87 fprintf(stderr, "File %s does not contain SFNT resources\n", paths[i]);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
88 free(buffer);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
89 continue;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
90 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
91 for (uint8_t j = 0; j < sfnt->num_fonts; j++)
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
92 {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
93 if (sfnt_has_truetype_glyphs(sfnt->tables + j)) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
94 ret = sfnt_flatten(sfnt->tables + j, size_out);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
95 sfnt = NULL;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
96 break;
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
97 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
98 fprintf(stderr, "Font %s in file %s doesn't have TrueType glyphs\n", sfnt_name(sfnt->tables + j, SFNT_POSTSCRIPT), paths[i]);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
99 }
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
100 if (sfnt) {
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
101 sfnt_free(sfnt);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
102 }
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
103 }
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
104 free(paths[0]);
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
105 free(paths);
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
106 error:
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
107 //TODO: try to find a suitable font in /usr/share/fonts as a fallback
2480
369a52e302e2 Try multiple results from fc-match on Linux rather than assuming the first choice font will be suitable
Michael Pavone <pavone@retrodev.com>
parents: 1976
diff changeset
108 return ret;
1527
4f6e8acd7b6a Added support for TTC and dfont format true type fonts. More robust font selection on Windows
Michael Pavone <pavone@retrodev.com>
parents: 1474
diff changeset
109 }