summaryrefslogtreecommitdiff
path: root/src/ui/text.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/text.c')
-rw-r--r--src/ui/text.c51
1 files changed, 34 insertions, 17 deletions
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 }