diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-08 15:27:14 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-08 15:27:14 +0300 |
commit | 52b6013cc01e17f4b500ea79fb786ccc14b1f7ec (patch) | |
tree | d3f1a91a282cbb225d8578fabf18a2690205738d /src | |
parent | deea4951aa8e4068daccb15b7960aa84ebfe906f (diff) |
Font configuration; Prefs has a string value array
Added a second version of Iosevka with more line spacing, to be used as the default monospace document font.
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 161 | ||||
-rw-r--r-- | src/fontpack.c | 112 | ||||
-rw-r--r-- | src/fontpack.h | 16 | ||||
-rw-r--r-- | src/gmdocument.c | 60 | ||||
-rw-r--r-- | src/prefs.c | 41 | ||||
-rw-r--r-- | src/prefs.h | 31 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 4 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 4 | ||||
-rw-r--r-- | src/ui/root.c | 3 | ||||
-rw-r--r-- | src/ui/text.c | 77 | ||||
-rw-r--r-- | src/ui/text.h | 116 | ||||
-rw-r--r-- | src/ui/util.c | 73 |
12 files changed, 397 insertions, 301 deletions
@@ -209,12 +209,16 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
209 | } | 209 | } |
210 | #endif | 210 | #endif |
211 | } | 211 | } |
212 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.uiLanguage)); | 212 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.strings[uiLanguage_PrefsString])); |
213 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window))); | 213 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window))); |
214 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); | 214 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); |
215 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); | 215 | appendFormat_String(str, |
216 | appendFormat_String(str, "font.user path:%s\n", cstr_String(&d->prefs.symbolFontPath)); | 216 | "font.set ui:%s heading:%s body:%s mono:%s monodoc:%s\n", |
217 | appendFormat_String(str, "headingfont.set arg:%d\n", d->prefs.headingFont); | 217 | cstr_String(&d->prefs.strings[uiFont_PrefsString]), |
218 | cstr_String(&d->prefs.strings[headingFont_PrefsString]), | ||
219 | cstr_String(&d->prefs.strings[bodyFont_PrefsString]), | ||
220 | cstr_String(&d->prefs.strings[monospaceFont_PrefsString]), | ||
221 | cstr_String(&d->prefs.strings[monospaceDocumentFont_PrefsString])); | ||
218 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); | 222 | appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent); |
219 | appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); | 223 | appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); |
220 | appendFormat_String(str, "scrollspeed arg:%d type:%d\n", d->prefs.smoothScrollSpeed[keyboard_ScrollType], keyboard_ScrollType); | 224 | appendFormat_String(str, "scrollspeed arg:%d type:%d\n", d->prefs.smoothScrollSpeed[keyboard_ScrollType], keyboard_ScrollType); |
@@ -247,15 +251,15 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
247 | appendFormat_String(str, "doctheme.light.set arg:%d\n", d->prefs.docThemeLight); | 251 | appendFormat_String(str, "doctheme.light.set arg:%d\n", d->prefs.docThemeLight); |
248 | appendFormat_String(str, "saturation.set arg:%d\n", (int) ((d->prefs.saturation * 100) + 0.5f)); | 252 | appendFormat_String(str, "saturation.set arg:%d\n", (int) ((d->prefs.saturation * 100) + 0.5f)); |
249 | appendFormat_String(str, "imagestyle.set arg:%d\n", d->prefs.imageStyle); | 253 | appendFormat_String(str, "imagestyle.set arg:%d\n", d->prefs.imageStyle); |
250 | appendFormat_String(str, "ca.file noset:1 path:%s\n", cstr_String(&d->prefs.caFile)); | 254 | appendFormat_String(str, "ca.file noset:1 path:%s\n", cstr_String(&d->prefs.strings[caFile_PrefsString])); |
251 | appendFormat_String(str, "ca.path path:%s\n", cstr_String(&d->prefs.caPath)); | 255 | appendFormat_String(str, "ca.path path:%s\n", cstr_String(&d->prefs.strings[caPath_PrefsString])); |
252 | appendFormat_String(str, "proxy.gemini address:%s\n", cstr_String(&d->prefs.geminiProxy)); | 256 | appendFormat_String(str, "proxy.gemini address:%s\n", cstr_String(&d->prefs.strings[geminiProxy_PrefsString])); |
253 | appendFormat_String(str, "proxy.gopher address:%s\n", cstr_String(&d->prefs.gopherProxy)); | 257 | appendFormat_String(str, "proxy.gopher address:%s\n", cstr_String(&d->prefs.strings[gopherProxy_PrefsString])); |
254 | appendFormat_String(str, "proxy.http address:%s\n", cstr_String(&d->prefs.httpProxy)); | 258 | appendFormat_String(str, "proxy.http address:%s\n", cstr_String(&d->prefs.strings[httpProxy_PrefsString])); |
255 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) | 259 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) |
256 | appendFormat_String(str, "downloads path:%s\n", cstr_String(&d->prefs.downloadDir)); | 260 | appendFormat_String(str, "downloads path:%s\n", cstr_String(&d->prefs.strings[downloadDir_PrefsString])); |
257 | #endif | 261 | #endif |
258 | appendFormat_String(str, "searchurl address:%s\n", cstr_String(&d->prefs.searchUrl)); | 262 | appendFormat_String(str, "searchurl address:%s\n", cstr_String(&d->prefs.strings[searchUrl_PrefsString])); |
259 | appendFormat_String(str, "translation.languages from:%d to:%d\n", d->prefs.langFrom, d->prefs.langTo); | 263 | appendFormat_String(str, "translation.languages from:%d to:%d\n", d->prefs.langFrom, d->prefs.langTo); |
260 | return str; | 264 | return str; |
261 | } | 265 | } |
@@ -329,7 +333,7 @@ static void loadPrefs_App_(iApp *d) { | |||
329 | } | 333 | } |
330 | else if (equal_Command(cmd, "uilang")) { | 334 | else if (equal_Command(cmd, "uilang")) { |
331 | const char *id = cstr_Rangecc(range_Command(cmd, "id")); | 335 | const char *id = cstr_Rangecc(range_Command(cmd, "id")); |
332 | setCStr_String(&d->prefs.uiLanguage, id); | 336 | setCStr_String(&d->prefs.strings[uiLanguage_PrefsString], id); |
333 | setCurrent_Lang(id); | 337 | setCurrent_Lang(id); |
334 | } | 338 | } |
335 | else if (equal_Command(cmd, "ca.file") || equal_Command(cmd, "ca.path")) { | 339 | else if (equal_Command(cmd, "ca.file") || equal_Command(cmd, "ca.path")) { |
@@ -360,7 +364,8 @@ static void loadPrefs_App_(iApp *d) { | |||
360 | } | 364 | } |
361 | if (!haveCA) { | 365 | if (!haveCA) { |
362 | /* Default CA setup. */ | 366 | /* Default CA setup. */ |
363 | setCACertificates_TlsRequest(&d->prefs.caFile, &d->prefs.caPath); | 367 | setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], |
368 | &d->prefs.strings[caPath_PrefsString]); | ||
364 | } | 369 | } |
365 | #if !defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 370 | #if !defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
366 | d->prefs.customFrame = iFalse; | 371 | d->prefs.customFrame = iFalse; |
@@ -787,7 +792,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
787 | #endif | 792 | #endif |
788 | init_Prefs(&d->prefs); | 793 | init_Prefs(&d->prefs); |
789 | init_SiteSpec(dataDir_App_()); | 794 | init_SiteSpec(dataDir_App_()); |
790 | setCStr_String(&d->prefs.downloadDir, downloadDir_App_()); | 795 | setCStr_String(&d->prefs.strings[downloadDir_PrefsString], downloadDir_App_()); |
791 | set_Atomic(&d->pendingRefresh, iFalse); | 796 | set_Atomic(&d->pendingRefresh, iFalse); |
792 | d->isRunning = iFalse; | 797 | d->isRunning = iFalse; |
793 | d->window = NULL; | 798 | d->window = NULL; |
@@ -918,7 +923,7 @@ const iString *dataDir_App(void) { | |||
918 | } | 923 | } |
919 | 924 | ||
920 | const iString *downloadDir_App(void) { | 925 | const iString *downloadDir_App(void) { |
921 | return collect_String(cleaned_Path(&app_.prefs.downloadDir)); | 926 | return collect_String(cleaned_Path(&app_.prefs.strings[downloadDir_PrefsString])); |
922 | } | 927 | } |
923 | 928 | ||
924 | const iString *downloadPathForUrl_App(const iString *url, const iString *mime) { | 929 | const iString *downloadPathForUrl_App(const iString *url, const iString *mime) { |
@@ -1517,13 +1522,13 @@ const iString *schemeProxy_App(iRangecc scheme) { | |||
1517 | iApp *d = &app_; | 1522 | iApp *d = &app_; |
1518 | const iString *proxy = NULL; | 1523 | const iString *proxy = NULL; |
1519 | if (equalCase_Rangecc(scheme, "gemini")) { | 1524 | if (equalCase_Rangecc(scheme, "gemini")) { |
1520 | proxy = &d->prefs.geminiProxy; | 1525 | proxy = &d->prefs.strings[geminiProxy_PrefsString]; |
1521 | } | 1526 | } |
1522 | else if (equalCase_Rangecc(scheme, "gopher")) { | 1527 | else if (equalCase_Rangecc(scheme, "gopher")) { |
1523 | proxy = &d->prefs.gopherProxy; | 1528 | proxy = &d->prefs.strings[gopherProxy_PrefsString]; |
1524 | } | 1529 | } |
1525 | else if (equalCase_Rangecc(scheme, "http") || equalCase_Rangecc(scheme, "https")) { | 1530 | else if (equalCase_Rangecc(scheme, "http") || equalCase_Rangecc(scheme, "https")) { |
1526 | proxy = &d->prefs.httpProxy; | 1531 | proxy = &d->prefs.strings[httpProxy_PrefsString]; |
1527 | } | 1532 | } |
1528 | return isEmpty_String(proxy) ? NULL : proxy; | 1533 | return isEmpty_String(proxy) ? NULL : proxy; |
1529 | } | 1534 | } |
@@ -1727,9 +1732,9 @@ static void updateColorThemeButton_(iLabelWidget *button, int theme) { | |||
1727 | updateDropdownSelection_LabelWidget(button, format_CStr(".set arg:%d", theme)); | 1732 | updateDropdownSelection_LabelWidget(button, format_CStr(".set arg:%d", theme)); |
1728 | } | 1733 | } |
1729 | 1734 | ||
1730 | static void updateFontButton_(iLabelWidget *button, int font) { | 1735 | static void updateFontButton_(iLabelWidget *button, const iString *fontId) { |
1731 | if (!button) return; | 1736 | if (!button || isEmpty_String(fontId)) return; |
1732 | updateDropdownSelection_LabelWidget(button, format_CStr(".set arg:%d", font)); | 1737 | updateDropdownSelection_LabelWidget(button, format_CStr(":%s", cstr_String(fontId))); |
1733 | } | 1738 | } |
1734 | 1739 | ||
1735 | static void updateImageStyleButton_(iLabelWidget *button, int style) { | 1740 | static void updateImageStyleButton_(iLabelWidget *button, int style) { |
@@ -1823,11 +1828,11 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1823 | return iFalse; | 1828 | return iFalse; |
1824 | } | 1829 | } |
1825 | else if (equal_Command(cmd, "font.set")) { | 1830 | else if (equal_Command(cmd, "font.set")) { |
1826 | updateFontButton_(findChild_Widget(d, "prefs.font"), arg_Command(cmd)); | 1831 | updateFontButton_(findChild_Widget(d, "prefs.font.ui"), string_Command(cmd, "ui")); |
1827 | return iFalse; | 1832 | updateFontButton_(findChild_Widget(d, "prefs.font.heading"), string_Command(cmd, "heading")); |
1828 | } | 1833 | updateFontButton_(findChild_Widget(d, "prefs.font.body"), string_Command(cmd, "body")); |
1829 | else if (equal_Command(cmd, "headingfont.set")) { | 1834 | updateFontButton_(findChild_Widget(d, "prefs.font.mono"), string_Command(cmd, "mono")); |
1830 | updateFontButton_(findChild_Widget(d, "prefs.headingfont"), arg_Command(cmd)); | 1835 | updateFontButton_(findChild_Widget(d, "prefs.font.monodoc"), string_Command(cmd, "monodoc")); |
1831 | return iFalse; | 1836 | return iFalse; |
1832 | } | 1837 | } |
1833 | else if (startsWith_CStr(cmd, "input.ended id:prefs.linespacing")) { | 1838 | else if (startsWith_CStr(cmd, "input.ended id:prefs.linespacing")) { |
@@ -2040,11 +2045,12 @@ iBool willUseProxy_App(const iRangecc scheme) { | |||
2040 | 2045 | ||
2041 | const iString *searchQueryUrl_App(const iString *queryStringUnescaped) { | 2046 | const iString *searchQueryUrl_App(const iString *queryStringUnescaped) { |
2042 | iApp *d = &app_; | 2047 | iApp *d = &app_; |
2043 | if (isEmpty_String(&d->prefs.searchUrl)) { | 2048 | if (isEmpty_String(&d->prefs.strings[searchUrl_PrefsString])) { |
2044 | return collectNew_String(); | 2049 | return collectNew_String(); |
2045 | } | 2050 | } |
2046 | const iString *escaped = urlEncode_String(queryStringUnescaped); | 2051 | const iString *escaped = urlEncode_String(queryStringUnescaped); |
2047 | return collectNewFormat_String("%s?%s", cstr_String(&d->prefs.searchUrl), cstr_String(escaped)); | 2052 | return collectNewFormat_String( |
2053 | "%s?%s", cstr_String(&d->prefs.strings[searchUrl_PrefsString]), cstr_String(escaped)); | ||
2048 | } | 2054 | } |
2049 | 2055 | ||
2050 | static void resetFonts_App_(iApp *d) { | 2056 | static void resetFonts_App_(iApp *d) { |
@@ -2074,9 +2080,10 @@ iBool handleCommand_App(const char *cmd) { | |||
2074 | } | 2080 | } |
2075 | else if (equal_Command(cmd, "uilang")) { | 2081 | else if (equal_Command(cmd, "uilang")) { |
2076 | const iString *lang = string_Command(cmd, "id"); | 2082 | const iString *lang = string_Command(cmd, "id"); |
2077 | if (!equal_String(lang, &d->prefs.uiLanguage)) { | 2083 | iString *val = &d->prefs.strings[uiLanguage_PrefsString]; |
2078 | set_String(&d->prefs.uiLanguage, lang); | 2084 | if (!equal_String(lang, val)) { |
2079 | setCurrent_Lang(cstr_String(&d->prefs.uiLanguage)); | 2085 | set_String(val, lang); |
2086 | setCurrent_Lang(cstr_String(val)); | ||
2080 | postCommand_App("lang.changed"); | 2087 | postCommand_App("lang.changed"); |
2081 | } | 2088 | } |
2082 | return iTrue; | 2089 | return iTrue; |
@@ -2148,14 +2155,38 @@ iBool handleCommand_App(const char *cmd) { | |||
2148 | if (!isFrozen) { | 2155 | if (!isFrozen) { |
2149 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); | 2156 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); |
2150 | } | 2157 | } |
2151 | d->prefs.font = arg_Command(cmd); | 2158 | struct { |
2152 | setContentFont_Text(text_Window(d->window), d->prefs.font); | 2159 | const char *label; |
2160 | enum iPrefsString ps; | ||
2161 | int fontId; | ||
2162 | } params[] = { | ||
2163 | { "ui", uiFont_PrefsString, default_FontId }, | ||
2164 | { "mono", monospaceFont_PrefsString, monospace_FontId }, | ||
2165 | { "heading", headingFont_PrefsString, documentHeading_FontId }, | ||
2166 | { "body", bodyFont_PrefsString, documentBody_FontId }, | ||
2167 | { "monodoc", monospaceDocumentFont_PrefsString, documentMonospace_FontId }, | ||
2168 | }; | ||
2169 | iBool wasChanged = iFalse; | ||
2170 | iForIndices(i, params) { | ||
2171 | if (hasLabel_Command(cmd, params[i].label)) { | ||
2172 | iString *ps = &d->prefs.strings[params[i].ps]; | ||
2173 | const iString *newFont = string_Command(cmd, params[i].label); | ||
2174 | if (!equal_String(ps, newFont)) { | ||
2175 | set_String(ps, newFont); | ||
2176 | wasChanged = iTrue; | ||
2177 | } | ||
2178 | } | ||
2179 | } | ||
2180 | if (wasChanged) { | ||
2181 | resetFonts_Text(text_Window(get_MainWindow())); | ||
2182 | } | ||
2153 | if (!isFrozen) { | 2183 | if (!isFrozen) { |
2154 | postCommand_App("font.changed"); | 2184 | postCommand_App("font.changed"); |
2155 | postCommand_App("window.unfreeze"); | 2185 | postCommand_App("window.unfreeze"); |
2156 | } | 2186 | } |
2157 | return iTrue; | 2187 | return iTrue; |
2158 | } | 2188 | } |
2189 | #if 0 | ||
2159 | else if (equal_Command(cmd, "headingfont.set")) { | 2190 | else if (equal_Command(cmd, "headingfont.set")) { |
2160 | if (!isFrozen) { | 2191 | if (!isFrozen) { |
2161 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); | 2192 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); |
@@ -2168,12 +2199,13 @@ iBool handleCommand_App(const char *cmd) { | |||
2168 | } | 2199 | } |
2169 | return iTrue; | 2200 | return iTrue; |
2170 | } | 2201 | } |
2202 | #endif | ||
2171 | else if (equal_Command(cmd, "zoom.set")) { | 2203 | else if (equal_Command(cmd, "zoom.set")) { |
2172 | if (!isFrozen) { | 2204 | if (!isFrozen) { |
2173 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */ | 2205 | setFreezeDraw_MainWindow(get_MainWindow(), iTrue); /* no intermediate draws before docs updated */ |
2174 | } | 2206 | } |
2175 | d->prefs.zoomPercent = arg_Command(cmd); | 2207 | d->prefs.zoomPercent = arg_Command(cmd); |
2176 | setContentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); | 2208 | setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); |
2177 | if (!isFrozen) { | 2209 | if (!isFrozen) { |
2178 | postCommand_App("font.changed"); | 2210 | postCommand_App("font.changed"); |
2179 | postCommand_App("window.unfreeze"); | 2211 | postCommand_App("window.unfreeze"); |
@@ -2189,7 +2221,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2189 | delta /= 2; | 2221 | delta /= 2; |
2190 | } | 2222 | } |
2191 | d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200); | 2223 | d->prefs.zoomPercent = iClamp(d->prefs.zoomPercent + delta, 50, 200); |
2192 | setContentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); | 2224 | setDocumentFontSize_Text(text_Window(d->window), (float) d->prefs.zoomPercent / 100.0f); |
2193 | if (!isFrozen) { | 2225 | if (!isFrozen) { |
2194 | postCommand_App("font.changed"); | 2226 | postCommand_App("font.changed"); |
2195 | postCommand_App("window.unfreeze"); | 2227 | postCommand_App("window.unfreeze"); |
@@ -2388,7 +2420,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2388 | return iTrue; | 2420 | return iTrue; |
2389 | } | 2421 | } |
2390 | else if (equal_Command(cmd, "searchurl")) { | 2422 | else if (equal_Command(cmd, "searchurl")) { |
2391 | iString *url = &d->prefs.searchUrl; | 2423 | iString *url = &d->prefs.strings[searchUrl_PrefsString]; |
2392 | setCStr_String(url, suffixPtr_Command(cmd, "address")); | 2424 | setCStr_String(url, suffixPtr_Command(cmd, "address")); |
2393 | if (startsWith_String(url, "//")) { | 2425 | if (startsWith_String(url, "//")) { |
2394 | prependCStr_String(url, "gemini:"); | 2426 | prependCStr_String(url, "gemini:"); |
@@ -2399,20 +2431,20 @@ iBool handleCommand_App(const char *cmd) { | |||
2399 | return iTrue; | 2431 | return iTrue; |
2400 | } | 2432 | } |
2401 | else if (equal_Command(cmd, "proxy.gemini")) { | 2433 | else if (equal_Command(cmd, "proxy.gemini")) { |
2402 | setCStr_String(&d->prefs.geminiProxy, suffixPtr_Command(cmd, "address")); | 2434 | setCStr_String(&d->prefs.strings[geminiProxy_PrefsString], suffixPtr_Command(cmd, "address")); |
2403 | return iTrue; | 2435 | return iTrue; |
2404 | } | 2436 | } |
2405 | else if (equal_Command(cmd, "proxy.gopher")) { | 2437 | else if (equal_Command(cmd, "proxy.gopher")) { |
2406 | setCStr_String(&d->prefs.gopherProxy, suffixPtr_Command(cmd, "address")); | 2438 | setCStr_String(&d->prefs.strings[gopherProxy_PrefsString], suffixPtr_Command(cmd, "address")); |
2407 | return iTrue; | 2439 | return iTrue; |
2408 | } | 2440 | } |
2409 | else if (equal_Command(cmd, "proxy.http")) { | 2441 | else if (equal_Command(cmd, "proxy.http")) { |
2410 | setCStr_String(&d->prefs.httpProxy, suffixPtr_Command(cmd, "address")); | 2442 | setCStr_String(&d->prefs.strings[httpProxy_PrefsString], suffixPtr_Command(cmd, "address")); |
2411 | return iTrue; | 2443 | return iTrue; |
2412 | } | 2444 | } |
2413 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) | 2445 | #if defined (LAGRANGE_ENABLE_DOWNLOAD_EDIT) |
2414 | else if (equal_Command(cmd, "downloads")) { | 2446 | else if (equal_Command(cmd, "downloads")) { |
2415 | setCStr_String(&d->prefs.downloadDir, suffixPtr_Command(cmd, "path")); | 2447 | setCStr_String(&d->prefs.strings[downloadDir_PrefsString], suffixPtr_Command(cmd, "path")); |
2416 | return iTrue; | 2448 | return iTrue; |
2417 | } | 2449 | } |
2418 | #endif | 2450 | #endif |
@@ -2421,16 +2453,16 @@ iBool handleCommand_App(const char *cmd) { | |||
2421 | return iTrue; | 2453 | return iTrue; |
2422 | } | 2454 | } |
2423 | else if (equal_Command(cmd, "ca.file")) { | 2455 | else if (equal_Command(cmd, "ca.file")) { |
2424 | setCStr_String(&d->prefs.caFile, suffixPtr_Command(cmd, "path")); | 2456 | setCStr_String(&d->prefs.strings[caFile_PrefsString], suffixPtr_Command(cmd, "path")); |
2425 | if (!argLabel_Command(cmd, "noset")) { | 2457 | if (!argLabel_Command(cmd, "noset")) { |
2426 | setCACertificates_TlsRequest(&d->prefs.caFile, &d->prefs.caPath); | 2458 | setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]); |
2427 | } | 2459 | } |
2428 | return iTrue; | 2460 | return iTrue; |
2429 | } | 2461 | } |
2430 | else if (equal_Command(cmd, "ca.path")) { | 2462 | else if (equal_Command(cmd, "ca.path")) { |
2431 | setCStr_String(&d->prefs.caPath, suffixPtr_Command(cmd, "path")); | 2463 | setCStr_String(&d->prefs.strings[caPath_PrefsString], suffixPtr_Command(cmd, "path")); |
2432 | if (!argLabel_Command(cmd, "noset")) { | 2464 | if (!argLabel_Command(cmd, "noset")) { |
2433 | setCACertificates_TlsRequest(&d->prefs.caFile, &d->prefs.caPath); | 2465 | setCACertificates_TlsRequest(&d->prefs.strings[caFile_PrefsString], &d->prefs.strings[caPath_PrefsString]); |
2434 | } | 2466 | } |
2435 | return iTrue; | 2467 | return iTrue; |
2436 | } | 2468 | } |
@@ -2465,7 +2497,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2465 | return iTrue; | 2497 | return iTrue; |
2466 | } | 2498 | } |
2467 | if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || | 2499 | if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || |
2468 | ((noProxy || isEmpty_String(&d->prefs.httpProxy)) && | 2500 | ((noProxy || isEmpty_String(&d->prefs.strings[httpProxy_PrefsString])) && |
2469 | (equalCase_Rangecc(parts.scheme, "http") || | 2501 | (equalCase_Rangecc(parts.scheme, "http") || |
2470 | equalCase_Rangecc(parts.scheme, "https")))) { | 2502 | equalCase_Rangecc(parts.scheme, "https")))) { |
2471 | openInDefaultBrowser_App(url); | 2503 | openInDefaultBrowser_App(url); |
@@ -2653,7 +2685,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2653 | else if (equal_Command(cmd, "preferences")) { | 2685 | else if (equal_Command(cmd, "preferences")) { |
2654 | iWidget *dlg = makePreferences_Widget(); | 2686 | iWidget *dlg = makePreferences_Widget(); |
2655 | updatePrefsThemeButtons_(dlg); | 2687 | updatePrefsThemeButtons_(dlg); |
2656 | setText_InputWidget(findChild_Widget(dlg, "prefs.downloads"), &d->prefs.downloadDir); | 2688 | setText_InputWidget(findChild_Widget(dlg, "prefs.downloads"), &d->prefs.strings[downloadDir_PrefsString]); |
2657 | setToggle_Widget(findChild_Widget(dlg, "prefs.hoverlink"), d->prefs.hoverLink); | 2689 | setToggle_Widget(findChild_Widget(dlg, "prefs.hoverlink"), d->prefs.hoverLink); |
2658 | setToggle_Widget(findChild_Widget(dlg, "prefs.smoothscroll"), d->prefs.smoothScrolling); | 2690 | setToggle_Widget(findChild_Widget(dlg, "prefs.smoothscroll"), d->prefs.smoothScrolling); |
2659 | setToggle_Widget(findChild_Widget(dlg, "prefs.imageloadscroll"), d->prefs.loadImageInsteadOfScrolling); | 2691 | setToggle_Widget(findChild_Widget(dlg, "prefs.imageloadscroll"), d->prefs.loadImageInsteadOfScrolling); |
@@ -2662,24 +2694,24 @@ iBool handleCommand_App(const char *cmd) { | |||
2662 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); | 2694 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); |
2663 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); | 2695 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); |
2664 | setToggle_Widget(findChild_Widget(dlg, "prefs.animate"), d->prefs.uiAnimations); | 2696 | setToggle_Widget(findChild_Widget(dlg, "prefs.animate"), d->prefs.uiAnimations); |
2665 | setText_InputWidget(findChild_Widget(dlg, "prefs.userfont"), &d->prefs.symbolFontPath); | 2697 | // setText_InputWidget(findChild_Widget(dlg, "prefs.userfont"), &d->prefs.symbolFontPath); |
2666 | updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit); | 2698 | updatePrefsPinSplitButtons_(dlg, d->prefs.pinSplit); |
2667 | updateScrollSpeedButtons_(dlg, mouse_ScrollType, d->prefs.smoothScrollSpeed[mouse_ScrollType]); | 2699 | updateScrollSpeedButtons_(dlg, mouse_ScrollType, d->prefs.smoothScrollSpeed[mouse_ScrollType]); |
2668 | updateScrollSpeedButtons_(dlg, keyboard_ScrollType, d->prefs.smoothScrollSpeed[keyboard_ScrollType]); | 2700 | updateScrollSpeedButtons_(dlg, keyboard_ScrollType, d->prefs.smoothScrollSpeed[keyboard_ScrollType]); |
2669 | updateDropdownSelection_LabelWidget(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage)); | 2701 | updateDropdownSelection_LabelWidget(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.strings[uiLanguage_PrefsString])); |
2670 | updateDropdownSelection_LabelWidget( | 2702 | updateDropdownSelection_LabelWidget( |
2671 | findChild_Widget(dlg, "prefs.returnkey"), | 2703 | findChild_Widget(dlg, "prefs.returnkey"), |
2672 | format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); | 2704 | format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); |
2673 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); | 2705 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); |
2674 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), | 2706 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), |
2675 | collectNewFormat_String("%g", uiScale_Window(as_Window(d->window)))); | 2707 | collectNewFormat_String("%g", uiScale_Window(as_Window(d->window)))); |
2676 | setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)), | 2708 | // setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)), |
2677 | selected_WidgetFlag, | 2709 | // selected_WidgetFlag, |
2678 | iTrue); | 2710 | // iTrue); |
2679 | setFlags_Widget( | 2711 | // setFlags_Widget( |
2680 | findChild_Widget(dlg, format_CStr("prefs.headingfont.%d", d->prefs.headingFont)), | 2712 | // findChild_Widget(dlg, format_CStr("prefs.headingfont.%d", d->prefs.headingFont)), |
2681 | selected_WidgetFlag, | 2713 | // selected_WidgetFlag, |
2682 | iTrue); | 2714 | // iTrue); |
2683 | setFlags_Widget(findChild_Widget(dlg, "prefs.mono.gemini"), | 2715 | setFlags_Widget(findChild_Widget(dlg, "prefs.mono.gemini"), |
2684 | selected_WidgetFlag, | 2716 | selected_WidgetFlag, |
2685 | d->prefs.monospaceGemini); | 2717 | d->prefs.monospaceGemini); |
@@ -2710,8 +2742,11 @@ iBool handleCommand_App(const char *cmd) { | |||
2710 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.dark"), d->prefs.docThemeDark); | 2742 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.dark"), d->prefs.docThemeDark); |
2711 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.light"), d->prefs.docThemeLight); | 2743 | updateColorThemeButton_(findChild_Widget(dlg, "prefs.doctheme.light"), d->prefs.docThemeLight); |
2712 | updateImageStyleButton_(findChild_Widget(dlg, "prefs.imagestyle"), d->prefs.imageStyle); | 2744 | updateImageStyleButton_(findChild_Widget(dlg, "prefs.imagestyle"), d->prefs.imageStyle); |
2713 | updateFontButton_(findChild_Widget(dlg, "prefs.font"), d->prefs.font); | 2745 | updateFontButton_(findChild_Widget(dlg, "prefs.font.ui"), &d->prefs.strings[uiFont_PrefsString]); |
2714 | updateFontButton_(findChild_Widget(dlg, "prefs.headingfont"), d->prefs.headingFont); | 2746 | updateFontButton_(findChild_Widget(dlg, "prefs.font.heading"), &d->prefs.strings[headingFont_PrefsString]); |
2747 | updateFontButton_(findChild_Widget(dlg, "prefs.font.body"), &d->prefs.strings[bodyFont_PrefsString]); | ||
2748 | updateFontButton_(findChild_Widget(dlg, "prefs.font.mono"), &d->prefs.strings[monospaceFont_PrefsString]); | ||
2749 | updateFontButton_(findChild_Widget(dlg, "prefs.font.monodoc"), &d->prefs.strings[monospaceDocumentFont_PrefsString]); | ||
2715 | setFlags_Widget( | 2750 | setFlags_Widget( |
2716 | findChild_Widget( | 2751 | findChild_Widget( |
2717 | dlg, format_CStr("prefs.saturation.%d", (int) (d->prefs.saturation * 3.99f))), | 2752 | dlg, format_CStr("prefs.saturation.%d", (int) (d->prefs.saturation * 3.99f))), |
@@ -2722,12 +2757,12 @@ iBool handleCommand_App(const char *cmd) { | |||
2722 | setText_InputWidget(findChild_Widget(dlg, "prefs.memorysize"), | 2757 | setText_InputWidget(findChild_Widget(dlg, "prefs.memorysize"), |
2723 | collectNewFormat_String("%d", d->prefs.maxMemorySize)); | 2758 | collectNewFormat_String("%d", d->prefs.maxMemorySize)); |
2724 | setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs); | 2759 | setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs); |
2725 | setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.searchUrl); | 2760 | setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.strings[searchUrl_PrefsString]); |
2726 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.caFile); | 2761 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.strings[caFile_PrefsString]); |
2727 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.path"), &d->prefs.caPath); | 2762 | setText_InputWidget(findChild_Widget(dlg, "prefs.ca.path"), &d->prefs.strings[caPath_PrefsString]); |
2728 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gemini"), &d->prefs.geminiProxy); | 2763 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gemini"), &d->prefs.strings[geminiProxy_PrefsString]); |
2729 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gopher"), &d->prefs.gopherProxy); | 2764 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gopher"), &d->prefs.strings[gopherProxy_PrefsString]); |
2730 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.http"), &d->prefs.httpProxy); | 2765 | setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.http"), &d->prefs.strings[httpProxy_PrefsString]); |
2731 | iWidget *tabs = findChild_Widget(dlg, "prefs.tabs"); | 2766 | iWidget *tabs = findChild_Widget(dlg, "prefs.tabs"); |
2732 | if (tabs) { | 2767 | if (tabs) { |
2733 | showTabPage_Widget(tabs, tabPage_Widget(tabs, d->prefs.dialogTab)); | 2768 | showTabPage_Widget(tabs, tabPage_Widget(tabs, d->prefs.dialogTab)); |
diff --git a/src/fontpack.c b/src/fontpack.c index a1f3b829..3b42e848 100644 --- a/src/fontpack.c +++ b/src/fontpack.c | |||
@@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
32 | 32 | ||
33 | #include "embedded.h" | 33 | #include "embedded.h" |
34 | 34 | ||
35 | /* TODO: Clean up and/or reorder this file, it's a bit unorganized. */ | ||
36 | |||
35 | float scale_FontSize(enum iFontSize size) { | 37 | float scale_FontSize(enum iFontSize size) { |
36 | static const float sizes[max_FontSize] = { | 38 | static const float sizes[max_FontSize] = { |
37 | 1.000, /* UI sizes */ | 39 | 1.000, /* UI sizes */ |
@@ -46,8 +48,7 @@ float scale_FontSize(enum iFontSize size) { | |||
46 | 1.666, | 48 | 1.666, |
47 | 2.000, | 49 | 2.000, |
48 | 0.568, | 50 | 0.568, |
49 | 0.710, | 51 | 0.710, /* calibration: fits the Lagrange title screen with Normal line width */ |
50 | 0.800, | ||
51 | }; | 52 | }; |
52 | if (size < 0 || size >= max_FontSize) { | 53 | if (size < 0 || size >= max_FontSize) { |
53 | return 1.0f; | 54 | return 1.0f; |
@@ -66,9 +67,30 @@ struct Impl_Fonts { | |||
66 | 67 | ||
67 | static iFonts fonts_; | 68 | static iFonts fonts_; |
68 | 69 | ||
70 | static void unloadFiles_Fonts_(iFonts *d) { | ||
71 | /* TODO: Mark all files in font packs as not resident. */ | ||
72 | iForEach(PtrArray, i, &d->files) { | ||
73 | delete_FontFile(i.ptr); | ||
74 | } | ||
75 | clear_PtrArray(&d->files); | ||
76 | } | ||
77 | |||
78 | static iFontFile *findFile_Fonts_(iFonts *d, const iString *id) { | ||
79 | iForEach(PtrArray, i, &d->files) { | ||
80 | iFontFile *ff = i.ptr; | ||
81 | if (equal_String(&ff->id, id)) { | ||
82 | return ff; | ||
83 | } | ||
84 | } | ||
85 | return NULL; | ||
86 | } | ||
87 | |||
88 | /*----------------------------------------------------------------------------------------------*/ | ||
89 | |||
69 | iDefineTypeConstruction(FontFile) | 90 | iDefineTypeConstruction(FontFile) |
70 | 91 | ||
71 | void init_FontFile(iFontFile *d) { | 92 | void init_FontFile(iFontFile *d) { |
93 | init_String(&d->id); | ||
72 | d->style = regular_FontStyle; | 94 | d->style = regular_FontStyle; |
73 | init_Block(&d->sourceData, 0); | 95 | init_Block(&d->sourceData, 0); |
74 | iZap(d->stbInfo); | 96 | iZap(d->stbInfo); |
@@ -111,6 +133,7 @@ static void unload_FontFile_(iFontFile *d) { | |||
111 | void deinit_FontFile(iFontFile *d) { | 133 | void deinit_FontFile(iFontFile *d) { |
112 | unload_FontFile_(d); | 134 | unload_FontFile_(d); |
113 | deinit_Block(&d->sourceData); | 135 | deinit_Block(&d->sourceData); |
136 | deinit_String(&d->id); | ||
114 | } | 137 | } |
115 | 138 | ||
116 | float scaleForPixelHeight_FontFile(const iFontFile *d, int pixelHeight) { | 139 | float scaleForPixelHeight_FontFile(const iFontFile *d, int pixelHeight) { |
@@ -140,8 +163,11 @@ void init_FontSpec(iFontSpec *d) { | |||
140 | init_String(&d->name); | 163 | init_String(&d->name); |
141 | d->flags = 0; | 164 | d->flags = 0; |
142 | d->priority = 0; | 165 | d->priority = 0; |
143 | d->scaling = 1.0f; | 166 | for (int i = 0; i < 2; ++i) { |
144 | d->vertOffset = 1.0f; | 167 | d->heightScale[i] = 1.0f; |
168 | d->glyphScale[i] = 1.0f; | ||
169 | d->vertOffsetScale[i] = 1.0f; | ||
170 | } | ||
145 | iZap(d->styles); | 171 | iZap(d->styles); |
146 | } | 172 | } |
147 | 173 | ||
@@ -154,12 +180,12 @@ void deinit_FontSpec(iFontSpec *d) { | |||
154 | 180 | ||
155 | iDeclareType(FontPack) | 181 | iDeclareType(FontPack) |
156 | iDeclareTypeConstruction(FontPack) | 182 | iDeclareTypeConstruction(FontPack) |
157 | 183 | ||
158 | struct Impl_FontPack { | 184 | struct Impl_FontPack { |
159 | const iArchive *archive; /* opened ZIP archive */ | 185 | const iArchive *archive; /* opened ZIP archive */ |
160 | iArray fonts; /* array of FontSpecs */ | 186 | iArray fonts; /* array of FontSpecs */ |
161 | iString * loadPath; | 187 | iString * loadPath; |
162 | iFontSpec *loadSpec; | 188 | iFontSpec * loadSpec; |
163 | }; | 189 | }; |
164 | 190 | ||
165 | void init_FontPack(iFontPack *d) { | 191 | void init_FontPack(iFontPack *d) { |
@@ -238,11 +264,27 @@ void handleIniKeyValue_FontPack_(void *context, const iString *table, const iStr | |||
238 | else if (!cmp_String(key, "priority") && value->type == int64_TomlType) { | 264 | else if (!cmp_String(key, "priority") && value->type == int64_TomlType) { |
239 | d->loadSpec->priority = (int) value->value.int64; | 265 | d->loadSpec->priority = (int) value->value.int64; |
240 | } | 266 | } |
241 | else if (!cmp_String(key, "scaling")) { | 267 | else if (!cmp_String(key, "height")) { |
242 | d->loadSpec->scaling = (float) number_TomlValue(value); | 268 | d->loadSpec->heightScale[0] = d->loadSpec->heightScale[1] = (float) number_TomlValue(value); |
269 | } | ||
270 | else if (!cmp_String(key, "glyphscale")) { | ||
271 | d->loadSpec->glyphScale[0] = d->loadSpec->glyphScale[1] = (float) number_TomlValue(value); | ||
243 | } | 272 | } |
244 | else if (!cmp_String(key, "voffset")) { | 273 | else if (!cmp_String(key, "voffset")) { |
245 | d->loadSpec->vertOffset = (float) number_TomlValue(value); | 274 | d->loadSpec->vertOffsetScale[0] = d->loadSpec->vertOffsetScale[1] = |
275 | (float) number_TomlValue(value); | ||
276 | } | ||
277 | else if (startsWith_String(key, "ui.") || startsWith_String(key, "doc.")) { | ||
278 | const int scope = startsWith_String(key, "ui.") ? 0 : 1; | ||
279 | if (endsWith_String(key, ".height")) { | ||
280 | d->loadSpec->heightScale[scope] = (float) number_TomlValue(value); | ||
281 | } | ||
282 | if (endsWith_String(key, ".glyphscale")) { | ||
283 | d->loadSpec->glyphScale[scope] = (float) number_TomlValue(value); | ||
284 | } | ||
285 | else if (endsWith_String(key, ".voffset")) { | ||
286 | d->loadSpec->vertOffsetScale[scope] = (float) number_TomlValue(value); | ||
287 | } | ||
246 | } | 288 | } |
247 | else if (!cmp_String(key, "override") && value->type == boolean_TomlType) { | 289 | else if (!cmp_String(key, "override") && value->type == boolean_TomlType) { |
248 | iChangeFlags(d->loadSpec->flags, override_FontSpecFlag, value->value.boolean); | 290 | iChangeFlags(d->loadSpec->flags, override_FontSpecFlag, value->value.boolean); |
@@ -265,14 +307,20 @@ void handleIniKeyValue_FontPack_(void *context, const iString *table, const iStr | |||
265 | iForIndices(i, styles) { | 307 | iForIndices(i, styles) { |
266 | if (!cmp_String(key, styles[i]) && !d->loadSpec->styles[i]) { | 308 | if (!cmp_String(key, styles[i]) && !d->loadSpec->styles[i]) { |
267 | iFontFile *ff = NULL; | 309 | iFontFile *ff = NULL; |
268 | iBlock *data = readFile_FontPack_(d, value->value.string); | 310 | iString *fontFileId = concat_Path(d->loadPath, value->value.string); |
269 | if (data) { | 311 | if (!(ff = findFile_Fonts_(&fonts_, fontFileId))) { |
270 | ff = new_FontFile(); | 312 | iBlock *data = readFile_FontPack_(d, value->value.string); |
271 | load_FontFile_(ff, data); | 313 | if (data) { |
272 | pushBack_PtrArray(&fonts_.files, ff); /* centralized ownership */ | 314 | ff = new_FontFile(); |
273 | d->loadSpec->styles[i] = ff; | 315 | set_String(&ff->id, fontFileId); |
274 | delete_Block(data); | 316 | load_FontFile_(ff, data); |
317 | pushBack_PtrArray(&fonts_.files, ff); /* centralized ownership */ | ||
318 | delete_Block(data); | ||
319 | // printf("[FontPack] loaded file: %s\n", cstr_String(fontFileId)); | ||
320 | } | ||
275 | } | 321 | } |
322 | d->loadSpec->styles[i] = ff; | ||
323 | delete_String(fontFileId); | ||
276 | break; | 324 | break; |
277 | } | 325 | } |
278 | } | 326 | } |
@@ -290,7 +338,6 @@ static iBool load_FontPack_(iFontPack *d, const iString *ini) { | |||
290 | setHandlers_TomlParser(toml, handleIniTable_FontPack_, handleIniKeyValue_FontPack_, d); | 338 | setHandlers_TomlParser(toml, handleIniTable_FontPack_, handleIniKeyValue_FontPack_, d); |
291 | if (parse_TomlParser(toml, ini)) { | 339 | if (parse_TomlParser(toml, ini)) { |
292 | ok = iTrue; | 340 | ok = iTrue; |
293 | // fprintf(stderr, "[FontPack] error parsing %s\n", cstr_String(iniPath)); | ||
294 | } | 341 | } |
295 | iAssert(d->loadSpec == NULL); | 342 | iAssert(d->loadSpec == NULL); |
296 | // d->loadPath = NULL; | 343 | // d->loadPath = NULL; |
@@ -331,7 +378,7 @@ iBool loadArchive_FontPack(iFontPack *d, const iArchive *zip) { | |||
331 | initBlock_String(&ini, iniData); | 378 | initBlock_String(&ini, iniData); |
332 | if (load_FontPack_(d, &ini)) { | 379 | if (load_FontPack_(d, &ini)) { |
333 | ok = iTrue; | 380 | ok = iTrue; |
334 | } | 381 | } |
335 | deinit_String(&ini); | 382 | deinit_String(&ini); |
336 | } | 383 | } |
337 | return ok; | 384 | return ok; |
@@ -339,14 +386,6 @@ iBool loadArchive_FontPack(iFontPack *d, const iArchive *zip) { | |||
339 | 386 | ||
340 | /*----------------------------------------------------------------------------------------------*/ | 387 | /*----------------------------------------------------------------------------------------------*/ |
341 | 388 | ||
342 | static void unloadFiles_Fonts_(iFonts *d) { | ||
343 | /* TODO: Mark all files in font packs as not resident. */ | ||
344 | iForEach(PtrArray, i, &d->files) { | ||
345 | delete_FontFile(i.ptr); | ||
346 | } | ||
347 | clear_PtrArray(&d->files); | ||
348 | } | ||
349 | |||
350 | static void unloadFonts_Fonts_(iFonts *d) { | 389 | static void unloadFonts_Fonts_(iFonts *d) { |
351 | iForEach(PtrArray, i, &d->packs) { | 390 | iForEach(PtrArray, i, &d->packs) { |
352 | iFontPack *pack = i.ptr; | 391 | iFontPack *pack = i.ptr; |
@@ -360,6 +399,11 @@ static int cmpPriority_FontSpecPtr_(const void *a, const void *b) { | |||
360 | return -iCmp((*p1)->priority, (*p2)->priority); /* highest priority first */ | 399 | return -iCmp((*p1)->priority, (*p2)->priority); /* highest priority first */ |
361 | } | 400 | } |
362 | 401 | ||
402 | static int cmpName_FontSpecPtr_(const void *a, const void *b) { | ||
403 | const iFontSpec **p1 = (const iFontSpec **) a, **p2 = (const iFontSpec **) b; | ||
404 | return cmpStringCase_String(&(*p1)->name, &(*p2)->name); | ||
405 | } | ||
406 | |||
363 | static void sortSpecs_Fonts_(iFonts *d) { | 407 | static void sortSpecs_Fonts_(iFonts *d) { |
364 | clear_PtrArray(&d->specOrder); | 408 | clear_PtrArray(&d->specOrder); |
365 | iConstForEach(PtrArray, p, &d->packs) { | 409 | iConstForEach(PtrArray, p, &d->packs) { |
@@ -410,6 +454,18 @@ const iFontSpec *findSpec_Fonts(const char *fontId) { | |||
410 | return NULL; | 454 | return NULL; |
411 | } | 455 | } |
412 | 456 | ||
457 | const iPtrArray *listSpecs_Fonts(iBool (*filterFunc)(const iFontSpec *)) { | ||
458 | iFonts *d = &fonts_; | ||
459 | iPtrArray *list = collectNew_PtrArray(); | ||
460 | iConstForEach(PtrArray, i, &d->specOrder) { | ||
461 | if (filterFunc == NULL || filterFunc(i.ptr)) { | ||
462 | pushBack_PtrArray(list, i.ptr); | ||
463 | } | ||
464 | } | ||
465 | sort_Array(list, cmpName_FontSpecPtr_); | ||
466 | return list; | ||
467 | } | ||
468 | |||
413 | const iPtrArray *listSpecsByPriority_Fonts(void) { | 469 | const iPtrArray *listSpecsByPriority_Fonts(void) { |
414 | return &fonts_.specOrder; | 470 | return &fonts_.specOrder; |
415 | } | 471 | } |
diff --git a/src/fontpack.h b/src/fontpack.h index c5aa993b..e59154e3 100644 --- a/src/fontpack.h +++ b/src/fontpack.h | |||
@@ -50,9 +50,8 @@ enum iFontSize { | |||
50 | contentBig_FontSize, | 50 | contentBig_FontSize, |
51 | contentLarge_FontSize, | 51 | contentLarge_FontSize, |
52 | contentHuge_FontSize, | 52 | contentHuge_FontSize, |
53 | contentMonoSmall_FontSize, | 53 | contentTiny_FontSize, |
54 | contentMono_FontSize, | 54 | contentSmall_FontSize, /* e.g., preformatted block scaled smaller to fit */ |
55 | contentSmall_FontSize, | ||
56 | max_FontSize | 55 | max_FontSize |
57 | }; | 56 | }; |
58 | 57 | ||
@@ -84,6 +83,7 @@ iDeclareType(FontFile) | |||
84 | iDeclareTypeConstruction(FontFile) | 83 | iDeclareTypeConstruction(FontFile) |
85 | 84 | ||
86 | struct Impl_FontFile { | 85 | struct Impl_FontFile { |
86 | iString id; /* for detecting when the same file is used in many places */ | ||
87 | enum iFontStyle style; | 87 | enum iFontStyle style; |
88 | iBlock sourceData; | 88 | iBlock sourceData; |
89 | stbtt_fontinfo stbInfo; | 89 | stbtt_fontinfo stbInfo; |
@@ -112,13 +112,19 @@ struct Impl_FontSpec { | |||
112 | iString name; /* human-readable label */ | 112 | iString name; /* human-readable label */ |
113 | int flags; | 113 | int flags; |
114 | int priority; | 114 | int priority; |
115 | float scaling; | 115 | float heightScale[2]; /* overall height scaling; ui, document */ |
116 | float vertOffset; | 116 | float glyphScale[2]; /* ui, document */ |
117 | float vertOffsetScale[2]; /* ui, document */ | ||
117 | const iFontFile *styles[max_FontStyle]; | 118 | const iFontFile *styles[max_FontStyle]; |
118 | }; | 119 | }; |
120 | |||
121 | iLocalDef int scaleType_FontSpec(enum iFontSize sizeId) { | ||
122 | return sizeId / contentRegular_FontSize; | ||
123 | } | ||
119 | 124 | ||
120 | void init_Fonts (const char *userDir); | 125 | void init_Fonts (const char *userDir); |
121 | void deinit_Fonts (void); | 126 | void deinit_Fonts (void); |
122 | 127 | ||
123 | const iFontSpec * findSpec_Fonts (const char *fontId); | 128 | const iFontSpec * findSpec_Fonts (const char *fontId); |
129 | const iPtrArray * listSpecs_Fonts (iBool (*filterFunc)(const iFontSpec *)); | ||
124 | const iPtrArray * listSpecsByPriority_Fonts (void); | 130 | const iPtrArray * listSpecsByPriority_Fonts (void); |
diff --git a/src/gmdocument.c b/src/gmdocument.c index ce9fdec8..c98b0bb8 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -468,22 +468,23 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
468 | const iBool isDarkBg = isDark_GmDocumentTheme( | 468 | const iBool isDarkBg = isDark_GmDocumentTheme( |
469 | isDark_ColorTheme(colorTheme_App()) ? prefs->docThemeDark : prefs->docThemeLight); | 469 | isDark_ColorTheme(colorTheme_App()) ? prefs->docThemeDark : prefs->docThemeLight); |
470 | /* TODO: Collect these parameters into a GmTheme. */ | 470 | /* TODO: Collect these parameters into a GmTheme. */ |
471 | const enum iFontId headingFont = isMono ? documentMonospace_FontId : documentHeading_FontId; | ||
472 | const enum iFontId bodyFont = isMono ? documentMonospace_FontId : documentBody_FontId; | ||
471 | const int fonts[max_GmLineType] = { | 473 | const int fonts[max_GmLineType] = { |
472 | isMono ? regularMonospace_FontId : paragraph_FontId, | 474 | FONT_ID(bodyFont, regular_FontStyle, contentRegular_FontSize), /* text */ |
473 | isMono ? regularMonospace_FontId : paragraph_FontId, /* bullet */ | 475 | FONT_ID(bodyFont, regular_FontStyle, contentRegular_FontSize), /* bullet */ |
474 | preformatted_FontId, | 476 | preformatted_FontId, /* pre */ |
475 | isMono ? regularMonospace_FontId : quote_FontId, | 477 | isMono ? monospaceParagraph_FontId : quote_FontId, /* quote */ |
476 | heading1_FontId, | 478 | FONT_ID(headingFont, bold_FontStyle, contentHuge_FontSize), /* h1 */ |
477 | heading2_FontId, | 479 | FONT_ID(headingFont, bold_FontStyle, contentLarge_FontSize), /* h2 */ |
478 | heading3_FontId, | 480 | FONT_ID(headingFont, regular_FontStyle, contentBig_FontSize), /* h3 */ |
479 | isMono ? regularMonospace_FontId | 481 | FONT_ID(bodyFont, |
480 | : ((isDarkBg && prefs->boldLinkDark) || (!isDarkBg && prefs->boldLinkLight)) | 482 | ((isDarkBg && prefs->boldLinkDark) || (!isDarkBg && prefs->boldLinkLight)) |
481 | ? bold_FontId | 483 | ? semiBold_FontStyle |
482 | : paragraph_FontId, | 484 | : regular_FontStyle, |
483 | }; | 485 | contentRegular_FontSize) /* link */ |
484 | float indents[max_GmLineType] = { | ||
485 | 5, 10, 5, isNarrow ? 5 : 10, 0, 0, 0, 5 | ||
486 | }; | 486 | }; |
487 | float indents[max_GmLineType] = { 5, 10, 5, isNarrow ? 5 : 10, 0, 0, 0, 5 }; | ||
487 | if (isExtremelyNarrow) { | 488 | if (isExtremelyNarrow) { |
488 | /* Further reduce the margins. */ | 489 | /* Further reduce the margins. */ |
489 | indents[text_GmLineType] -= 5; | 490 | indents[text_GmLineType] -= 5; |
@@ -562,10 +563,13 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
562 | iGmPreMeta meta = { .bounds = line }; | 563 | iGmPreMeta meta = { .bounds = line }; |
563 | meta.pixelRect.size = measurePreformattedBlock_GmDocument_( | 564 | meta.pixelRect.size = measurePreformattedBlock_GmDocument_( |
564 | d, line.start, preFont, &meta.contents, &meta.bounds.end); | 565 | d, line.start, preFont, &meta.contents, &meta.bounds.end); |
565 | if (meta.pixelRect.size.x > | 566 | const float oversizeRatio = |
566 | d->size.x - (enableIndents ? indents[preformatted_GmLineType] : 0) * gap_Text) { | 567 | meta.pixelRect.size.x / |
567 | preFont = preformattedSmall_FontId; | 568 | (float) (d->size.x - |
568 | meta.pixelRect.size = measureRange_Text(preFont, meta.contents).bounds.size; | 569 | (enableIndents ? indents[preformatted_GmLineType] : 0) * gap_Text); |
570 | if (oversizeRatio > 1.0f) { | ||
571 | preFont--; /* one notch smaller in the font size */ | ||
572 | meta.pixelRect.size = measureRange_Text(preFont, meta.contents).bounds.size; | ||
569 | } | 573 | } |
570 | trimLine_Rangecc(&line, type, isNormalized); | 574 | trimLine_Rangecc(&line, type, isNormalized); |
571 | meta.altText = line; /* without the ``` */ | 575 | meta.altText = line; /* without the ``` */ |
@@ -611,7 +615,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
611 | continue; | 615 | continue; |
612 | } | 616 | } |
613 | run.preId = preId; | 617 | run.preId = preId; |
614 | run.font = (d->format == plainText_SourceFormat ? regularMonospace_FontId : preFont); | 618 | run.font = (d->format == plainText_SourceFormat ? plainText_FontId : preFont); |
615 | indent = indents[type]; | 619 | indent = indents[type]; |
616 | } | 620 | } |
617 | if (addSiteBanner) { | 621 | if (addSiteBanner) { |
@@ -719,11 +723,13 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
719 | if (type == bullet_GmLineType) { | 723 | if (type == bullet_GmLineType) { |
720 | /* TODO: Literata bullet is broken? */ | 724 | /* TODO: Literata bullet is broken? */ |
721 | iGmRun bulRun = run; | 725 | iGmRun bulRun = run; |
726 | #if 0 | ||
722 | if (prefs->font == literata_TextFont) { | 727 | if (prefs->font == literata_TextFont) { |
723 | /* Something wrong this the glyph in Literata, looks cropped. */ | 728 | /* Something wrong this the glyph in Literata, looks cropped. */ |
724 | bulRun.font = FONT_ID(default_FontId, regular_FontStyle, | 729 | bulRun.font = FONT_ID(default_FontId, regular_FontStyle, |
725 | contentRegular_FontSize); | 730 | contentRegular_FontSize); |
726 | } | 731 | } |
732 | #endif | ||
727 | bulRun.color = tmQuote_ColorId; | 733 | bulRun.color = tmQuote_ColorId; |
728 | bulRun.visBounds.pos = addX_I2(pos, (indents[text_GmLineType] - 0.55f) * gap_Text); | 734 | bulRun.visBounds.pos = addX_I2(pos, (indents[text_GmLineType] - 0.55f) * gap_Text); |
729 | bulRun.visBounds.size = | 735 | bulRun.visBounds.size = |
@@ -778,7 +784,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
778 | } | 784 | } |
779 | /* TODO: List bullets needs the same centering logic. */ | 785 | /* TODO: List bullets needs the same centering logic. */ |
780 | /* Special exception for the tiny bullet operator. */ | 786 | /* Special exception for the tiny bullet operator. */ |
781 | icon.font = equal_Rangecc(link->labelIcon, "\u2219") ? regularMonospace_FontId | 787 | icon.font = equal_Rangecc(link->labelIcon, "\u2219") ? preformatted_FontId |
782 | : paragraph_FontId; | 788 | : paragraph_FontId; |
783 | alignDecoration_GmRun_(&icon, iFalse); | 789 | alignDecoration_GmRun_(&icon, iFalse); |
784 | icon.color = linkColor_GmDocument(d, run.linkId, icon_GmLinkPart); | 790 | icon.color = linkColor_GmDocument(d, run.linkId, icon_GmLinkPart); |
@@ -882,9 +888,9 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
882 | break; | 888 | break; |
883 | } | 889 | } |
884 | clear_RunTypesetter_(&rts); | 890 | clear_RunTypesetter_(&rts); |
885 | rts.pos = pos; | 891 | rts.pos = pos; |
886 | rts.run.font = rts.fonts[text_GmLineType]; | 892 | rts.run.font = rts.fonts[text_GmLineType]; |
887 | rts.run.color = colors[text_GmLineType]; | 893 | rts.run.color = colors[text_GmLineType]; |
888 | isLedeParagraph = iFalse; | 894 | isLedeParagraph = iFalse; |
889 | } | 895 | } |
890 | pos = rts.pos; | 896 | pos = rts.pos; |
@@ -925,7 +931,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
925 | run.visBounds.pos.x = run.bounds.size.x / 2 - width_Rect(run.visBounds) / 2; | 931 | run.visBounds.pos.x = run.bounds.size.x / 2 - width_Rect(run.visBounds) / 2; |
926 | run.bounds.size.y = run.visBounds.size.y; | 932 | run.bounds.size.y = run.visBounds.size.y; |
927 | } | 933 | } |
928 | run.text = iNullRange; | 934 | run.text = iNullRange; |
929 | run.font = 0; | 935 | run.font = 0; |
930 | run.color = 0; | 936 | run.color = 0; |
931 | run.mediaType = image_GmRunMediaType; | 937 | run.mediaType = image_GmRunMediaType; |
@@ -944,9 +950,9 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
944 | run.bounds.size.y = lineHeight_Text(uiContent_FontId) + 3 * gap_UI; | 950 | run.bounds.size.y = lineHeight_Text(uiContent_FontId) + 3 * gap_UI; |
945 | run.visBounds = run.bounds; | 951 | run.visBounds = run.bounds; |
946 | run.text = iNullRange; | 952 | run.text = iNullRange; |
947 | run.color = 0; | 953 | run.color = 0; |
948 | run.mediaType = audio_GmRunMediaType; | 954 | run.mediaType = audio_GmRunMediaType; |
949 | run.mediaId = audioId; | 955 | run.mediaId = audioId; |
950 | pushBack_Array(&d->layout, &run); | 956 | pushBack_Array(&d->layout, &run); |
951 | pos.y += run.bounds.size.y + margin; | 957 | pos.y += run.bounds.size.y + margin; |
952 | } | 958 | } |
diff --git a/src/prefs.c b/src/prefs.c index 088cc7bc..4d079402 100644 --- a/src/prefs.c +++ b/src/prefs.c | |||
@@ -25,6 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
25 | #include <the_Foundation/fileinfo.h> | 25 | #include <the_Foundation/fileinfo.h> |
26 | 26 | ||
27 | void init_Prefs(iPrefs *d) { | 27 | void init_Prefs(iPrefs *d) { |
28 | iForIndices(i, d->strings) { | ||
29 | init_String(&d->strings[i]); | ||
30 | } | ||
28 | d->dialogTab = 0; | 31 | d->dialogTab = 0; |
29 | d->langFrom = 3; /* fr */ | 32 | d->langFrom = 3; /* fr */ |
30 | d->langTo = 2; /* en */ | 33 | d->langTo = 2; /* en */ |
@@ -50,8 +53,11 @@ void init_Prefs(iPrefs *d) { | |||
50 | d->decodeUserVisibleURLs = iTrue; | 53 | d->decodeUserVisibleURLs = iTrue; |
51 | d->maxCacheSize = 10; | 54 | d->maxCacheSize = 10; |
52 | d->maxMemorySize = 200; | 55 | d->maxMemorySize = 200; |
53 | d->font = nunito_TextFont; | 56 | setCStr_String(&d->strings[uiFont_PrefsString], "default"); |
54 | d->headingFont = nunito_TextFont; | 57 | setCStr_String(&d->strings[headingFont_PrefsString], "default"); |
58 | setCStr_String(&d->strings[bodyFont_PrefsString], "default"); | ||
59 | setCStr_String(&d->strings[monospaceFont_PrefsString], "iosevka"); | ||
60 | setCStr_String(&d->strings[monospaceDocumentFont_PrefsString], "iosevka-body"); | ||
55 | d->monospaceGemini = iFalse; | 61 | d->monospaceGemini = iFalse; |
56 | d->monospaceGopher = iFalse; | 62 | d->monospaceGopher = iFalse; |
57 | d->boldLinkDark = iTrue; | 63 | d->boldLinkDark = iTrue; |
@@ -66,37 +72,18 @@ void init_Prefs(iPrefs *d) { | |||
66 | d->docThemeDark = colorfulDark_GmDocumentTheme; | 72 | d->docThemeDark = colorfulDark_GmDocumentTheme; |
67 | d->docThemeLight = white_GmDocumentTheme; | 73 | d->docThemeLight = white_GmDocumentTheme; |
68 | d->saturation = 1.0f; | 74 | d->saturation = 1.0f; |
69 | initCStr_String(&d->uiLanguage, "en"); | 75 | setCStr_String(&d->strings[uiLanguage_PrefsString], "en"); |
70 | init_String(&d->caFile); | ||
71 | init_String(&d->caPath); | ||
72 | init_String(&d->geminiProxy); | ||
73 | init_String(&d->gopherProxy); | ||
74 | init_String(&d->httpProxy); | ||
75 | init_String(&d->downloadDir); | ||
76 | init_String(&d->searchUrl); | ||
77 | init_String(&d->symbolFontPath); | ||
78 | /* TODO: Add some platform-specific common locations? */ | 76 | /* TODO: Add some platform-specific common locations? */ |
79 | if (fileExistsCStr_FileInfo("/etc/ssl/cert.pem")) { /* macOS */ | 77 | if (fileExistsCStr_FileInfo("/etc/ssl/cert.pem")) { /* macOS */ |
80 | setCStr_String(&d->caFile, "/etc/ssl/cert.pem"); | 78 | setCStr_String(&d->strings[caFile_PrefsString], "/etc/ssl/cert.pem"); |
81 | } | 79 | } |
82 | if (fileExistsCStr_FileInfo("/etc/ssl/certs")) { | 80 | if (fileExistsCStr_FileInfo("/etc/ssl/certs")) { |
83 | setCStr_String(&d->caPath, "/etc/ssl/certs"); | 81 | setCStr_String(&d->strings[caPath_PrefsString], "/etc/ssl/certs"); |
84 | } | 82 | } |
85 | /* | ||
86 | #if defined (iPlatformAppleDesktop) | ||
87 | setCStr_String(&d->symbolFontPath, "/System/Library/Fonts/Apple Symbols.ttf"); | ||
88 | #endif | ||
89 | */ | ||
90 | } | 83 | } |
91 | 84 | ||
92 | void deinit_Prefs(iPrefs *d) { | 85 | void deinit_Prefs(iPrefs *d) { |
93 | deinit_String(&d->symbolFontPath); | 86 | iForIndices(i, d->strings) { |
94 | deinit_String(&d->searchUrl); | 87 | deinit_String(&d->strings[i]); |
95 | deinit_String(&d->geminiProxy); | 88 | } |
96 | deinit_String(&d->gopherProxy); | ||
97 | deinit_String(&d->httpProxy); | ||
98 | deinit_String(&d->downloadDir); | ||
99 | deinit_String(&d->caPath); | ||
100 | deinit_String(&d->caFile); | ||
101 | deinit_String(&d->uiLanguage); | ||
102 | } | 89 | } |
diff --git a/src/prefs.h b/src/prefs.h index 37aeb260..1ba3a2ab 100644 --- a/src/prefs.h +++ b/src/prefs.h | |||
@@ -31,17 +31,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
31 | /* User preferences */ | 31 | /* User preferences */ |
32 | 32 | ||
33 | iDeclareType(Prefs) | 33 | iDeclareType(Prefs) |
34 | |||
35 | enum iPrefsString { | ||
36 | uiLanguage_PrefsString, | ||
37 | downloadDir_PrefsString, | ||
38 | searchUrl_PrefsString, | ||
39 | /* Network */ | ||
40 | caFile_PrefsString, | ||
41 | caPath_PrefsString, | ||
42 | geminiProxy_PrefsString, | ||
43 | gopherProxy_PrefsString, | ||
44 | httpProxy_PrefsString, | ||
45 | /* Style */ | ||
46 | uiFont_PrefsString, | ||
47 | headingFont_PrefsString, | ||
48 | bodyFont_PrefsString, | ||
49 | monospaceFont_PrefsString, | ||
50 | monospaceDocumentFont_PrefsString, | ||
51 | max_PrefsString | ||
52 | }; | ||
34 | 53 | ||
35 | /* TODO: Refactor at least the boolean values into an array for easier manipulation. | 54 | /* TODO: Refactor at least the boolean values into an array for easier manipulation. |
36 | Then they can be (de)serialized as a group. Need to use a systematic command naming | 55 | Then they can be (de)serialized as a group. Need to use a systematic command naming |
37 | convention for notifications. */ | 56 | convention for notifications. */ |
38 | struct Impl_Prefs { | 57 | struct Impl_Prefs { |
58 | iString strings[max_PrefsString]; | ||
39 | /* UI state */ | 59 | /* UI state */ |
40 | int dialogTab; | 60 | int dialogTab; |
41 | int langFrom; | 61 | int langFrom; |
42 | int langTo; | 62 | int langTo; |
43 | /* Window */ | 63 | /* Window */ |
44 | iString uiLanguage; | ||
45 | iBool useSystemTheme; | 64 | iBool useSystemTheme; |
46 | enum iColorTheme theme; | 65 | enum iColorTheme theme; |
47 | enum iColorAccent accent; | 66 | enum iColorAccent accent; |
@@ -55,27 +74,17 @@ struct Impl_Prefs { | |||
55 | int pinSplit; /* 0: no pinning, 1: left doc, 2: right doc */ | 74 | int pinSplit; /* 0: no pinning, 1: left doc, 2: right doc */ |
56 | /* Behavior */ | 75 | /* Behavior */ |
57 | int returnKey; | 76 | int returnKey; |
58 | iString downloadDir; | ||
59 | iBool hoverLink; | 77 | iBool hoverLink; |
60 | iBool smoothScrolling; | 78 | iBool smoothScrolling; |
61 | int smoothScrollSpeed[max_ScrollType]; | 79 | int smoothScrollSpeed[max_ScrollType]; |
62 | iBool loadImageInsteadOfScrolling; | 80 | iBool loadImageInsteadOfScrolling; |
63 | iBool collapsePreOnLoad; | 81 | iBool collapsePreOnLoad; |
64 | iString searchUrl; | ||
65 | iBool openArchiveIndexPages; | 82 | iBool openArchiveIndexPages; |
66 | /* Network */ | 83 | /* Network */ |
67 | iString caFile; | ||
68 | iString caPath; | ||
69 | iBool decodeUserVisibleURLs; | 84 | iBool decodeUserVisibleURLs; |
70 | int maxCacheSize; /* MB */ | 85 | int maxCacheSize; /* MB */ |
71 | int maxMemorySize; /* MB */ | 86 | int maxMemorySize; /* MB */ |
72 | iString geminiProxy; | ||
73 | iString gopherProxy; | ||
74 | iString httpProxy; | ||
75 | /* Style */ | 87 | /* Style */ |
76 | iString symbolFontPath; | ||
77 | enum iTextFont font; | ||
78 | enum iTextFont headingFont; | ||
79 | iBool monospaceGemini; | 88 | iBool monospaceGemini; |
80 | iBool monospaceGopher; | 89 | iBool monospaceGopher; |
81 | iBool boldLinkDark; | 90 | iBool boldLinkDark; |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 2ba2fa12..45a8cf2d 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -496,7 +496,7 @@ static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { | |||
496 | -1.0f, 10.0f); /* adapt to width */ | 496 | -1.0f, 10.0f); /* adapt to width */ |
497 | //printf("%f\n", adjust); fflush(stdout); | 497 | //printf("%f\n", adjust); fflush(stdout); |
498 | return iMini(iMax(minWidth, bounds.size.x - gap_UI * (d->pageMargin + adjust) * 2), | 498 | return iMini(iMax(minWidth, bounds.size.x - gap_UI * (d->pageMargin + adjust) * 2), |
499 | fontSize_UI * emRatio_Text(paragraph_FontId) * /* dependent on avg. glyph width */ | 499 | fontSize_UI * //emRatio_Text(paragraph_FontId) * /* dependent on avg. glyph width */ |
500 | prefs->lineWidth * prefs->zoomPercent / 100); | 500 | prefs->lineWidth * prefs->zoomPercent / 100); |
501 | } | 501 | } |
502 | 502 | ||
@@ -3441,7 +3441,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3441 | return iTrue; | 3441 | return iTrue; |
3442 | } | 3442 | } |
3443 | break; | 3443 | break; |
3444 | #if 1 | 3444 | #if !defined (NDEBUG) |
3445 | case SDLK_KP_1: | 3445 | case SDLK_KP_1: |
3446 | case '`': { | 3446 | case '`': { |
3447 | iBlock *seed = new_Block(64); | 3447 | iBlock *seed = new_Block(64); |
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index cfc81863..9713e1f2 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -384,7 +384,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
384 | } | 384 | } |
385 | else if (flags & alignLeft_WidgetFlag) { | 385 | else if (flags & alignLeft_WidgetFlag) { |
386 | draw_Text(d->font, add_I2(bounds.pos, addX_I2(padding_LabelWidget_(d, 0), iconPad)), | 386 | draw_Text(d->font, add_I2(bounds.pos, addX_I2(padding_LabelWidget_(d, 0), iconPad)), |
387 | fg, cstr_String(&d->label)); | 387 | fg, "%s", cstr_String(&d->label)); |
388 | if ((flags & drawKey_WidgetFlag) && d->key) { | 388 | if ((flags & drawKey_WidgetFlag) && d->key) { |
389 | iString str; | 389 | iString str; |
390 | init_String(&str); | 390 | init_String(&str); |
@@ -399,6 +399,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
399 | : colorEscape != none_ColorId ? colorEscape | 399 | : colorEscape != none_ColorId ? colorEscape |
400 | : uiTextShortcut_ColorId,*/ | 400 | : uiTextShortcut_ColorId,*/ |
401 | right_Alignment, | 401 | right_Alignment, |
402 | "%s", | ||
402 | cstr_String(&str)); | 403 | cstr_String(&str)); |
403 | deinit_String(&str); | 404 | deinit_String(&str); |
404 | } | 405 | } |
@@ -409,6 +410,7 @@ static void draw_LabelWidget_(const iLabelWidget *d) { | |||
409 | add_I2(topRight_Rect(bounds), negX_I2(padding_LabelWidget_(d, 1))), | 410 | add_I2(topRight_Rect(bounds), negX_I2(padding_LabelWidget_(d, 1))), |
410 | fg, | 411 | fg, |
411 | right_Alignment, | 412 | right_Alignment, |
413 | "%s", | ||
412 | cstr_String(&d->label)); | 414 | cstr_String(&d->label)); |
413 | } | 415 | } |
414 | else { | 416 | else { |
diff --git a/src/ui/root.c b/src/ui/root.c index a2e6062f..f6d6f11d 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -566,7 +566,8 @@ static iBool willPerformSearchQuery_(const iString *userInput) { | |||
566 | if (isEmpty_String(clean)) { | 566 | if (isEmpty_String(clean)) { |
567 | return iFalse; | 567 | return iFalse; |
568 | } | 568 | } |
569 | return !isEmpty_String(&prefs_App()->searchUrl) && !isLikelyUrl_String(userInput); | 569 | return !isEmpty_String(&prefs_App()->strings[searchUrl_PrefsString]) && |
570 | !isLikelyUrl_String(userInput); | ||
570 | } | 571 | } |
571 | 572 | ||
572 | static void updateUrlInputContentPadding_(iWidget *navBar) { | 573 | static void updateUrlInputContentPadding_(iWidget *navBar) { |
diff --git a/src/ui/text.c b/src/ui/text.c index 8adfa019..14b4e305 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -171,7 +171,8 @@ iLocalDef iBool isMonospaced_Font(const iFont *d) { | |||
171 | static iFont *font_Text_(enum iFontId id); | 171 | static iFont *font_Text_(enum iFontId id); |
172 | 172 | ||
173 | static void init_Font(iFont *d, const iFontSpec *fontSpec, const iFontFile *fontFile, | 173 | static void init_Font(iFont *d, const iFontSpec *fontSpec, const iFontFile *fontFile, |
174 | enum iFontSize sizeId, int height) { | 174 | enum iFontSize sizeId, float height) { |
175 | const int scaleType = scaleType_FontSpec(sizeId); | ||
175 | d->fontSpec = fontSpec; | 176 | d->fontSpec = fontSpec; |
176 | d->fontFile = fontFile; | 177 | d->fontFile = fontFile; |
177 | /* TODO: Nunito kerning fixes need to be a font parameter of its own. */ | 178 | /* TODO: Nunito kerning fixes need to be a font parameter of its own. */ |
@@ -197,15 +198,9 @@ static void init_Font(iFont *d, const iFontSpec *fontSpec, const iFontFile *font | |||
197 | d->family = emojiAndSymbols_TextFont; | 198 | d->family = emojiAndSymbols_TextFont; |
198 | } | 199 | } |
199 | #endif | 200 | #endif |
200 | // d->isMonospaced = (fontSpec->flags & monospace_FontSpecFlag) != 0; | 201 | d->height = (int) (height * fontSpec->heightScale[scaleType]); |
201 | d->height = height; | 202 | const float glyphScale = fontSpec->glyphScale[scaleType]; |
202 | //iZap(d->font); | 203 | d->xScale = d->yScale = scaleForPixelHeight_FontFile(fontFile, d->height) * glyphScale; |
203 | // stbtt_InitFont(&d->font, constData_Block(data), 0); | ||
204 | // int ascent, descent, emAdv; | ||
205 | // stbtt_GetFontVMetrics(&d->font, &ascent, &descent, NULL); | ||
206 | // stbtt_GetCodepointHMetrics(&d->font, 'M', &emAdv, NULL); | ||
207 | const float scale = fontSpec->scaling; | ||
208 | d->xScale = d->yScale = scaleForPixelHeight_FontFile(fontFile, height) * scale; | ||
209 | if (isMonospaced_Font(d)) { | 204 | if (isMonospaced_Font(d)) { |
210 | /* It is important that monospaced fonts align 1:1 with the pixel grid so that | 205 | /* It is important that monospaced fonts align 1:1 with the pixel grid so that |
211 | box-drawing characters don't have partially occupied edge pixels, leading to seams | 206 | box-drawing characters don't have partially occupied edge pixels, leading to seams |
@@ -217,8 +212,9 @@ static void init_Font(iFont *d, const iFontSpec *fontSpec, const iFontFile *font | |||
217 | } | 212 | } |
218 | d->emAdvance = fontFile->emAdvance * d->xScale; | 213 | d->emAdvance = fontFile->emAdvance * d->xScale; |
219 | d->baseline = fontFile->ascent * d->yScale; | 214 | d->baseline = fontFile->ascent * d->yScale; |
220 | d->vertOffset = height * (1.0f - scale) / 2 * fontSpec->vertOffset; | 215 | d->vertOffset = d->height * (1.0f - glyphScale) / 2 * fontSpec->vertOffsetScale[scaleType]; |
221 | d->table = NULL; | 216 | d->table = NULL; |
217 | // printf("{%s} height:%d baseline:%d\n", cstr_String(&d->fontSpec->id), d->height, d->baseline); | ||
222 | } | 218 | } |
223 | 219 | ||
224 | static void deinit_Font(iFont *d) { | 220 | static void deinit_Font(iFont *d) { |
@@ -252,8 +248,8 @@ struct Impl_CacheRow { | |||
252 | }; | 248 | }; |
253 | 249 | ||
254 | struct Impl_Text { | 250 | struct Impl_Text { |
255 | enum iTextFont contentFont; | 251 | // enum iTextFont contentFont; |
256 | enum iTextFont headingFont; | 252 | // enum iTextFont headingFont; |
257 | float contentFontSize; | 253 | float contentFontSize; |
258 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ | 254 | iArray fonts; /* fonts currently selected for use (incl. all styles/sizes) */ |
259 | int overrideFontId; /* always checked for glyphs first, regardless of which font is used */ | 255 | int overrideFontId; /* always checked for glyphs first, regardless of which font is used */ |
@@ -290,7 +286,8 @@ static void setupFontVariants_Text_(iText *d, const iFontSpec *spec, int baseId) | |||
290 | spec, | 286 | spec, |
291 | spec->styles[style], | 287 | spec->styles[style], |
292 | sizeId, | 288 | sizeId, |
293 | (sizeId < contentRegular_FontSize ? uiSize : textSize) * scale_FontSize(sizeId)); | 289 | (sizeId < contentRegular_FontSize ? uiSize : textSize) * |
290 | scale_FontSize(sizeId)); | ||
294 | } | 291 | } |
295 | } | 292 | } |
296 | } | 293 | } |
@@ -311,6 +308,11 @@ iLocalDef enum iFontStyle styleId_Text_(const iFont *d) { | |||
311 | return (fontId_Text_(d) / max_FontSize) % max_FontStyle; | 308 | return (fontId_Text_(d) / max_FontSize) % max_FontStyle; |
312 | } | 309 | } |
313 | 310 | ||
311 | static const iFontSpec *tryFindSpec_(enum iPrefsString ps, const char *fallback) { | ||
312 | const iFontSpec *spec = findSpec_Fonts(cstr_String(&prefs_App()->strings[ps])); | ||
313 | return spec ? spec : findSpec_Fonts(fallback); | ||
314 | } | ||
315 | |||
314 | static void initFonts_Text_(iText *d) { | 316 | static void initFonts_Text_(iText *d) { |
315 | #if 0 | 317 | #if 0 |
316 | const iBlock *regularFont = &fontNunitoRegular_Embedded; | 318 | const iBlock *regularFont = &fontNunitoRegular_Embedded; |
@@ -445,11 +447,11 @@ static void initFonts_Text_(iText *d) { | |||
445 | /* First the mandatory fonts. */ | 447 | /* First the mandatory fonts. */ |
446 | d->overrideFontId = -1; | 448 | d->overrideFontId = -1; |
447 | resize_Array(&d->fonts, auxiliary_FontId); /* room for the built-ins */ | 449 | resize_Array(&d->fonts, auxiliary_FontId); /* room for the built-ins */ |
448 | iAssert(auxiliary_FontId == documentHeading_FontId + maxVariants_Fonts); | 450 | setupFontVariants_Text_(d, tryFindSpec_(uiFont_PrefsString, "default"), default_FontId); |
449 | setupFontVariants_Text_(d, findSpec_Fonts("default"), default_FontId); | 451 | setupFontVariants_Text_(d, tryFindSpec_(monospaceFont_PrefsString, "iosevka"), monospace_FontId); |
450 | setupFontVariants_Text_(d, findSpec_Fonts("iosevka"), monospace_FontId); | 452 | setupFontVariants_Text_(d, tryFindSpec_(headingFont_PrefsString, "default"), documentHeading_FontId); |
451 | setupFontVariants_Text_(d, findSpec_Fonts("default"), documentBody_FontId); | 453 | setupFontVariants_Text_(d, tryFindSpec_(bodyFont_PrefsString, "default"), documentBody_FontId); |
452 | setupFontVariants_Text_(d, findSpec_Fonts("default"), documentHeading_FontId); | 454 | setupFontVariants_Text_(d, tryFindSpec_(monospaceDocumentFont_PrefsString, "iosevka-body"), documentMonospace_FontId); |
453 | /* Check if there are auxiliary fonts available and set those up, too. */ | 455 | /* Check if there are auxiliary fonts available and set those up, too. */ |
454 | iConstForEach(PtrArray, s, listSpecsByPriority_Fonts()) { | 456 | iConstForEach(PtrArray, s, listSpecsByPriority_Fonts()) { |
455 | const iFontSpec *spec = s.ptr; | 457 | const iFontSpec *spec = s.ptr; |
@@ -459,17 +461,6 @@ static void initFonts_Text_(iText *d) { | |||
459 | setupFontVariants_Text_(d, spec, fontId); | 461 | setupFontVariants_Text_(d, spec, fontId); |
460 | } | 462 | } |
461 | } | 463 | } |
462 | #if 0 | ||
463 | iForIndices(i, fontData) { | ||
464 | iFont *font = font_Text_(i); | ||
465 | init_Font(font, | ||
466 | fontData[i].ttf, | ||
467 | fontData[i].size, | ||
468 | fontData[i].scaling, | ||
469 | fontData[i].sizeId, | ||
470 | fontData[i].ttf == &fontIosevkaTermExtended_Embedded); | ||
471 | } | ||
472 | #endif | ||
473 | gap_Text = iRound(gap_UI * d->contentFontSize); | 464 | gap_Text = iRound(gap_UI * d->contentFontSize); |
474 | } | 465 | } |
475 | 466 | ||
@@ -544,8 +535,8 @@ void init_Text(iText *d, SDL_Renderer *render) { | |||
544 | iText *oldActive = activeText_; | 535 | iText *oldActive = activeText_; |
545 | activeText_ = d; | 536 | activeText_ = d; |
546 | init_Array(&d->fonts, sizeof(iFont)); | 537 | init_Array(&d->fonts, sizeof(iFont)); |
547 | d->contentFont = nunito_TextFont; | 538 | // d->contentFont = nunito_TextFont; |
548 | d->headingFont = nunito_TextFont; | 539 | // d->headingFont = nunito_TextFont; |
549 | d->contentFontSize = contentScale_Text_; | 540 | d->contentFontSize = contentScale_Text_; |
550 | d->ansiEscape = new_RegExp("[[()]([0-9;AB]*)m", 0); | 541 | d->ansiEscape = new_RegExp("[[()]([0-9;AB]*)m", 0); |
551 | d->render = render; | 542 | d->render = render; |
@@ -579,21 +570,15 @@ void setOpacity_Text(float opacity) { | |||
579 | SDL_SetTextureAlphaMod(activeText_->cache, iClamp(opacity, 0.0f, 1.0f) * 255 + 0.5f); | 570 | SDL_SetTextureAlphaMod(activeText_->cache, iClamp(opacity, 0.0f, 1.0f) * 255 + 0.5f); |
580 | } | 571 | } |
581 | 572 | ||
582 | void setContentFont_Text(iText *d, enum iTextFont font) { | 573 | //void setFont_Text(iText *d, int fontId, const char *fontSpecId) { |
583 | if (d->contentFont != font) { | 574 | // setupFontVariants_Text_(d, findSpec_Fonts(fontSpecId), fontId); |
584 | d->contentFont = font; | 575 | // if (d->contentFont != font) { |
585 | resetFonts_Text(d); | 576 | // d->contentFont = font; |
586 | } | 577 | // resetFonts_Text(d); |
587 | } | 578 | // } |
588 | 579 | //} | |
589 | void setHeadingFont_Text(iText *d, enum iTextFont font) { | ||
590 | if (d->headingFont != font) { | ||
591 | d->headingFont = font; | ||
592 | resetFonts_Text(d); | ||
593 | } | ||
594 | } | ||
595 | 580 | ||
596 | void setContentFontSize_Text(iText *d, float fontSizeFactor) { | 581 | void setDocumentFontSize_Text(iText *d, float fontSizeFactor) { |
597 | fontSizeFactor *= contentScale_Text_; | 582 | fontSizeFactor *= contentScale_Text_; |
598 | iAssert(fontSizeFactor > 0); | 583 | iAssert(fontSizeFactor > 0); |
599 | if (iAbs(d->contentFontSize - fontSizeFactor) > 0.001f) { | 584 | if (iAbs(d->contentFontSize - fontSizeFactor) > 0.001f) { |
diff --git a/src/ui/text.h b/src/ui/text.h index af69795a..ac59e7c8 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -34,80 +34,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
34 | #define FONT_ID(name, style, size) ((name) + ((style) * max_FontSize) + (size)) | 34 | #define FONT_ID(name, style, size) ((name) + ((style) * max_FontSize) + (size)) |
35 | 35 | ||
36 | enum iFontId { | 36 | enum iFontId { |
37 | default_FontId = 0, /* default is always the first font */ | 37 | default_FontId = 0, /* default is always the first font */ |
38 | monospace_FontId = maxVariants_Fonts, /* 2nd font is always the monospace font */ | 38 | monospace_FontId = maxVariants_Fonts, /* 2nd font is always the monospace font */ |
39 | documentBody_FontId = maxVariants_Fonts * 2, /* 3rd font is the body font */ | 39 | documentHeading_FontId = maxVariants_Fonts * 2, /* heading font */ |
40 | documentHeading_FontId = maxVariants_Fonts * 3, /* heading font */ | 40 | documentBody_FontId = maxVariants_Fonts * 3, /* body font */ |
41 | auxiliary_FontId = maxVariants_Fonts * 4, /* the first auxiliary font (e.g., symbols) */ | 41 | documentMonospace_FontId = maxVariants_Fonts * 4, |
42 | 42 | auxiliary_FontId = maxVariants_Fonts * 5, /* the first auxiliary font (e.g., symbols) */ | |
43 | // defaultMedium_FontId, | ||
44 | // defaultBig_FontId, | ||
45 | // defaultLarge_FontId, | ||
46 | // defaultTiny_FontId, | ||
47 | // defaultSmall_FontId, | ||
48 | /* UI fonts: bold weight */ | ||
49 | // defaultBold_FontId, | ||
50 | // defaultMediumBold_FontId, | ||
51 | // defaultBigBold_FontId, | ||
52 | // defaultLargeBold_FontId, | ||
53 | /* content fonts */ | ||
54 | // bold_FontId, | ||
55 | // italic_FontId, | ||
56 | // medium_FontId, | ||
57 | // big_FontId, | ||
58 | // largeBold_FontId, | ||
59 | // largeLight_FontId, | ||
60 | // hugeBold_FontId, | ||
61 | // monospaceSmall_FontId, | ||
62 | /* extra content fonts */ | ||
63 | // defaultContentRegular_FontId, /* UI font but sized to regular_FontId */ | ||
64 | // defaultContentSmall_FontId, /* UI font but sized smaller */ | ||
65 | /* symbols and scripts */ | ||
66 | // userSymbols_FontId, | ||
67 | // iosevka_FontId = userSymbols_FontId + max_FontSize, | ||
68 | // symbols_FontId = iosevka_FontId + max_FontSize, | ||
69 | // symbols2_FontId = symbols_FontId + max_FontSize, | ||
70 | // smolEmoji_FontId = symbols2_FontId + max_FontSize, | ||
71 | // notoEmoji_FontId = smolEmoji_FontId + max_FontSize, | ||
72 | // japanese_FontId = notoEmoji_FontId + max_FontSize, | ||
73 | // chineseSimplified_FontId = japanese_FontId + max_FontSize, | ||
74 | // korean_FontId = chineseSimplified_FontId + max_FontSize, | ||
75 | // arabic_FontId = korean_FontId + max_FontSize, | ||
76 | // max_FontId = arabic_FontId + max_FontSize, | ||
77 | 43 | ||
78 | /* Meta: */ | 44 | /* Meta: */ |
79 | mask_FontId = 0x0000ffff, /* font IDs are 16-bit; see GmRun's packing */ | 45 | mask_FontId = 0x0000ffff, /* font IDs are 16-bit; see GmRun's packing */ |
80 | alwaysVariableFlag_FontId = 0x00010000, | 46 | alwaysVariableFlag_FontId = 0x00010000, |
81 | 47 | ||
82 | /* UI fonts: */ | 48 | /* UI fonts: */ |
83 | uiLabelTiny_FontId = FONT_ID(default_FontId, semiBold_FontStyle, uiTiny_FontSize), | 49 | uiLabelTiny_FontId = FONT_ID(default_FontId, semiBold_FontStyle, uiTiny_FontSize), |
84 | uiLabelSmall_FontId = FONT_ID(default_FontId, regular_FontStyle, uiSmall_FontSize), | 50 | uiLabelSmall_FontId = FONT_ID(default_FontId, regular_FontStyle, uiSmall_FontSize), |
85 | uiLabel_FontId = FONT_ID(default_FontId, regular_FontStyle, uiNormal_FontSize), | 51 | uiLabel_FontId = FONT_ID(default_FontId, regular_FontStyle, uiNormal_FontSize), |
86 | uiLabelMedium_FontId = FONT_ID(default_FontId, regular_FontStyle, uiMedium_FontSize), | 52 | uiLabelMedium_FontId = FONT_ID(default_FontId, regular_FontStyle, uiMedium_FontSize), |
87 | uiLabelMediumBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiMedium_FontSize), | 53 | uiLabelMediumBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiMedium_FontSize), |
88 | uiLabelBig_FontId = FONT_ID(default_FontId, regular_FontStyle, uiBig_FontSize), | 54 | uiLabelBig_FontId = FONT_ID(default_FontId, regular_FontStyle, uiBig_FontSize), |
89 | uiLabelBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiNormal_FontSize), | 55 | uiLabelBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiNormal_FontSize), |
90 | uiLabelBigBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiBig_FontSize), | 56 | uiLabelBigBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiBig_FontSize), |
91 | uiLabelLarge_FontId = FONT_ID(default_FontId, regular_FontStyle, uiLarge_FontSize), | 57 | uiLabelLarge_FontId = FONT_ID(default_FontId, regular_FontStyle, uiLarge_FontSize), |
92 | uiLabelLargeBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiLarge_FontSize), | 58 | uiLabelLargeBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiLarge_FontSize), |
93 | uiLabelSymbols_FontId = FONT_ID(auxiliary_FontId, regular_FontStyle, uiNormal_FontSize), | 59 | uiLabelSymbols_FontId = FONT_ID(auxiliary_FontId, regular_FontStyle, uiNormal_FontSize), |
94 | uiShortcuts_FontId = FONT_ID(default_FontId, regular_FontStyle, uiNormal_FontSize), | 60 | uiShortcuts_FontId = FONT_ID(default_FontId, regular_FontStyle, uiNormal_FontSize), |
95 | uiInput_FontId = FONT_ID(default_FontId, regular_FontStyle, uiMedium_FontSize), | 61 | uiInput_FontId = FONT_ID(default_FontId, regular_FontStyle, uiMedium_FontSize), |
96 | uiContent_FontId = FONT_ID(default_FontId, regular_FontStyle, uiMedium_FontSize), | 62 | uiContent_FontId = FONT_ID(default_FontId, regular_FontStyle, uiMedium_FontSize), |
97 | uiContentBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiMedium_FontSize), | 63 | uiContentBold_FontId = FONT_ID(default_FontId, bold_FontStyle, uiMedium_FontSize), |
98 | uiContentSymbols_FontId = FONT_ID(auxiliary_FontId, regular_FontStyle, uiMedium_FontSize), | 64 | uiContentSymbols_FontId = FONT_ID(auxiliary_FontId, regular_FontStyle, uiMedium_FontSize), |
99 | /* Document fonts: */ | 65 | |
100 | paragraph_FontId = FONT_ID(documentBody_FontId, regular_FontStyle, contentRegular_FontSize), | 66 | /* Document fonts: */ |
101 | bold_FontId = FONT_ID(documentBody_FontId, semiBold_FontStyle, contentRegular_FontSize), | 67 | paragraph_FontId = FONT_ID(documentBody_FontId, regular_FontStyle, contentRegular_FontSize), |
102 | firstParagraph_FontId = FONT_ID(documentBody_FontId, regular_FontStyle, contentMedium_FontSize), | 68 | bold_FontId = FONT_ID(documentBody_FontId, semiBold_FontStyle, contentRegular_FontSize), |
103 | preformatted_FontId = FONT_ID(monospace_FontId, regular_FontStyle, contentMono_FontSize), | 69 | firstParagraph_FontId = FONT_ID(documentBody_FontId, regular_FontStyle, contentMedium_FontSize), |
104 | preformattedSmall_FontId = FONT_ID(monospace_FontId, regular_FontStyle, contentMonoSmall_FontSize), | 70 | preformatted_FontId = FONT_ID(monospace_FontId, regular_FontStyle, contentSmall_FontSize), |
105 | quote_FontId = FONT_ID(documentBody_FontId, italic_FontStyle, contentRegular_FontSize), | 71 | preformattedSmall_FontId = FONT_ID(monospace_FontId, regular_FontStyle, contentTiny_FontSize), |
106 | heading1_FontId = FONT_ID(documentHeading_FontId, bold_FontStyle, contentHuge_FontSize), | 72 | quote_FontId = FONT_ID(documentBody_FontId, italic_FontStyle, contentRegular_FontSize), |
107 | heading2_FontId = FONT_ID(documentHeading_FontId, bold_FontStyle, contentLarge_FontSize), | 73 | heading1_FontId = FONT_ID(documentHeading_FontId, bold_FontStyle, contentHuge_FontSize), |
108 | heading3_FontId = FONT_ID(documentHeading_FontId, regular_FontStyle, contentBig_FontSize), | 74 | heading2_FontId = FONT_ID(documentHeading_FontId, bold_FontStyle, contentLarge_FontSize), |
109 | banner_FontId = FONT_ID(documentHeading_FontId, light_FontStyle, contentLarge_FontSize), | 75 | heading3_FontId = FONT_ID(documentHeading_FontId, regular_FontStyle, contentBig_FontSize), |
110 | regularMonospace_FontId = FONT_ID(monospace_FontId, regular_FontStyle, contentRegular_FontSize), | 76 | banner_FontId = FONT_ID(documentHeading_FontId, light_FontStyle, contentLarge_FontSize), |
77 | monospaceParagraph_FontId = FONT_ID(documentMonospace_FontId, regular_FontStyle, contentRegular_FontSize), | ||
78 | monospaceBold_FontId = FONT_ID(documentMonospace_FontId, semiBold_FontStyle, contentRegular_FontSize), | ||
79 | plainText_FontId = FONT_ID(documentMonospace_FontId, regular_FontStyle, contentRegular_FontSize), | ||
111 | }; | 80 | }; |
112 | 81 | ||
113 | //iLocalDef iBool isJapanese_FontId(enum iFontId id) { | 82 | //iLocalDef iBool isJapanese_FontId(enum iFontId id) { |
@@ -116,6 +85,7 @@ enum iFontId { | |||
116 | 85 | ||
117 | #define emojiVariationSelector_Char ((iChar) 0xfe0f) | 86 | #define emojiVariationSelector_Char ((iChar) 0xfe0f) |
118 | 87 | ||
88 | #if 0 | ||
119 | /* TODO: get rid of this; configure using font ID strings, check RTL from FontFile flags */ | 89 | /* TODO: get rid of this; configure using font ID strings, check RTL from FontFile flags */ |
120 | enum iTextFont { | 90 | enum iTextFont { |
121 | undefined_TextFont = -1, | 91 | undefined_TextFont = -1, |
@@ -129,6 +99,7 @@ enum iTextFont { | |||
129 | arabic_TextFont, | 99 | arabic_TextFont, |
130 | emojiAndSymbols_TextFont, | 100 | emojiAndSymbols_TextFont, |
131 | }; | 101 | }; |
102 | #endif | ||
132 | 103 | ||
133 | extern int gap_Text; /* affected by content font size */ | 104 | extern int gap_Text; /* affected by content font size */ |
134 | 105 | ||
@@ -140,11 +111,10 @@ void deinit_Text (iText *); | |||
140 | 111 | ||
141 | void setCurrent_Text (iText *); | 112 | void setCurrent_Text (iText *); |
142 | 113 | ||
143 | //void loadUserFonts_Text (void); /* based on Prefs */ | 114 | //void setContentFont_Text (iText *, enum iTextFont font); |
144 | 115 | //void setHeadingFont_Text (iText *, enum iTextFont font); | |
145 | void setContentFont_Text (iText *, enum iTextFont font); | 116 | //void setFont_Text (iText *, int fontId, const char *fontSpecId); |
146 | void setHeadingFont_Text (iText *, enum iTextFont font); | 117 | void setDocumentFontSize_Text(iText *, float fontSizeFactor); /* affects all except `default*` fonts */ |
147 | void setContentFontSize_Text (iText *, float fontSizeFactor); /* affects all except `default*` fonts */ | ||
148 | void resetFonts_Text (iText *); | 118 | void resetFonts_Text (iText *); |
149 | 119 | ||
150 | int lineHeight_Text (int fontId); | 120 | int lineHeight_Text (int fontId); |
diff --git a/src/ui/util.c b/src/ui/util.c index ae72dbee..73193c7a 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1931,7 +1931,38 @@ static void addRadioButton_(iWidget *parent, const char *id, const char *label, | |||
1931 | id); | 1931 | id); |
1932 | } | 1932 | } |
1933 | 1933 | ||
1934 | static iBool proportionalFonts_(const iFontSpec *spec) { | ||
1935 | return (spec->flags & monospace_FontSpecFlag) == 0 && ~spec->flags & auxiliary_FontSpecFlag; | ||
1936 | } | ||
1937 | |||
1938 | static iBool monospaceFonts_(const iFontSpec *spec) { | ||
1939 | return (spec->flags & monospace_FontSpecFlag) != 0 && ~spec->flags & auxiliary_FontSpecFlag; | ||
1940 | } | ||
1941 | |||
1934 | static const iArray *makeFontItems_(const char *id) { | 1942 | static const iArray *makeFontItems_(const char *id) { |
1943 | iArray *items = collectNew_Array(sizeof(iMenuItem)); | ||
1944 | if (!startsWith_CStr(id, "mono")) { | ||
1945 | iConstForEach(PtrArray, i, listSpecs_Fonts(proportionalFonts_)) { | ||
1946 | const iFontSpec *spec = i.ptr; | ||
1947 | pushBack_Array( | ||
1948 | items, | ||
1949 | &(iMenuItem){ cstr_String(&spec->name), | ||
1950 | 0, | ||
1951 | 0, | ||
1952 | format_CStr("!font.set %s:%s", id, cstr_String(&spec->id)) }); | ||
1953 | } | ||
1954 | pushBack_Array(items, &(iMenuItem){ "---" }); | ||
1955 | } | ||
1956 | iConstForEach(PtrArray, j, listSpecs_Fonts(monospaceFonts_)) { | ||
1957 | const iFontSpec *spec = j.ptr; | ||
1958 | pushBack_Array( | ||
1959 | items, | ||
1960 | &(iMenuItem){ cstr_String(&spec->name), | ||
1961 | 0, | ||
1962 | 0, | ||
1963 | format_CStr("!font.set %s:%s", id, cstr_String(&spec->id)) }); | ||
1964 | } | ||
1965 | #if 0 | ||
1935 | const struct { | 1966 | const struct { |
1936 | const char * name; | 1967 | const char * name; |
1937 | enum iTextFont cfgId; | 1968 | enum iTextFont cfgId; |
@@ -1943,7 +1974,6 @@ static const iArray *makeFontItems_(const char *id) { | |||
1943 | { "Tinos", tinos_TextFont }, | 1974 | { "Tinos", tinos_TextFont }, |
1944 | { "---", -1 }, | 1975 | { "---", -1 }, |
1945 | { "Iosevka", iosevka_TextFont } }; | 1976 | { "Iosevka", iosevka_TextFont } }; |
1946 | iArray *items = collectNew_Array(sizeof(iMenuItem)); | ||
1947 | iForIndices(i, fonts) { | 1977 | iForIndices(i, fonts) { |
1948 | pushBack_Array(items, | 1978 | pushBack_Array(items, |
1949 | &(iMenuItem){ fonts[i].name, | 1979 | &(iMenuItem){ fonts[i].name, |
@@ -1953,17 +1983,19 @@ static const iArray *makeFontItems_(const char *id) { | |||
1953 | ? format_CStr("!%s.set arg:%d", id, fonts[i].cfgId) | 1983 | ? format_CStr("!%s.set arg:%d", id, fonts[i].cfgId) |
1954 | : NULL }); | 1984 | : NULL }); |
1955 | } | 1985 | } |
1986 | #endif | ||
1956 | pushBack_Array(items, &(iMenuItem){ NULL }); /* terminator */ | 1987 | pushBack_Array(items, &(iMenuItem){ NULL }); /* terminator */ |
1957 | return items; | 1988 | return items; |
1958 | } | 1989 | } |
1959 | 1990 | ||
1960 | static void addFontButtons_(iWidget *parent, const char *id) { | 1991 | static void addFontButtons_(iWidget *parent, const char *id) { |
1961 | const iArray *items = makeFontItems_(id); | 1992 | const iArray *items = makeFontItems_(id); |
1962 | iLabelWidget *button = makeMenuButton_LabelWidget("Source Sans 3", | 1993 | size_t widestIndex = findWidestLabel_MenuItem(constData_Array(items), size_Array(items)); |
1994 | iLabelWidget *button = makeMenuButton_LabelWidget(constValue_Array(items, widestIndex, iMenuItem).label, | ||
1963 | constData_Array(items), size_Array(items)); | 1995 | constData_Array(items), size_Array(items)); |
1964 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), | 1996 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), |
1965 | uiBackgroundMenu_ColorId); | 1997 | uiBackgroundMenu_ColorId); |
1966 | setId_Widget(as_Widget(button), format_CStr("prefs.%s", id)); | 1998 | setId_Widget(as_Widget(button), format_CStr("prefs.font.%s", id)); |
1967 | addChildFlags_Widget(parent, iClob(button), alignLeft_WidgetFlag); | 1999 | addChildFlags_Widget(parent, iClob(button), alignLeft_WidgetFlag); |
1968 | } | 2000 | } |
1969 | 2001 | ||
@@ -2170,11 +2202,11 @@ iWidget *makePreferences_Widget(void) { | |||
2170 | { NULL } | 2202 | { NULL } |
2171 | }; | 2203 | }; |
2172 | const iMenuItem lineWidthItems[] = { | 2204 | const iMenuItem lineWidthItems[] = { |
2173 | { "button id:prefs.linewidth.50 text:\u20132", 0, 0, "linewidth.set arg:50" }, | 2205 | { "button id:prefs.linewidth.30 text:\u20132", 0, 0, "linewidth.set arg:30" }, |
2174 | { "button id:prefs.linewidth.58 text:\u20131", 0, 0, "linewidth.set arg:58" }, | 2206 | { "button id:prefs.linewidth.34 text:\u20131", 0, 0, "linewidth.set arg:34" }, |
2175 | { "button id:prefs.linewidth.66 label:prefs.linewidth.normal", 0, 0, "linewidth.set arg:66" }, | 2207 | { "button id:prefs.linewidth.38 label:prefs.linewidth.normal", 0, 0, "linewidth.set arg:38" }, |
2176 | { "button id:prefs.linewidth.76 text:+1", 0, 0, "linewidth.set arg:76" }, | 2208 | { "button id:prefs.linewidth.43 text:+1", 0, 0, "linewidth.set arg:43" }, |
2177 | { "button id:prefs.linewidth.86 text:+2", 0, 0, "linewidth.set arg:86" }, | 2209 | { "button id:prefs.linewidth.48 text:+2", 0, 0, "linewidth.set arg:48" }, |
2178 | { "button id:prefs.linewidth.1000 label:prefs.linewidth.fill", 0, 0, "linewidth.set arg:1000" }, | 2210 | { "button id:prefs.linewidth.1000 label:prefs.linewidth.fill", 0, 0, "linewidth.set arg:1000" }, |
2179 | { NULL } | 2211 | { NULL } |
2180 | }; | 2212 | }; |
@@ -2491,10 +2523,14 @@ iWidget *makePreferences_Widget(void) { | |||
2491 | /* Fonts. */ { | 2523 | /* Fonts. */ { |
2492 | setId_Widget(appendTwoColumnTabPage_Widget(tabs, "${heading.prefs.fonts}", '4', &headings, &values), "prefs.page.fonts"); | 2524 | setId_Widget(appendTwoColumnTabPage_Widget(tabs, "${heading.prefs.fonts}", '4', &headings, &values), "prefs.page.fonts"); |
2493 | /* Fonts. */ { | 2525 | /* Fonts. */ { |
2494 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.headingfont}"))); | 2526 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.ui}"))); |
2495 | addFontButtons_(values, "headingfont"); | 2527 | addFontButtons_(values, "ui"); |
2496 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font}"))); | 2528 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.heading}"))); |
2497 | addFontButtons_(values, "font"); | 2529 | addFontButtons_(values, "heading"); |
2530 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.body}"))); | ||
2531 | addFontButtons_(values, "body"); | ||
2532 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.mono}"))); | ||
2533 | addFontButtons_(values, "mono"); | ||
2498 | addDialogPadding_(headings, values); | 2534 | addDialogPadding_(headings, values); |
2499 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.mono}"))); | 2535 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.mono}"))); |
2500 | iWidget *mono = new_Widget(); { | 2536 | iWidget *mono = new_Widget(); { |
@@ -2511,6 +2547,9 @@ iWidget *makePreferences_Widget(void) { | |||
2511 | updateSize_LabelWidget((iLabelWidget *) tog); | 2547 | updateSize_LabelWidget((iLabelWidget *) tog); |
2512 | } | 2548 | } |
2513 | addChildFlags_Widget(values, iClob(mono), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 2549 | addChildFlags_Widget(values, iClob(mono), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
2550 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.font.monodoc}"))); | ||
2551 | addFontButtons_(values, "monodoc"); | ||
2552 | addDialogPadding_(headings, values); | ||
2514 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.boldlink}"))); | 2553 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.boldlink}"))); |
2515 | iWidget *boldLink = new_Widget(); { | 2554 | iWidget *boldLink = new_Widget(); { |
2516 | /* TODO: Add a utility function for this type of toggles? (also for above) */ | 2555 | /* TODO: Add a utility function for this type of toggles? (also for above) */ |
@@ -2528,11 +2567,11 @@ iWidget *makePreferences_Widget(void) { | |||
2528 | } | 2567 | } |
2529 | addChildFlags_Widget(values, iClob(boldLink), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 2568 | addChildFlags_Widget(values, iClob(boldLink), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
2530 | addDialogPadding_(headings, values); | 2569 | addDialogPadding_(headings, values); |
2531 | /* Custom font. */ { | 2570 | // /* Custom font. */ { |
2532 | iInputWidget *customFont = new_InputWidget(0); | 2571 | // iInputWidget *customFont = new_InputWidget(0); |
2533 | setHint_InputWidget(customFont, "${hint.prefs.userfont}"); | 2572 | // setHint_InputWidget(customFont, "${hint.prefs.userfont}"); |
2534 | addPrefsInputWithHeading_(headings, values, "prefs.userfont", iClob(customFont)); | 2573 | // addPrefsInputWithHeading_(headings, values, "prefs.userfont", iClob(customFont)); |
2535 | } | 2574 | // } |
2536 | } | 2575 | } |
2537 | } | 2576 | } |
2538 | /* Style. */ { | 2577 | /* Style. */ { |