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 |