dkl9 commited on 2025-181 00:45:39
Showing 1 changed files, with 78 additions and 64 deletions.
| ... | ... |
@@ -17,8 +17,7 @@ |
| 17 | 17 |
#define DZDS 0.25 |
| 18 | 18 |
|
| 19 | 19 |
struct ViewState {
|
| 20 |
- /* image index */ |
|
| 21 |
- int ci; |
|
| 20 |
+ SDL_Texture* tex; |
|
| 22 | 21 |
/* image dimensions */ |
| 23 | 22 |
int iw; |
| 24 | 23 |
int ih; |
| ... | ... |
@@ -27,9 +26,6 @@ struct ViewState {
|
| 27 | 26 |
/* pan position (centre of image) */ |
| 28 | 27 |
int px; |
| 29 | 28 |
int py; |
| 30 |
- /* keep track of mouse coordinates */ |
|
| 31 |
- int mx; |
|
| 32 |
- int my; |
|
| 33 | 29 |
}; |
| 34 | 30 |
|
| 35 | 31 |
/* if cond is true, exit the program as a failure, |
| ... | ... |
@@ -128,6 +124,35 @@ void showcoords(const SDL_MouseButtonEvent button, const struct ViewState vs) {
|
| 128 | 124 |
fflush(stdout); |
| 129 | 125 |
} |
| 130 | 126 |
|
| 127 |
+int handlekey(SDL_Keycode sym, struct ViewState* vs, int ci, int fc, int ww, int wh) {
|
|
| 128 |
+ switch (sym) {
|
|
| 129 |
+ /* bring image back into focus when Space is pressed */ |
|
| 130 |
+ case SDLK_SPACE: |
|
| 131 |
+ vs->px = ww / 2; |
|
| 132 |
+ vs->py = wh / 2; |
|
| 133 |
+ return 2; |
|
| 134 |
+ break; |
|
| 135 |
+ /* exit when Esc is pressed */ |
|
| 136 |
+ case SDLK_ESCAPE: |
|
| 137 |
+ return 4; |
|
| 138 |
+ break; |
|
| 139 |
+ /* navigate image list with arrow keys */ |
|
| 140 |
+ case SDLK_LEFT: |
|
| 141 |
+ case SDLK_UP: |
|
| 142 |
+ if (ci > 0) {
|
|
| 143 |
+ return -1; |
|
| 144 |
+ } |
|
| 145 |
+ break; |
|
| 146 |
+ case SDLK_RIGHT: |
|
| 147 |
+ case SDLK_DOWN: |
|
| 148 |
+ if (ci < fc - 1) {
|
|
| 149 |
+ return 1; |
|
| 150 |
+ } |
|
| 151 |
+ break; |
|
| 152 |
+ } |
|
| 153 |
+ return 0; |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 131 | 156 |
void drawbg(SDL_Renderer* ren, const int ww, const int wh, const int cw, const int ch, SDL_Texture* act) {
|
| 132 | 157 |
/* clear to background colour */ |
| 133 | 158 |
cfail(SDL_RenderClear(ren), "clear screen", 1); |
| ... | ... |
@@ -141,9 +166,9 @@ void drawbg(SDL_Renderer* ren, const int ww, const int wh, const int cw, const i |
| 141 | 166 |
} |
| 142 | 167 |
} |
| 143 | 168 |
|
| 144 |
-void drawfg(SDL_Renderer* ren, const struct ViewState vs, SDL_Texture* imgtex) {
|
|
| 169 |
+void drawfg(SDL_Renderer* ren, const struct ViewState vs) {
|
|
| 145 | 170 |
/* render image */ |
| 146 |
- cfail(SDL_RenderCopy(ren, imgtex, NULL, &(SDL_Rect){
|
|
| 171 |
+ cfail(SDL_RenderCopy(ren, vs.tex, NULL, &(SDL_Rect){
|
|
| 147 | 172 |
.x = vs.px - ZSH(vs.iw, vs.zoom - 1.0), .y = vs.py - ZSH(vs.ih, vs.zoom - 1.0), |
| 148 | 173 |
.w = ZSH(vs.iw, vs.zoom), .h = ZSH(vs.ih, vs.zoom) |
| 149 | 174 |
}), "display image", 1); |
| ... | ... |
@@ -160,8 +185,9 @@ int main(int argc, char** argv) {
|
| 160 | 185 |
cfail(optind >= argc, "find filename(s) in options", 0); |
| 161 | 186 |
int fc = argc - optind; |
| 162 | 187 |
SDL_Surface** isurf = loadimages(argv, fc); |
| 163 |
- int iw = isurf[0]->w; |
|
| 164 |
- int ih = isurf[0]->h; |
|
| 188 |
+ int ci = 0; |
|
| 189 |
+ int iw = isurf[ci]->w; |
|
| 190 |
+ int ih = isurf[ci]->h; |
|
| 165 | 191 |
|
| 166 | 192 |
/* create window and renderer */ |
| 167 | 193 |
char* title = NULL; |
| ... | ... |
@@ -183,10 +209,14 @@ int main(int argc, char** argv) {
|
| 183 | 209 |
/* make images into textures */ |
| 184 | 210 |
int cw, ch; |
| 185 | 211 |
SDL_Texture* act = checker(ren, argv[0], &cw, &ch); |
| 186 |
- SDL_Texture** itex = calloc(fc, sizeof (SDL_Texture*)); |
|
| 212 |
+ struct ViewState* sl = calloc(fc, sizeof(struct ViewState)); |
|
| 187 | 213 |
for (int i = 0; i < fc; i++) {
|
| 188 |
- itex[i] = SDL_CreateTextureFromSurface(ren, isurf[i]); |
|
| 189 |
- cfail(!itex[i], "create texture", 1); |
|
| 214 |
+ sl[i].tex = SDL_CreateTextureFromSurface(ren, isurf[i]); |
|
| 215 |
+ 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; |
|
| 190 | 220 |
SDL_FreeSurface(isurf[i]); |
| 191 | 221 |
} |
| 192 | 222 |
|
| ... | ... |
@@ -203,10 +233,8 @@ int main(int argc, char** argv) {
|
| 203 | 233 |
/* window size */ |
| 204 | 234 |
int ww = iw; |
| 205 | 235 |
int wh = ih; |
| 206 |
- struct ViewState vs = {
|
|
| 207 |
- .ci = 0, .iw = iw, .ih = ih, .zoom = 0, |
|
| 208 |
- .px = iw / 2, .py = ih / 2, .mx = 0, .my = 0 |
|
| 209 |
- }; |
|
| 236 |
+ /* mouse position */ |
|
| 237 |
+ int mx, my; |
|
| 210 | 238 |
|
| 211 | 239 |
while (r) {
|
| 212 | 240 |
ef = 0; |
| ... | ... |
@@ -215,52 +243,37 @@ int main(int argc, char** argv) {
|
| 215 | 243 |
|
| 216 | 244 |
case SDL_KEYUP: |
| 217 | 245 |
int iic = 0; |
| 218 |
- switch (ev.key.keysym.sym) {
|
|
| 219 |
- /* bring image back into focus when Space is pressed */ |
|
| 220 |
- case SDLK_SPACE: |
|
| 221 |
- vs.px = ww / 2; |
|
| 222 |
- vs.py = wh / 2; |
|
| 223 |
- ef = 1; |
|
| 224 |
- break; |
|
| 225 |
- /* exit when Esc is pressed */ |
|
| 226 |
- case SDLK_ESCAPE: |
|
| 246 |
+ switch (handlekey(ev.key.keysym.sym, &sl[ci], ci, fc, ww, wh)) {
|
|
| 247 |
+ case 4: |
|
| 227 | 248 |
r = 0; |
| 228 | 249 |
break; |
| 229 |
- /* navigate image list with arrow keys */ |
|
| 230 |
- case SDLK_LEFT: |
|
| 231 |
- case SDLK_UP: |
|
| 232 |
- if (vs.ci > 0) {
|
|
| 233 |
- vs.ci--; |
|
| 250 |
+ case 2: |
|
| 251 |
+ ef = 1; |
|
| 252 |
+ break; |
|
| 253 |
+ case 1: |
|
| 234 | 254 |
iic = 1; |
| 235 |
- } |
|
| 255 |
+ ci++; |
|
| 236 | 256 |
break; |
| 237 |
- case SDLK_RIGHT: |
|
| 238 |
- case SDLK_DOWN: |
|
| 239 |
- if (vs.ci < fc - 1) {
|
|
| 240 |
- vs.ci++; |
|
| 257 |
+ case -1: |
|
| 241 | 258 |
iic = 1; |
| 242 |
- } |
|
| 259 |
+ ci--; |
|
| 243 | 260 |
break; |
| 244 | 261 |
} |
| 245 | 262 |
if (iic) {
|
| 246 |
- cfail(SDL_QueryTexture(itex[vs.ci], NULL, NULL, &vs.iw, &vs.ih), "query texture", 1); |
|
| 247 |
- vs.zoom = 0; |
|
| 248 |
- vs.px = vs.iw / 2; |
|
| 249 |
- vs.py = vs.ih / 2; |
|
| 250 | 263 |
ef = 1; |
| 251 |
- updatetitle(window, ct, &title, argv[optind + vs.ci], vs); |
|
| 264 |
+ updatetitle(window, ct, &title, argv[optind + ci], sl[ci]); |
|
| 252 | 265 |
} |
| 253 | 266 |
break; |
| 254 | 267 |
|
| 255 | 268 |
case SDL_MOUSEBUTTONDOWN: |
| 256 | 269 |
/* output coordinates of cursor in image on middle-click */ |
| 257 | 270 |
if (ev.button.button == 2) {
|
| 258 |
- showcoords(ev.button, vs); |
|
| 271 |
+ showcoords(ev.button, sl[ci]); |
|
| 259 | 272 |
} |
| 260 | 273 |
/* bring image back into focus on right-click */ |
| 261 | 274 |
if (ev.button.button == 3) {
|
| 262 |
- vs.px = ww / 2; |
|
| 263 |
- vs.py = wh / 2; |
|
| 275 |
+ sl[ci].px = ww / 2; |
|
| 276 |
+ sl[ci].py = wh / 2; |
|
| 264 | 277 |
ef = 1; |
| 265 | 278 |
} |
| 266 | 279 |
break; |
| ... | ... |
@@ -268,31 +281,32 @@ int main(int argc, char** argv) {
|
| 268 | 281 |
case SDL_MOUSEMOTION: |
| 269 | 282 |
/* pan-dragging if mouse is down */ |
| 270 | 283 |
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) {
|
| 271 |
- int sw = ZSH(vs.iw, vs.zoom - 1.0); |
|
| 272 |
- int sh = ZSH(vs.ih, vs.zoom - 1.0); |
|
| 273 |
- /* clamp panning to edges of window, |
|
| 274 |
- unless zoomed image is bigger than window */ |
|
| 275 |
- if (2 * sw > ww) {
|
|
| 276 |
- vs.px += ev.motion.xrel; |
|
| 277 |
- } else {
|
|
| 278 |
- vs.px = CLAMP(sw, vs.px + ev.motion.xrel, ww - sw); |
|
| 279 |
- } |
|
| 280 |
- if (2 * sh > wh) {
|
|
| 281 |
- vs.py += ev.motion.yrel; |
|
| 282 |
- } else {
|
|
| 283 |
- vs.py = CLAMP(sh, vs.py + ev.motion.yrel, wh - sh); |
|
| 284 |
- } |
|
| 284 |
+ int sw = ZSH(sl[ci].iw, sl[ci].zoom - 1.0); |
|
| 285 |
+ int sh = ZSH(sl[ci].ih, sl[ci].zoom - 1.0); |
|
| 286 |
+ /* 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 |
+ ); |
|
| 285 | 299 |
ef = 1; |
| 286 | 300 |
} |
| 287 |
- vs.mx = ev.motion.x; |
|
| 288 |
- vs.my = ev.motion.y; |
|
| 301 |
+ mx = ev.motion.x; |
|
| 302 |
+ my = ev.motion.y; |
|
| 289 | 303 |
break; |
| 290 | 304 |
|
| 291 | 305 |
case SDL_MOUSEWHEEL: |
| 292 | 306 |
/* scrolling changes zoom */ |
| 293 |
- vs.zoom += DZDS * ev.wheel.y; |
|
| 294 |
- vs.px = vs.mx - ZSH((vs.mx - vs.px), DZDS * ev.wheel.y); |
|
| 295 |
- vs.py = vs.my - ZSH((vs.my - vs.py), DZDS * ev.wheel.y); |
|
| 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); |
|
| 296 | 310 |
ef = 1; |
| 297 | 311 |
break; |
| 298 | 312 |
|
| ... | ... |
@@ -323,7 +337,7 @@ int main(int argc, char** argv) {
|
| 323 | 337 |
|
| 324 | 338 |
if (ef) {
|
| 325 | 339 |
drawbg(ren, ww, wh, cw, ch, act); |
| 326 |
- drawfg(ren, vs, itex[vs.ci]); |
|
| 340 |
+ drawfg(ren, sl[ci]); |
|
| 327 | 341 |
SDL_RenderPresent(ren); |
| 328 | 342 |
} |
| 329 | 343 |
|
| 330 | 344 |