summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--res/about/license.gmi3
-rw-r--r--res/about/version.gmi5
-rw-r--r--res/fonts/FiraMono-Regular.ttfbin174632 -> 0 bytes
-rw-r--r--res/fonts/IosevkaTerm-Extended.ttfbin0 -> 1503504 bytes
-rw-r--r--src/ui/text.c51
-rw-r--r--src/ui/text.h21
7 files changed, 51 insertions, 31 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 995432cb..394f1b6b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,7 +61,7 @@ set (EMBED_RESOURCES
61 res/fonts/Tinos-Regular.ttf 61 res/fonts/Tinos-Regular.ttf
62 res/fonts/Tinos-Italic.ttf 62 res/fonts/Tinos-Italic.ttf
63 res/fonts/Tinos-Bold.ttf 63 res/fonts/Tinos-Bold.ttf
64 res/fonts/FiraMono-Regular.ttf 64 res/fonts/IosevkaTerm-Extended.ttf
65 res/fonts/FiraSans-Bold.ttf 65 res/fonts/FiraSans-Bold.ttf
66 res/fonts/FiraSans-Italic.ttf 66 res/fonts/FiraSans-Italic.ttf
67 res/fonts/FiraSans-Light.ttf 67 res/fonts/FiraSans-Light.ttf
diff --git a/res/about/license.gmi b/res/about/license.gmi
index 0ea0897a..d5ffe3c4 100644
--- a/res/about/license.gmi
+++ b/res/about/license.gmi
@@ -100,7 +100,8 @@ The libunistring library is covered by the GNU Lesser General Public License (LG
100 100
101This application uses fonts licensed under the Open Font License. 101This application uses fonts licensed under the Open Font License.
102 102
103=> https://github.com/mozilla/Fira/blob/master/LICENSE Fira Sans, Fira Mono 103=> https://github.com/mozilla/Fira/blob/master/LICENSE Fira Sans
104=> https://typeof.net/Iosevka/ Iosevka
104=> https://github.com/googlefonts/literata/blob/master/OFL.txt Literata 105=> https://github.com/googlefonts/literata/blob/master/OFL.txt Literata
105=> https://github.com/google/fonts/blob/master/ofl/nanumgothic/OFL.txt Nanum Gothic 106=> https://github.com/google/fonts/blob/master/ofl/nanumgothic/OFL.txt Nanum Gothic
106=> https://www.google.com/get/noto/help/cjk/ Noto Sans CJK JP 107=> https://www.google.com/get/noto/help/cjk/ Noto Sans CJK JP
diff --git a/res/about/version.gmi b/res/about/version.gmi
index 42475e13..1932baa1 100644
--- a/res/about/version.gmi
+++ b/res/about/version.gmi
@@ -8,9 +8,9 @@
8 8
9## 0.13 9## 0.13
10* Support for Internationalized Domain Names (IDN) in network requests. 10* Support for Internationalized Domain Names (IDN) in network requests.
11* IDNs show up in decoded form in the UI. 11* UI shows decoded IDNs.
12* Percent-encoded Unicode characters in URL paths are decoded for the UI, and encoded in outgoing requests. 12* Percent-encoded Unicode characters in URL paths are decoded for the UI, and encoded in outgoing requests.
13* Added option to disable decoding of percent-encoded paths. 13* Added option to disable decoding of percent-encoded paths for the UI.
14* Quick search via URL bar shows entries from subscribed feeds. 14* Quick search via URL bar shows entries from subscribed feeds.
15* Added keybindings for zooming. 15* Added keybindings for zooming.
16* Improved usability of page content searching (${CTRL+}F, Escape). 16* Improved usability of page content searching (${CTRL+}F, Escape).
@@ -19,6 +19,7 @@
19* Fixed handling of Unicode joiners and modifiers (by ignoring them, since we lack the glyphs). 19* Fixed handling of Unicode joiners and modifiers (by ignoring them, since we lack the glyphs).
20* Fixed a layout issue with sidebars where the bottommost content line was occasionally not visible. 20* Fixed a layout issue with sidebars where the bottommost content line was occasionally not visible.
21* Fixed exit when a hook program didn't read its input. 21* Fixed exit when a hook program didn't read its input.
22* Fixed use of variable-width fonts in input fields.
22* Fixed crash when using an identity (with LibreSSL on OpenBSD). 23* Fixed crash when using an identity (with LibreSSL on OpenBSD).
23 24
24## 0.12.1 25## 0.12.1
diff --git a/res/fonts/FiraMono-Regular.ttf b/res/fonts/FiraMono-Regular.ttf
deleted file mode 100644
index 59e1e1a1..00000000
--- a/res/fonts/FiraMono-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/res/fonts/IosevkaTerm-Extended.ttf b/res/fonts/IosevkaTerm-Extended.ttf
new file mode 100644
index 00000000..16989a85
--- /dev/null
+++ b/res/fonts/IosevkaTerm-Extended.ttf
Binary files differ
diff --git a/src/ui/text.c b/src/ui/text.c
index 4229217c..ec240c75 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -120,10 +120,10 @@ static void init_Font(iFont *d, const iBlock *data, int height, float scale,
120 d->xScale *= floorf(advance) / advance; 120 d->xScale *= floorf(advance) / advance;
121 } 121 }
122 } 122 }
123 d->vertOffset = height * (1.0f - scale) / 2; 123 d->vertOffset = height * (1.0f - scale) / 2;
124 int ascent; 124 int ascent;
125 stbtt_GetFontVMetrics(&d->font, &ascent, NULL, NULL); 125 stbtt_GetFontVMetrics(&d->font, &ascent, NULL, NULL);
126 d->baseline = ceil(ascent * d->yScale); 126 d->baseline = /*ceil*/(ascent * d->yScale);
127 d->symbolsFont = symbolsFont; 127 d->symbolsFont = symbolsFont;
128 d->japaneseFont = regularJapanese_FontId; 128 d->japaneseFont = regularJapanese_FontId;
129 d->koreanFont = regularKorean_FontId; 129 d->koreanFont = regularKorean_FontId;
@@ -176,8 +176,8 @@ static iText text_;
176 176
177static void initFonts_Text_(iText *d) { 177static void initFonts_Text_(iText *d) {
178 const float textSize = fontSize_UI * d->contentFontSize; 178 const float textSize = fontSize_UI * d->contentFontSize;
179 const float monoSize = fontSize_UI * d->contentFontSize / contentScale_Text_ * 0.866f; 179 const float monoSize = textSize * 0.71f; //fontSize_UI * d->contentFontSize / contentScale_Text_ * 1.0f; //0.866f;
180 const float smallMonoSize = monoSize * 0.866f; 180 const float smallMonoSize = monoSize * 0.8f;
181 const iBlock *regularFont = &fontNunitoRegular_Embedded; 181 const iBlock *regularFont = &fontNunitoRegular_Embedded;
182 const iBlock *italicFont = &fontNunitoLightItalic_Embedded; 182 const iBlock *italicFont = &fontNunitoLightItalic_Embedded;
183 const iBlock *h12Font = &fontNunitoExtraBold_Embedded; 183 const iBlock *h12Font = &fontNunitoExtraBold_Embedded;
@@ -226,12 +226,12 @@ static void initFonts_Text_(iText *d) {
226 { &fontSourceSansProRegular_Embedded, fontSize_UI, 1.0f, defaultSymbols_FontId }, 226 { &fontSourceSansProRegular_Embedded, fontSize_UI, 1.0f, defaultSymbols_FontId },
227 { &fontSourceSansProRegular_Embedded, fontSize_UI * 1.125f, 1.0f, defaultMediumSymbols_FontId }, 227 { &fontSourceSansProRegular_Embedded, fontSize_UI * 1.125f, 1.0f, defaultMediumSymbols_FontId },
228 { &fontSourceSansProRegular_Embedded, fontSize_UI * 1.666f, 1.0f, defaultLargeSymbols_FontId }, 228 { &fontSourceSansProRegular_Embedded, fontSize_UI * 1.666f, 1.0f, defaultLargeSymbols_FontId },
229 { &fontFiraMonoRegular_Embedded, fontSize_UI * 0.866f, 1.0f, defaultSymbols_FontId }, 229 { &fontIosevkaTermExtended_Embedded, fontSize_UI * 0.866f, 1.0f, defaultSymbols_FontId },
230 { &fontSourceSansProRegular_Embedded, textSize, scaling, symbols_FontId }, 230 { &fontSourceSansProRegular_Embedded, textSize, scaling, symbols_FontId },
231 /* content fonts */ 231 /* content fonts */
232 { regularFont, textSize, scaling, symbols_FontId }, 232 { regularFont, textSize, scaling, symbols_FontId },
233 { &fontFiraMonoRegular_Embedded, monoSize, 1.0f, monospaceSymbols_FontId }, 233 { &fontIosevkaTermExtended_Embedded, monoSize, 1.0f, monospaceSymbols_FontId },
234 { &fontFiraMonoRegular_Embedded, smallMonoSize, 1.0f, monospaceSmallSymbols_FontId }, 234 { &fontIosevkaTermExtended_Embedded, smallMonoSize, 1.0f, monospaceSmallSymbols_FontId },
235 { regularFont, textSize * 1.200f, scaling, mediumSymbols_FontId }, 235 { regularFont, textSize * 1.200f, scaling, mediumSymbols_FontId },
236 { h3Font, textSize * 1.333f, h123Scaling, bigSymbols_FontId }, 236 { h3Font, textSize * 1.333f, h123Scaling, bigSymbols_FontId },
237 { italicFont, textSize, scaling, symbols_FontId }, 237 { italicFont, textSize, scaling, symbols_FontId },
@@ -239,7 +239,7 @@ static void initFonts_Text_(iText *d) {
239 { h12Font, textSize * 2.000f, h123Scaling, hugeSymbols_FontId }, 239 { h12Font, textSize * 2.000f, h123Scaling, hugeSymbols_FontId },
240 { lightFont, textSize * 1.666f, lightScaling, largeSymbols_FontId }, 240 { lightFont, textSize * 1.666f, lightScaling, largeSymbols_FontId },
241 /* monospace content fonts */ 241 /* monospace content fonts */
242 { &fontFiraMonoRegular_Embedded, textSize, 0.8f, symbols_FontId }, 242 { &fontIosevkaTermExtended_Embedded, textSize, 0.866f, symbols_FontId },
243 /* symbol fonts */ 243 /* symbol fonts */
244 { &fontSymbola_Embedded, fontSize_UI, 1.0f, defaultSymbols_FontId }, 244 { &fontSymbola_Embedded, fontSize_UI, 1.0f, defaultSymbols_FontId },
245 { &fontSymbola_Embedded, fontSize_UI * 1.125f, 1.0f, defaultMediumSymbols_FontId }, 245 { &fontSymbola_Embedded, fontSize_UI * 1.125f, 1.0f, defaultMediumSymbols_FontId },
@@ -288,7 +288,7 @@ static void initFonts_Text_(iText *d) {
288 fontData[i].size, 288 fontData[i].size,
289 fontData[i].scaling, 289 fontData[i].scaling,
290 fontData[i].symbolsFont, 290 fontData[i].symbolsFont,
291 fontData[i].ttf == &fontFiraMonoRegular_Embedded); 291 fontData[i].ttf == &fontIosevkaTermExtended_Embedded);
292 if (i == default_FontId || i == defaultMedium_FontId) { 292 if (i == default_FontId || i == defaultMedium_FontId) {
293 font->manualKernOnly = iTrue; 293 font->manualKernOnly = iTrue;
294 } 294 }
@@ -636,6 +636,7 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
636 iRect bounds = zero_Rect(); 636 iRect bounds = zero_Rect();
637 const iInt2 orig = pos; 637 const iInt2 orig = pos;
638 float xpos = pos.x; 638 float xpos = pos.x;
639 float xposExtend = pos.x; /* allows wide glyphs to use more space; restored by whitespace */
639 float xposMax = xpos; 640 float xposMax = xpos;
640 float monoAdvance = 0; 641 float monoAdvance = 0;
641 iAssert(xposLimit == 0 || isMeasuring_(mode)); 642 iAssert(xposLimit == 0 || isMeasuring_(mode));
@@ -668,6 +669,7 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
668 } 669 }
669 } 670 }
670 iChar ch = nextChar_(&chPos, text.end); 671 iChar ch = nextChar_(&chPos, text.end);
672 iBool isEmoji = isEmoji_Char(ch);
671 if (ch == 0x200d) { /* zero-width joiner */ 673 if (ch == 0x200d) { /* zero-width joiner */
672 /* We don't have the composited Emojis. */ 674 /* We don't have the composited Emojis. */
673 if (isEmoji_Char(prevCh)) { 675 if (isEmoji_Char(prevCh)) {
@@ -676,9 +678,19 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
676 ch = nextChar_(&chPos, text.end); 678 ch = nextChar_(&chPos, text.end);
677 } 679 }
678 } 680 }
681#if 0
682 iChar nextCh = 0; {
683 /* TODO: Since we're peeking ahead, should use this on the next loop iteration. */
684 const char *ncp = chPos;
685 nextCh = nextChar_(&ncp, text.end);
686 }
687 /* VS15: Peek ahead and treat as Emoji font. */
688 if (nextCh == emojiVariationSelector_Char) {
689 isEmoji = iTrue;
690 }
691#endif
679 if (isVariationSelector_Char(ch)) { 692 if (isVariationSelector_Char(ch)) {
680 /* TODO: VS15: Should peek ahead for this and prefer the Emoji font. */ 693 ch = nextChar_(&chPos, text.end); /* skip it */
681 ch = nextChar_(&chPos, text.end); /* just ignore */
682 } 694 }
683 /* Special instructions. */ { 695 /* Special instructions. */ {
684 if (ch == 0xad) { /* soft hyphen */ 696 if (ch == 0xad) { /* soft hyphen */
@@ -703,7 +715,7 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
703 } 715 }
704 } 716 }
705 if (ch == '\n') { 717 if (ch == '\n') {
706 xpos = pos.x; 718 xpos = xposExtend = pos.x;
707 pos.y += d->height; 719 pos.y += d->height;
708 prevCh = ch; 720 prevCh = ch;
709 continue; 721 continue;
@@ -711,6 +723,7 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
711 if (ch == '\t') { 723 if (ch == '\t') {
712 const int tabStopWidth = d->height * 8; 724 const int tabStopWidth = d->height * 8;
713 xpos = pos.x + ((int) ((xpos - pos.x) / tabStopWidth) + 1) * tabStopWidth; 725 xpos = pos.x + ((int) ((xpos - pos.x) / tabStopWidth) + 1) * tabStopWidth;
726 xposExtend = iMax(xposExtend, xpos);
714 prevCh = 0; 727 prevCh = 0;
715 continue; 728 continue;
716 } 729 }
@@ -728,7 +741,7 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
728 } 741 }
729 } 742 }
730 const iGlyph *glyph = glyph_Font_(d, ch); 743 const iGlyph *glyph = glyph_Font_(d, ch);
731 int x1 = xpos; 744 int x1 = iMax(xpos, xposExtend);
732 const int hoff = enableHalfPixelGlyphs_Text ? (xpos - x1 > 0.5f ? 1 : 0) : 0; 745 const int hoff = enableHalfPixelGlyphs_Text ? (xpos - x1 > 0.5f ? 1 : 0) : 0;
733 int x2 = x1 + glyph->rect[hoff].size.x; 746 int x2 = x1 + glyph->rect[hoff].size.x;
734 /* Out of the allotted space? */ 747 /* Out of the allotted space? */
@@ -765,11 +778,13 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
765 bounds.size.x = iMax(bounds.size.x, x2 - orig.x); 778 bounds.size.x = iMax(bounds.size.x, x2 - orig.x);
766 bounds.size.y = iMax(bounds.size.y, pos.y + glyph->font->height - orig.y); 779 bounds.size.y = iMax(bounds.size.y, pos.y + glyph->font->height - orig.y);
767 } 780 }
781 /* Symbols and emojis are NOT monospaced, so must conform when the primary font
782 is monospaced. Except with Japanese script, that's larger than the normal monospace. */
768 const iBool useMonoAdvance = 783 const iBool useMonoAdvance =
769 monoAdvance > 0 && !isJapanese_FontId(fontId_Text_(glyph->font)); 784 monoAdvance > 0 && !isJapanese_FontId(fontId_Text_(glyph->font));
770 const float advance = (useMonoAdvance ? monoAdvance : glyph->advance); 785 const float advance = (useMonoAdvance ? monoAdvance : glyph->advance);
771 if (!isMeasuring_(mode)) { 786 if (!isMeasuring_(mode)) {
772 if (useMonoAdvance && dst.w > advance && glyph->font != d) { 787 if (useMonoAdvance && dst.w > advance && glyph->font != d && !isEmoji) {
773 /* Glyphs from a different font may need recentering to look better. */ 788 /* Glyphs from a different font may need recentering to look better. */
774 dst.x -= (dst.w - advance) / 2; 789 dst.x -= (dst.w - advance) / 2;
775 } 790 }
@@ -784,10 +799,12 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
784 } 799 }
785 SDL_RenderCopy(text_.render, text_.cache, &src, &dst); 800 SDL_RenderCopy(text_.render, text_.cache, &src, &dst);
786 } 801 }
787 /* Symbols and emojis are NOT monospaced, so must conform when the primary font
788 is monospaced. Except with Japanese script, that's larger than the normal monospace. */
789 xpos += advance; 802 xpos += advance;
790 xposMax = iMax(xposMax, xpos); 803 if (!isSpace_Char(ch)) {
804 xposExtend += isEmoji ? glyph->advance : advance;
805 }
806 xposExtend = iMax(xposExtend, xpos);
807 xposMax = iMax(xposMax, xposExtend);
791 if (continueFrom_out && ((mode & noWrapFlag_RunMode) || isWrapBoundary_(prevCh, ch))) { 808 if (continueFrom_out && ((mode & noWrapFlag_RunMode) || isWrapBoundary_(prevCh, ch))) {
792 lastWordEnd = chPos; 809 lastWordEnd = chPos;
793 } 810 }
diff --git a/src/ui/text.h b/src/ui/text.h
index 6728bb62..5867a84b 100644
--- a/src/ui/text.h
+++ b/src/ui/text.h
@@ -127,7 +127,8 @@ iLocalDef iBool isDefaultIgnorable_Char(iChar c) {
127 c == 0xfeff; 127 c == 0xfeff;
128} 128}
129iLocalDef iBool isEmoji_Char(iChar c) { 129iLocalDef iBool isEmoji_Char(iChar c) {
130 return (c >= 0x1f300 && c < 0x1f700) || (c >= 0x1f900 && c <= 0x1f9ff); 130 return (c >= 0x1f300 && c < 0x1f700) || (c >= 0x1f7e0 && c <= 0x1f7eb) ||
131 (c >= 0x1f900 && c <= 0x1f9ff);
131} 132}
132 133
133#define emojiVariationSelector_Char ((iChar) 0xfe0f) 134#define emojiVariationSelector_Char ((iChar) 0xfe0f)
@@ -141,21 +142,21 @@ enum iTextFont {
141 142
142extern int gap_Text; /* affected by content font size */ 143extern int gap_Text; /* affected by content font size */
143 144
144void init_Text (SDL_Renderer *); 145void init_Text (SDL_Renderer *);
145void deinit_Text (void); 146void deinit_Text (void);
146 147
147void setContentFont_Text (enum iTextFont font); 148void setContentFont_Text (enum iTextFont font);
148void setHeadingFont_Text (enum iTextFont font); 149void setHeadingFont_Text (enum iTextFont font);
149void setContentFontSize_Text (float fontSizeFactor); /* affects all except `default*` fonts */ 150void setContentFontSize_Text (float fontSizeFactor); /* affects all except `default*` fonts */
150void resetFonts_Text (void); 151void resetFonts_Text (void);
151 152
152int lineHeight_Text (int fontId); 153int lineHeight_Text (int fontId);
153iInt2 measure_Text (int fontId, const char *text); 154iInt2 measure_Text (int fontId, const char *text);
154iInt2 measureRange_Text (int fontId, iRangecc text); 155iInt2 measureRange_Text (int fontId, iRangecc text);
155iRect visualBounds_Text (int fontId, iRangecc text); 156iRect visualBounds_Text (int fontId, iRangecc text);
156iInt2 advance_Text (int fontId, const char *text); 157iInt2 advance_Text (int fontId, const char *text);
157iInt2 advanceN_Text (int fontId, const char *text, size_t n); /* `n` in characters */ 158iInt2 advanceN_Text (int fontId, const char *text, size_t n); /* `n` in characters */
158iInt2 advanceRange_Text (int fontId, iRangecc text); 159iInt2 advanceRange_Text (int fontId, iRangecc text);
159iInt2 advanceWrapRange_Text (int fontId, int maxWidth, iRangecc text); 160iInt2 advanceWrapRange_Text (int fontId, int maxWidth, iRangecc text);
160 161
161iInt2 tryAdvance_Text (int fontId, iRangecc text, int width, const char **endPos); 162iInt2 tryAdvance_Text (int fontId, iRangecc text, int width, const char **endPos);