From b1a03400b2d32cf3d82defe15ebe64a3cdcf6981 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Mon, 29 Mar 2021 15:33:19 +0300 Subject: VisBuf: Increase buffer size for scrolling; fixed glitches Instead of 1.5x coverage, the buffer now has a full 2x. --- src/ui/documentwidget.c | 7 +++--- src/ui/listwidget.c | 13 +++++----- src/ui/visbuf.c | 64 ++++++++++++++++++++++++++++++++++--------------- src/ui/visbuf.h | 2 +- 4 files changed, 56 insertions(+), 30 deletions(-) (limited to 'src') 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) fetchNextUnfetchedImage_DocumentWidget_(d)) { return iTrue; } - const float amount = argLabel_Command(cmd, "full") ? 1.0f : 0.5f; + const float amount = argLabel_Command(cmd, "full") != 0 ? 1.0f : 0.5f; smoothScroll_DocumentWidget_(d, - dir * (amount * height_Rect(documentBounds_DocumentWidget_(d)) - - 0 * lineHeight_Text(paragraph_FontId)), + dir * amount * height_Rect(documentBounds_DocumentWidget_(d)), smoothDuration_DocumentWidget_); return iTrue; } @@ -3391,7 +3390,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { const iRangei vis = visibleRange_DocumentWidget_(d); const iRangei full = { 0, size_GmDocument(d->doc).y }; reposition_VisBuf(visBuf, vis); - iRangei invalidRange[3]; + iRangei invalidRange[iElemCount(d->visBuf->buffers)]; invalidRanges_VisBuf(visBuf, full, invalidRange); /* Redraw the invalid ranges. */ { 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) { /* TODO: This seems to draw two items per each shift of the visible region, even though one should be enough. Probably an off-by-one error in the calculation of the invalid range. */ - iAssert(d->visBuf->buffers[0].texture); - iAssert(d->visBuf->buffers[1].texture); - iAssert(d->visBuf->buffers[2].texture); - const int bg[3] = { w->bgColor, w->bgColor, w->bgColor }; -// const int bg[3] = { red_ColorId, magenta_ColorId, blue_ColorId }; + iForIndices(i, d->visBuf->buffers) { + iAssert(d->visBuf->buffers[i].texture); + } + const int bg[iElemCount(d->visBuf->buffers)] = { + w->bgColor, w->bgColor, w->bgColor, w->bgColor + }; const int bottom = numItems_ListWidget(d) * d->itemHeight; const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight, ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; reposition_VisBuf(d->visBuf, vis); /* Check which parts are invalid. */ - iRangei invalidRange[3]; + iRangei invalidRange[iElemCount(d->visBuf->buffers)]; invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange); iForIndices(i, d->visBuf->buffers) { 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) { void reposition_VisBuf(iVisBuf *d, const iRangei vis) { d->vis = vis; iRangei good = { 0, 0 }; - size_t avail[3], numAvail = 0; + size_t avail[iElemCount(d->buffers)], numAvail = 0; /* Check which buffers are available for reuse. */ { iForIndices(i, d->buffers) { - iVisBufTexture *buf = d->buffers + i; - const iRangei region = { buf->origin, buf->origin + d->texSize.y }; - if (region.start >= vis.end || region.end <= vis.start) { + iVisBufTexture *buf = d->buffers + i; + const iRangei region = { buf->origin, buf->origin + d->texSize.y }; + if (isEmpty_Rangei(buf->validRange) || + buf->validRange.start >= vis.end || buf->validRange.end <= vis.start) { avail[numAvail++] = i; iZap(buf->validRange); } @@ -89,25 +90,50 @@ void reposition_VisBuf(iVisBuf *d, const iRangei vis) { } } } - if (numAvail == iElemCount(d->buffers)) { - /* All buffers are outside the visible range, do a reset. */ - d->buffers[0].origin = vis.start; - d->buffers[1].origin = vis.start + d->texSize.y; - d->buffers[2].origin = vis.start + 2 * d->texSize.y; + iBool wasChanged = iFalse; + iBool doReset = (numAvail == iElemCount(d->buffers)); + /* Try to extend to cover the visible range. */ + while (!doReset && vis.start < good.start) { + if (numAvail == 0) { + doReset = iTrue; + break; + } + good.start -= d->texSize.y; + d->buffers[avail[--numAvail]].origin = good.start; + wasChanged = iTrue; } - else { - /* Extend to cover the visible range. */ - while (vis.start < good.start) { - iAssert(numAvail > 0); - d->buffers[avail[--numAvail]].origin = good.start - d->texSize.y; - good.start -= d->texSize.y; + while (!doReset && vis.end > good.end) { + if (numAvail == 0) { + doReset = iTrue; + break; } - while (vis.end > good.end) { - iAssert(numAvail > 0); - d->buffers[avail[--numAvail]].origin = good.end; - good.end += d->texSize.y; + d->buffers[avail[--numAvail]].origin = good.end; + good.end += d->texSize.y; + wasChanged = iTrue; + } + if (doReset) { +// puts("VisBuf reset!"); +// fflush(stdout); + wasChanged = iTrue; + int pos = -1; + iForIndices(i, d->buffers) { + iZap(d->buffers[i].validRange); + d->buffers[i].origin = vis.start + pos++ * d->texSize.y; } } +#if 0 + if (wasChanged) { + printf("\nVISIBLE RANGE: %d ... %d\n", vis.start, vis.end); + iForIndices(i, d->buffers) { + const iVisBufTexture *bt = &d->buffers[i]; + printf(" %zu: buf %5d ... %5d valid %5d ... %5d\n", i, bt->origin, + bt->origin + d->texSize.y, + bt->validRange.start, + bt->validRange.end); + } + fflush(stdout); + } +#endif } void 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 { struct Impl_VisBuf { iInt2 texSize; iRangei vis; - iVisBufTexture buffers[3]; + iVisBufTexture buffers[4]; }; iDeclareTypeConstruction(VisBuf) -- cgit v1.2.3