#include #include #include #include #include #include "mandel.h" using namespace std; #if 1 struct State { SDL_Window *window = nullptr; int w = -1, h = -1; Mandel *ctx = nullptr; Params par = mandel_default_params(); uint8_t *imgdata = nullptr; SDL_Surface *mandelsurf = nullptr; static const size_t init_render_resolution = 4; size_t current_resolution = init_render_resolution; State() { if (SDL_Init(SDL_INIT_VIDEO) < 0) { cerr << "SDL init error: " << SDL_GetError() << endl; exit(1); } window = SDL_CreateWindow("Mandel", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 960, 640, SDL_WINDOW_SHOWN); if (!window) { cerr << "SDL window creation error: " << SDL_GetError() << endl; exit(1); } handle_resize(); mandel_render(imgdata, ctx, &par, current_resolution); blit(); SDL_UpdateWindowSurface(window); } void blit() { SDL_Surface *winsurf = SDL_GetWindowSurface(window); if (SDL_MUSTLOCK(winsurf)) SDL_LockSurface(winsurf); SDL_BlitSurface(mandelsurf, nullptr, winsurf, nullptr); if (SDL_MUSTLOCK(winsurf)) SDL_UnlockSurface(winsurf); } string build_title() { stringstream ss; ss << "Mandel " << setprecision(17) << " x=" << par.cx << " y=" << par.cy << " w=" << par.imgw << " i=" << par.maxit << " par1=" << par.par1 << " par2=" << par.par2; return ss.str(); } void update_title() { SDL_SetWindowTitle(window, build_title().data()); } SDL_Event wait_event() const { SDL_Event e; if (SDL_WaitEvent(&e) == 0) { cerr << "SDL event wait error: " << SDL_GetError() << endl; exit(1); } return e; } optional poll_event() const { SDL_Event e; if (SDL_PollEvent(&e) == 0) { return nullopt; } return {e}; } void handle_resize() { if (ctx) mandel_free(ctx); if (imgdata) delete[] imgdata; if (mandelsurf) SDL_FreeSurface(mandelsurf); SDL_GetWindowSize(window, &w, &h); cerr << "w=" << w << " h=" << h << endl; imgdata = new uint8_t[3 * w * h]; mandelsurf = SDL_CreateRGBSurfaceFrom(imgdata, w, h, 24, 3 * w, 255, 255 << 8, 255 << 16, 0); ctx = mandel_init(w, h); } enum class action { quit, redraw, idle, }; action handle_event(const SDL_Event &e) { const double min_img_size = min(par.imgw, mandel_imgh(ctx, &par)); const double scroll_dist = min_img_size * 0.1; switch (e.type) { case SDL_QUIT: return action::quit; case SDL_KEYDOWN: switch (e.key.keysym.sym) { case SDLK_UP: par.cy += scroll_dist; return action::redraw; case SDLK_DOWN: par.cy -= scroll_dist; return action::redraw; case SDLK_RIGHT: par.cx += scroll_dist; return action::redraw; case SDLK_LEFT: par.cx -= scroll_dist; return action::redraw; case SDLK_KP_PLUS: case SDLK_PLUS: case SDLK_EQUALS: par.imgw *= 0.8; return action::redraw; case SDLK_KP_MINUS: case SDLK_MINUS: par.imgw *= 1.25; return action::redraw; case SDLK_PAGEUP: par.maxit += 128; return action::redraw; case SDLK_PAGEDOWN: if (par.maxit > 256) { par.maxit -= 128; return action::redraw; } break; case SDLK_w: par.par1++; return action::redraw; case SDLK_s: par.par1 = max(1, par.par1) - 1; return action::redraw; case SDLK_e: par.par2++; return action::redraw; case SDLK_d: par.par2 = max(1, par.par2) - 1; return action::redraw; case SDLK_q: return action::quit; } break; case SDL_WINDOWEVENT: switch (e.window.event) { case SDL_WINDOWEVENT_FOCUS_GAINED: SDL_UpdateWindowSurface(window); return action::idle; case SDL_WINDOWEVENT_SIZE_CHANGED: handle_resize(); return action::redraw; } break; } return action::idle; } }; int main() { State state; while (true) { state.update_title(); State::action action; if (state.current_resolution == 1) { SDL_Event ev = state.wait_event(); action = state.handle_event(ev); } else { if (optional optev = state.poll_event()) { action = state.handle_event(*optev); } else { action = State::action::idle; } } switch (action) { case State::action::quit: goto exit_app; case State::action::redraw: state.current_resolution = State::init_render_resolution; SDL_GetWindowSize(state.window, &state.w, &state.h); cerr << "w=" << state.w << " h=" << state.h << endl; // cerr << "mandelsurf: w=" << state.mandelsurf->w << " h=" << state.mandelsurf->h << endl; mandel_render(state.imgdata, state.ctx, &state.par, state.current_resolution); state.blit(); SDL_UpdateWindowSurface(state.window); break; case State::action::idle: if (state.current_resolution > 1) { state.current_resolution /= 2; mandel_render(state.imgdata, state.ctx, &state.par, state.current_resolution); } state.blit(); SDL_UpdateWindowSurface(state.window); break; } } exit_app: cout << state.build_title() << endl; } #endif