From a956d5e1f82e98097602e289ac8f02374ea3b5e7 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Wed, 7 Feb 2018 00:07:12 -0800 Subject: Fix Windows build, added Windows default_font_path implementation --HG-- branch : nuklear_ui --- nuklear_ui/font_win.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 nuklear_ui/font_win.c (limited to 'nuklear_ui/font_win.c') diff --git a/nuklear_ui/font_win.c b/nuklear_ui/font_win.c new file mode 100644 index 0000000..c95fcb3 --- /dev/null +++ b/nuklear_ui/font_win.c @@ -0,0 +1,56 @@ +#include +#include +#include "../paths.h" +#include "../util.h" + +char *default_font_path(void) +{ + NONCLIENTMETRICSA metrics = { + .cbSize = sizeof(metrics) + }; + char *pref_name = NULL; + if (SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) { + pref_name = metrics.lfCaptionFont.lfFaceName; + } + char windows[MAX_PATH]; + SHGetFolderPathA(NULL, CSIDL_WINDOWS, NULL, 0, windows); + char *fonts = path_append(windows, "Fonts"); + size_t num_entries; + char *preferred = NULL, *tahoma = NULL, *arial = NULL; + dir_entry *entries = get_dir_list(fonts, &num_entries); + for (size_t i = 0; i < num_entries; i++) + { + if (entries[i].is_dir) { + continue; + } + char *ext = path_extension(entries[i].name); + if (!ext || strcasecmp(ext, "ttf")) { + //not a truetype font, ignore + free(ext); + continue; + } + free(ext); + char *base = basename_no_extension(entries[i].name); + if (!strcasecmp(base, pref_name)) { + preferred = entries[i].name; + free(base); + break; + } else if (!strcasecmp(base, "tahoma")) { + tahoma = entries[i].name; + } else if (!strcasecmp(base, "arial")) { + arial = entries[i].name; + } + free(base); + } + char *path = NULL; + if (preferred) { + path = path_append(fonts, preferred); + } else if(tahoma) { + path = path_append(fonts, tahoma); + } else if(arial) { + path = path_append(fonts, arial); + } + free(fonts); + free_dir_list(entries, num_entries); + return path; +} -- cgit v1.2.3 From d738c30dec8a7c9f351094851c00a4623f339084 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Tue, 6 Mar 2018 21:27:12 -0800 Subject: Added support for TTC and dfont format true type fonts. More robust font selection on Windows --HG-- branch : nuklear_ui --- nuklear_ui/font_win.c | 121 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 16 deletions(-) (limited to 'nuklear_ui/font_win.c') diff --git a/nuklear_ui/font_win.c b/nuklear_ui/font_win.c index c95fcb3..cc7efe3 100644 --- a/nuklear_ui/font_win.c +++ b/nuklear_ui/font_win.c @@ -1,40 +1,107 @@ #include #include +#include #include "../paths.h" #include "../util.h" +#include "sfnt.h" -char *default_font_path(void) +uint8_t *default_font(uint32_t *size_out) { + static const char *thin[] = {"Thin", NULL}; + static const char *extra_light[] = {"ExtraLight", "UltraLight", NULL}; + static const char *light[] = {"Light", NULL}; + static const char *regular[] = {"Regular", "Normal", "Book", NULL}; + static const char *medium[] = {"Medium", NULL}; + static const char *semi_bold[] = {"SemiBold", "DemiBold", NULL}; + static const char *bold[] = {"Bold", NULL}; + static const char *extra_bold[] = {"ExtraBold", "UltraBold", NULL}; + static const char *heavy[] = {"Heavy", "Black", NULL}; + static const char **weight_to_subfamilies[] = { + NULL, + thin, + extra_light, + light, + regular, + medium, + semi_bold, + bold, + extra_bold, + heavy + }; + NONCLIENTMETRICSA metrics = { .cbSize = sizeof(metrics) }; - char *pref_name = NULL; + char *pref_name = NULL, *pref_prefix = NULL; + const char **pref_sub_families; if (SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0)) { - pref_name = metrics.lfCaptionFont.lfFaceName; + pref_name = metrics.lfMenuFont.lfFaceName; + int32_t weight = metrics.lfMenuFont.lfWeight / 100; + if (weight < 1 || weight > 9) { + weight = 4; + } + printf("Preferred family: %s, weight: %d\n", pref_name, weight); + pref_sub_families = weight_to_subfamilies[weight]; + } + if (pref_name) { + uint32_t prefix_len = 0; + while (pref_name[prefix_len] && pref_name[prefix_len] != ' ') + { + prefix_len++; + } + pref_prefix = malloc(prefix_len + 1); + memcpy(pref_prefix, pref_name, prefix_len); + pref_prefix[prefix_len] = 0; } + sfnt_table *selected = NULL; char windows[MAX_PATH]; SHGetFolderPathA(NULL, CSIDL_WINDOWS, NULL, 0, windows); char *fonts = path_append(windows, "Fonts"); size_t num_entries; - char *preferred = NULL, *tahoma = NULL, *arial = NULL; + char *tahoma = NULL, *arial = NULL; dir_entry *entries = get_dir_list(fonts, &num_entries); + char *path = NULL; for (size_t i = 0; i < num_entries; i++) { if (entries[i].is_dir) { continue; } char *ext = path_extension(entries[i].name); - if (!ext || strcasecmp(ext, "ttf")) { + if (!ext || (strcasecmp(ext, "ttf") && strcasecmp(ext, "ttc") && strcasecmp(ext, "dfont"))) { //not a truetype font, ignore free(ext); continue; } free(ext); char *base = basename_no_extension(entries[i].name); - if (!strcasecmp(base, pref_name)) { - preferred = entries[i].name; + printf("basename: %s\n", base); + if (pref_prefix && !strncasecmp(base, pref_prefix, 6)) { + path = path_append(fonts, entries[i].name); + FILE *f = fopen(path, "rb"); + if (f) + { + long font_size = file_size(f); + uint8_t *blob = malloc(font_size); + if (font_size == fread(blob, 1, font_size, f)) + { + sfnt_container *sfnt = load_sfnt(blob, font_size); + if (sfnt) { + selected = sfnt_subfamily_by_names(sfnt, pref_sub_families); + if (!selected) { + sfnt_free(sfnt); + } + } else { + free(blob); + } + } + fclose(f); + } + free(path); free(base); - break; + if (selected) { + printf("Found preferred font in %s\n", entries[i].name); + break; + } } else if (!strcasecmp(base, "tahoma")) { tahoma = entries[i].name; } else if (!strcasecmp(base, "arial")) { @@ -42,15 +109,37 @@ char *default_font_path(void) } free(base); } - char *path = NULL; - if (preferred) { - path = path_append(fonts, preferred); - } else if(tahoma) { - path = path_append(fonts, tahoma); - } else if(arial) { - path = path_append(fonts, arial); + if (!selected) { + path = NULL; + if (tahoma) { + path = path_append(fonts, tahoma); + } else if (arial) { + path = path_append(fonts, arial); + } + if (path) { + FILE *f = fopen(path, "rb"); + if (f) + { + long font_size = file_size(f); + uint8_t *blob = malloc(font_size); + if (font_size == fread(blob, 1, font_size, f)) + { + sfnt_container *sfnt = load_sfnt(blob, font_size); + if (sfnt) { + selected = sfnt->tables; + } else { + free(blob); + } + } + fclose(f); + } + free(path); + } } free(fonts); free_dir_list(entries, num_entries); - return path; + if (selected) { + return sfnt_flatten(selected, size_out); + } + return NULL; } -- cgit v1.2.3 From 6f3353890e160718d38fb8b433746af7fdf60d52 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 25 Mar 2018 10:29:40 -0700 Subject: Fix memory leak in edge case of font_win --HG-- branch : nuklear_ui --- nuklear_ui/font_win.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nuklear_ui/font_win.c') diff --git a/nuklear_ui/font_win.c b/nuklear_ui/font_win.c index cc7efe3..1235d9e 100644 --- a/nuklear_ui/font_win.c +++ b/nuklear_ui/font_win.c @@ -93,6 +93,8 @@ uint8_t *default_font(uint32_t *size_out) } else { free(blob); } + } else { + free(blob); } fclose(f); } -- cgit v1.2.3