summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-05-25 18:25:40 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-05-25 18:25:51 +0300
commitf53e6d34fbb8d2f2fb54aff8b746b1c5d06fe497 (patch)
treec8cbe09db582b66262dd6472bd55be7b485fdf66 /src/ui
parent54d38100bb49a34f9ad11570e0144dc1ec006858 (diff)
Removed Symbola, replaced with other/new fonts
Symbola's license is not permissive enough, so it has been removed. Added "Smol Emoji" with face emoticons and other UI characters for Lagrange. More symbols provided by Noto Sans Symbols and Noto Sans Symbols 2. The fallback fonts are now Iosevka, which has a pretty good coverage (although monospace), and the user's chosen TrueType font (which could still be a local copy of Symbola). Still a work in progress: some characters are missing. IssueID #283
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/inputwidget.h5
-rw-r--r--src/ui/keys.c8
-rw-r--r--src/ui/root.c8
-rw-r--r--src/ui/text.c127
-rw-r--r--src/ui/text.h16
-rw-r--r--src/ui/util.c2
6 files changed, 109 insertions, 57 deletions
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);
63void setEatEscape_InputWidget (iInputWidget *, iBool eatEscape); 63void setEatEscape_InputWidget (iInputWidget *, iBool eatEscape);
64 64
65const iString * text_InputWidget (const iInputWidget *); 65const iString * text_InputWidget (const iInputWidget *);
66
67iLocalDef const char *cstrText_InputWidget(const iInputWidget *d) {
68 return cstr_String(text_InputWidget(d));
69}
70
66iInputWidgetContentPadding 71iInputWidgetContentPadding
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) {
311static void updateLookup_Keys_(iKeys *d) { 311static 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? */
157static const char *stopSeqCStr_[] = { 157static 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
218static iText text_; 214static iText text_;
215static iBlock *userFont_;
219 216
220static void initFonts_Text_(iText *d) { 217static 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
405void 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
404void init_Text(SDL_Renderer *render) { 424void 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
544iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) { 565iLocalDef 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
600static iGlyph *glyph_Font_(iFont *d, iChar ch) { 639static 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
107iLocalDef iBool isJapanese_FontId(enum iFontId id) { 111iLocalDef iBool isJapanese_FontId(enum iFontId id) {
@@ -124,6 +128,8 @@ extern int gap_Text; /* affected by content font size */
124void init_Text (SDL_Renderer *); 128void init_Text (SDL_Renderer *);
125void deinit_Text (void); 129void deinit_Text (void);
126 130
131void loadUserFonts_Text (void); /* based on Prefs */
132
127void setContentFont_Text (enum iTextFont font); 133void setContentFont_Text (enum iTextFont font);
128void setHeadingFont_Text (enum iTextFont font); 134void setHeadingFont_Text (enum iTextFont font);
129void setContentFontSize_Text (float fontSizeFactor); /* affects all except `default*` fonts */ 135void 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}")));