comparison nuklear_ui/font_win.c @ 1692:5dacaef602a7 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Jan 2019 00:58:08 -0800
parents 137dbd05ceab
children
comparison
equal deleted inserted replaced
1504:95b3a1a8b26c 1692:5dacaef602a7
1 #include <windows.h>
2 #include <shlobj.h>
3 #include <string.h>
4 #include "../paths.h"
5 #include "../util.h"
6 #include "sfnt.h"
7
8 uint8_t *default_font(uint32_t *size_out)
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
32 NONCLIENTMETRICSA metrics = {
33 .cbSize = sizeof(metrics)
34 };
35 char *pref_name = NULL, *pref_prefix = NULL;
36 const char **pref_sub_families;
37 if (SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) {
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 pref_sub_families = weight_to_subfamilies[weight];
44 }
45 if (pref_name) {
46 uint32_t prefix_len = 0;
47 while (pref_name[prefix_len] && pref_name[prefix_len] != ' ')
48 {
49 prefix_len++;
50 }
51 pref_prefix = malloc(prefix_len + 1);
52 memcpy(pref_prefix, pref_name, prefix_len);
53 pref_prefix[prefix_len] = 0;
54 }
55 sfnt_table *selected = NULL;
56 char windows[MAX_PATH];
57 SHGetFolderPathA(NULL, CSIDL_WINDOWS, NULL, 0, windows);
58 char *fonts = path_append(windows, "Fonts");
59 size_t num_entries;
60 char *tahoma = NULL, *arial = NULL;
61 dir_entry *entries = get_dir_list(fonts, &num_entries);
62 char *path = NULL;
63 for (size_t i = 0; i < num_entries; i++)
64 {
65 if (entries[i].is_dir) {
66 continue;
67 }
68 char *ext = path_extension(entries[i].name);
69 if (!ext || (strcasecmp(ext, "ttf") && strcasecmp(ext, "ttc") && strcasecmp(ext, "dfont"))) {
70 //not a truetype font, ignore
71 free(ext);
72 continue;
73 }
74 free(ext);
75 char *base = basename_no_extension(entries[i].name);
76 if (pref_prefix && !strncasecmp(base, pref_prefix, 6)) {
77 path = path_append(fonts, entries[i].name);
78 FILE *f = fopen(path, "rb");
79 if (f)
80 {
81 long font_size = file_size(f);
82 uint8_t *blob = malloc(font_size);
83 if (font_size == fread(blob, 1, font_size, f))
84 {
85 sfnt_container *sfnt = load_sfnt(blob, font_size);
86 if (sfnt) {
87 selected = sfnt_subfamily_by_names(sfnt, pref_sub_families);
88 if (!selected) {
89 sfnt_free(sfnt);
90 }
91 } else {
92 free(blob);
93 }
94 } else {
95 free(blob);
96 }
97 fclose(f);
98 }
99 free(path);
100 free(base);
101 if (selected) {
102 printf("Found preferred font in %s\n", entries[i].name);
103 break;
104 }
105 } else if (!strcasecmp(base, "tahoma")) {
106 tahoma = entries[i].name;
107 } else if (!strcasecmp(base, "arial")) {
108 arial = entries[i].name;
109 }
110 free(base);
111 }
112 if (!selected) {
113 path = NULL;
114 if (tahoma) {
115 path = path_append(fonts, tahoma);
116 } else if (arial) {
117 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 }
138 }
139 free(pref_prefix);
140 free(fonts);
141 free_dir_list(entries, num_entries);
142 if (selected) {
143 return sfnt_flatten(selected, size_out);
144 }
145 return NULL;
146 }