summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-29 15:33:19 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-29 15:33:19 +0300
commitb1a03400b2d32cf3d82defe15ebe64a3cdcf6981 (patch)
treeec56e8c36de779659dfb95c1761c5891d4b37cde /src
parent2578441c43544205991467720afdfdd0df1ecf4e (diff)
VisBuf: Increase buffer size for scrolling; fixed glitches
Instead of 1.5x coverage, the buffer now has a full 2x.
Diffstat (limited to 'src')
-rw-r--r--src/ui/documentwidget.c7
-rw-r--r--src/ui/listwidget.c13
-rw-r--r--src/ui/visbuf.c64
-rw-r--r--src/ui/visbuf.h2
4 files changed, 56 insertions, 30 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 3b5ddb7c..07b359da 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -2040,10 +2040,9 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
2040 fetchNextUnfetchedImage_DocumentWidget_(d)) { 2040 fetchNextUnfetchedImage_DocumentWidget_(d)) {
2041 return iTrue; 2041 return iTrue;
2042 } 2042 }
2043 const float amount = argLabel_Command(cmd, "full") ? 1.0f : 0.5f; 2043 const float amount = argLabel_Command(cmd, "full") != 0 ? 1.0f : 0.5f;
2044 smoothScroll_DocumentWidget_(d, 2044 smoothScroll_DocumentWidget_(d,
2045 dir * (amount * height_Rect(documentBounds_DocumentWidget_(d)) - 2045 dir * amount * height_Rect(documentBounds_DocumentWidget_(d)),
2046 0 * lineHeight_Text(paragraph_FontId)),
2047 smoothDuration_DocumentWidget_); 2046 smoothDuration_DocumentWidget_);
2048 return iTrue; 2047 return iTrue;
2049 } 2048 }
@@ -3391,7 +3390,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
3391 const iRangei vis = visibleRange_DocumentWidget_(d); 3390 const iRangei vis = visibleRange_DocumentWidget_(d);
3392 const iRangei full = { 0, size_GmDocument(d->doc).y }; 3391 const iRangei full = { 0, size_GmDocument(d->doc).y };
3393 reposition_VisBuf(visBuf, vis); 3392 reposition_VisBuf(visBuf, vis);
3394 iRangei invalidRange[3]; 3393 iRangei invalidRange[iElemCount(d->visBuf->buffers)];
3395 invalidRanges_VisBuf(visBuf, full, invalidRange); 3394 invalidRanges_VisBuf(visBuf, full, invalidRange);
3396 /* Redraw the invalid ranges. */ { 3395 /* Redraw the invalid ranges. */ {
3397 iPaint *p = &ctx.paint; 3396 iPaint *p = &ctx.paint;
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index 942c46dd..95a59090 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -361,17 +361,18 @@ static void draw_ListWidget_(const iListWidget *d) {
361 /* TODO: This seems to draw two items per each shift of the visible region, even though 361 /* TODO: This seems to draw two items per each shift of the visible region, even though
362 one should be enough. Probably an off-by-one error in the calculation of the 362 one should be enough. Probably an off-by-one error in the calculation of the
363 invalid range. */ 363 invalid range. */
364 iAssert(d->visBuf->buffers[0].texture); 364 iForIndices(i, d->visBuf->buffers) {
365 iAssert(d->visBuf->buffers[1].texture); 365 iAssert(d->visBuf->buffers[i].texture);
366 iAssert(d->visBuf->buffers[2].texture); 366 }
367 const int bg[3] = { w->bgColor, w->bgColor, w->bgColor }; 367 const int bg[iElemCount(d->visBuf->buffers)] = {
368// const int bg[3] = { red_ColorId, magenta_ColorId, blue_ColorId }; 368 w->bgColor, w->bgColor, w->bgColor, w->bgColor
369 };
369 const int bottom = numItems_ListWidget(d) * d->itemHeight; 370 const int bottom = numItems_ListWidget(d) * d->itemHeight;
370 const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight, 371 const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight,
371 ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; 372 ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight };
372 reposition_VisBuf(d->visBuf, vis); 373 reposition_VisBuf(d->visBuf, vis);
373 /* Check which parts are invalid. */ 374 /* Check which parts are invalid. */
374 iRangei invalidRange[3]; 375 iRangei invalidRange[iElemCount(d->visBuf->buffers)];
375 invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange); 376 invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange);
376 iForIndices(i, d->visBuf->buffers) { 377 iForIndices(i, d->visBuf->buffers) {
377 iVisBufTexture *buf = &d->visBuf->buffers[i]; 378 iVisBufTexture *buf = &d->visBuf->buffers[i];
diff --git a/src/ui/visbuf.c b/src/ui/visbuf.c
index 0f9e1092..198ad574 100644
--- a/src/ui/visbuf.c
+++ b/src/ui/visbuf.c
@@ -75,12 +75,13 @@ void dealloc_VisBuf(iVisBuf *d) {
75void reposition_VisBuf(iVisBuf *d, const iRangei vis) { 75void reposition_VisBuf(iVisBuf *d, const iRangei vis) {
76 d->vis = vis; 76 d->vis = vis;
77 iRangei good = { 0, 0 }; 77 iRangei good = { 0, 0 };
78 size_t avail[3], numAvail = 0; 78 size_t avail[iElemCount(d->buffers)], numAvail = 0;
79 /* Check which buffers are available for reuse. */ { 79 /* Check which buffers are available for reuse. */ {
80 iForIndices(i, d->buffers) { 80 iForIndices(i, d->buffers) {
81 iVisBufTexture *buf = d->buffers + i; 81 iVisBufTexture *buf = d->buffers + i;
82 const iRangei region = { buf->origin, buf->origin + d->texSize.y }; 82 const iRangei region = { buf->origin, buf->origin + d->texSize.y };
83 if (region.start >= vis.end || region.end <= vis.start) { 83 if (isEmpty_Rangei(buf->validRange) ||
84 buf->validRange.start >= vis.end || buf->validRange.end <= vis.start) {
84 avail[numAvail++] = i; 85 avail[numAvail++] = i;
85 iZap(buf->validRange); 86 iZap(buf->validRange);
86 } 87 }
@@ -89,25 +90,50 @@ void reposition_VisBuf(iVisBuf *d, const iRangei vis) {
89 } 90 }
90 } 91 }
91 } 92 }
92 if (numAvail == iElemCount(d->buffers)) { 93 iBool wasChanged = iFalse;
93 /* All buffers are outside the visible range, do a reset. */ 94 iBool doReset = (numAvail == iElemCount(d->buffers));
94 d->buffers[0].origin = vis.start; 95 /* Try to extend to cover the visible range. */
95 d->buffers[1].origin = vis.start + d->texSize.y; 96 while (!doReset && vis.start < good.start) {
96 d->buffers[2].origin = vis.start + 2 * d->texSize.y; 97 if (numAvail == 0) {
98 doReset = iTrue;
99 break;
100 }
101 good.start -= d->texSize.y;
102 d->buffers[avail[--numAvail]].origin = good.start;
103 wasChanged = iTrue;
97 } 104 }
98 else { 105 while (!doReset && vis.end > good.end) {
99 /* Extend to cover the visible range. */ 106 if (numAvail == 0) {
100 while (vis.start < good.start) { 107 doReset = iTrue;
101 iAssert(numAvail > 0); 108 break;
102 d->buffers[avail[--numAvail]].origin = good.start - d->texSize.y;
103 good.start -= d->texSize.y;
104 } 109 }
105 while (vis.end > good.end) { 110 d->buffers[avail[--numAvail]].origin = good.end;
106 iAssert(numAvail > 0); 111 good.end += d->texSize.y;
107 d->buffers[avail[--numAvail]].origin = good.end; 112 wasChanged = iTrue;
108 good.end += d->texSize.y; 113 }
114 if (doReset) {
115// puts("VisBuf reset!");
116// fflush(stdout);
117 wasChanged = iTrue;
118 int pos = -1;
119 iForIndices(i, d->buffers) {
120 iZap(d->buffers[i].validRange);
121 d->buffers[i].origin = vis.start + pos++ * d->texSize.y;
109 } 122 }
110 } 123 }
124#if 0
125 if (wasChanged) {
126 printf("\nVISIBLE RANGE: %d ... %d\n", vis.start, vis.end);
127 iForIndices(i, d->buffers) {
128 const iVisBufTexture *bt = &d->buffers[i];
129 printf(" %zu: buf %5d ... %5d valid %5d ... %5d\n", i, bt->origin,
130 bt->origin + d->texSize.y,
131 bt->validRange.start,
132 bt->validRange.end);
133 }
134 fflush(stdout);
135 }
136#endif
111} 137}
112 138
113void invalidRanges_VisBuf(const iVisBuf *d, const iRangei full, iRangei *out_invalidRanges) { 139void invalidRanges_VisBuf(const iVisBuf *d, const iRangei full, iRangei *out_invalidRanges) {
diff --git a/src/ui/visbuf.h b/src/ui/visbuf.h
index 4b0908f9..b285e90b 100644
--- a/src/ui/visbuf.h
+++ b/src/ui/visbuf.h
@@ -38,7 +38,7 @@ struct Impl_VisBufTexture {
38struct Impl_VisBuf { 38struct Impl_VisBuf {
39 iInt2 texSize; 39 iInt2 texSize;
40 iRangei vis; 40 iRangei vis;
41 iVisBufTexture buffers[3]; 41 iVisBufTexture buffers[4];
42}; 42};
43 43
44iDeclareTypeConstruction(VisBuf) 44iDeclareTypeConstruction(VisBuf)