diff options
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}"))); |