diff options
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 51 |
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 | ||
177 | static void initFonts_Text_(iText *d) { | 177 | static 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 | } |