diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-13 09:49:44 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-13 09:49:44 +0300 |
commit | 6b931c95725eef2ebb7e831c4017d3d67b33294f (patch) | |
tree | 254595663d93c0dcc33baad475fb2f6c3ddeec40 /src/ui/documentwidget.c | |
parent | dd0a8798f32bf192ed703c6c512d4a76c4d407bc (diff) |
Text attributes that change inside a run
These changes concern the situation when the attributes of text (i.e., font, color) are changed via escape sequences.
The concept of "base attributes" was added so that the low-level text renderer knows which font/color to set when a "reset" escape sequence is encountered. This depends on what kind of text is being renderer, e.g., preformatted or regular paragraphs.
The base attributes were added as variables in Text because it was getting unwieldy to pass all the information via the draw/measure/WrapText functions.
GmDocument now has a GmTheme struct that collects the font and color information into a single place.
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 8c87ba1a..8b2d6a5a 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -569,7 +569,7 @@ static void addVisible_DocumentWidget_(void *context, const iGmRun *run) { | |||
569 | } | 569 | } |
570 | d->visibleRuns.end = run; | 570 | d->visibleRuns.end = run; |
571 | } | 571 | } |
572 | if (run->preId) { | 572 | if (preId_GmRun(run)) { |
573 | pushBack_PtrArray(&d->visiblePre, run); | 573 | pushBack_PtrArray(&d->visiblePre, run); |
574 | if (run->flags & wide_GmRunFlag) { | 574 | if (run->flags & wide_GmRunFlag) { |
575 | pushBack_PtrArray(&d->visibleWideRuns, run); | 575 | pushBack_PtrArray(&d->visibleWideRuns, run); |
@@ -635,14 +635,14 @@ static void invalidateVisibleLinks_DocumentWidget_(iDocumentWidget *d) { | |||
635 | } | 635 | } |
636 | 636 | ||
637 | static int runOffset_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) { | 637 | static int runOffset_DocumentWidget_(const iDocumentWidget *d, const iGmRun *run) { |
638 | if (run->preId && run->flags & wide_GmRunFlag) { | 638 | if (preId_GmRun(run) && run->flags & wide_GmRunFlag) { |
639 | if (d->animWideRunId == run->preId) { | 639 | if (d->animWideRunId == preId_GmRun(run)) { |
640 | return -value_Anim(&d->animWideRunOffset); | 640 | return -value_Anim(&d->animWideRunOffset); |
641 | } | 641 | } |
642 | const size_t numOffsets = size_Array(&d->wideRunOffsets); | 642 | const size_t numOffsets = size_Array(&d->wideRunOffsets); |
643 | const int *offsets = constData_Array(&d->wideRunOffsets); | 643 | const int *offsets = constData_Array(&d->wideRunOffsets); |
644 | if (run->preId <= numOffsets) { | 644 | if (preId_GmRun(run) <= numOffsets) { |
645 | return -offsets[run->preId - 1]; | 645 | return -offsets[preId_GmRun(run) - 1]; |
646 | } | 646 | } |
647 | } | 647 | } |
648 | return 0; | 648 | return 0; |
@@ -731,7 +731,7 @@ static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { | |||
731 | } | 731 | } |
732 | } | 732 | } |
733 | else if (d->hoverPre && | 733 | else if (d->hoverPre && |
734 | preHasAltText_GmDocument(d->doc, d->hoverPre->preId) && | 734 | preHasAltText_GmDocument(d->doc, preId_GmRun(d->hoverPre)) && |
735 | ~d->flags & noHoverWhileScrolling_DocumentWidgetFlag) { | 735 | ~d->flags & noHoverWhileScrolling_DocumentWidgetFlag) { |
736 | setValueSpeed_Anim(&d->altTextOpacity, 1.0f, 1.5f); | 736 | setValueSpeed_Anim(&d->altTextOpacity, 1.0f, 1.5f); |
737 | if (!isFinished_Anim(&d->altTextOpacity)) { | 737 | if (!isFinished_Anim(&d->altTextOpacity)) { |
@@ -1812,10 +1812,10 @@ static void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos, | |||
1812 | maxWidth = iMax(maxWidth, width_Rect(r->visBounds)); | 1812 | maxWidth = iMax(maxWidth, width_Rect(r->visBounds)); |
1813 | } | 1813 | } |
1814 | const int maxOffset = maxWidth - documentWidth_DocumentWidget_(d) + d->pageMargin * gap_UI; | 1814 | const int maxOffset = maxWidth - documentWidth_DocumentWidget_(d) + d->pageMargin * gap_UI; |
1815 | if (size_Array(&d->wideRunOffsets) <= run->preId) { | 1815 | if (size_Array(&d->wideRunOffsets) <= preId_GmRun(run)) { |
1816 | resize_Array(&d->wideRunOffsets, run->preId + 1); | 1816 | resize_Array(&d->wideRunOffsets, preId_GmRun(run) + 1); |
1817 | } | 1817 | } |
1818 | int *offset = at_Array(&d->wideRunOffsets, run->preId - 1); | 1818 | int *offset = at_Array(&d->wideRunOffsets, preId_GmRun(run) - 1); |
1819 | const int oldOffset = *offset; | 1819 | const int oldOffset = *offset; |
1820 | *offset = iClamp(*offset + delta, 0, maxOffset); | 1820 | *offset = iClamp(*offset + delta, 0, maxOffset); |
1821 | /* Make sure the whole block gets redraw. */ | 1821 | /* Make sure the whole block gets redraw. */ |
@@ -1828,8 +1828,8 @@ static void scrollWideBlock_DocumentWidget_(iDocumentWidget *d, iInt2 mousePos, | |||
1828 | d->foundMark = iNullRange; | 1828 | d->foundMark = iNullRange; |
1829 | } | 1829 | } |
1830 | if (duration) { | 1830 | if (duration) { |
1831 | if (d->animWideRunId != run->preId || isFinished_Anim(&d->animWideRunOffset)) { | 1831 | if (d->animWideRunId != preId_GmRun(run) || isFinished_Anim(&d->animWideRunOffset)) { |
1832 | d->animWideRunId = run->preId; | 1832 | d->animWideRunId = preId_GmRun(run); |
1833 | init_Anim(&d->animWideRunOffset, oldOffset); | 1833 | init_Anim(&d->animWideRunOffset, oldOffset); |
1834 | } | 1834 | } |
1835 | setValueEased_Anim(&d->animWideRunOffset, *offset, duration); | 1835 | setValueEased_Anim(&d->animWideRunOffset, *offset, duration); |
@@ -3814,7 +3814,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3814 | } | 3814 | } |
3815 | /* Fold/unfold a preformatted block. */ | 3815 | /* Fold/unfold a preformatted block. */ |
3816 | if (~d->flags & selecting_DocumentWidgetFlag && d->hoverPre && | 3816 | if (~d->flags & selecting_DocumentWidgetFlag && d->hoverPre && |
3817 | preIsFolded_GmDocument(d->doc, d->hoverPre->preId)) { | 3817 | preIsFolded_GmDocument(d->doc, preId_GmRun(d->hoverPre))) { |
3818 | return iTrue; | 3818 | return iTrue; |
3819 | } | 3819 | } |
3820 | /* Begin selecting a range of text. */ | 3820 | /* Begin selecting a range of text. */ |
@@ -3925,7 +3925,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3925 | } | 3925 | } |
3926 | } | 3926 | } |
3927 | if (d->hoverPre) { | 3927 | if (d->hoverPre) { |
3928 | togglePreFold_DocumentWidget_(d, d->hoverPre->preId); | 3928 | togglePreFold_DocumentWidget_(d, preId_GmRun(d->hoverPre)); |
3929 | return iTrue; | 3929 | return iTrue; |
3930 | } | 3930 | } |
3931 | if (d->hoverLink) { | 3931 | if (d->hoverLink) { |
@@ -4124,7 +4124,7 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol | |||
4124 | 4124 | ||
4125 | static void drawMark_DrawContext_(void *context, const iGmRun *run) { | 4125 | static void drawMark_DrawContext_(void *context, const iGmRun *run) { |
4126 | iDrawContext *d = context; | 4126 | iDrawContext *d = context; |
4127 | if (run->mediaType == none_MediaType) { | 4127 | if (!isMedia_GmRun(run)) { |
4128 | fillRange_DrawContext_(d, run, uiMatching_ColorId, d->widget->foundMark, &d->inFoundMark); | 4128 | fillRange_DrawContext_(d, run, uiMatching_ColorId, d->widget->foundMark, &d->inFoundMark); |
4129 | fillRange_DrawContext_(d, run, uiMarked_ColorId, d->widget->selectMark, &d->inSelectMark); | 4129 | fillRange_DrawContext_(d, run, uiMarked_ColorId, d->widget->selectMark, &d->inSelectMark); |
4130 | } | 4130 | } |
@@ -4249,7 +4249,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4249 | } | 4249 | } |
4250 | return; | 4250 | return; |
4251 | } | 4251 | } |
4252 | else if (run->mediaType) { | 4252 | else if (isMedia_GmRun(run)) { |
4253 | /* Media UIs are drawn afterwards as a dynamic overlay. */ | 4253 | /* Media UIs are drawn afterwards as a dynamic overlay. */ |
4254 | return; | 4254 | return; |
4255 | } | 4255 | } |
@@ -4317,7 +4317,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4317 | } | 4317 | } |
4318 | } | 4318 | } |
4319 | if (run->flags & altText_GmRunFlag) { | 4319 | if (run->flags & altText_GmRunFlag) { |
4320 | const iInt2 margin = preRunMargin_GmDocument(doc, run->preId); | 4320 | const iInt2 margin = preRunMargin_GmDocument(doc, preId_GmRun(run)); |
4321 | fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackgroundAltText_ColorId); | 4321 | fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackgroundAltText_ColorId); |
4322 | drawRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmQuoteIcon_ColorId); | 4322 | drawRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmQuoteIcon_ColorId); |
4323 | drawWrapRange_Text(run->font, | 4323 | drawWrapRange_Text(run->font, |
@@ -4368,11 +4368,17 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4368 | height_Rect(run->visBounds), | 4368 | height_Rect(run->visBounds), |
4369 | tmQuoteIcon_ColorId); | 4369 | tmQuoteIcon_ColorId); |
4370 | } | 4370 | } |
4371 | /* Base attributes. */ { | ||
4372 | int f, c; | ||
4373 | runBaseAttributes_GmDocument(doc, run, &f, &c); | ||
4374 | setBaseAttributes_Text(f, c); | ||
4375 | } | ||
4371 | drawBoundRange_Text(run->font, | 4376 | drawBoundRange_Text(run->font, |
4372 | visPos, | 4377 | visPos, |
4373 | (run->isRTL ? -1 : 1) * width_Rect(run->visBounds), | 4378 | (run->isRTL ? -1 : 1) * width_Rect(run->visBounds), |
4374 | fg, | 4379 | fg, |
4375 | run->text); | 4380 | run->text); |
4381 | setBaseAttributes_Text(-1, -1); | ||
4376 | runDrawn:; | 4382 | runDrawn:; |
4377 | } | 4383 | } |
4378 | /* Presentation of links. */ | 4384 | /* Presentation of links. */ |
@@ -4944,7 +4950,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4944 | /* Alt text. */ | 4950 | /* Alt text. */ |
4945 | const float altTextOpacity = value_Anim(&d->altTextOpacity) * 6 - 5; | 4951 | const float altTextOpacity = value_Anim(&d->altTextOpacity) * 6 - 5; |
4946 | if (d->hoverAltPre && altTextOpacity > 0) { | 4952 | if (d->hoverAltPre && altTextOpacity > 0) { |
4947 | const iGmPreMeta *meta = preMeta_GmDocument(d->doc, d->hoverAltPre->preId); | 4953 | const iGmPreMeta *meta = preMeta_GmDocument(d->doc, preId_GmRun(d->hoverAltPre)); |
4948 | if (meta->flags & topLeft_GmPreMetaFlag && ~meta->flags & decoration_GmRunFlag && | 4954 | if (meta->flags & topLeft_GmPreMetaFlag && ~meta->flags & decoration_GmRunFlag && |
4949 | !isEmpty_Range(&meta->altText)) { | 4955 | !isEmpty_Range(&meta->altText)) { |
4950 | const int margin = 3 * gap_UI / 2; | 4956 | const int margin = 3 * gap_UI / 2; |