summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ui/text.c86
1 files changed, 65 insertions, 21 deletions
diff --git a/src/ui/text.c b/src/ui/text.c
index 6cfb5c51..7e8c7871 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -742,10 +742,15 @@ static iChar nextChar_(const char **chPos, const char *end) {
742 742
743iDeclareType(AttributedRun) 743iDeclareType(AttributedRun)
744 744
745/*enum iAttributedRunFlags {
746 newline_AttributedRunFlag = iBit(1),
747};*/
748
745struct Impl_AttributedRun { 749struct Impl_AttributedRun {
746 iRangecc text; 750 iRangecc text;
747 iFont *font; 751 iFont * font;
748 iColor fgColor; 752 iColor fgColor;
753 int lineBreaks;
749}; 754};
750 755
751iDeclareType(AttributedText) 756iDeclareType(AttributedText)
@@ -753,7 +758,7 @@ iDeclareTypeConstructionArgs(AttributedText, iRangecc text, iFont *font, iColor
753 758
754struct Impl_AttributedText { 759struct Impl_AttributedText {
755 iRangecc text; 760 iRangecc text;
756 iFont *font; 761 iFont * font;
757 iColor fgColor; 762 iColor fgColor;
758 iArray runs; 763 iArray runs;
759}; 764};
@@ -765,27 +770,63 @@ static void prepare_AttributedText_(iAttributedText *d) {
765 iAssert(isEmpty_Array(&d->runs)); 770 iAssert(isEmpty_Array(&d->runs));
766 const char *chPos = d->text.start; 771 const char *chPos = d->text.start;
767 iAttributedRun run = { .text = d->text, .font = d->font, .fgColor = d->fgColor }; 772 iAttributedRun run = { .text = d->text, .font = d->font, .fgColor = d->fgColor };
773#define finishRun_() { \
774 iAttributedRun finishedRun = run; \
775 finishedRun.text.end = currentPos; \
776 if (!isEmpty_Range(&finishedRun.text)) { \
777 pushBack_Array(&d->runs, &finishedRun); \
778 run.lineBreaks = 0; \
779 } \
780 run.text.start = currentPos; \
781}
768 while (chPos < d->text.end) { 782 while (chPos < d->text.end) {
769 const char *currentPos = chPos; 783 const char *currentPos = chPos;
784 if (*chPos == 0x1b) { /* ANSI escape. */
785 chPos++;
786 iRegExpMatch m;
787 init_RegExpMatch(&m);
788 if (match_RegExp(text_.ansiEscape, chPos, d->text.end - chPos, &m)) {
789 finishRun_();
790 run.fgColor = ansiForeground_Color(capturedRange_RegExpMatch(&m, 1),
791 tmParagraph_ColorId);
792 chPos = end_RegExpMatch(&m);
793 run.text.start = chPos;
794 continue;
795 }
796 }
770 const iChar ch = nextChar_(&chPos, d->text.end); 797 const iChar ch = nextChar_(&chPos, d->text.end);
771 if (ch == '\v') { 798 if (ch == '\v') {
772 /* TODO: Color escapes. */ 799 finishRun_();
773 800 /* An internal color escape. */
801 iChar esc = nextChar_(&chPos, d->text.end);
802 int colorNum = none_ColorId; /* default color */
803 if (esc == '\v') { /* Extended range. */
804 esc = nextChar_(&chPos, d->text.end) + asciiExtended_ColorEscape;
805 colorNum = esc - asciiBase_ColorEscape;
806 }
807 else if (esc != 0x24) { /* ASCII Cancel */
808 colorNum = esc - asciiBase_ColorEscape;
809 }
810 run.text.start = chPos;
811 run.fgColor = (colorNum >= 0 ? get_Color(colorNum) : d->fgColor);
812 //prevCh = 0;
813 continue;
814 }
815 if (ch == '\n') {
816 finishRun_();
817 run.text.start = chPos;
818 run.lineBreaks++;
819 continue;
774 } 820 }
775 if (isSpace_Char(ch) || isVariationSelector_Char(ch) || isDefaultIgnorable_Char(ch) || 821 if (isVariationSelector_Char(ch) || isDefaultIgnorable_Char(ch) ||
776 isFitzpatrickType_Char(ch)) { 822 isFitzpatrickType_Char(ch)) {
777 continue; 823 continue;
778 } 824 }
779 const iGlyph *glyph = glyph_Font_(d->font, ch); 825 const iGlyph *glyph = glyph_Font_(d->font, ch);
780 /* TODO: Look for ANSI/color escapes. */ 826 /* TODO: Look for ANSI/color escapes. */
781 if (glyph->font != run.font) { 827 if (index_Glyph_(glyph) && glyph->font != run.font) {
782 /* A different font is being used for this glyph. */ 828 /* A different font is being used for this glyph. */
783 iAttributedRun finishedRun = run; 829 finishRun_();
784 finishedRun.text.end = currentPos;
785 if (!isEmpty_Range(&finishedRun.text)) {
786 pushBack_Array(&d->runs, &finishedRun);
787 }
788 run.text.start = currentPos;
789 run.font = glyph->font; 830 run.font = glyph->font;
790 } 831 }
791 } 832 }
@@ -818,7 +859,6 @@ struct Impl_RasterGlyph {
818 859
819static void cacheGlyphs_Font_(iFont *d, const iArray *glyphIndices) { 860static void cacheGlyphs_Font_(iFont *d, const iArray *glyphIndices) {
820 /* TODO: Make this an object so it can be used sequentially without reallocating buffers. */ 861 /* TODO: Make this an object so it can be used sequentially without reallocating buffers. */
821// const char * chPos = text.start;
822 SDL_Surface *buf = NULL; 862 SDL_Surface *buf = NULL;
823 const iInt2 bufSize = init_I2(iMin(512, d->height * iMin(2 * size_Array(glyphIndices), 20)), 863 const iInt2 bufSize = init_I2(iMin(512, d->height * iMin(2 * size_Array(glyphIndices), 20)),
824 d->height * 4 / 3); 864 d->height * 4 / 3);
@@ -827,17 +867,10 @@ static void cacheGlyphs_Font_(iFont *d, const iArray *glyphIndices) {
827 SDL_Texture *oldTarget = NULL; 867 SDL_Texture *oldTarget = NULL;
828 iBool isTargetChanged = iFalse; 868 iBool isTargetChanged = iFalse;
829 iAssert(isExposed_Window(get_Window())); 869 iAssert(isExposed_Window(get_Window()));
830// iAttributedText *attrText = new_AttributedText(text, d, (iColor){ 255, 255, 255, 255 });
831 /* We'll flush the buffered rasters periodically until everything is cached. */ 870 /* We'll flush the buffered rasters periodically until everything is cached. */
832 size_t index = 0; 871 size_t index = 0;
833 while (index < size_Array(glyphIndices)) { 872 while (index < size_Array(glyphIndices)) {
834 for (; index < size_Array(glyphIndices); index++) { 873 for (; index < size_Array(glyphIndices); index++) {
835// const char *lastPos = chPos;
836// const iChar ch = nextChar_(&chPos, text.end);
837// if (ch == 0 || isSpace_Char(ch) || isDefaultIgnorable_Char(ch) ||
838// isFitzpatrickType_Char(ch)) {
839// continue;
840// }
841 const uint32_t glyphIndex = constValue_Array(glyphIndices, index, uint32_t); 874 const uint32_t glyphIndex = constValue_Array(glyphIndices, index, uint32_t);
842 const int lastCacheBottom = text_.cacheBottom; 875 const int lastCacheBottom = text_.cacheBottom;
843 iGlyph *glyph = glyphByIndex_Font_(d, glyphIndex); 876 iGlyph *glyph = glyphByIndex_Font_(d, glyphIndex);
@@ -929,7 +962,6 @@ static void cacheGlyphs_Font_(iFont *d, const iArray *glyphIndices) {
929 bufX = 0; 962 bufX = 0;
930 } 963 }
931 } 964 }
932// delete_AttributedText(attrText);
933 if (rasters) { 965 if (rasters) {
934 delete_Array(rasters); 966 delete_Array(rasters);
935 } 967 }
@@ -952,6 +984,7 @@ static void cacheSingleGlyph_Font_(iFont *d, uint32_t glyphIndex) {
952static void cacheTextGlyphs_Font_(iFont *d, const iRangecc text) { 984static void cacheTextGlyphs_Font_(iFont *d, const iRangecc text) {
953 iArray glyphIndices; 985 iArray glyphIndices;
954 init_Array(&glyphIndices, sizeof(uint32_t)); 986 init_Array(&glyphIndices, sizeof(uint32_t));
987 /* TODO: Do this with AttributedText */
955 for (const char *chPos = text.start; chPos != text.end; ) { 988 for (const char *chPos = text.start; chPos != text.end; ) {
956 const char *oldPos = chPos; 989 const char *oldPos = chPos;
957 const iChar ch = nextChar_(&chPos, text.end); 990 const iChar ch = nextChar_(&chPos, text.end);
@@ -1015,6 +1048,10 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1015 iAttributedText *attrText = new_AttributedText(args->text, d, get_Color(args->color)); 1048 iAttributedText *attrText = new_AttributedText(args->text, d, get_Color(args->color));
1016 iConstForEach(Array, i, &attrText->runs) { 1049 iConstForEach(Array, i, &attrText->runs) {
1017 const iAttributedRun *run = i.value; 1050 const iAttributedRun *run = i.value;
1051 if (run->lineBreaks) {
1052 xCursor = 0.0f;
1053 yCursor += d->height * run->lineBreaks;
1054 }
1018 hb_buffer_clear_contents(hbBuf); 1055 hb_buffer_clear_contents(hbBuf);
1019 hb_buffer_add_utf8(hbBuf, run->text.start, size_Range(&run->text), 0, -1); 1056 hb_buffer_add_utf8(hbBuf, run->text.start, size_Range(&run->text), 0, -1);
1020 hb_buffer_set_direction(hbBuf, HB_DIRECTION_LTR); /* TODO: FriBidi? */ 1057 hb_buffer_set_direction(hbBuf, HB_DIRECTION_LTR); /* TODO: FriBidi? */
@@ -1057,6 +1094,13 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1057 glyph = glyphByIndex_Font_(run->font, glyphId); 1094 glyph = glyphByIndex_Font_(run->font, glyphId);
1058 iAssert(isRasterized_Glyph_(glyph, hoff)); 1095 iAssert(isRasterized_Glyph_(glyph, hoff));
1059 } 1096 }
1097 if (~mode & permanentColorFlag_RunMode) {
1098 //const iColor clr = get_Color(colorNum);
1099 SDL_SetTextureColorMod(text_.cache, run->fgColor.r, run->fgColor.g, run->fgColor.b);
1100// if (args->mode & fillBackground_RunMode) {
1101// SDL_SetRenderDrawColor(text_.render, clr.r, clr.g, clr.b, 0);
1102// }
1103 }
1060 SDL_Rect src; 1104 SDL_Rect src;
1061 memcpy(&src, &glyph->rect[hoff], sizeof(SDL_Rect)); 1105 memcpy(&src, &glyph->rect[hoff], sizeof(SDL_Rect));
1062 if (args->mode & fillBackground_RunMode) { 1106 if (args->mode & fillBackground_RunMode) {