diff options
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/src/ui/text.c b/src/ui/text.c index e1638368..03ce46c7 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -792,7 +792,8 @@ struct Impl_AttributedRun { | |||
792 | }; | 792 | }; |
793 | 793 | ||
794 | iDeclareType(AttributedText) | 794 | iDeclareType(AttributedText) |
795 | iDeclareTypeConstructionArgs(AttributedText, iRangecc text, size_t maxLen, iFont *font, iColor fgColor) | 795 | iDeclareTypeConstructionArgs(AttributedText, iRangecc text, size_t maxLen, iFont *font, |
796 | iColor fgColor, int baseDir) | ||
796 | 797 | ||
797 | struct Impl_AttributedText { | 798 | struct Impl_AttributedText { |
798 | iRangecc source; /* original source text */ | 799 | iRangecc source; /* original source text */ |
@@ -809,8 +810,9 @@ struct Impl_AttributedText { | |||
809 | iBool isBaseRTL; | 810 | iBool isBaseRTL; |
810 | }; | 811 | }; |
811 | 812 | ||
812 | iDefineTypeConstructionArgs(AttributedText, (iRangecc text, size_t maxLen, iFont *font, iColor fgColor), | 813 | iDefineTypeConstructionArgs(AttributedText, |
813 | text, maxLen, font, fgColor) | 814 | (iRangecc text, size_t maxLen, iFont *font, iColor fgColor, int baseDir), |
815 | text, maxLen, font, fgColor, baseDir) | ||
814 | 816 | ||
815 | static const char *sourcePtr_AttributedText_(const iAttributedText *d, int logicalPos) { | 817 | static const char *sourcePtr_AttributedText_(const iAttributedText *d, int logicalPos) { |
816 | const int *logToSource = constData_Array(&d->logicalToSourceOffset); | 818 | const int *logToSource = constData_Array(&d->logicalToSourceOffset); |
@@ -867,7 +869,7 @@ static enum iFontId fontId_Text_(const iFont *font) { | |||
867 | return (enum iFontId) (font - text_.fonts); | 869 | return (enum iFontId) (font - text_.fonts); |
868 | } | 870 | } |
869 | 871 | ||
870 | static void prepare_AttributedText_(iAttributedText *d) { | 872 | static void prepare_AttributedText_(iAttributedText *d, int overrideBaseDir) { |
871 | iAssert(isEmpty_Array(&d->runs)); | 873 | iAssert(isEmpty_Array(&d->runs)); |
872 | size_t length = 0; | 874 | size_t length = 0; |
873 | /* Prepare the UTF-32 logical string. */ { | 875 | /* Prepare the UTF-32 logical string. */ { |
@@ -896,7 +898,7 @@ static void prepare_AttributedText_(iAttributedText *d) { | |||
896 | data_Array(&d->logicalToVisual), | 898 | data_Array(&d->logicalToVisual), |
897 | data_Array(&d->visualToLogical), | 899 | data_Array(&d->visualToLogical), |
898 | (FriBidiLevel *) d->bidiLevels); | 900 | (FriBidiLevel *) d->bidiLevels); |
899 | d->isBaseRTL = FRIBIDI_IS_RTL(baseDir); | 901 | d->isBaseRTL = (overrideBaseDir == 0 ? FRIBIDI_IS_RTL(baseDir) : (overrideBaseDir < 0)); |
900 | #endif | 902 | #endif |
901 | } | 903 | } |
902 | /* The mapping needs to include the terminating NULL position. */ { | 904 | /* The mapping needs to include the terminating NULL position. */ { |
@@ -1017,7 +1019,8 @@ static void prepare_AttributedText_(iAttributedText *d) { | |||
1017 | #endif | 1019 | #endif |
1018 | } | 1020 | } |
1019 | 1021 | ||
1020 | void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont *font, iColor fgColor) { | 1022 | void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont *font, iColor fgColor, |
1023 | int baseDir) { | ||
1021 | d->source = text; | 1024 | d->source = text; |
1022 | d->maxLen = maxLen ? maxLen : iInvalidSize; | 1025 | d->maxLen = maxLen ? maxLen : iInvalidSize; |
1023 | d->font = font; | 1026 | d->font = font; |
@@ -1030,7 +1033,7 @@ void init_AttributedText(iAttributedText *d, iRangecc text, size_t maxLen, iFont | |||
1030 | init_Array(&d->logicalToSourceOffset, sizeof(int)); | 1033 | init_Array(&d->logicalToSourceOffset, sizeof(int)); |
1031 | d->bidiLevels = NULL; | 1034 | d->bidiLevels = NULL; |
1032 | d->isBaseRTL = iFalse; | 1035 | d->isBaseRTL = iFalse; |
1033 | prepare_AttributedText_(d); | 1036 | prepare_AttributedText_(d, baseDir); |
1034 | } | 1037 | } |
1035 | 1038 | ||
1036 | void deinit_AttributedText(iAttributedText *d) { | 1039 | void deinit_AttributedText(iAttributedText *d) { |
@@ -1181,7 +1184,7 @@ static void cacheTextGlyphs_Font_(iFont *d, const iRangecc text) { | |||
1181 | iArray glyphIndices; | 1184 | iArray glyphIndices; |
1182 | init_Array(&glyphIndices, sizeof(uint32_t)); | 1185 | init_Array(&glyphIndices, sizeof(uint32_t)); |
1183 | iAttributedText attrText; | 1186 | iAttributedText attrText; |
1184 | init_AttributedText(&attrText, text, 0, d, (iColor){}); | 1187 | init_AttributedText(&attrText, text, 0, d, (iColor){}, 0); |
1185 | /* We use AttributedText here so the font lookup matches the behavior during text drawing -- | 1188 | /* We use AttributedText here so the font lookup matches the behavior during text drawing -- |
1186 | glyphs may be selected from a font that's different than `d`. */ | 1189 | glyphs may be selected from a font that's different than `d`. */ |
1187 | const iChar *logicalText = constData_Array(&attrText.logical); | 1190 | const iChar *logicalText = constData_Array(&attrText.logical); |
@@ -1229,9 +1232,10 @@ struct Impl_RunArgs { | |||
1229 | size_t maxLen; /* max characters to process */ | 1232 | size_t maxLen; /* max characters to process */ |
1230 | iInt2 pos; | 1233 | iInt2 pos; |
1231 | iWrapText * wrap; | 1234 | iWrapText * wrap; |
1232 | int xposLimit; /* hard limit for wrapping */ | 1235 | int xposLimit; /* hard limit for wrapping */ |
1233 | int xposLayoutBound; /* visible bound for layout purposes; does not affect wrapping */ | 1236 | int xposLayoutBound; /* visible bound for layout purposes; does not affect wrapping */ |
1234 | int color; | 1237 | int color; |
1238 | int baseDir; | ||
1235 | /* TODO: Cleanup using TextMetrics | 1239 | /* TODO: Cleanup using TextMetrics |
1236 | Use TextMetrics output pointer instead of return value & cursorAdvance_out. */ | 1240 | Use TextMetrics output pointer instead of return value & cursorAdvance_out. */ |
1237 | iInt2 * cursorAdvance_out; | 1241 | iInt2 * cursorAdvance_out; |
@@ -1239,13 +1243,13 @@ struct Impl_RunArgs { | |||
1239 | int * runAdvance_out; | 1243 | int * runAdvance_out; |
1240 | }; | 1244 | }; |
1241 | 1245 | ||
1242 | static iBool notify_WrapText_(iWrapText *d, const char *ending, int origin, int advance) { | 1246 | static iBool notify_WrapText_(iWrapText *d, const char *ending, int origin, int advance, iBool isBaseRTL) { |
1243 | if (d && d->wrapFunc && d->wrapRange_.start) { | 1247 | if (d && d->wrapFunc && d->wrapRange_.start) { |
1244 | /* `wrapRange_` uses logical indices. */ | 1248 | /* `wrapRange_` uses logical indices. */ |
1245 | const char *end = ending ? ending : d->wrapRange_.end; | 1249 | const char *end = ending ? ending : d->wrapRange_.end; |
1246 | iRangecc range = { d->wrapRange_.start, end }; | 1250 | iRangecc range = { d->wrapRange_.start, end }; |
1247 | iAssert(range.start <= range.end); | 1251 | iAssert(range.start <= range.end); |
1248 | const iBool result = d->wrapFunc(d, range, origin, advance); | 1252 | const iBool result = d->wrapFunc(d, range, origin, advance, isBaseRTL); |
1249 | if (result) { | 1253 | if (result) { |
1250 | d->wrapRange_.start = end; | 1254 | d->wrapRange_.start = end; |
1251 | } | 1255 | } |
@@ -1380,7 +1384,8 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1380 | font is used and other attributes such as color. (HarfBuzz shaping is done | 1384 | font is used and other attributes such as color. (HarfBuzz shaping is done |
1381 | with one specific font.) */ | 1385 | with one specific font.) */ |
1382 | iAttributedText attrText; | 1386 | iAttributedText attrText; |
1383 | init_AttributedText(&attrText, args->text, args->maxLen, d, get_Color(args->color)); | 1387 | init_AttributedText(&attrText, args->text, args->maxLen, d, get_Color(args->color), |
1388 | args->baseDir); | ||
1384 | if (args->wrap) { | 1389 | if (args->wrap) { |
1385 | /* TODO: Duplicated args? */ | 1390 | /* TODO: Duplicated args? */ |
1386 | iAssert(equalRange_Rangecc(args->wrap->text, args->text)); | 1391 | iAssert(equalRange_Rangecc(args->wrap->text, args->text)); |
@@ -1390,7 +1395,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1390 | const iChar *logicalText = constData_Array(&attrText.logical); | 1395 | const iChar *logicalText = constData_Array(&attrText.logical); |
1391 | const iChar *visualText = constData_Array(&attrText.visual); | 1396 | const iChar *visualText = constData_Array(&attrText.visual); |
1392 | const int * logToVis = constData_Array(&attrText.logicalToVisual); | 1397 | const int * logToVis = constData_Array(&attrText.logicalToVisual); |
1393 | const int * visToLog = constData_Array(&attrText.visualToLogical); | 1398 | // const int * visToLog = constData_Array(&attrText.visualToLogical); |
1394 | const size_t runCount = size_Array(&attrText.runs); | 1399 | const size_t runCount = size_Array(&attrText.runs); |
1395 | iArray buffers; | 1400 | iArray buffers; |
1396 | init_Array(&buffers, sizeof(iGlyphBuffer)); | 1401 | init_Array(&buffers, sizeof(iGlyphBuffer)); |
@@ -1580,7 +1585,8 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
1580 | if (!notify_WrapText_(args->wrap, | 1585 | if (!notify_WrapText_(args->wrap, |
1581 | sourcePtr_AttributedText_(&attrText, wrapResumePos), | 1586 | sourcePtr_AttributedText_(&attrText, wrapResumePos), |
1582 | origin, | 1587 | origin, |
1583 | iRound(wrapAdvance))) { | 1588 | iRound(wrapAdvance), |
1589 | attrText.isBaseRTL)) { | ||
1584 | willAbortDueToWrap = iTrue; | 1590 | willAbortDueToWrap = iTrue; |
1585 | } | 1591 | } |
1586 | xCursor = origin; | 1592 | xCursor = origin; |
@@ -1743,8 +1749,9 @@ static int runFlagsFromId_(enum iFontId fontId) { | |||
1743 | return runFlags; | 1749 | return runFlags; |
1744 | } | 1750 | } |
1745 | 1751 | ||
1746 | static iBool cbAdvanceOneLine_(iWrapText *d, iRangecc range, int origin, int advance) { | 1752 | static iBool cbAdvanceOneLine_(iWrapText *d, iRangecc range, int origin, int advance, |
1747 | iUnused(origin, advance); | 1753 | iBool isBaseRTL) { |
1754 | iUnused(origin, advance, isBaseRTL); | ||
1748 | *((const char **) d->context) = range.end; | 1755 | *((const char **) d->context) = range.end; |
1749 | return iFalse; /* just one line */ | 1756 | return iFalse; /* just one line */ |
1750 | } | 1757 | } |
@@ -1785,9 +1792,9 @@ iTextMetrics measureN_Text(int fontId, const char *text, size_t n) { | |||
1785 | } | 1792 | } |
1786 | 1793 | ||
1787 | static void drawBoundedN_Text_(int fontId, iInt2 pos, int xposBound, int color, iRangecc text, size_t maxLen) { | 1794 | static void drawBoundedN_Text_(int fontId, iInt2 pos, int xposBound, int color, iRangecc text, size_t maxLen) { |
1788 | iText *d = &text_; | 1795 | iText * d = &text_; |
1789 | iFont *font = font_Text_(fontId); | 1796 | iFont * font = font_Text_(fontId); |
1790 | const iColor clr = get_Color(color & mask_ColorId); | 1797 | const iColor clr = get_Color(color & mask_ColorId); |
1791 | SDL_SetTextureColorMod(d->cache, clr.r, clr.g, clr.b); | 1798 | SDL_SetTextureColorMod(d->cache, clr.r, clr.g, clr.b); |
1792 | run_Font_(font, | 1799 | run_Font_(font, |
1793 | &(iRunArgs){ .mode = draw_RunMode | | 1800 | &(iRunArgs){ .mode = draw_RunMode | |
@@ -1798,7 +1805,8 @@ static void drawBoundedN_Text_(int fontId, iInt2 pos, int xposBound, int color, | |||
1798 | .maxLen = maxLen, | 1805 | .maxLen = maxLen, |
1799 | .pos = pos, | 1806 | .pos = pos, |
1800 | .xposLayoutBound = xposBound, | 1807 | .xposLayoutBound = xposBound, |
1801 | .color = color & mask_ColorId }); | 1808 | .color = color & mask_ColorId, |
1809 | .baseDir = xposBound ? iSign(xposBound - pos.x) : 0 }); | ||
1802 | } | 1810 | } |
1803 | 1811 | ||
1804 | static void drawBounded_Text_(int fontId, iInt2 pos, int xposBound, int color, iRangecc text) { | 1812 | static void drawBounded_Text_(int fontId, iInt2 pos, int xposBound, int color, iRangecc text) { |