diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-05-25 18:25:40 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-05-25 18:25:51 +0300 |
commit | f53e6d34fbb8d2f2fb54aff8b746b1c5d06fe497 (patch) | |
tree | c8cbe09db582b66262dd6472bd55be7b485fdf66 /src | |
parent | 54d38100bb49a34f9ad11570e0144dc1ec006858 (diff) |
Removed Symbola, replaced with other/new fonts
Symbola's license is not permissive enough, so it has been removed. Added "Smol Emoji" with face emoticons and other UI characters for Lagrange. More symbols provided by Noto Sans Symbols and Noto Sans Symbols 2.
The fallback fonts are now Iosevka, which has a pretty good coverage (although monospace), and the user's chosen TrueType font (which could still be a local copy of Symbola).
Still a work in progress: some characters are missing.
IssueID #283
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 37 | ||||
-rw-r--r-- | src/defs.h | 2 | ||||
-rw-r--r-- | src/gmrequest.c | 4 | ||||
-rw-r--r-- | src/prefs.c | 5 | ||||
-rw-r--r-- | src/prefs.h | 1 | ||||
-rw-r--r-- | src/ui/inputwidget.h | 5 | ||||
-rw-r--r-- | src/ui/keys.c | 8 | ||||
-rw-r--r-- | src/ui/root.c | 8 | ||||
-rw-r--r-- | src/ui/text.c | 127 | ||||
-rw-r--r-- | src/ui/text.h | 16 | ||||
-rw-r--r-- | src/ui/util.c | 2 |
11 files changed, 147 insertions, 68 deletions
@@ -204,6 +204,7 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
204 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); | 204 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); |
205 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); | 205 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); |
206 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); | 206 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); |
207 | appendFormat_String(str, "font.user path:%s\n", cstr_String(&d->prefs.symbolFontPath)); | ||
207 | appendFormat_String(str, "headingfont.set arg:%d\n", d->prefs.headingFont); | 208 | appendFormat_String(str, "headingfont.set arg:%d\n", d->prefs.headingFont); |
208 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); | 209 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); |
209 | appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); | 210 | appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); |
@@ -1555,24 +1556,25 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1555 | isSelected_Widget(findChild_Widget(d, "prefs.imageloadscroll"))); | 1556 | isSelected_Widget(findChild_Widget(d, "prefs.imageloadscroll"))); |
1556 | postCommandf_App("hidetoolbarscroll arg:%d", | 1557 | postCommandf_App("hidetoolbarscroll arg:%d", |
1557 | isSelected_Widget(findChild_Widget(d, "prefs.hidetoolbarscroll"))); | 1558 | isSelected_Widget(findChild_Widget(d, "prefs.hidetoolbarscroll"))); |
1558 | postCommandf_App("ostheme arg:%d", | 1559 | postCommandf_App("ostheme arg:%d", isSelected_Widget(findChild_Widget(d, "prefs.ostheme"))); |
1559 | isSelected_Widget(findChild_Widget(d, "prefs.ostheme"))); | 1560 | postCommandf_App("font.user path:%s", |
1561 | cstrText_InputWidget(findChild_Widget(d, "prefs.userfont"))); | ||
1560 | postCommandf_App("decodeurls arg:%d", | 1562 | postCommandf_App("decodeurls arg:%d", |
1561 | isSelected_Widget(findChild_Widget(d, "prefs.decodeurls"))); | 1563 | isSelected_Widget(findChild_Widget(d, "prefs.decodeurls"))); |
1562 | postCommandf_App("searchurl address:%s", | 1564 | postCommandf_App("searchurl address:%s", |
1563 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.searchurl")))); | 1565 | cstrText_InputWidget(findChild_Widget(d, "prefs.searchurl"))); |
1564 | postCommandf_App("cachesize.set arg:%d", | 1566 | postCommandf_App("cachesize.set arg:%d", |
1565 | toInt_String(text_InputWidget(findChild_Widget(d, "prefs.cachesize")))); | 1567 | toInt_String(text_InputWidget(findChild_Widget(d, "prefs.cachesize")))); |
1566 | postCommandf_App("ca.file path:%s", | 1568 | postCommandf_App("ca.file path:%s", |
1567 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.ca.file")))); | 1569 | cstrText_InputWidget(findChild_Widget(d, "prefs.ca.file"))); |
1568 | postCommandf_App("ca.path path:%s", | 1570 | postCommandf_App("ca.path path:%s", |
1569 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.ca.path")))); | 1571 | cstrText_InputWidget(findChild_Widget(d, "prefs.ca.path"))); |
1570 | postCommandf_App("proxy.gemini address:%s", | 1572 | postCommandf_App("proxy.gemini address:%s", |
1571 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.proxy.gemini")))); | 1573 | cstrText_InputWidget(findChild_Widget(d, "prefs.proxy.gemini"))); |
1572 | postCommandf_App("proxy.gopher address:%s", | 1574 | postCommandf_App("proxy.gopher address:%s", |
1573 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.proxy.gopher")))); | 1575 | cstrText_InputWidget(findChild_Widget(d, "prefs.proxy.gopher"))); |
1574 | postCommandf_App("proxy.http address:%s", | 1576 | postCommandf_App("proxy.http address:%s", |
1575 | cstr_String(text_InputWidget(findChild_Widget(d, "prefs.proxy.http")))); | 1577 | cstrText_InputWidget(findChild_Widget(d, "prefs.proxy.http"))); |
1576 | const iWidget *tabs = findChild_Widget(d, "prefs.tabs"); | 1578 | const iWidget *tabs = findChild_Widget(d, "prefs.tabs"); |
1577 | if (tabs) { | 1579 | if (tabs) { |
1578 | postCommandf_App("prefs.dialogtab arg:%u", | 1580 | postCommandf_App("prefs.dialogtab arg:%u", |
@@ -1892,6 +1894,22 @@ iBool handleCommand_App(const char *cmd) { | |||
1892 | resetFonts_Text(); | 1894 | resetFonts_Text(); |
1893 | return iTrue; | 1895 | return iTrue; |
1894 | } | 1896 | } |
1897 | else if (equal_Command(cmd, "font.user")) { | ||
1898 | const char *path = suffixPtr_Command(cmd, "path"); | ||
1899 | if (cmp_String(&d->prefs.symbolFontPath, path)) { | ||
1900 | if (!isFrozen) { | ||
1901 | setFreezeDraw_Window(get_Window(), iTrue); | ||
1902 | } | ||
1903 | setCStr_String(&d->prefs.symbolFontPath, path); | ||
1904 | loadUserFonts_Text(); | ||
1905 | resetFonts_Text(); | ||
1906 | if (!isFrozen) { | ||
1907 | postCommand_App("font.changed"); | ||
1908 | postCommand_App("window.unfreeze"); | ||
1909 | } | ||
1910 | } | ||
1911 | return iTrue; | ||
1912 | } | ||
1895 | else if (equal_Command(cmd, "font.set")) { | 1913 | else if (equal_Command(cmd, "font.set")) { |
1896 | if (!isFrozen) { | 1914 | if (!isFrozen) { |
1897 | setFreezeDraw_Window(get_Window(), iTrue); | 1915 | setFreezeDraw_Window(get_Window(), iTrue); |
@@ -2332,6 +2350,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2332 | setToggle_Widget(findChild_Widget(dlg, "prefs.archive.openindex"), d->prefs.openArchiveIndexPages); | 2350 | setToggle_Widget(findChild_Widget(dlg, "prefs.archive.openindex"), d->prefs.openArchiveIndexPages); |
2333 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); | 2351 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); |
2334 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); | 2352 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); |
2353 | setText_InputWidget(findChild_Widget(dlg, "prefs.userfont"), &d->prefs.symbolFontPath); | ||
2335 | updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit); | 2354 | updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit); |
2336 | updateDropdownSelection_(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage)); | 2355 | updateDropdownSelection_(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage)); |
2337 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); | 2356 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); |
@@ -62,7 +62,7 @@ enum iFileVersion { | |||
62 | #define home_Icon "\U0001f3e0" | 62 | #define home_Icon "\U0001f3e0" |
63 | #define edit_Icon "\u270e" | 63 | #define edit_Icon "\u270e" |
64 | #define delete_Icon "\u232b" | 64 | #define delete_Icon "\u232b" |
65 | #define copy_Icon "\u2bba" | 65 | #define copy_Icon "\u2398" //"\u2bba" |
66 | #define check_Icon "\u2714" | 66 | #define check_Icon "\u2714" |
67 | #define ballotCheck_Icon "\U0001f5f9" | 67 | #define ballotCheck_Icon "\U0001f5f9" |
68 | #define inbox_Icon "\U0001f4e5" | 68 | #define inbox_Icon "\U0001f4e5" |
diff --git a/src/gmrequest.c b/src/gmrequest.c index 3dd92eec..1325c025 100644 --- a/src/gmrequest.c +++ b/src/gmrequest.c | |||
@@ -346,6 +346,7 @@ static const iBlock *replaceVariables_(const iBlock *block) { | |||
346 | if (equal_Rangecc(name, "APP_VERSION")) { | 346 | if (equal_Rangecc(name, "APP_VERSION")) { |
347 | repl = range_CStr(LAGRANGE_APP_VERSION); | 347 | repl = range_CStr(LAGRANGE_APP_VERSION); |
348 | } | 348 | } |
349 | #if 0 | ||
349 | else if (startsWith_Rangecc(name, "BT:")) { /* block text */ | 350 | else if (startsWith_Rangecc(name, "BT:")) { /* block text */ |
350 | repl = range_String(collect_String(renderBlockChars_Text( | 351 | repl = range_String(collect_String(renderBlockChars_Text( |
351 | &fontFiraSansRegular_Embedded, | 352 | &fontFiraSansRegular_Embedded, |
@@ -356,12 +357,13 @@ static const iBlock *replaceVariables_(const iBlock *block) { | |||
356 | } | 357 | } |
357 | else if (startsWith_Rangecc(name, "ST:")) { /* shaded text */ | 358 | else if (startsWith_Rangecc(name, "ST:")) { /* shaded text */ |
358 | repl = range_String(collect_String(renderBlockChars_Text( | 359 | repl = range_String(collect_String(renderBlockChars_Text( |
359 | &fontSymbola_Embedded, | 360 | &fontSmolEmojiRegular_Embedded, |
360 | 20, | 361 | 20, |
361 | shading_TextBlockMode, | 362 | shading_TextBlockMode, |
362 | &(iString){ iBlockLiteral( | 363 | &(iString){ iBlockLiteral( |
363 | name.start + 3, size_Range(&name) - 3, size_Range(&name) - 3) }))); | 364 | name.start + 3, size_Range(&name) - 3, size_Range(&name) - 3) }))); |
364 | } | 365 | } |
366 | #endif | ||
365 | else if (equal_Rangecc(name, "ALT")) { | 367 | else if (equal_Rangecc(name, "ALT")) { |
366 | #if defined (iPlatformApple) | 368 | #if defined (iPlatformApple) |
367 | repl = range_CStr("\u2325"); | 369 | repl = range_CStr("\u2325"); |
diff --git a/src/prefs.c b/src/prefs.c index 96fa3c59..b29b33b5 100644 --- a/src/prefs.c +++ b/src/prefs.c | |||
@@ -68,6 +68,7 @@ void init_Prefs(iPrefs *d) { | |||
68 | init_String(&d->httpProxy); | 68 | init_String(&d->httpProxy); |
69 | init_String(&d->downloadDir); | 69 | init_String(&d->downloadDir); |
70 | init_String(&d->searchUrl); | 70 | init_String(&d->searchUrl); |
71 | init_String(&d->symbolFontPath); | ||
71 | /* TODO: Add some platform-specific common locations? */ | 72 | /* TODO: Add some platform-specific common locations? */ |
72 | if (fileExistsCStr_FileInfo("/etc/ssl/cert.pem")) { /* macOS */ | 73 | if (fileExistsCStr_FileInfo("/etc/ssl/cert.pem")) { /* macOS */ |
73 | setCStr_String(&d->caFile, "/etc/ssl/cert.pem"); | 74 | setCStr_String(&d->caFile, "/etc/ssl/cert.pem"); |
@@ -75,9 +76,13 @@ void init_Prefs(iPrefs *d) { | |||
75 | if (fileExistsCStr_FileInfo("/etc/ssl/certs")) { | 76 | if (fileExistsCStr_FileInfo("/etc/ssl/certs")) { |
76 | setCStr_String(&d->caPath, "/etc/ssl/certs"); | 77 | setCStr_String(&d->caPath, "/etc/ssl/certs"); |
77 | } | 78 | } |
79 | #if defined (iPlatformAppleDesktop) | ||
80 | setCStr_String(&d->symbolFontPath, "/System/Library/Fonts/Apple Symbols.ttf"); | ||
81 | #endif | ||
78 | } | 82 | } |
79 | 83 | ||
80 | void deinit_Prefs(iPrefs *d) { | 84 | void deinit_Prefs(iPrefs *d) { |
85 | deinit_String(&d->symbolFontPath); | ||
81 | deinit_String(&d->searchUrl); | 86 | deinit_String(&d->searchUrl); |
82 | deinit_String(&d->geminiProxy); | 87 | deinit_String(&d->geminiProxy); |
83 | deinit_String(&d->gopherProxy); | 88 | deinit_String(&d->gopherProxy); |
diff --git a/src/prefs.h b/src/prefs.h index 5c01ebda..7185c8f9 100644 --- a/src/prefs.h +++ b/src/prefs.h | |||
@@ -70,6 +70,7 @@ struct Impl_Prefs { | |||
70 | iString gopherProxy; | 70 | iString gopherProxy; |
71 | iString httpProxy; | 71 | iString httpProxy; |
72 | /* Style */ | 72 | /* Style */ |
73 | iString symbolFontPath; | ||
73 | enum iTextFont font; | 74 | enum iTextFont font; |
74 | enum iTextFont headingFont; | 75 | enum iTextFont headingFont; |
75 | iBool monospaceGemini; | 76 | iBool monospaceGemini; |
diff --git a/src/ui/inputwidget.h b/src/ui/inputwidget.h index cb32a29c..5c39aae0 100644 --- a/src/ui/inputwidget.h +++ b/src/ui/inputwidget.h | |||
@@ -63,6 +63,11 @@ void setNotifyEdits_InputWidget (iInputWidget *, iBool notifyEdits); | |||
63 | void setEatEscape_InputWidget (iInputWidget *, iBool eatEscape); | 63 | void setEatEscape_InputWidget (iInputWidget *, iBool eatEscape); |
64 | 64 | ||
65 | const iString * text_InputWidget (const iInputWidget *); | 65 | const iString * text_InputWidget (const iInputWidget *); |
66 | |||
67 | iLocalDef const char *cstrText_InputWidget(const iInputWidget *d) { | ||
68 | return cstr_String(text_InputWidget(d)); | ||
69 | } | ||
70 | |||
66 | iInputWidgetContentPadding | 71 | iInputWidgetContentPadding |
67 | contentPadding_InputWidget (const iInputWidget *); | 72 | contentPadding_InputWidget (const iInputWidget *); |
68 | 73 | ||
diff --git a/src/ui/keys.c b/src/ui/keys.c index 87a5fb88..17cc0e72 100644 --- a/src/ui/keys.c +++ b/src/ui/keys.c | |||
@@ -311,7 +311,10 @@ static iBinding *findCommand_Keys_(iKeys *d, const char *command) { | |||
311 | static void updateLookup_Keys_(iKeys *d) { | 311 | static void updateLookup_Keys_(iKeys *d) { |
312 | clear_PtrSet(&d->lookup); | 312 | clear_PtrSet(&d->lookup); |
313 | iConstForEach(Array, i, &d->bindings) { | 313 | iConstForEach(Array, i, &d->bindings) { |
314 | insert_PtrSet(&d->lookup, i.value); | 314 | const iBinding *bind = i.value; |
315 | if (~bind->flags & noDirectTrigger_BindFlag) { | ||
316 | insert_PtrSet(&d->lookup, i.value); | ||
317 | } | ||
315 | } | 318 | } |
316 | } | 319 | } |
317 | 320 | ||
@@ -442,9 +445,6 @@ iBool processEvent_Keys(const SDL_Event *ev) { | |||
442 | if (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) { | 445 | if (ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) { |
443 | const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod)); | 446 | const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod)); |
444 | if (bind) { | 447 | if (bind) { |
445 | if (bind->flags & noDirectTrigger_BindFlag) { | ||
446 | return iFalse; | ||
447 | } | ||
448 | if (ev->type == SDL_KEYUP) { | 448 | if (ev->type == SDL_KEYUP) { |
449 | if (bind->flags & argRelease_BindFlag) { | 449 | if (bind->flags & argRelease_BindFlag) { |
450 | postCommandf_Root(root, "%s release:1", cstr_String(&bind->command)); | 450 | postCommandf_Root(root, "%s release:1", cstr_String(&bind->command)); |
diff --git a/src/ui/root.c b/src/ui/root.c index 7a409a75..49925856 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -156,10 +156,10 @@ static const char *pageMenuCStr_ = midEllipsis_Icon; | |||
156 | /* TODO: A preference for these, maybe? */ | 156 | /* TODO: A preference for these, maybe? */ |
157 | static const char *stopSeqCStr_[] = { | 157 | static const char *stopSeqCStr_[] = { |
158 | /* Corners */ | 158 | /* Corners */ |
159 | uiTextCaution_ColorEscape "\U0000230c", | 159 | uiTextCaution_ColorEscape "\U0000231c", |
160 | uiTextCaution_ColorEscape "\U0000230d", | 160 | uiTextCaution_ColorEscape "\U0000231d", |
161 | uiTextCaution_ColorEscape "\U0000230f", | 161 | uiTextCaution_ColorEscape "\U0000231f", |
162 | uiTextCaution_ColorEscape "\U0000230e", | 162 | uiTextCaution_ColorEscape "\U0000231e", |
163 | #if 0 | 163 | #if 0 |
164 | /* Rotating arrow */ | 164 | /* Rotating arrow */ |
165 | uiTextCaution_ColorEscape "\U00002b62", | 165 | uiTextCaution_ColorEscape "\U00002b62", |
diff --git a/src/ui/text.c b/src/ui/text.c index b0c4f557..0e6a6d32 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
32 | 32 | ||
33 | #include <the_Foundation/array.h> | 33 | #include <the_Foundation/array.h> |
34 | #include <the_Foundation/file.h> | 34 | #include <the_Foundation/file.h> |
35 | #include <the_Foundation/fileinfo.h> | ||
35 | #include <the_Foundation/hash.h> | 36 | #include <the_Foundation/hash.h> |
36 | #include <the_Foundation/math.h> | 37 | #include <the_Foundation/math.h> |
37 | #include <the_Foundation/stringlist.h> | 38 | #include <the_Foundation/stringlist.h> |
@@ -124,10 +125,6 @@ struct Impl_Font { | |||
124 | iBool isMonospaced; | 125 | iBool isMonospaced; |
125 | iBool manualKernOnly; | 126 | iBool manualKernOnly; |
126 | enum iFontSize sizeId; /* used to look up different fonts of matching size */ | 127 | enum iFontSize sizeId; /* used to look up different fonts of matching size */ |
127 | // enum iFontId | ||
128 | // enum iFontId japaneseFont; /* font to use for Japanese glyphs */ | ||
129 | // enum iFontId chineseFont; /* font to use for Simplified Chinese glyphs */ | ||
130 | // enum iFontId koreanFont; /* font to use for Korean glyphs */ | ||
131 | uint32_t indexTable[128 - 32]; /* quick ASCII lookup */ | 128 | uint32_t indexTable[128 - 32]; /* quick ASCII lookup */ |
132 | }; | 129 | }; |
133 | 130 | ||
@@ -155,13 +152,12 @@ static void init_Font(iFont *d, const iBlock *data, int height, float scale, | |||
155 | d->xScale *= floorf(advance) / advance; | 152 | d->xScale *= floorf(advance) / advance; |
156 | } | 153 | } |
157 | } | 154 | } |
158 | d->vertOffset = height * (1.0f - scale) / 2; | 155 | d->baseline = ascent * d->yScale; |
159 | d->baseline = ascent * d->yScale; | 156 | d->vertOffset = height * (1.0f - scale) / 2; |
160 | d->sizeId = sizeId; | 157 | if (scale > 1.0f) { |
161 | // d->symbolsFont = symbolsFont; | 158 | d->vertOffset /= 2; /* Tweak for Noto Sans Symbols */ |
162 | // d->japaneseFont = regularJapanese_FontId; | 159 | } |
163 | // d->chineseFont = regularChinese_FontId; | 160 | d->sizeId = sizeId; |
164 | // d->koreanFont = regularKorean_FontId; | ||
165 | memset(d->indexTable, 0xff, sizeof(d->indexTable)); | 161 | memset(d->indexTable, 0xff, sizeof(d->indexTable)); |
166 | } | 162 | } |
167 | 163 | ||
@@ -215,7 +211,8 @@ struct Impl_Text { | |||
215 | iRegExp * ansiEscape; | 211 | iRegExp * ansiEscape; |
216 | }; | 212 | }; |
217 | 213 | ||
218 | static iText text_; | 214 | static iText text_; |
215 | static iBlock *userFont_; | ||
219 | 216 | ||
220 | static void initFonts_Text_(iText *d) { | 217 | static void initFonts_Text_(iText *d) { |
221 | const float textSize = fontSize_UI * d->contentFontSize; | 218 | const float textSize = fontSize_UI * d->contentFontSize; |
@@ -321,27 +318,31 @@ static void initFonts_Text_(iText *d) { | |||
321 | { &fontIosevkaTermExtended_Embedded, smallMonoSize, 1.0f, contentMonoSmall_FontSize }, | 318 | { &fontIosevkaTermExtended_Embedded, smallMonoSize, 1.0f, contentMonoSmall_FontSize }, |
322 | { &fontIosevkaTermExtended_Embedded, monoSize, 1.0f, contentMono_FontSize }, | 319 | { &fontIosevkaTermExtended_Embedded, monoSize, 1.0f, contentMono_FontSize }, |
323 | /* extra content fonts */ | 320 | /* extra content fonts */ |
324 | { &fontSourceSans3Regular_Embedded, textSize, scaling, contentRegular_FontSize }, | 321 | { &fontSourceSans3Regular_Embedded, textSize, scaling, contentRegular_FontSize }, |
325 | { &fontIosevkaTermExtended_Embedded, textSize, 0.866f, contentRegular_FontSize }, | 322 | // { &fontIosevkaTermExtended_Embedded, textSize, 0.866f, contentRegular_FontSize }, |
326 | /* symbols and scripts */ | 323 | /* symbols and scripts */ |
327 | #define DEFINE_FONT_SET(data) \ | 324 | #define DEFINE_FONT_SET(data, glyphScale) \ |
328 | { &data, uiSize, 1.0f, uiNormal_FontSize }, \ | 325 | { (data), uiSize, glyphScale, uiNormal_FontSize }, \ |
329 | { &data, uiSize * 1.125f, 1.0f, uiMedium_FontSize }, \ | 326 | { (data), uiSize * 1.125f, glyphScale, uiMedium_FontSize }, \ |
330 | { &data, uiSize * 1.333f, 1.0f, uiBig_FontSize }, \ | 327 | { (data), uiSize * 1.333f, glyphScale, uiBig_FontSize }, \ |
331 | { &data, uiSize * 1.666f, 1.0f, uiLarge_FontSize }, \ | 328 | { (data), uiSize * 1.666f, glyphScale, uiLarge_FontSize }, \ |
332 | { &data, textSize, 1.0f, contentRegular_FontSize }, \ | 329 | { (data), textSize, glyphScale, contentRegular_FontSize }, \ |
333 | { &data, textSize * 1.200f, 1.0f, contentMedium_FontSize }, \ | 330 | { (data), textSize * 1.200f, glyphScale, contentMedium_FontSize }, \ |
334 | { &data, textSize * 1.333f, 1.0f, contentBig_FontSize }, \ | 331 | { (data), textSize * 1.333f, glyphScale, contentBig_FontSize }, \ |
335 | { &data, textSize * 1.666f, 1.0f, contentLarge_FontSize }, \ | 332 | { (data), textSize * 1.666f, glyphScale, contentLarge_FontSize }, \ |
336 | { &data, textSize * 2.000f, 1.0f, contentHuge_FontSize }, \ | 333 | { (data), textSize * 2.000f, glyphScale, contentHuge_FontSize }, \ |
337 | { &data, smallMonoSize, 1.0f, contentMonoSmall_FontSize }, \ | 334 | { (data), smallMonoSize, glyphScale, contentMonoSmall_FontSize }, \ |
338 | { &data, monoSize, 1.0f, contentMono_FontSize } | 335 | { (data), monoSize, glyphScale, contentMono_FontSize } |
339 | DEFINE_FONT_SET(fontSymbola_Embedded), | 336 | DEFINE_FONT_SET(userFont_ ? userFont_ : &fontIosevkaTermExtended_Embedded, 1.0f), |
340 | DEFINE_FONT_SET(fontNotoEmojiRegular_Embedded), | 337 | DEFINE_FONT_SET(&fontIosevkaTermExtended_Embedded, 0.866f), |
341 | DEFINE_FONT_SET(fontNotoSansJPRegular_Embedded), | 338 | DEFINE_FONT_SET(&fontNotoSansSymbolsRegular_Embedded, 1.45f), |
342 | DEFINE_FONT_SET(fontNotoSansSCRegular_Embedded), | 339 | DEFINE_FONT_SET(&fontNotoSansSymbols2Regular_Embedded, 1.45f), |
343 | DEFINE_FONT_SET(fontNanumGothicRegular_Embedded), /* TODO: should use Noto Sans here, too */ | 340 | DEFINE_FONT_SET(&fontSmolEmojiRegular_Embedded, 1.0f), |
344 | DEFINE_FONT_SET(fontNotoSansArabicUIRegular_Embedded), | 341 | DEFINE_FONT_SET(&fontNotoEmojiRegular_Embedded, 1.0f), |
342 | DEFINE_FONT_SET(&fontNotoSansJPRegular_Embedded, 1.0f), | ||
343 | DEFINE_FONT_SET(&fontNotoSansSCRegular_Embedded, 1.0f), | ||
344 | DEFINE_FONT_SET(&fontNanumGothicRegular_Embedded, 1.0f), /* TODO: should use Noto Sans here, too */ | ||
345 | DEFINE_FONT_SET(&fontNotoSansArabicUIRegular_Embedded, 1.0f), | ||
345 | }; | 346 | }; |
346 | iForIndices(i, fontData) { | 347 | iForIndices(i, fontData) { |
347 | iFont *font = &d->fonts[i]; | 348 | iFont *font = &d->fonts[i]; |
@@ -401,8 +402,28 @@ static void deinitCache_Text_(iText *d) { | |||
401 | SDL_DestroyTexture(d->cache); | 402 | SDL_DestroyTexture(d->cache); |
402 | } | 403 | } |
403 | 404 | ||
405 | void loadUserFonts_Text(void) { | ||
406 | if (userFont_) { | ||
407 | delete_Block(userFont_); | ||
408 | userFont_ = NULL; | ||
409 | } | ||
410 | /* Load the system font. */ | ||
411 | const iPrefs *prefs = prefs_App(); | ||
412 | if (!isEmpty_String(&prefs->symbolFontPath)) { | ||
413 | iFile *f = new_File(&prefs->symbolFontPath); | ||
414 | if (open_File(f, readOnly_FileMode)) { | ||
415 | userFont_ = readAll_File(f); | ||
416 | } | ||
417 | else { | ||
418 | fprintf(stderr, "[Text] failed to open: %s\n", cstr_String(&prefs->symbolFontPath)); | ||
419 | } | ||
420 | iRelease(f); | ||
421 | } | ||
422 | } | ||
423 | |||
404 | void init_Text(SDL_Renderer *render) { | 424 | void init_Text(SDL_Renderer *render) { |
405 | iText *d = &text_; | 425 | iText *d = &text_; |
426 | loadUserFonts_Text(); | ||
406 | d->contentFont = nunito_TextFont; | 427 | d->contentFont = nunito_TextFont; |
407 | d->headingFont = nunito_TextFont; | 428 | d->headingFont = nunito_TextFont; |
408 | d->contentFontSize = contentScale_Text_; | 429 | d->contentFontSize = contentScale_Text_; |
@@ -542,14 +563,27 @@ static void allocate_Font_(iFont *d, iGlyph *glyph, int hoff) { | |||
542 | } | 563 | } |
543 | 564 | ||
544 | iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { | 565 | iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { |
566 | /* Smol Emoji overrides all other fonts. */ | ||
567 | if (ch != 0x20) { | ||
568 | iFont *smol = font_Text_(smolEmoji_FontId + d->sizeId); | ||
569 | if (smol != d && (*glyphIndex = glyphIndex_Font_(smol, ch)) != 0) { | ||
570 | return smol; | ||
571 | } | ||
572 | } | ||
545 | if ((*glyphIndex = glyphIndex_Font_(d, ch)) != 0) { | 573 | if ((*glyphIndex = glyphIndex_Font_(d, ch)) != 0) { |
546 | return d; | 574 | return d; |
547 | } | 575 | } |
548 | /* Not defined in current font, try Noto Emoji (for selected characters). */ | 576 | const int fallbacks[] = { |
549 | if ((ch >= 0x1f300 && ch < 0x1f600) || (ch >= 0x1f680 && ch <= 0x1f6c5)) { | 577 | smolEmoji_FontId, |
550 | iFont *emoji = font_Text_(emoji_FontId + d->sizeId); | 578 | notoEmoji_FontId, |
551 | if (emoji != d && (*glyphIndex = glyphIndex_Font_(emoji, ch)) != 0) { | 579 | symbols2_FontId, |
552 | return emoji; | 580 | symbols_FontId |
581 | }; | ||
582 | /* First fallback is Smol Emoji. */ | ||
583 | iForIndices(i, fallbacks) { | ||
584 | iFont *fallback = font_Text_(fallbacks[i] + d->sizeId); | ||
585 | if (fallback != d && (*glyphIndex = glyphIndex_Font_(fallback, ch)) != 0) { | ||
586 | return fallback; | ||
553 | } | 587 | } |
554 | } | 588 | } |
555 | /* Try Simplified Chinese. */ | 589 | /* Try Simplified Chinese. */ |
@@ -588,13 +622,18 @@ iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { | |||
588 | return d; | 622 | return d; |
589 | } | 623 | } |
590 | #endif | 624 | #endif |
591 | /* Fall back to Symbola for anything else. */ | 625 | /* User's symbols font. */ { |
592 | iFont *font = font_Text_(symbols_FontId + d->sizeId); | 626 | iFont *sys = font_Text_(userSymbols_FontId + d->sizeId); |
593 | *glyphIndex = glyphIndex_Font_(font, ch); | 627 | if (sys != d && (*glyphIndex = glyphIndex_Font_(sys, ch)) != 0) { |
594 | // if (!*glyphIndex) { | 628 | return sys; |
595 | // fprintf(stderr, "failed to find %08x (%lc)\n", ch, ch); fflush(stderr); | 629 | } |
596 | // } | 630 | } |
597 | return font; | 631 | // iFont *font = font_Text_(iosevka_FontId + d->sizeId); |
632 | // *glyphIndex = glyphIndex_Font_(font, ch); | ||
633 | if (!*glyphIndex) { | ||
634 | fprintf(stderr, "failed to find %08x (%lc)\n", ch, (int)ch); fflush(stderr); | ||
635 | } | ||
636 | return d; | ||
598 | } | 637 | } |
599 | 638 | ||
600 | static iGlyph *glyph_Font_(iFont *d, iChar ch) { | 639 | static iGlyph *glyph_Font_(iFont *d, iChar ch) { |
diff --git a/src/ui/text.h b/src/ui/text.h index 044ddd32..1bb60e8b 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -68,11 +68,14 @@ enum iFontId { | |||
68 | monospace_FontId, | 68 | monospace_FontId, |
69 | /* extra content fonts */ | 69 | /* extra content fonts */ |
70 | defaultContentSized_FontId, /* UI font but sized to regular_FontId */ | 70 | defaultContentSized_FontId, /* UI font but sized to regular_FontId */ |
71 | regularMonospace_FontId, | ||
72 | /* symbols and scripts */ | 71 | /* symbols and scripts */ |
73 | symbols_FontId, | 72 | userSymbols_FontId, |
74 | emoji_FontId = symbols_FontId + max_FontSize, | 73 | iosevka_FontId = userSymbols_FontId + max_FontSize, |
75 | japanese_FontId = emoji_FontId + max_FontSize, | 74 | symbols_FontId = iosevka_FontId + max_FontSize, |
75 | symbols2_FontId = symbols_FontId + max_FontSize, | ||
76 | smolEmoji_FontId = symbols2_FontId + max_FontSize, | ||
77 | notoEmoji_FontId = smolEmoji_FontId + max_FontSize, | ||
78 | japanese_FontId = notoEmoji_FontId + max_FontSize, | ||
76 | chineseSimplified_FontId = japanese_FontId + max_FontSize, | 79 | chineseSimplified_FontId = japanese_FontId + max_FontSize, |
77 | korean_FontId = chineseSimplified_FontId + max_FontSize, | 80 | korean_FontId = chineseSimplified_FontId + max_FontSize, |
78 | arabic_FontId = korean_FontId + max_FontSize, | 81 | arabic_FontId = korean_FontId + max_FontSize, |
@@ -91,7 +94,7 @@ enum iFontId { | |||
91 | uiInput_FontId = defaultMedium_FontId, | 94 | uiInput_FontId = defaultMedium_FontId, |
92 | uiContent_FontId = defaultMedium_FontId, | 95 | uiContent_FontId = defaultMedium_FontId, |
93 | uiContentBold_FontId = defaultMediumBold_FontId, | 96 | uiContentBold_FontId = defaultMediumBold_FontId, |
94 | uiContentSymbols_FontId = symbols_FontId + uiMedium_FontSize, | 97 | uiContentSymbols_FontId = symbols_FontId + uiMedium_FontSize, |
95 | /* Document fonts: */ | 98 | /* Document fonts: */ |
96 | paragraph_FontId = regular_FontId, | 99 | paragraph_FontId = regular_FontId, |
97 | firstParagraph_FontId = medium_FontId, | 100 | firstParagraph_FontId = medium_FontId, |
@@ -102,6 +105,7 @@ enum iFontId { | |||
102 | heading2_FontId = largeBold_FontId, | 105 | heading2_FontId = largeBold_FontId, |
103 | heading3_FontId = big_FontId, | 106 | heading3_FontId = big_FontId, |
104 | banner_FontId = largeLight_FontId, | 107 | banner_FontId = largeLight_FontId, |
108 | regularMonospace_FontId = iosevka_FontId + contentRegular_FontSize | ||
105 | }; | 109 | }; |
106 | 110 | ||
107 | iLocalDef iBool isJapanese_FontId(enum iFontId id) { | 111 | iLocalDef iBool isJapanese_FontId(enum iFontId id) { |
@@ -124,6 +128,8 @@ extern int gap_Text; /* affected by content font size */ | |||
124 | void init_Text (SDL_Renderer *); | 128 | void init_Text (SDL_Renderer *); |
125 | void deinit_Text (void); | 129 | void deinit_Text (void); |
126 | 130 | ||
131 | void loadUserFonts_Text (void); /* based on Prefs */ | ||
132 | |||
127 | void setContentFont_Text (enum iTextFont font); | 133 | void setContentFont_Text (enum iTextFont font); |
128 | void setHeadingFont_Text (enum iTextFont font); | 134 | void setHeadingFont_Text (enum iTextFont font); |
129 | void setContentFontSize_Text (float fontSizeFactor); /* affects all except `default*` fonts */ | 135 | void setContentFontSize_Text (float fontSizeFactor); /* affects all except `default*` fonts */ |
diff --git a/src/ui/util.c b/src/ui/util.c index 6c87ba26..977eba9d 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1525,6 +1525,7 @@ void updatePreferencesLayout_Widget(iWidget *prefs) { | |||
1525 | static const char *inputIds[] = { | 1525 | static const char *inputIds[] = { |
1526 | "prefs.searchurl", | 1526 | "prefs.searchurl", |
1527 | "prefs.downloads", | 1527 | "prefs.downloads", |
1528 | "prefs.userfont", | ||
1528 | "prefs.ca.file", | 1529 | "prefs.ca.file", |
1529 | "prefs.ca.path", | 1530 | "prefs.ca.path", |
1530 | "prefs.proxy.gemini", | 1531 | "prefs.proxy.gemini", |
@@ -1786,6 +1787,7 @@ iWidget *makePreferences_Widget(void) { | |||
1786 | updateSize_LabelWidget((iLabelWidget *) tog); | 1787 | updateSize_LabelWidget((iLabelWidget *) tog); |
1787 | } | 1788 | } |
1788 | addChildFlags_Widget(values, iClob(boldLink), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 1789 | addChildFlags_Widget(values, iClob(boldLink), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
1790 | addPrefsInputWithHeading_(headings, values, "prefs.userfont", iClob(new_InputWidget(0))); | ||
1789 | } | 1791 | } |
1790 | makeTwoColumnHeading_("${heading.prefs.paragraph}", headings, values); | 1792 | makeTwoColumnHeading_("${heading.prefs.paragraph}", headings, values); |
1791 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.linewidth}"))); | 1793 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.linewidth}"))); |