Mercurial > repos > blastem
comparison nuklear_ui/font_win.c @ 1527:4f6e8acd7b6a nuklear_ui
Added support for TTC and dfont format true type fonts. More robust font selection on Windows
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Mar 2018 21:27:12 -0800 |
parents | b96f9fae757f |
children | 982c5327dfcc |
comparison
equal
deleted
inserted
replaced
1526:9bea1a199f15 | 1527:4f6e8acd7b6a |
---|---|
1 #include <windows.h> | 1 #include <windows.h> |
2 #include <shlobj.h> | 2 #include <shlobj.h> |
3 #include <string.h> | |
3 #include "../paths.h" | 4 #include "../paths.h" |
4 #include "../util.h" | 5 #include "../util.h" |
6 #include "sfnt.h" | |
5 | 7 |
6 char *default_font_path(void) | 8 uint8_t *default_font(uint32_t *size_out) |
7 { | 9 { |
10 static const char *thin[] = {"Thin", NULL}; | |
11 static const char *extra_light[] = {"ExtraLight", "UltraLight", NULL}; | |
12 static const char *light[] = {"Light", NULL}; | |
13 static const char *regular[] = {"Regular", "Normal", "Book", NULL}; | |
14 static const char *medium[] = {"Medium", NULL}; | |
15 static const char *semi_bold[] = {"SemiBold", "DemiBold", NULL}; | |
16 static const char *bold[] = {"Bold", NULL}; | |
17 static const char *extra_bold[] = {"ExtraBold", "UltraBold", NULL}; | |
18 static const char *heavy[] = {"Heavy", "Black", NULL}; | |
19 static const char **weight_to_subfamilies[] = { | |
20 NULL, | |
21 thin, | |
22 extra_light, | |
23 light, | |
24 regular, | |
25 medium, | |
26 semi_bold, | |
27 bold, | |
28 extra_bold, | |
29 heavy | |
30 }; | |
31 | |
8 NONCLIENTMETRICSA metrics = { | 32 NONCLIENTMETRICSA metrics = { |
9 .cbSize = sizeof(metrics) | 33 .cbSize = sizeof(metrics) |
10 }; | 34 }; |
11 char *pref_name = NULL; | 35 char *pref_name = NULL, *pref_prefix = NULL; |
36 const char **pref_sub_families; | |
12 if (SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) { | 37 if (SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) { |
13 pref_name = metrics.lfCaptionFont.lfFaceName; | 38 pref_name = metrics.lfMenuFont.lfFaceName; |
39 int32_t weight = metrics.lfMenuFont.lfWeight / 100; | |
40 if (weight < 1 || weight > 9) { | |
41 weight = 4; | |
42 } | |
43 printf("Preferred family: %s, weight: %d\n", pref_name, weight); | |
44 pref_sub_families = weight_to_subfamilies[weight]; | |
14 } | 45 } |
46 if (pref_name) { | |
47 uint32_t prefix_len = 0; | |
48 while (pref_name[prefix_len] && pref_name[prefix_len] != ' ') | |
49 { | |
50 prefix_len++; | |
51 } | |
52 pref_prefix = malloc(prefix_len + 1); | |
53 memcpy(pref_prefix, pref_name, prefix_len); | |
54 pref_prefix[prefix_len] = 0; | |
55 } | |
56 sfnt_table *selected = NULL; | |
15 char windows[MAX_PATH]; | 57 char windows[MAX_PATH]; |
16 SHGetFolderPathA(NULL, CSIDL_WINDOWS, NULL, 0, windows); | 58 SHGetFolderPathA(NULL, CSIDL_WINDOWS, NULL, 0, windows); |
17 char *fonts = path_append(windows, "Fonts"); | 59 char *fonts = path_append(windows, "Fonts"); |
18 size_t num_entries; | 60 size_t num_entries; |
19 char *preferred = NULL, *tahoma = NULL, *arial = NULL; | 61 char *tahoma = NULL, *arial = NULL; |
20 dir_entry *entries = get_dir_list(fonts, &num_entries); | 62 dir_entry *entries = get_dir_list(fonts, &num_entries); |
63 char *path = NULL; | |
21 for (size_t i = 0; i < num_entries; i++) | 64 for (size_t i = 0; i < num_entries; i++) |
22 { | 65 { |
23 if (entries[i].is_dir) { | 66 if (entries[i].is_dir) { |
24 continue; | 67 continue; |
25 } | 68 } |
26 char *ext = path_extension(entries[i].name); | 69 char *ext = path_extension(entries[i].name); |
27 if (!ext || strcasecmp(ext, "ttf")) { | 70 if (!ext || (strcasecmp(ext, "ttf") && strcasecmp(ext, "ttc") && strcasecmp(ext, "dfont"))) { |
28 //not a truetype font, ignore | 71 //not a truetype font, ignore |
29 free(ext); | 72 free(ext); |
30 continue; | 73 continue; |
31 } | 74 } |
32 free(ext); | 75 free(ext); |
33 char *base = basename_no_extension(entries[i].name); | 76 char *base = basename_no_extension(entries[i].name); |
34 if (!strcasecmp(base, pref_name)) { | 77 printf("basename: %s\n", base); |
35 preferred = entries[i].name; | 78 if (pref_prefix && !strncasecmp(base, pref_prefix, 6)) { |
79 path = path_append(fonts, entries[i].name); | |
80 FILE *f = fopen(path, "rb"); | |
81 if (f) | |
82 { | |
83 long font_size = file_size(f); | |
84 uint8_t *blob = malloc(font_size); | |
85 if (font_size == fread(blob, 1, font_size, f)) | |
86 { | |
87 sfnt_container *sfnt = load_sfnt(blob, font_size); | |
88 if (sfnt) { | |
89 selected = sfnt_subfamily_by_names(sfnt, pref_sub_families); | |
90 if (!selected) { | |
91 sfnt_free(sfnt); | |
92 } | |
93 } else { | |
94 free(blob); | |
95 } | |
96 } | |
97 fclose(f); | |
98 } | |
99 free(path); | |
36 free(base); | 100 free(base); |
37 break; | 101 if (selected) { |
102 printf("Found preferred font in %s\n", entries[i].name); | |
103 break; | |
104 } | |
38 } else if (!strcasecmp(base, "tahoma")) { | 105 } else if (!strcasecmp(base, "tahoma")) { |
39 tahoma = entries[i].name; | 106 tahoma = entries[i].name; |
40 } else if (!strcasecmp(base, "arial")) { | 107 } else if (!strcasecmp(base, "arial")) { |
41 arial = entries[i].name; | 108 arial = entries[i].name; |
42 } | 109 } |
43 free(base); | 110 free(base); |
44 } | 111 } |
45 char *path = NULL; | 112 if (!selected) { |
46 if (preferred) { | 113 path = NULL; |
47 path = path_append(fonts, preferred); | 114 if (tahoma) { |
48 } else if(tahoma) { | 115 path = path_append(fonts, tahoma); |
49 path = path_append(fonts, tahoma); | 116 } else if (arial) { |
50 } else if(arial) { | 117 path = path_append(fonts, arial); |
51 path = path_append(fonts, arial); | 118 } |
119 if (path) { | |
120 FILE *f = fopen(path, "rb"); | |
121 if (f) | |
122 { | |
123 long font_size = file_size(f); | |
124 uint8_t *blob = malloc(font_size); | |
125 if (font_size == fread(blob, 1, font_size, f)) | |
126 { | |
127 sfnt_container *sfnt = load_sfnt(blob, font_size); | |
128 if (sfnt) { | |
129 selected = sfnt->tables; | |
130 } else { | |
131 free(blob); | |
132 } | |
133 } | |
134 fclose(f); | |
135 } | |
136 free(path); | |
137 } | |
52 } | 138 } |
53 free(fonts); | 139 free(fonts); |
54 free_dir_list(entries, num_entries); | 140 free_dir_list(entries, num_entries); |
55 return path; | 141 if (selected) { |
142 return sfnt_flatten(selected, size_out); | |
143 } | |
144 return NULL; | |
56 } | 145 } |