diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-12 22:16:33 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-12 22:16:33 +0300 |
commit | 6f02d2520ff9dc8d98ce0c8d2f554407c2f479fe (patch) | |
tree | a9e1d3a1d84978caa1e09ce5e4c4ffad3636b94a /src | |
parent | 804c677bc9f9a3c89de257a1e6b14be27dea999b (diff) |
DocumentWidget: Use VisBuf for buffering
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/documentwidget.c | 196 |
1 files changed, 144 insertions, 52 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 199b6aa9..edfab0be 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
24 | #include "scrollwidget.h" | 24 | #include "scrollwidget.h" |
25 | #include "inputwidget.h" | 25 | #include "inputwidget.h" |
26 | #include "labelwidget.h" | 26 | #include "labelwidget.h" |
27 | #include "visbuf.h" | ||
27 | #include "paint.h" | 28 | #include "paint.h" |
28 | #include "command.h" | 29 | #include "command.h" |
29 | #include "keys.h" | 30 | #include "keys.h" |
@@ -38,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
38 | #include <the_Foundation/objectlist.h> | 39 | #include <the_Foundation/objectlist.h> |
39 | #include <the_Foundation/path.h> | 40 | #include <the_Foundation/path.h> |
40 | #include <the_Foundation/ptrarray.h> | 41 | #include <the_Foundation/ptrarray.h> |
42 | #include <the_Foundation/ptrset.h> | ||
41 | #include <the_Foundation/regexp.h> | 43 | #include <the_Foundation/regexp.h> |
42 | #include <the_Foundation/stringarray.h> | 44 | #include <the_Foundation/stringarray.h> |
43 | #include <SDL_clipboard.h> | 45 | #include <SDL_clipboard.h> |
@@ -126,6 +128,7 @@ void deserialize_Model(iModel *d, iStream *ins) { | |||
126 | 128 | ||
127 | iDefineTypeConstruction(Model) | 129 | iDefineTypeConstruction(Model) |
128 | 130 | ||
131 | #if 0 | ||
129 | /*----------------------------------------------------------------------------------------------*/ | 132 | /*----------------------------------------------------------------------------------------------*/ |
130 | 133 | ||
131 | iDeclareType(VisBuffer) | 134 | iDeclareType(VisBuffer) |
@@ -160,7 +163,7 @@ void dealloc_VisBuffer(iVisBuffer *d) { | |||
160 | } | 163 | } |
161 | 164 | ||
162 | iDefineTypeConstruction(VisBuffer) | 165 | iDefineTypeConstruction(VisBuffer) |
163 | 166 | #endif | |
164 | /*----------------------------------------------------------------------------------------------*/ | 167 | /*----------------------------------------------------------------------------------------------*/ |
165 | 168 | ||
166 | static const int smoothSpeed_DocumentWidget_ = 120; /* unit: gap_Text per second */ | 169 | static const int smoothSpeed_DocumentWidget_ = 120; /* unit: gap_Text per second */ |
@@ -203,7 +206,8 @@ struct Impl_DocumentWidget { | |||
203 | int smoothLastOffset; | 206 | int smoothLastOffset; |
204 | iBool smoothContinue; | 207 | iBool smoothContinue; |
205 | iWidget * menu; | 208 | iWidget * menu; |
206 | iVisBuffer * visBuffer; | 209 | iVisBuf * visBuf; |
210 | iPtrSet * invalidRuns; | ||
207 | }; | 211 | }; |
208 | 212 | ||
209 | iDefineObjectConstruction(DocumentWidget) | 213 | iDefineObjectConstruction(DocumentWidget) |
@@ -238,7 +242,8 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
238 | d->contextLink = NULL; | 242 | d->contextLink = NULL; |
239 | d->noHoverWhileScrolling = iFalse; | 243 | d->noHoverWhileScrolling = iFalse; |
240 | d->showLinkNumbers = iFalse; | 244 | d->showLinkNumbers = iFalse; |
241 | d->visBuffer = new_VisBuffer(); | 245 | d->visBuf = new_VisBuf(); |
246 | d->invalidRuns = new_PtrSet(); | ||
242 | init_PtrArray(&d->visibleLinks); | 247 | init_PtrArray(&d->visibleLinks); |
243 | init_Click(&d->click, d, SDL_BUTTON_LEFT); | 248 | init_Click(&d->click, d, SDL_BUTTON_LEFT); |
244 | addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); | 249 | addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); |
@@ -252,7 +257,8 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
252 | } | 257 | } |
253 | 258 | ||
254 | void deinit_DocumentWidget(iDocumentWidget *d) { | 259 | void deinit_DocumentWidget(iDocumentWidget *d) { |
255 | delete_VisBuffer(d->visBuffer); | 260 | delete_VisBuf(d->visBuf); |
261 | delete_PtrSet(d->invalidRuns); | ||
256 | iRelease(d->media); | 262 | iRelease(d->media); |
257 | iRelease(d->request); | 263 | iRelease(d->request); |
258 | iRelease(d->doc); | 264 | iRelease(d->doc); |
@@ -365,6 +371,16 @@ static int scrollMax_DocumentWidget_(const iDocumentWidget *d) { | |||
365 | (hasSiteBanner_GmDocument(d->doc) ? 1 : 2) * d->pageMargin * gap_UI; | 371 | (hasSiteBanner_GmDocument(d->doc) ? 1 : 2) * d->pageMargin * gap_UI; |
366 | } | 372 | } |
367 | 373 | ||
374 | static void invalidateLink_DocumentWidget_(iDocumentWidget *d, iGmLinkId id) { | ||
375 | /* A link has multiple runs associated with it. */ | ||
376 | iConstForEach(PtrArray, i, &d->visibleLinks) { | ||
377 | const iGmRun *run = i.ptr; | ||
378 | if (run->linkId == id) { | ||
379 | insert_PtrSet(d->invalidRuns, run); | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
368 | static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { | 384 | static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { |
369 | const iWidget *w = constAs_Widget(d); | 385 | const iWidget *w = constAs_Widget(d); |
370 | const iRect docBounds = documentBounds_DocumentWidget_(d); | 386 | const iRect docBounds = documentBounds_DocumentWidget_(d); |
@@ -382,6 +398,12 @@ static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) { | |||
382 | } | 398 | } |
383 | } | 399 | } |
384 | if (d->hoverLink != oldHoverLink) { | 400 | if (d->hoverLink != oldHoverLink) { |
401 | if (oldHoverLink) { | ||
402 | invalidateLink_DocumentWidget_(d, oldHoverLink->linkId); | ||
403 | } | ||
404 | if (d->hoverLink) { | ||
405 | invalidateLink_DocumentWidget_(d, d->hoverLink->linkId); | ||
406 | } | ||
385 | refresh_Widget(as_Widget(d)); | 407 | refresh_Widget(as_Widget(d)); |
386 | } | 408 | } |
387 | if (isHover_Widget(w) && !contains_Widget(constAs_Widget(d->scroll), mouse)) { | 409 | if (isHover_Widget(w) && !contains_Widget(constAs_Widget(d->scroll), mouse)) { |
@@ -497,7 +519,8 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | |||
497 | } | 519 | } |
498 | 520 | ||
499 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { | 521 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { |
500 | iZap(d->visBuffer->validRange); | 522 | invalidate_VisBuf(d->visBuf); |
523 | clear_PtrSet(d->invalidRuns); | ||
501 | } | 524 | } |
502 | 525 | ||
503 | static void setSource_DocumentWidget_(iDocumentWidget *d, const iString *source) { | 526 | static void setSource_DocumentWidget_(iDocumentWidget *d, const iString *source) { |
@@ -1013,23 +1036,16 @@ static iBool handleMediaCommand_DocumentWidget_(iDocumentWidget *d, const char * | |||
1013 | return iFalse; | 1036 | return iFalse; |
1014 | } | 1037 | } |
1015 | 1038 | ||
1016 | static void deallocVisBuffer_DocumentWidget_(const iDocumentWidget *d) { | ||
1017 | d->visBuffer->size = zero_I2(); | ||
1018 | iZap(d->visBuffer->validRange); | ||
1019 | iForIndices(i, d->visBuffer->texture) { | ||
1020 | SDL_DestroyTexture(d->visBuffer->texture[i]); | ||
1021 | d->visBuffer->texture[i] = NULL; | ||
1022 | } | ||
1023 | } | ||
1024 | |||
1025 | static void allocVisBuffer_DocumentWidget_(const iDocumentWidget *d) { | 1039 | static void allocVisBuffer_DocumentWidget_(const iDocumentWidget *d) { |
1026 | const iWidget *w = constAs_Widget(d); | 1040 | const iWidget *w = constAs_Widget(d); |
1027 | const iBool isVisible = isVisible_Widget(w); | 1041 | const iBool isVisible = isVisible_Widget(w); |
1028 | const iInt2 size = bounds_Widget(w).size; | 1042 | const iInt2 size = bounds_Widget(w).size; |
1029 | if (!isEqual_I2(size, d->visBuffer->size) || !isVisible) { | 1043 | if (isVisible) { |
1030 | dealloc_VisBuffer(d->visBuffer); | 1044 | alloc_VisBuf(d->visBuf, size, 1); |
1031 | } | 1045 | } |
1032 | if (isVisible && !d->visBuffer->texture[0]) { | 1046 | else { |
1047 | dealloc_VisBuf(d->visBuf); | ||
1048 | #if 0 | ||
1033 | iZap(d->visBuffer->validRange); | 1049 | iZap(d->visBuffer->validRange); |
1034 | d->visBuffer->size = size; | 1050 | d->visBuffer->size = size; |
1035 | iAssert(size.x > 0); | 1051 | iAssert(size.x > 0); |
@@ -1042,6 +1058,7 @@ static void allocVisBuffer_DocumentWidget_(const iDocumentWidget *d) { | |||
1042 | size.y); | 1058 | size.y); |
1043 | SDL_SetTextureBlendMode(d->visBuffer->texture[i], SDL_BLENDMODE_NONE); | 1059 | SDL_SetTextureBlendMode(d->visBuffer->texture[i], SDL_BLENDMODE_NONE); |
1044 | } | 1060 | } |
1061 | #endif | ||
1045 | } | 1062 | } |
1046 | } | 1063 | } |
1047 | 1064 | ||
@@ -1067,7 +1084,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1067 | } | 1084 | } |
1068 | } | 1085 | } |
1069 | invalidate_DocumentWidget_(d); | 1086 | invalidate_DocumentWidget_(d); |
1070 | deallocVisBuffer_DocumentWidget_(d); | 1087 | dealloc_VisBuf(d->visBuf); |
1071 | refresh_Widget(w); | 1088 | refresh_Widget(w); |
1072 | updateWindowTitle_DocumentWidget_(d); | 1089 | updateWindowTitle_DocumentWidget_(d); |
1073 | } | 1090 | } |
@@ -1568,16 +1585,18 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
1568 | 1585 | ||
1569 | iDeclareType(DrawContext) | 1586 | iDeclareType(DrawContext) |
1570 | 1587 | ||
1588 | #if 0 | ||
1571 | enum iDrawRunPass { | 1589 | enum iDrawRunPass { |
1572 | static_DrawRunPass, | 1590 | static_DrawRunPass, |
1573 | dynamic_DrawRunPass, | 1591 | dynamic_DrawRunPass, |
1574 | }; | 1592 | }; |
1593 | #endif | ||
1575 | 1594 | ||
1576 | struct Impl_DrawContext { | 1595 | struct Impl_DrawContext { |
1577 | enum iDrawRunPass pass; | 1596 | // enum iDrawRunPass pass; |
1578 | const iDocumentWidget *widget; | 1597 | const iDocumentWidget *widget; |
1579 | iRect widgetBounds; | 1598 | iRect widgetBounds; |
1580 | iRect bounds; /* document area */ | 1599 | iInt2 viewPos; /* document area origin */ |
1581 | iPaint paint; | 1600 | iPaint paint; |
1582 | iBool inSelectMark; | 1601 | iBool inSelectMark; |
1583 | iBool inFoundMark; | 1602 | iBool inFoundMark; |
@@ -1607,7 +1626,7 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol | |||
1607 | if (w > width_Rect(run->visBounds) - x) { | 1626 | if (w > width_Rect(run->visBounds) - x) { |
1608 | w = width_Rect(run->visBounds) - x; | 1627 | w = width_Rect(run->visBounds) - x; |
1609 | } | 1628 | } |
1610 | const iInt2 visPos = add_I2(run->bounds.pos, addY_I2(d->bounds.pos, -d->widget->scrollY)); | 1629 | const iInt2 visPos = add_I2(run->bounds.pos, addY_I2(d->viewPos, -d->widget->scrollY)); |
1611 | fillRect_Paint(&d->paint, (iRect){ addX_I2(visPos, x), | 1630 | fillRect_Paint(&d->paint, (iRect){ addX_I2(visPos, x), |
1612 | init_I2(w, height_Rect(run->bounds)) }, color); | 1631 | init_I2(w, height_Rect(run->bounds)) }, color); |
1613 | } | 1632 | } |
@@ -1615,9 +1634,9 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol | |||
1615 | 1634 | ||
1616 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { | 1635 | static void drawRun_DrawContext_(void *context, const iGmRun *run) { |
1617 | iDrawContext *d = context; | 1636 | iDrawContext *d = context; |
1618 | const iInt2 origin = addY_I2(d->bounds.pos, -d->widget->scrollY); | 1637 | const iInt2 origin = d->viewPos; //addY_I2(d->bounds.pos, -d->widget->scrollY); |
1619 | if (run->imageId) { | 1638 | if (run->imageId) { |
1620 | if (d->pass == static_DrawRunPass) { | 1639 | /*if (d->pass == static_DrawRunPass)*/ { |
1621 | SDL_Texture *tex = imageTexture_GmDocument(d->widget->doc, run->imageId); | 1640 | SDL_Texture *tex = imageTexture_GmDocument(d->widget->doc, run->imageId); |
1622 | if (tex) { | 1641 | if (tex) { |
1623 | const iRect dst = moved_Rect(run->visBounds, origin); | 1642 | const iRect dst = moved_Rect(run->visBounds, origin); |
@@ -1627,8 +1646,9 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
1627 | } | 1646 | } |
1628 | return; | 1647 | return; |
1629 | } | 1648 | } |
1649 | #if 0 | ||
1630 | /* Text markers. */ | 1650 | /* Text markers. */ |
1631 | if (d->pass == dynamic_DrawRunPass) { | 1651 | /*if (d->pass == dynamic_DrawRunPass)*/ { |
1632 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), | 1652 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), |
1633 | isDark_ColorTheme(colorTheme_App()) ? SDL_BLENDMODE_ADD | 1653 | isDark_ColorTheme(colorTheme_App()) ? SDL_BLENDMODE_ADD |
1634 | : SDL_BLENDMODE_BLEND); | 1654 | : SDL_BLENDMODE_BLEND); |
@@ -1636,17 +1656,26 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
1636 | fillRange_DrawContext_(d, run, uiMarked_ColorId, d->widget->selectMark, &d->inSelectMark); | 1656 | fillRange_DrawContext_(d, run, uiMarked_ColorId, d->widget->selectMark, &d->inSelectMark); |
1637 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); | 1657 | SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); |
1638 | } | 1658 | } |
1659 | #endif | ||
1639 | enum iColorId fg = run->color; | 1660 | enum iColorId fg = run->color; |
1640 | const iGmDocument *doc = d->widget->doc; | 1661 | const iGmDocument *doc = d->widget->doc; |
1641 | /* Matches the current drawing pass? */ | 1662 | /* Matches the current drawing pass? */ |
1642 | const iBool isDynamic = (run->linkId && ~run->flags & decoration_GmRunFlag); | 1663 | // const iBool isDynamic = (run->linkId && ~run->flags & decoration_GmRunFlag); |
1643 | if (isDynamic ^ (d->pass == dynamic_DrawRunPass)) { | 1664 | // if (isDynamic ^ (d->pass == dynamic_DrawRunPass)) { |
1644 | return; | 1665 | // return; |
1645 | } | 1666 | // } |
1646 | const iBool isHover = | 1667 | const iBool isHover = |
1647 | (run->linkId && d->widget->hoverLink && run->linkId == d->widget->hoverLink->linkId && | 1668 | (run->linkId && d->widget->hoverLink && run->linkId == d->widget->hoverLink->linkId && |
1648 | ~run->flags & decoration_GmRunFlag); | 1669 | ~run->flags & decoration_GmRunFlag); |
1649 | const iInt2 visPos = add_I2(run->visBounds.pos, origin); | 1670 | const iInt2 visPos = add_I2(run->visBounds.pos, origin); |
1671 | fillRect_Paint(&d->paint, | ||
1672 | (iRect){ visPos, | ||
1673 | /* Links have additional hover info on the right side. */ | ||
1674 | init_I2(run->linkId && ~run->flags & decoration_GmRunFlag | ||
1675 | ? d->widgetBounds.size.x - visPos.x | ||
1676 | : run->visBounds.size.x, | ||
1677 | run->visBounds.size.y) }, | ||
1678 | tmBackground_ColorId); | ||
1650 | if (run->linkId && ~run->flags & decoration_GmRunFlag) { | 1679 | if (run->linkId && ~run->flags & decoration_GmRunFlag) { |
1651 | fg = linkColor_GmDocument(doc, run->linkId, isHover ? textHover_GmLinkPart : text_GmLinkPart); | 1680 | fg = linkColor_GmDocument(doc, run->linkId, isHover ? textHover_GmLinkPart : text_GmLinkPart); |
1652 | if (linkFlags_GmDocument(doc, run->linkId) & content_GmLinkFlag) { | 1681 | if (linkFlags_GmDocument(doc, run->linkId) & content_GmLinkFlag) { |
@@ -1654,7 +1683,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
1654 | } | 1683 | } |
1655 | } | 1684 | } |
1656 | if (run->flags & siteBanner_GmRunFlag) { | 1685 | if (run->flags & siteBanner_GmRunFlag) { |
1657 | if (d->pass == static_DrawRunPass) { | 1686 | /*if (d->pass == static_DrawRunPass)*/ { |
1658 | /* Draw the site banner. */ | 1687 | /* Draw the site banner. */ |
1659 | fillRect_Paint( | 1688 | fillRect_Paint( |
1660 | &d->paint, | 1689 | &d->paint, |
@@ -1697,7 +1726,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
1697 | if (ord < 9 + 26) { | 1726 | if (ord < 9 + 26) { |
1698 | const iChar ordChar = ord < 9 ? 0x278a + ord : (0x24b6 + ord - 9); | 1727 | const iChar ordChar = ord < 9 ? 0x278a + ord : (0x24b6 + ord - 9); |
1699 | drawString_Text(run->font, | 1728 | drawString_Text(run->font, |
1700 | init_I2(left_Rect(d->bounds) - gap_UI / 3, visPos.y), | 1729 | init_I2(d->viewPos.x - gap_UI / 3, visPos.y), |
1701 | fg, | 1730 | fg, |
1702 | collect_String(newUnicodeN_String(&ordChar, 1))); | 1731 | collect_String(newUnicodeN_String(&ordChar, 1))); |
1703 | goto runDrawn; | 1732 | goto runDrawn; |
@@ -1708,7 +1737,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
1708 | runDrawn:; | 1737 | runDrawn:; |
1709 | } | 1738 | } |
1710 | /* Presentation of links. */ | 1739 | /* Presentation of links. */ |
1711 | if (run->linkId && ~run->flags & decoration_GmRunFlag && d->pass == dynamic_DrawRunPass) { | 1740 | if (run->linkId && ~run->flags & decoration_GmRunFlag/* && d->pass == dynamic_DrawRunPass*/) { |
1712 | const int metaFont = paragraph_FontId; | 1741 | const int metaFont = paragraph_FontId; |
1713 | /* TODO: Show status of an ongoing media request. */ | 1742 | /* TODO: Show status of an ongoing media request. */ |
1714 | const int flags = linkFlags_GmDocument(doc, run->linkId); | 1743 | const int flags = linkFlags_GmDocument(doc, run->linkId); |
@@ -1819,32 +1848,78 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
1819 | static void draw_DocumentWidget_(const iDocumentWidget *d) { | 1848 | static void draw_DocumentWidget_(const iDocumentWidget *d) { |
1820 | const iWidget *w = constAs_Widget(d); | 1849 | const iWidget *w = constAs_Widget(d); |
1821 | const iRect bounds = bounds_Widget(w); | 1850 | const iRect bounds = bounds_Widget(w); |
1822 | const iInt2 origin = topLeft_Rect(bounds); | 1851 | // const iInt2 origin = topLeft_Rect(bounds); |
1823 | const iRangei visRange = visibleRange_DocumentWidget_(d); | 1852 | //const iRangei visRange = visibleRange_DocumentWidget_(d); |
1824 | iVisBuffer * visBuf = d->visBuffer; /* this may be updated/modified here */ | 1853 | iVisBuf * visBuf = d->visBuf; /* will be updated now */ |
1825 | draw_Widget(w); | 1854 | draw_Widget(w); |
1826 | allocVisBuffer_DocumentWidget_(d); | 1855 | allocVisBuffer_DocumentWidget_(d); |
1827 | iDrawContext ctxDynamic = { | 1856 | const iRect ctxWidgetBounds = init_Rect( |
1828 | .pass = dynamic_DrawRunPass, | 1857 | 0, 0, width_Rect(bounds) - constAs_Widget(d->scroll)->rect.size.x, height_Rect(bounds)); |
1858 | // adjusted_Rect(bounds, zero_I2(), init_I2(-constAs_Widget(d->scroll)->rect.size.x, 0)), | ||
1859 | // neg_I2(origin)); /* omit scrollbar width */ | ||
1860 | const iRect docBounds = documentBounds_DocumentWidget_(d); | ||
1861 | // const iRect ctxBounds = moved_Rect(documentBounds_DocumentWidget_(d), neg_I2(origin)); | ||
1862 | iDrawContext ctx = { | ||
1863 | // .pass = dynamic_DrawRunPass, | ||
1829 | .widget = d, | 1864 | .widget = d, |
1830 | .widgetBounds = adjusted_Rect(bounds, | ||
1831 | zero_I2(), | ||
1832 | init_I2(-constAs_Widget(d->scroll)->rect.size.x, 0)), /* omit scrollbar width */ | ||
1833 | .bounds = documentBounds_DocumentWidget_(d), | ||
1834 | .showLinkNumbers = d->showLinkNumbers, | 1865 | .showLinkNumbers = d->showLinkNumbers, |
1835 | }; | 1866 | }; |
1836 | iDrawContext ctxStatic = ctxDynamic; | 1867 | // iDrawContext ctxStatic = ctxDynamic; |
1837 | ctxStatic.pass = static_DrawRunPass; | 1868 | // ctxStatic.pass = static_DrawRunPass; |
1838 | subv_I2(&ctxStatic.widgetBounds.pos, origin); | 1869 | // subv_I2(&ctx.widgetBounds.pos, origin); |
1839 | subv_I2(&ctxStatic.bounds.pos, origin); | 1870 | // subv_I2(&ctx.bounds.pos, origin); |
1840 | SDL_Renderer *render = get_Window()->render; | 1871 | // SDL_Renderer *render = get_Window()->render; |
1841 | /* Static content. */ { | 1872 | /* Currently visible region. */ |
1842 | iPaint *p = &ctxStatic.paint; | 1873 | const iRangei vis = visibleRange_DocumentWidget_(d); |
1874 | const iRangei full = { 0, size_GmDocument(d->doc).y }; | ||
1875 | reposition_VisBuf(visBuf, vis); | ||
1876 | iRangei invalidRange[3]; | ||
1877 | invalidRanges_VisBuf(visBuf, full, invalidRange); | ||
1878 | /* Redraw the invalid ranges. */ { | ||
1879 | iPaint *p = &ctx.paint; | ||
1843 | init_Paint(p); | 1880 | init_Paint(p); |
1844 | const int vbSrc = visBuf->index; | 1881 | // const int vbSrc = visBuf->index; |
1845 | const int vbDst = visBuf->index ^ 1; | 1882 | // const int vbDst = visBuf->index ^ 1; |
1846 | iRangei drawRange = visRange; | 1883 | // iRangei drawRange = visRange; |
1847 | iAssert(visBuf->texture[vbDst]); | 1884 | iForIndices(i, visBuf->buffers) { |
1885 | iBool isTargetSet = iFalse; | ||
1886 | iVisBufTexture *buf = &visBuf->buffers[i]; | ||
1887 | ctx.widgetBounds = moved_Rect(ctxWidgetBounds, init_I2(0, -buf->origin)); | ||
1888 | ctx.viewPos = init_I2(left_Rect(docBounds) - left_Rect(bounds), -buf->origin); | ||
1889 | if (!isEmpty_Rangei(invalidRange[i])) { | ||
1890 | if (!isTargetSet) { | ||
1891 | beginTarget_Paint(p, buf->texture); | ||
1892 | isTargetSet = iTrue; | ||
1893 | } | ||
1894 | if (isEmpty_Rangei(buf->validRange)) { | ||
1895 | fillRect_Paint(p, (iRect){ zero_I2(), visBuf->texSize }, tmBackground_ColorId); | ||
1896 | } | ||
1897 | render_GmDocument(d->doc, invalidRange[i], drawRun_DrawContext_, &ctx); | ||
1898 | } | ||
1899 | /* Draw any invalidated runs that fall within this buffer. */ | ||
1900 | const iRangei bufRange = { buf->origin, buf->origin + visBuf->texSize.y }; | ||
1901 | iConstForEach(PtrSet, r, d->invalidRuns) { | ||
1902 | const iGmRun *run = *r.value; | ||
1903 | if (!isEmpty_Rangei(intersect_Rangei( | ||
1904 | bufRange, | ||
1905 | (iRangei){ top_Rect(run->visBounds), bottom_Rect(run->visBounds) }))) { | ||
1906 | if (!isTargetSet) { | ||
1907 | beginTarget_Paint(p, buf->texture); | ||
1908 | isTargetSet = iTrue; | ||
1909 | } | ||
1910 | drawRun_DrawContext_(&ctx, run); | ||
1911 | } | ||
1912 | } | ||
1913 | if (isTargetSet) { | ||
1914 | endTarget_Paint(&ctx.paint); | ||
1915 | } | ||
1916 | fflush(stdout); | ||
1917 | } | ||
1918 | validate_VisBuf(visBuf); | ||
1919 | clear_PtrSet(d->invalidRuns); | ||
1920 | } | ||
1921 | #if 0 | ||
1922 | // iAssert(visBuf->texture[vbDst]); | ||
1848 | beginTarget_Paint(p, visBuf->texture[vbDst]); | 1923 | beginTarget_Paint(p, visBuf->texture[vbDst]); |
1849 | const iRect visBufferRect = { zero_I2(), visBuf->size }; | 1924 | const iRect visBufferRect = { zero_I2(), visBuf->size }; |
1850 | iRect drawRect = visBufferRect; | 1925 | iRect drawRect = visBufferRect; |
@@ -1897,7 +1972,24 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
1897 | unsetClip_Paint(p); | 1972 | unsetClip_Paint(p); |
1898 | enableKerning_Text = iTrue; | 1973 | enableKerning_Text = iTrue; |
1899 | } | 1974 | } |
1900 | 1975 | #endif | |
1976 | setClip_Paint(&ctx.paint, bounds); | ||
1977 | const int yTop = docBounds.pos.y - d->scrollY; | ||
1978 | draw_VisBuf(visBuf, init_I2(bounds.pos.x, yTop)); | ||
1979 | unsetClip_Paint(&ctx.paint); | ||
1980 | /* Fill the top and bottom, in case the document is short. */ | ||
1981 | if (yTop > top_Rect(bounds)) { | ||
1982 | fillRect_Paint(&ctx.paint, | ||
1983 | (iRect){ bounds.pos, init_I2(bounds.size.x, yTop - top_Rect(bounds)) }, | ||
1984 | hasSiteBanner_GmDocument(d->doc) ? tmBannerBackground_ColorId | ||
1985 | : tmBackground_ColorId); | ||
1986 | } | ||
1987 | const int yBottom = yTop + size_GmDocument(d->doc).y; | ||
1988 | if (yBottom < bottom_Rect(bounds)) { | ||
1989 | fillRect_Paint(&ctx.paint, | ||
1990 | init_Rect(bounds.pos.x, yBottom, bounds.size.x, bottom_Rect(bounds) - yBottom), | ||
1991 | tmBackground_ColorId); | ||
1992 | } | ||
1901 | // drawRect_Paint(&ctx.paint, | 1993 | // drawRect_Paint(&ctx.paint, |
1902 | // moved_Rect((iRect){ zero_I2(), size_GmDocument(d->doc) }, | 1994 | // moved_Rect((iRect){ zero_I2(), size_GmDocument(d->doc) }, |
1903 | // add_I2(topLeft_Rect(ctx.bounds), init_I2(0, -d->scrollY))), | 1995 | // add_I2(topLeft_Rect(ctx.bounds), init_I2(0, -d->scrollY))), |