"Vectorise" most coordinate operations
dkl9

dkl9 commited on 2025-181 16:30:28
Showing 1 changed files, with 43 additions and 50 deletions.

... ...
@@ -9,6 +9,7 @@
9 9
 #include "SDL2/SDL.h"
10 10
 #include "SDL2/SDL_image.h"
11 11
 
12
+#define TWICE(x) for (int j = 0; j < 2; j++) { x; }
12 13
 #define ZSH(a, b) ((a) * powf(2, b))
13 14
 #define CLAMP(a, x, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
14 15
 #define APS 6
... ...
@@ -19,13 +20,11 @@
19 20
 struct ViewState {
20 21
     SDL_Texture* tex;
21 22
     /* image dimensions */
22
-    int iw;
23
-    int ih;
23
+    unsigned int idim[2];
24 24
     /* zoom level */
25 25
     float zoom;
26 26
     /* pan position (centre of image) */
27
-    int px;
28
-    int py;
27
+    int pan[2];
29 28
 };
30 29
 
31 30
 /* if cond is true, exit the program as a failure,
... ...
@@ -110,26 +109,24 @@ void updatetitle(SDL_Window* window, const char* ct, char** title, const char* f
110 109
         free(*title);
111 110
         *title = malloc(strlen(fname) + 32);
112 111
         cfail(!*title, "allocate memory", 0);
113
-        sprintf(*title, "iv: %s (%dx%d)", fname, vs.iw, vs.ih);
112
+        sprintf(*title, "iv: %s (%dx%d)", fname, vs.idim[0], vs.idim[1]);
114 113
         SDL_SetWindowTitle(window, *title);
115 114
     }
116 115
 }
117 116
 
118 117
 void showcoords(const SDL_MouseButtonEvent button, const struct ViewState vs) {
119
-    printf(
120
-        "%.0f, %.0f\n",
121
-        ZSH((float)button.x - (float)vs.px + ZSH(vs.iw, vs.zoom - 1.0), -vs.zoom),
122
-        ZSH((float)button.y - (float)vs.py + ZSH(vs.ih, vs.zoom - 1.0), -vs.zoom)
123
-    );
118
+    float cc[2];
119
+    int bpos[2] = {button.x, button.y};
120
+    TWICE(cc[j] = ZSH((float)bpos[j] - (float)vs.pan[j] + ZSH(vs.idim[j], vs.zoom - 1.0), -vs.zoom))
121
+    printf("%.0f, %.0f\n", cc[0], cc[1]);
124 122
     fflush(stdout);
125 123
 }
126 124
 
127
-int handlekey(SDL_Keycode sym, struct ViewState* vs, int ci, int fc, int ww, int wh) {
125
+int handlekey(SDL_Keycode sym, struct ViewState* vs, int ci, int fc, const unsigned int wdim[2]) {
128 126
     switch (sym) {
129 127
         /* bring image back into focus when Space is pressed */
130 128
         case SDLK_SPACE:
131
-            vs->px = ww / 2;
132
-            vs->py = wh / 2;
129
+            TWICE(vs->pan[j] = wdim[j] / 2)
133 130
             return 2;
134 131
             break;
135 132
         /* exit when Esc is pressed */
... ...
@@ -153,12 +150,12 @@ int handlekey(SDL_Keycode sym, struct ViewState* vs, int ci, int fc, int ww, int
153 150
     return 0;
154 151
 }
155 152
 
156
-void drawbg(SDL_Renderer* ren, const int ww, const int wh, const int cw, const int ch, SDL_Texture* act) {
153
+void drawbg(SDL_Renderer* ren, const unsigned int wdim[2], const int cw, const int ch, SDL_Texture* act) {
157 154
     /* clear to background colour */
158 155
     cfail(SDL_RenderClear(ren), "clear screen", 1);
159 156
     /* alpha checker background */
160
-    for (int i = 0; i < ww; i += APS * cw) {
161
-        for (int j = 0; j < wh; j += APS * ch) {
157
+    for (int i = 0; i < wdim[0]; i += APS * cw) {
158
+        for (int j = 0; j < wdim[1]; j += APS * ch) {
162 159
             cfail(SDL_RenderCopy(ren, act, NULL, &(SDL_Rect){
163 160
                 .x = i, .y = j, .w = APS * cw, .h = APS * ch
164 161
             }), "draw checker background", 1);
... ...
@@ -167,10 +164,12 @@ void drawbg(SDL_Renderer* ren, const int ww, const int wh, const int cw, const i
167 164
 }
168 165
 
169 166
 void drawfg(SDL_Renderer* ren, const struct ViewState vs) {
167
+    int ic[2];
168
+    TWICE(ic[j] = vs.pan[j] - ZSH(vs.idim[j], vs.zoom - 1.0))
170 169
     /* render image */
171 170
     cfail(SDL_RenderCopy(ren, vs.tex, NULL, &(SDL_Rect){
172
-        .x = vs.px - ZSH(vs.iw, vs.zoom - 1.0), .y = vs.py - ZSH(vs.ih, vs.zoom - 1.0),
173
-        .w = ZSH(vs.iw, vs.zoom), .h = ZSH(vs.ih, vs.zoom)
171
+        .x = ic[0], .y = ic[1],
172
+        .w = ZSH(vs.idim[0], vs.zoom), .h = ZSH(vs.idim[1], vs.zoom)
174 173
     }), "display image", 1);
175 174
 }
176 175
 
... ...
@@ -213,10 +212,9 @@ int main(int argc, char** argv) {
213 212
     for (int i = 0; i < fc; i++) {
214 213
         sl[i].tex = SDL_CreateTextureFromSurface(ren, isurf[i]);
215 214
         cfail(!sl[i].tex, "create texture", 1);
216
-        sl[i].px = sl[i].iw = isurf[i]->w;
217
-        sl[i].px /= 2;
218
-        sl[i].py = sl[i].ih = isurf[i]->h;
219
-        sl[i].py /= 2;
215
+        sl[i].idim[0] = isurf[i]->w;
216
+        sl[i].idim[1] = isurf[i]->h;
217
+        TWICE(sl[i].pan[j] = sl[i].idim[j] / 2)
220 218
         SDL_FreeSurface(isurf[i]);
221 219
     }
222 220
 
... ...
@@ -231,10 +229,9 @@ int main(int argc, char** argv) {
231 229
     /* only bother to redraw if an event that requires it is found */
232 230
     int ef;
233 231
     /* window size */
234
-    int ww = iw;
235
-    int wh = ih;
232
+    unsigned int wdim[2] = {iw, ih};
236 233
     /* mouse position */
237
-    int mx, my;
234
+    int mpos[2];
238 235
 
239 236
     while (r) {
240 237
         ef = 0;
... ...
@@ -243,7 +240,7 @@ int main(int argc, char** argv) {
243 240
 
244 241
                 case SDL_KEYUP:
245 242
                     int iic = 0;
246
-                    switch (handlekey(ev.key.keysym.sym, &sl[ci], ci, fc, ww, wh)) {
243
+                    switch (handlekey(ev.key.keysym.sym, &sl[ci], ci, fc, wdim)) {
247 244
                         case 4:
248 245
                             r = 0;
249 246
                             break;
... ...
@@ -272,8 +269,7 @@ int main(int argc, char** argv) {
272 269
                     }
273 270
                     /* bring image back into focus on right-click */
274 271
                     if (ev.button.button == 3) {
275
-                        sl[ci].px = ww / 2;
276
-                        sl[ci].py = wh / 2;
272
+                        TWICE(sl[ci].pan[j] = wdim[j] / 2)
277 273
                         ef = 1;
278 274
                     }
279 275
                     break;
... ...
@@ -281,32 +277,29 @@ int main(int argc, char** argv) {
281 277
                 case SDL_MOUSEMOTION:
282 278
                     /* pan-dragging if mouse is down */
283 279
                     if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) {
284
-                        int sw = ZSH(sl[ci].iw, sl[ci].zoom - 1.0);
285
-                        int sh = ZSH(sl[ci].ih, sl[ci].zoom - 1.0);
280
+                        int hid, big;
281
+                        int rel[2] = {ev.motion.xrel, ev.motion.yrel};
286 282
                         /* clamp panning to edges of window */
287
-                        int big = 2 * sw > ww;
288
-                        sl[ci].px = CLAMP(
289
-                            big ? ww - sw : sw,
290
-                            sl[ci].px + ev.motion.xrel,
291
-                            big ? sw : ww - sw
292
-                        );
293
-                        big = 2 * sh > wh;
294
-                        sl[ci].py = CLAMP(
295
-                            big ? wh - sh : sh,
296
-                            sl[ci].py + ev.motion.yrel,
297
-                            big ? sh : wh - sh
298
-                        );
283
+                        TWICE(
284
+                            hid = ZSH(sl[ci].idim[j], sl[ci].zoom - 1.0);
285
+                            big = 2 * hid > wdim[j];
286
+                            sl[ci].pan[j] = CLAMP(
287
+                                big ? wdim[j] - hid : hid,
288
+                                sl[ci].pan[j] + rel[j],
289
+                                big ? hid : wdim[j] - hid
290
+                            )
291
+                        )
299 292
                         ef = 1;
300 293
                     }
301
-                    mx = ev.motion.x;
302
-                    my = ev.motion.y;
294
+                    mpos[0] = ev.motion.x;
295
+                    mpos[1] = ev.motion.y;
303 296
                     break;
304 297
 
305 298
                 case SDL_MOUSEWHEEL:
306 299
                     /* scrolling changes zoom */
307
-                    sl[ci].zoom += DZDS * ev.wheel.y;
308
-                    sl[ci].px = mx - ZSH((mx - sl[ci].px), DZDS * ev.wheel.y);
309
-                    sl[ci].py = my - ZSH((my - sl[ci].py), DZDS * ev.wheel.y);
300
+                    float dz = DZDS * ev.wheel.y;
301
+                    sl[ci].zoom += dz;
302
+                    TWICE(sl[ci].pan[j] = mpos[j] - ZSH((mpos[j] - sl[ci].pan[j]), dz))
310 303
                     ef = 1;
311 304
                     break;
312 305
 
... ...
@@ -326,8 +319,8 @@ int main(int argc, char** argv) {
326 319
                             ef = 1;
327 320
                             break;
328 321
                         case SDL_WINDOWEVENT_SIZE_CHANGED:
329
-                            ww = ev.window.data1;
330
-                            wh = ev.window.data2;
322
+                            wdim[0] = ev.window.data1;
323
+                            wdim[1] = ev.window.data2;
331 324
                             break;
332 325
                     }
333 326
                     break;
... ...
@@ -336,7 +329,7 @@ int main(int argc, char** argv) {
336 329
         }
337 330
 
338 331
         if (ef) {
339
-            drawbg(ren, ww, wh, cw, ch, act);
332
+            drawbg(ren, wdim, cw, ch, act);
340 333
             drawfg(ren, sl[ci]);
341 334
             SDL_RenderPresent(ren);
342 335
         }
343 336