summaryrefslogtreecommitdiff
path: root/src/ui/visbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/visbuf.c')
-rw-r--r--src/ui/visbuf.c86
1 files changed, 62 insertions, 24 deletions
diff --git a/src/ui/visbuf.c b/src/ui/visbuf.c
index e9bfee58..88a5fd60 100644
--- a/src/ui/visbuf.c
+++ b/src/ui/visbuf.c
@@ -38,7 +38,7 @@ void deinit_VisBuf(iVisBuf *d) {
38} 38}
39 39
40void invalidate_VisBuf(iVisBuf *d) { 40void invalidate_VisBuf(iVisBuf *d) {
41 int origin = d->vis.start - d->texSize.y; 41 int origin = iMax(0, d->vis.start - d->texSize.y);
42 iForIndices(i, d->buffers) { 42 iForIndices(i, d->buffers) {
43 d->buffers[i].origin = origin; 43 d->buffers[i].origin = origin;
44 origin += d->texSize.y; 44 origin += d->texSize.y;
@@ -109,10 +109,41 @@ static size_t take_(size_t *avail, size_t *numAvail, size_t index) {
109} 109}
110#endif 110#endif
111 111
112static void roll_VisBuf_(iVisBuf *d, int dir) {
113 const size_t lastPos = iElemCount(d->buffers) - 1;
114 if (dir < 0) {
115 /* Last buffer is moved to the beginning. */
116 SDL_Texture *last = d->buffers[lastPos].texture;
117 void * user = d->buffers[lastPos].user;
118 memmove(d->buffers + 1, d->buffers, sizeof(iVisBufTexture) * lastPos);
119 d->buffers[0].texture = last;
120 d->buffers[0].user = user;
121 d->buffers[0].origin = d->buffers[1].origin - d->texSize.y;
122 iZap(d->buffers[0].validRange);
123 if (d->bufferInvalidated) {
124 d->bufferInvalidated(d, 0);
125 }
126 }
127 else {
128 /* First buffer is moved to the end. */
129 SDL_Texture *first = d->buffers[0].texture;
130 void * user = d->buffers[0].user;
131 memmove(d->buffers, d->buffers + 1, sizeof(iVisBufTexture) * lastPos);
132 d->buffers[lastPos].texture = first;
133 d->buffers[lastPos].user = user;
134 d->buffers[lastPos].origin = d->buffers[lastPos - 1].origin + d->texSize.y;
135 iZap(d->buffers[lastPos].validRange);
136 if (d->bufferInvalidated) {
137 d->bufferInvalidated(d, lastPos);
138 }
139 }
140}
141
112iBool reposition_VisBuf(iVisBuf *d, const iRangei vis) { 142iBool reposition_VisBuf(iVisBuf *d, const iRangei vis) {
113 if (equal_Rangei(vis, d->vis)) { 143 if (equal_Rangei(vis, d->vis)) {
114 return iFalse; 144 return iFalse;
115 } 145 }
146 const int moveDir = vis.end > d->vis.end ? +1 : -1;
116 d->vis = vis; 147 d->vis = vis;
117 iBool wasChanged = iFalse; 148 iBool wasChanged = iFalse;
118 const size_t lastPos = iElemCount(d->buffers) - 1; 149 const size_t lastPos = iElemCount(d->buffers) - 1;
@@ -122,36 +153,26 @@ iBool reposition_VisBuf(iVisBuf *d, const iRangei vis) {
122 wasChanged = iTrue; 153 wasChanged = iTrue;
123 } 154 }
124 else { 155 else {
125 /* Roll up. */ 156 /* Check for mandatory rolls. */
126 while (d->buffers[0].origin > vis.start) { 157 while (d->buffers[0].origin > vis.start) {
127 SDL_Texture *last = d->buffers[lastPos].texture; 158 roll_VisBuf_(d, -1);
128 void * user = d->buffers[lastPos].user;
129 memmove(d->buffers + 1, d->buffers, sizeof(iVisBufTexture) * lastPos);
130 d->buffers[0].texture = last;
131 d->buffers[0].user = user;
132 d->buffers[0].origin = d->buffers[1].origin - d->texSize.y;
133 iZap(d->buffers[0].validRange);
134 if (d->bufferInvalidated) {
135 d->bufferInvalidated(d, 0);
136 }
137 wasChanged = iTrue; 159 wasChanged = iTrue;
138 } 160 }
139 if (!wasChanged) { 161 if (!wasChanged) {
140 /* Roll down. */
141 while (d->buffers[lastPos].origin + d->texSize.y < vis.end) { 162 while (d->buffers[lastPos].origin + d->texSize.y < vis.end) {
142 SDL_Texture *first = d->buffers[0].texture; 163 roll_VisBuf_(d, +1);
143 void * user = d->buffers[0].user;
144 memmove(d->buffers, d->buffers + 1, sizeof(iVisBufTexture) * lastPos);
145 d->buffers[lastPos].texture = first;
146 d->buffers[lastPos].user = user;
147 d->buffers[lastPos].origin = d->buffers[lastPos - 1].origin + d->texSize.y;
148 iZap(d->buffers[lastPos].validRange);
149 if (d->bufferInvalidated) {
150 d->bufferInvalidated(d, lastPos);
151 }
152 wasChanged = iTrue; 164 wasChanged = iTrue;
153 } 165 }
154 } 166 }
167 /* Scroll-direction dependent optional rolls, with a bit of overscroll allowed. */
168 if (moveDir > 0 && d->buffers[0].origin + d->texSize.y + d->texSize.y / 4 < vis.start) {
169 roll_VisBuf_(d, +1);
170 wasChanged = iTrue;
171 }
172 else if (moveDir < 0 && d->buffers[lastPos].origin - d->texSize.y / 4 > vis.end) {
173 roll_VisBuf_(d, -1);
174 wasChanged = iTrue;
175 }
155 } 176 }
156#if 0 177#if 0
157 if (wasChanged) { 178 if (wasChanged) {
@@ -228,7 +249,9 @@ void draw_VisBuf(const iVisBuf *d, const iInt2 topLeft, const iRangei yClipBound
228 d->texSize.x, 249 d->texSize.x,
229 d->texSize.y }; 250 d->texSize.y };
230 if (dst.y >= yClipBounds.end || dst.y + dst.h < yClipBounds.start) { 251 if (dst.y >= yClipBounds.end || dst.y + dst.h < yClipBounds.start) {
252#if !defined (DEBUG_SCALE)
231 continue; /* Outside the clipping area. */ 253 continue; /* Outside the clipping area. */
254#endif
232 } 255 }
233#if defined (DEBUG_SCALE) 256#if defined (DEBUG_SCALE)
234 dst.w *= DEBUG_SCALE; 257 dst.w *= DEBUG_SCALE;
@@ -239,5 +262,20 @@ void draw_VisBuf(const iVisBuf *d, const iInt2 topLeft, const iRangei yClipBound
239 dst.y += get_Window()->root->rect.size.y / 4; 262 dst.y += get_Window()->root->rect.size.y / 4;
240#endif 263#endif
241 SDL_RenderCopy(render, buf->texture, NULL, &dst); 264 SDL_RenderCopy(render, buf->texture, NULL, &dst);
242 } 265#if defined (DEBUG_SCALE)
266 SDL_SetRenderDrawColor(render, 0, 0, 255, 255);
267 SDL_RenderDrawRect(render, &dst);
268#endif
269 }
270#if defined (DEBUG_SCALE)
271 SDL_Rect dst = { topLeft.x, yClipBounds.start, d->texSize.x, 2 * d->texSize.y };
272 dst.w *= DEBUG_SCALE;
273 dst.h *= DEBUG_SCALE;
274 dst.x *= DEBUG_SCALE;
275 dst.y *= DEBUG_SCALE;
276 dst.x += get_Window()->root->rect.size.x / 4;
277 dst.y += get_Window()->root->rect.size.y / 4;
278 SDL_SetRenderDrawColor(render, 255, 255, 255, 255);
279 SDL_RenderDrawRect(render, &dst);
280#endif
243} 281}