changeset 3:0f4ad525f49a

Lot's of cleanup. Applied AbstractFactory to class Fractal and derivatives. Decoupled most objects. Removed remaining standard C function calls. Improved old_views handling.
author Eris Caffee <discordia@eldalin.com>
date Sat, 23 Oct 2010 04:24:48 -0500
parents 0684158d38a8
children df02a7de7fe2
files TODO include/App.h include/Fractal.h include/Julia.h include/Mandelbrot.h src/App.cpp src/Fractal.cpp src/Julia.cpp src/Mandelbrot.cpp
diffstat 9 files changed, 397 insertions(+), 271 deletions(-) [+]
line diff
     1.1 --- a/TODO	Fri Oct 22 02:21:52 2010 -0500
     1.2 +++ b/TODO	Sat Oct 23 04:24:48 2010 -0500
     1.3 @@ -1,6 +1,5 @@
     1.4 -- Make old_views store the fractal type (or clear the old_views list when changing type if lazy).
     1.5 -
     1.6 -- Make Fractal derived classes have unique type ID's that can can be used to identify the fractal type.  Need this for the good old_views solution.
     1.7 +- Make View into a class of it's own.
     1.8 +  Give it the ability to store a Fractals special options.
     1.9  
    1.10  - Find out how to save jpg or some other image format that allows comments I can use to store calculation data.
    1.11  
    1.12 @@ -20,13 +19,11 @@
    1.13  
    1.14  - More factal types
    1.15  
    1.16 -- Fix the lag of the selection box.  It needs to appear instantly and in the exact place the mouse is clicked.
    1.17 -	Using a timer callback function and SDL_WaitEvent is noticably better
    1.18 -	than my wait_event_timeout() function
    1.19 -
    1.20 -- Clean up the fractal class.  No more direct access to fractal settings.
    1.21 -
    1.22  - Performance improvment ideas:
    1.23  	- Create a partial rendering mechanism.
    1.24 -	OK - Use window events correctly to determine when a redraw is needed!  
    1.25 -	OK - Use a better way of handling events.  A timer callback and an SDL_WaitEvent/ SDL_PollEvent combo.  See here http://people.freedesktop.org/~idr/OpenGL_tutorials/01-SDL-intro.html
    1.26 \ No newline at end of file
    1.27 +
    1.28 +- Is there a way to handle the FRACTAL_TYPE_NAME without using a preprocessor define?
    1.29 +
    1.30 +- Replace Options with a real class.  Use Ini_File to save and load options.
    1.31 +  Allow max_iter to be a configurable setting to override the Fractal 
    1.32 +    class default.
    1.33 \ No newline at end of file
     2.1 --- a/include/App.h	Fri Oct 22 02:21:52 2010 -0500
     2.2 +++ b/include/App.h	Sat Oct 23 04:24:48 2010 -0500
     2.3 @@ -14,7 +14,6 @@
     2.4  
     2.5  #include <vector>
     2.6  
     2.7 -#include "png.h"
     2.8  #include "SDL.h"
     2.9  
    2.10  #include "EventHandler.h"
    2.11 @@ -30,6 +29,8 @@
    2.12  
    2.13     int run();
    2.14  
    2.15 +
    2.16 +
    2.17     private:
    2.18  
    2.19     bool init();
    2.20 @@ -44,6 +45,7 @@
    2.21     void on_Exit();
    2.22     void on_LButtonDown(int mx, int my);
    2.23     void on_LButtonUp(int mx, int my);
    2.24 +   void on_RButtonDown(int mx, int my);
    2.25     void on_MouseMove(int mx, int my, 
    2.26  		     int relx, int rely, 
    2.27  		     bool left, bool right, bool middle);
    2.28 @@ -52,9 +54,16 @@
    2.29  
    2.30  
    2.31     int mouse_move_width(int mx, int my);
    2.32 +
    2.33     bool create_new_surface(SDL_Surface * &surface);
    2.34 +
    2.35 +   void set_julia_k(int x, int y);
    2.36 +
    2.37     void restore_view();
    2.38 +   void save_view();
    2.39 +
    2.40     void set_caption();
    2.41 +
    2.42     bool save_image();
    2.43  
    2.44     static Uint32 timer_callback(Uint32 interval, void *param);
    2.45 @@ -74,7 +83,9 @@
    2.46  
    2.47     struct view
    2.48        {
    2.49 +      std::string type;
    2.50        double re_min, im_max, size;
    2.51 +      unsigned int max_iter;
    2.52        };
    2.53     static std::vector<view *> old_views;
    2.54  
     3.1 --- a/include/Fractal.h	Fri Oct 22 02:21:52 2010 -0500
     3.2 +++ b/include/Fractal.h	Sat Oct 23 04:24:48 2010 -0500
     3.3 @@ -13,8 +13,15 @@
     3.4  #ifndef FRACTAL_H
     3.5  #define FRACTAL_H
     3.6  
     3.7 +#include <map>
     3.8  #include <string>
     3.9  
    3.10 +// Need to define this via the pre-processor because if it's a staticaly
    3.11 +// initialized const string we still have no guarantee that it will be 
    3.12 +// initialized before it is needed by a FractalCreator class.
    3.13 +// Do the same in all derived classes.
    3.14 +#define FRACTAL_TYPE_NAME "Fractal"
    3.15 +
    3.16  class Fractal
    3.17     {
    3.18     public:
    3.19 @@ -22,35 +29,54 @@
    3.20  
    3.21     virtual bool calc_set() = 0;
    3.22     virtual bool init(SDL_Surface * surf) = 0;
    3.23 -   void set_re_min(const double r_min);
    3.24 -   void set_im_max(const double i_max);
    3.25 -   void set_size(const double s);
    3.26 -   void set_max_iter(const unsigned int iter);
    3.27 -   void inc_max_iter();
    3.28 -   void dec_max_iter();
    3.29 +
    3.30 +   double get_re_min();
    3.31 +   double set_re_min(const double r_min);
    3.32 +
    3.33 +   double get_im_max();
    3.34 +   double set_im_max(const double i_max);
    3.35 +
    3.36 +   double get_size();
    3.37 +   double set_size(const double s);
    3.38 +
    3.39 +   unsigned int get_max_iter();
    3.40 +   unsigned int set_max_iter(const unsigned int iter);
    3.41 +   unsigned int inc_max_iter();
    3.42 +   unsigned int dec_max_iter();
    3.43 +
    3.44     void set_calc_needed();
    3.45  
    3.46 -   double get_re_min();
    3.47 -   double get_im_max();
    3.48 -   double get_size();
    3.49 -   unsigned int get_max_iter();
    3.50 -   const char * get_name();
    3.51 +   virtual const char * get_display_name();
    3.52 +   virtual const char * get_type_name();
    3.53 +
    3.54 +   virtual bool get_option(std::string option, void * value) {};
    3.55 +   virtual bool set_option(std::string option, void * value) {};
    3.56 +
    3.57  
    3.58  
    3.59     protected:
    3.60  
    3.61     virtual void draw_pixel(int x, int y, Uint32 * color);
    3.62 -
    3.63 -   std::string name;
    3.64 +   
    3.65 +   std::string display_name;
    3.66 +   std::string type_name;
    3.67 +   
    3.68     double re_min;
    3.69     double im_max;
    3.70     double size;
    3.71     unsigned int max_iter;
    3.72     bool calc_needed;
    3.73 -
    3.74 +   
    3.75     SDL_Surface * surface;
    3.76 -
    3.77 -
    3.78 +   
    3.79     };
    3.80  
    3.81 +class FractalCreator
    3.82 +   {
    3.83 +   public:
    3.84 +   virtual Fractal * create() const = 0;
    3.85 +   };
    3.86 +
    3.87 +std::map <std::string, FractalCreator *> & get_Fractal_map();
    3.88 +
    3.89  #endif
     4.1 --- a/include/Julia.h	Fri Oct 22 02:21:52 2010 -0500
     4.2 +++ b/include/Julia.h	Sat Oct 23 04:24:48 2010 -0500
     4.3 @@ -18,6 +18,8 @@
     4.4  
     4.5  #include "Fractal.h"
     4.6  
     4.7 +#define JULIA_TYPE_NAME "Julia"
     4.8 +
     4.9  class Julia : public Fractal
    4.10     {
    4.11     public:
    4.12 @@ -26,16 +28,33 @@
    4.13     bool calc_set();
    4.14     bool init(SDL_Surface * surf);
    4.15  
    4.16 -   void get_k(double & re, double & im);
    4.17 -   void set_k(double re, double im);
    4.18 +   bool get_option(std::string option, void * value);
    4.19 +   bool set_option(std::string option, void * value);
    4.20 +
    4.21 +   const char * get_type_name();
    4.22  
    4.23     private:
    4.24  
    4.25     void draw_pixel(int x, int y, Uint32 * color);
    4.26 -   void set_name();
    4.27 +   void set_display_name();
    4.28  
    4.29     double k_re;
    4.30     double k_im;
    4.31     };
    4.32  
    4.33 +namespace
    4.34 +   {
    4.35 +   class JuliaCreator : public FractalCreator
    4.36 +      {
    4.37 +      public:
    4.38 +      JuliaCreator()
    4.39 +	 {
    4.40 +	 get_Fractal_map()["Julia"]=this;
    4.41 +	 }
    4.42 +      virtual Fractal * create() const
    4.43 +	 {
    4.44 +	 return new Julia;
    4.45 +	 }
    4.46 +      } theCreator;
    4.47 +   }
    4.48  #endif
     5.1 --- a/include/Mandelbrot.h	Fri Oct 22 02:21:52 2010 -0500
     5.2 +++ b/include/Mandelbrot.h	Sat Oct 23 04:24:48 2010 -0500
     5.3 @@ -18,6 +18,8 @@
     5.4  
     5.5  #include "Fractal.h"
     5.6  
     5.7 +#define MANDELBROT_TYPE_NAME "Mandelbrot"
     5.8 +
     5.9  class Mandelbrot : public Fractal
    5.10     {
    5.11     public:
    5.12 @@ -26,9 +28,28 @@
    5.13     bool calc_set();
    5.14     bool init(SDL_Surface * surf);
    5.15  
    5.16 +   const char * get_type_name();
    5.17 +
    5.18     private:
    5.19  
    5.20     void draw_pixel(int x, int y, Uint32 * color);
    5.21     };
    5.22  
    5.23 +namespace
    5.24 +   {
    5.25 +   class MandelbrotCreator : public FractalCreator
    5.26 +      {
    5.27 +      public:
    5.28 +      MandelbrotCreator()
    5.29 +	 {
    5.30 +	 get_Fractal_map()["Mandelbrot"]=this;
    5.31 +	 }
    5.32 +
    5.33 +      virtual Fractal * create() const
    5.34 +	 {
    5.35 +	 return new Mandelbrot;
    5.36 +	 }
    5.37 +      } theCreator;
    5.38 +   }
    5.39 +
    5.40  #endif
     6.1 --- a/src/App.cpp	Fri Oct 22 02:21:52 2010 -0500
     6.2 +++ b/src/App.cpp	Sat Oct 23 04:24:48 2010 -0500
     6.3 @@ -9,25 +9,19 @@
     6.4  //
     6.5  ////////////////////////////////////////////////////////////////////////////////
     6.6  
     6.7 -#include <cstdlib>
     6.8 -#include <cstring>
     6.9 +#include <iomanip>
    6.10  #include <iostream>
    6.11  #include <sstream>
    6.12 +#include <typeinfo>
    6.13  #include <vector>
    6.14  
    6.15  #include <dirent.h>
    6.16  
    6.17 -#include "png.h"
    6.18  #include "SDL.h"
    6.19  
    6.20  #include "App.h"
    6.21  #include "Options.h"
    6.22  
    6.23 -#include "Mandelbrot.h"
    6.24 -#include "Julia.h"
    6.25 -
    6.26 -
    6.27 -#define USE_SDL_WAITEVENT
    6.28  
    6.29  std::vector<App::view *> App::old_views;
    6.30  
    6.31 @@ -48,17 +42,14 @@
    6.32     {
    6.33     }
    6.34  
    6.35 +
    6.36  ////////////////////////////////////////////////////////////////////////////////
    6.37  App::~App()
    6.38     {
    6.39 -   if (old_views.size() > 0)
    6.40 -      {
    6.41 -      view * v = old_views.back();
    6.42 -      old_views.pop_back();
    6.43 -      delete v;
    6.44 -      }
    6.45 +   old_views.clear();
    6.46     }
    6.47  
    6.48 +
    6.49  ////////////////////////////////////////////////////////////////////////////////
    6.50  
    6.51  int App::run()
    6.52 @@ -70,19 +61,12 @@
    6.53  
    6.54     while (running)
    6.55        {
    6.56 -#ifdef USE_SDL_WAITEVENT
    6.57        SDL_WaitEvent(&event);
    6.58        do
    6.59  	 {
    6.60  	 on_event(&event);
    6.61  	 }
    6.62        while (SDL_PollEvent(&event));
    6.63 -#else
    6.64 -      while (wait_event_timeout(&event, 30) == 1)
    6.65 -	 {
    6.66 -	 on_event(&event);
    6.67 -	 }
    6.68 -#endif
    6.69  
    6.70        update();
    6.71  
    6.72 @@ -95,24 +79,6 @@
    6.73     return 0;
    6.74     }
    6.75  
    6.76 -////////////////////////////////////////////////////////////////////////////////
    6.77 -// Sample callback from
    6.78 -// http://people.freedesktop.org/~idr/OpenGL_tutorials/01-SDL-intro.html
    6.79 -
    6.80 -#ifdef USE_SDL_WAITEVENT
    6.81 -Uint32 App::timer_callback(Uint32 interval, void *param)
    6.82 -   {
    6.83 -   SDL_Event e;
    6.84 - 
    6.85 -   e.type = SDL_USEREVENT;
    6.86 -   e.user.code = 0;
    6.87 -   e.user.data1 = NULL;
    6.88 -   e.user.data2 = NULL;
    6.89 -   SDL_PushEvent(& e);
    6.90 - 
    6.91 -   return interval;
    6.92 -   }
    6.93 -#endif
    6.94  
    6.95  ////////////////////////////////////////////////////////////////////////////////
    6.96  bool App::init()
    6.97 @@ -139,26 +105,41 @@
    6.98     if (!create_new_surface(surf_selection)) { return false; }
    6.99     if (!create_new_surface(surf_fractal))   { return false; }
   6.100  
   6.101 -   fractal = new Mandelbrot();
   6.102 +
   6.103 +   std::cerr << "Available fractal types are" << std::endl;
   6.104 +   std::map <std::string, FractalCreator *> mymap = get_Fractal_map();
   6.105 +   std::map <std::string, FractalCreator *>::iterator it;
   6.106 +   for ( it=mymap.begin() ; it != mymap.end(); it++ )
   6.107 +      std::cerr << "  " << (*it).first << std::endl;
   6.108 +
   6.109 +   FractalCreator * fractal_creator = get_Fractal_map()["Mandelbrot"];
   6.110 +   if (!fractal_creator)
   6.111 +      {
   6.112 +      std::cerr << "Mandelbrot set not available!" << std::endl;
   6.113 +      return false;
   6.114 +      }
   6.115 +   fractal = fractal_creator->create();
   6.116     fractal->init(surf_fractal);
   6.117 +   redraw = true;
   6.118 +
   6.119     can_set_julia_k = true;
   6.120 -   redraw = true;
   6.121 +
   6.122  
   6.123     set_caption();
   6.124  
   6.125 -#ifdef USE_SDL_WAITEVENT
   6.126     SDL_TimerID timer_id = SDL_AddTimer(10, App::timer_callback, NULL);
   6.127 -#endif
   6.128  
   6.129     return true;
   6.130     }
   6.131  
   6.132 +
   6.133  ////////////////////////////////////////////////////////////////////////////////
   6.134  
   6.135  void App::update()
   6.136     {
   6.137     }
   6.138  
   6.139 +
   6.140  ////////////////////////////////////////////////////////////////////////////////
   6.141  
   6.142  void App::render()
   6.143 @@ -185,6 +166,7 @@
   6.144        }
   6.145     }
   6.146  
   6.147 +
   6.148  ////////////////////////////////////////////////////////////////////////////////
   6.149  
   6.150  void App::cleanup()
   6.151 @@ -204,6 +186,7 @@
   6.152     SDL_Quit();
   6.153     }
   6.154  
   6.155 +
   6.156  ////////////////////////////////////////////////////////////////////////////////
   6.157  
   6.158  void App::on_event(SDL_Event * event)
   6.159 @@ -211,6 +194,7 @@
   6.160     EventHandler::on_event(event);
   6.161     }
   6.162  
   6.163 +
   6.164  ////////////////////////////////////////////////////////////////////////////////
   6.165  
   6.166  void App::on_KeyDown(SDLKey sym, SDLMod mod, Uint16 unicode)
   6.167 @@ -226,7 +210,6 @@
   6.168  
   6.169        case SDLK_b:
   6.170        	 restore_view();
   6.171 -	 fractal->set_calc_needed();
   6.172  	 redraw = true;
   6.173  	 set_caption();
   6.174        	 break;
   6.175 @@ -248,8 +231,18 @@
   6.176        case SDLK_m:
   6.177  	 if (fractal)
   6.178  	    {
   6.179 +	    save_view();
   6.180  	    delete fractal;
   6.181 -	    fractal = new Mandelbrot();
   6.182 +	    FractalCreator * fractal_creator = get_Fractal_map()["Mandelbrot"];
   6.183 +	    if (!fractal_creator)
   6.184 +	       {
   6.185 +	       std::cerr << "Mandelbrot set not available!" << std::endl;
   6.186 +	       SDL_Event event;
   6.187 +	       event.type = SDL_QUIT;
   6.188 +	       SDL_PushEvent(&event);
   6.189 +	       break;
   6.190 +	       }
   6.191 +	    fractal = fractal_creator->create();
   6.192  	    fractal->init(surf_fractal);
   6.193  	    fractal->set_calc_needed();
   6.194  	    redraw = true;
   6.195 @@ -260,13 +253,22 @@
   6.196        case SDLK_j:
   6.197  	 if (fractal)
   6.198  	    {
   6.199 -	    delete fractal;
   6.200 -	    fractal = new Julia();
   6.201 -	    fractal->init(surf_fractal);
   6.202 -	    fractal->set_calc_needed();
   6.203 -	    redraw = true;
   6.204 -	    set_caption();
   6.205 -	    can_set_julia_k = false;
   6.206 +	    FractalCreator * fractal_creator = get_Fractal_map()["Julia"];
   6.207 +	    if (!fractal_creator)
   6.208 +	       {
   6.209 +	       std::cerr << "Julia set not available!" << std::endl;
   6.210 +	       }
   6.211 +	    else
   6.212 +	       {
   6.213 +	       save_view();
   6.214 +	       delete fractal;
   6.215 +	       fractal = fractal_creator->create();
   6.216 +	       fractal->init(surf_fractal);
   6.217 +	       fractal->set_calc_needed();
   6.218 +	       redraw = true;
   6.219 +	       set_caption();
   6.220 +	       can_set_julia_k = false;
   6.221 +	       }
   6.222  	    }
   6.223  	 break;
   6.224  
   6.225 @@ -315,20 +317,7 @@
   6.226     {
   6.227     if (setting_julia_k)
   6.228        {
   6.229 -      double K_Re = fractal->get_re_min() + mx * 
   6.230 -	    (fractal->get_size())/(Options::width-1);
   6.231 -      double K_Im = fractal->get_im_max() - my * 
   6.232 -	    (fractal->get_size())/(Options::height-1);
   6.233 -
   6.234 -      delete fractal;
   6.235 -      fractal = new Julia();
   6.236 -      fractal->init(surf_fractal);
   6.237 -      ((Julia *)fractal)->set_k(K_Re, K_Im);
   6.238 -      fractal->set_calc_needed();
   6.239 -      redraw = true;
   6.240 -
   6.241 -      set_caption();
   6.242 -      setting_julia_k = false;
   6.243 +      set_julia_k(mx, my);
   6.244        }
   6.245     else
   6.246        {
   6.247 @@ -346,9 +335,9 @@
   6.248     if (setting_zoom)
   6.249        {
   6.250        if ( (mx <= 0) || 
   6.251 -	   (mx >= Options::width - 1) || 
   6.252 +	   (mx >= surf_display->w - 1) || 
   6.253  	   (my <= 0) || 
   6.254 -	   (my >= Options::height - 1))
   6.255 +	   (my >= surf_display->h - 1))
   6.256  	 {
   6.257  	 // Selection cancelled
   6.258  	 setting_zoom = false;
   6.259 @@ -358,19 +347,15 @@
   6.260        selection_width = mouse_move_width(mx, my);
   6.261  
   6.262        // calculate new min/max re/im
   6.263 -      double Re_scale = (fractal->get_size())/(Options::width-1);
   6.264 -      double Im_scale = (fractal->get_size())/(Options::height-1);
   6.265 +      double Re_scale = (fractal->get_size())/(surf_fractal->w - 1);
   6.266 +      double Im_scale = (fractal->get_size())/(surf_fractal->h - 1);
   6.267  
   6.268        double new_re_min = fractal->get_re_min() + (selection_x) * Re_scale;
   6.269        double new_im_max = fractal->get_im_max() - (selection_y) * Im_scale;
   6.270        double new_size = selection_width * Re_scale;
   6.271  
   6.272 -      
   6.273 -      view * v = new view;
   6.274 -      v->re_min = fractal->get_re_min();
   6.275 -      v->im_max = fractal->get_im_max();
   6.276 -      v->size = fractal->get_size();
   6.277 -      old_views.push_back(v);
   6.278 +
   6.279 +      save_view();
   6.280  
   6.281        fractal->set_re_min(new_re_min);
   6.282        fractal->set_im_max(new_im_max);
   6.283 @@ -386,6 +371,17 @@
   6.284  
   6.285  
   6.286  ////////////////////////////////////////////////////////////////////////////////
   6.287 +
   6.288 +void App::on_RButtonDown(int mx, int my)
   6.289 +   {
   6.290 +   if (can_set_julia_k)
   6.291 +      {
   6.292 +      set_julia_k(mx, my);
   6.293 +      }
   6.294 +   }
   6.295 +
   6.296 +
   6.297 +////////////////////////////////////////////////////////////////////////////////
   6.298  void App::on_MouseMove(int mx, int my, 
   6.299  		       int relx, int rely, 
   6.300  		       bool left, bool right, bool middle)
   6.301 @@ -465,8 +461,8 @@
   6.302  
   6.303     SDL_Surface * tmp;
   6.304     if ((tmp = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA, 
   6.305 -				   Options::width,
   6.306 -				   Options::height, Options::bpp, 0, 0, 0, 0))
   6.307 +				   Options::width, Options::height, 
   6.308 +				   Options::bpp, 0, 0, 0, 0))
   6.309         == NULL)
   6.310        {
   6.311        std::cerr << "SDL_CreateRGBSurface() failed in "
   6.312 @@ -483,6 +479,38 @@
   6.313  
   6.314  
   6.315  ////////////////////////////////////////////////////////////////////////////////
   6.316 +void App::set_julia_k(int x, int y)
   6.317 +   {
   6.318 +   save_view();
   6.319 +   
   6.320 +   double k[2];
   6.321 +   k[0]= fractal->get_re_min() + x * 
   6.322 +	 (fractal->get_size())/(surf_fractal->w - 1);
   6.323 +   k[1] = fractal->get_im_max() - y * 
   6.324 +	 (fractal->get_size())/(surf_fractal->h - 1);
   6.325 +      
   6.326 +   FractalCreator * fractal_creator = get_Fractal_map()["Julia"];
   6.327 +   if (!fractal_creator)
   6.328 +      {
   6.329 +      std::cerr << "Julia set not available!" << std::endl;
   6.330 +      return;
   6.331 +      }
   6.332 +   else
   6.333 +      {
   6.334 +      delete fractal;
   6.335 +      fractal = fractal_creator->create();
   6.336 +      fractal->init(surf_fractal);
   6.337 +      fractal->set_option("k", k);
   6.338 +      fractal->set_calc_needed();
   6.339 +      redraw = true;
   6.340 +      
   6.341 +      set_caption();
   6.342 +      setting_julia_k = false;
   6.343 +      }
   6.344 +   }
   6.345 +
   6.346 +
   6.347 +////////////////////////////////////////////////////////////////////////////////
   6.348  
   6.349  void App::restore_view()
   6.350     {
   6.351 @@ -490,19 +518,67 @@
   6.352        {
   6.353        view * v = old_views.back();
   6.354        old_views.pop_back();
   6.355 +
   6.356 +      if (v->type.compare(fractal->get_type_name()) != 0)
   6.357 +	 {
   6.358 +	 delete fractal;
   6.359 +	 FractalCreator * fractal_creator = get_Fractal_map()[v->type];
   6.360 +	 if (!fractal_creator)
   6.361 +	    {
   6.362 +	    std::cerr << "Cannot restore old view: unknown Fractal type " 
   6.363 +		      << v->type << std::endl;
   6.364 +	    SDL_Event event;
   6.365 +	    event.type = SDL_QUIT;
   6.366 +	    SDL_PushEvent(&event);
   6.367 +	    }
   6.368 +	 fractal = fractal_creator->create();
   6.369 +	 fractal->init(surf_fractal);
   6.370 +	 }
   6.371 +
   6.372        fractal->set_re_min(v->re_min);
   6.373        fractal->set_im_max(v->im_max);
   6.374        fractal->set_size(v->size);
   6.375 +      fractal->set_max_iter(v->max_iter);
   6.376 +      fractal->set_calc_needed();
   6.377 +
   6.378 +      std::cerr << "Restored view:" << std::endl
   6.379 +		<< "  type     " << v->type << std::endl
   6.380 +		<< "  re_min   " << v->re_min << std::endl
   6.381 +		<< "  im_max   " << v->im_max << std::endl
   6.382 +		<< "  size     " << v->size << std::endl
   6.383 +		<< "  max_iter " << v->max_iter << std::endl
   6.384 +		<< std::endl;
   6.385        delete v;
   6.386        }
   6.387     }
   6.388  
   6.389  
   6.390  ////////////////////////////////////////////////////////////////////////////////
   6.391 +void App::save_view()
   6.392 +   {
   6.393 +   view * v = new view;
   6.394 +   v->type = fractal->get_type_name();
   6.395 +   v->re_min = fractal->get_re_min();
   6.396 +   v->im_max = fractal->get_im_max();
   6.397 +   v->size = fractal->get_size();
   6.398 +   v->max_iter = fractal->get_max_iter();
   6.399 +   old_views.push_back(v);
   6.400 +
   6.401 +   std::cerr << "Saved view:" << std::endl
   6.402 +	     << "  type     " << v->type << std::endl
   6.403 +	     << "  re_min   " << v->re_min << std::endl
   6.404 +	     << "  im_max   " << v->im_max << std::endl
   6.405 +	     << "  size     " << v->size << std::endl
   6.406 +	     << "  max_iter " << v->max_iter << std::endl
   6.407 +	     << std::endl;
   6.408 +   }
   6.409 +
   6.410 +
   6.411 +////////////////////////////////////////////////////////////////////////////////
   6.412  void App::set_caption()
   6.413     {
   6.414     std::stringstream ss;
   6.415 -   ss << fractal->get_name() << " / "
   6.416 +   ss << fractal->get_display_name() << " / "
   6.417        << "Real: " << fractal->get_re_min()
   6.418         << " to "<< fractal->get_re_min() + fractal->get_size()
   6.419        << " / Imaginary: " << fractal->get_im_max() - fractal->get_size()
   6.420 @@ -531,7 +607,6 @@
   6.421  bool App::save_image()
   6.422     {
   6.423     static int i = 0;
   6.424 -   char name[20];
   6.425  
   6.426     if (i == 0)
   6.427        {
   6.428 @@ -541,120 +616,34 @@
   6.429  	 sscanf(file_list[num_files-1]->d_name, "mandelbrot-%03d.bmp", &i);
   6.430        }
   6.431     i++;
   6.432 -   sprintf(name, "mandelbrot-%03d.bmp", i);
   6.433  
   6.434 -   FILE * file;
   6.435 -   if ((file = fopen(name, "wb")) == NULL)
   6.436 +   std::stringstream name;
   6.437 +   name << "mandelbrot-" << std::setw(3) << std::setfill('0') << i << ".bmp";
   6.438 +
   6.439 +   if (SDL_SaveBMP(surf_display, name.str().c_str()) != 0)
   6.440        {
   6.441 -      std::cerr << "fopen() failed in save_image() on file " 
   6.442 -		<< name << " for saving." << std::endl;
   6.443 +      std::cerr << "Unable to save image file " << name.str() << "" << std::endl;
   6.444        return false;
   6.445        }
   6.446  
   6.447 -   if (SDL_SaveBMP(surf_display, name) != 0)
   6.448 -      {
   6.449 -      std::cerr << "Unable to save image file " << name << "" << std::endl;
   6.450 -      return false;
   6.451 -      }
   6.452 +   std::cerr << "Saved image as " << name.str() << std::endl;
   6.453  
   6.454     return true;
   6.455     }
   6.456  
   6.457  
   6.458  ////////////////////////////////////////////////////////////////////////////////
   6.459 -#ifdef SAVE_AS_PNG
   6.460 -void png_user_error(png_structp png, png_const_charp s);
   6.461 -void png_user_warning(png_structp png, png_const_charp s);
   6.462 -
   6.463 -void png_user_warning(png_structp png, png_const_charp s)
   6.464 +Uint32 App::timer_callback(Uint32 interval, void *param)
   6.465     {
   6.466 -   std::cerr << "libpng: warning " << (char *) s << std::endl;
   6.467 +   SDL_Event e;
   6.468 + 
   6.469 +   e.type = SDL_USEREVENT;
   6.470 +   e.user.code = 0;
   6.471 +   e.user.data1 = NULL;
   6.472 +   e.user.data2 = NULL;
   6.473 +   SDL_PushEvent(& e);
   6.474 + 
   6.475 +   return interval;
   6.476     }
   6.477  
   6.478  
   6.479 -////////////////////////////////////////////////////////////////////////////////
   6.480 -void png_user_error(png_structp png, png_const_charp s)
   6.481 -   {
   6.482 -   std::cerr << "libpng: error " << (char *) s << std::endl;
   6.483 -   }
   6.484 -
   6.485 -
   6.486 -////////////////////////////////////////////////////////////////////////////////
   6.487 -
   6.488 -bool App::save_image()
   6.489 -   {
   6.490 -   static int i = 0;
   6.491 -   char name[20];
   6.492 -
   6.493 -   i++;
   6.494 -   sprintf(name, "mandelbrot-%03d.png", i);
   6.495 -
   6.496 -   png_save_surface(name, surf_display);
   6.497 -
   6.498 -   FILE * file;
   6.499 -   if ((file = fopen(name, "wb")) == NULL)
   6.500 -      {
   6.501 -      std::cerr << "fopen() failed in save_image() on file " 
   6.502 -		<< name << " for saving." << std::endl;
   6.503 -      return false;
   6.504 -      }
   6.505 -
   6.506 -
   6.507 -   
   6.508 -   png_structp png;
   6.509 -   png_infop png_info;
   6.510 -
   6.511 -   if ((png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, 
   6.512 -				      png_user_error, png_user_warning)) == NULL)
   6.513 -      {
   6.514 -      std::cerr << "png_create_write_struct() failed in save_image()"
   6.515 -		<< std::endl;
   6.516 -      fclose(file);
   6.517 -      return false;
   6.518 -      }
   6.519 -
   6.520 -
   6.521 -   if ((png_info = png_create_info_struct(png)) == NULL)
   6.522 -      {
   6.523 -      std::cerr << "png_create_info_struct() failed in save_image()"
   6.524 -		<< std::endl;
   6.525 -      fclose(file);
   6.526 -      return false;
   6.527 -      }
   6.528 -
   6.529 -   if (setjmp(png_jmpbuf(png)))
   6.530 -      {
   6.531 -      std::cerr << "png_jmpbuf() failed in save_image()" << std::endl;
   6.532 -      png_destroy_write_struct(&png, &png_info);
   6.533 -      fclose(file);
   6.534 -      return false;
   6.535 -      }
   6.536 -
   6.537 -   png_init_io(png, file);
   6.538 -   int colortype = PNG_COLOR_MASK_COLOR;
   6.539 -   png_set_IHDR(png, png_info, 
   6.540 -		surf_display->w, surf_display->h,
   6.541 -		8, colortype, PNG_INTERLACE_NONE,
   6.542 -		PNG_COMPRESSION_TYPE_DEFAULT,
   6.543 -		PNG_FILTER_TYPE_DEFAULT);
   6.544 -
   6.545 -   png_write_info(png, png_info);
   6.546 -   png_set_packing(png);
   6.547 -
   6.548 -   png_bytep * rows = (png_bytep *) malloc(sizeof(png_bytep)*surf_display->h);
   6.549 -   for (int i = 0; i < surf_display->h; i++)
   6.550 -      {
   6.551 -      rows[i] = (png_bytep) surf_display->pixels +
   6.552 -	    i * surf_display->pitch;
   6.553 -      }
   6.554 -
   6.555 -   png_write_image(png, rows);
   6.556 -   png_write_end(png, png_info);
   6.557 -
   6.558 -   free(rows);
   6.559 -   png_destroy_write_struct(&png, &png_info);
   6.560 -   fclose(file);
   6.561 -
   6.562 -   return true;
   6.563 -   }
   6.564 -#endif
     7.1 --- a/src/Fractal.cpp	Fri Oct 22 02:21:52 2010 -0500
     7.2 +++ b/src/Fractal.cpp	Sat Oct 23 04:24:48 2010 -0500
     7.3 @@ -20,7 +20,8 @@
     7.4  ////////////////////////////////////////////////////////////////////////////////
     7.5  
     7.6  Fractal::Fractal() :
     7.7 -   name ("No fractal selected"),
     7.8 +   display_name ("No fractal selected"),
     7.9 +   type_name (FRACTAL_TYPE_NAME),
    7.10     re_min (0),
    7.11     im_max (0),
    7.12     size (0),
    7.13 @@ -31,51 +32,91 @@
    7.14     }
    7.15  
    7.16  ////////////////////////////////////////////////////////////////////////////////
    7.17 -void Fractal::set_re_min(const double r_min)
    7.18 +double Fractal::get_re_min()
    7.19     {
    7.20 -   re_min = r_min;
    7.21 +   return re_min;
    7.22     }
    7.23  
    7.24  
    7.25  ////////////////////////////////////////////////////////////////////////////////
    7.26 -void Fractal::set_im_max(const double i_max)
    7.27 +double Fractal::set_re_min(const double r_min)
    7.28     {
    7.29 -   im_max = i_max;
    7.30 +   double t = re_min;
    7.31 +   re_min = r_min;
    7.32 +   return t;
    7.33     }
    7.34  
    7.35  
    7.36  ////////////////////////////////////////////////////////////////////////////////
    7.37 -void Fractal::set_size(const double s)
    7.38 +double Fractal::get_im_max()
    7.39     {
    7.40 +   return im_max;
    7.41 +   }
    7.42 +
    7.43 +
    7.44 +////////////////////////////////////////////////////////////////////////////////
    7.45 +double Fractal::set_im_max(const double i_max)
    7.46 +   {
    7.47 +   double t = im_max;
    7.48 +   im_max = i_max;
    7.49 +   return t;
    7.50 +   }
    7.51 +
    7.52 +
    7.53 +////////////////////////////////////////////////////////////////////////////////
    7.54 +double Fractal::get_size()
    7.55 +   {
    7.56 +   return size;
    7.57 +   }
    7.58 +
    7.59 +
    7.60 +////////////////////////////////////////////////////////////////////////////////
    7.61 +double Fractal::set_size(const double s)
    7.62 +   {
    7.63 +   double t;
    7.64     if (s > 0.0)
    7.65        size = s;
    7.66     else
    7.67        size = 1.0;
    7.68 +   return t;
    7.69     }
    7.70  
    7.71  
    7.72  ////////////////////////////////////////////////////////////////////////////////
    7.73 -void Fractal::set_max_iter(const unsigned int iter)
    7.74 +unsigned int Fractal::get_max_iter()
    7.75     {
    7.76 +   return max_iter;
    7.77 +   }
    7.78 +
    7.79 +
    7.80 +////////////////////////////////////////////////////////////////////////////////
    7.81 +unsigned int Fractal::set_max_iter(const unsigned int iter)
    7.82 +   {
    7.83 +   unsigned int t;
    7.84     if (iter > 0)
    7.85        max_iter = iter;
    7.86     else
    7.87        max_iter = 1;
    7.88 +   return t;
    7.89     }
    7.90  
    7.91  
    7.92  ////////////////////////////////////////////////////////////////////////////////
    7.93 -void Fractal::inc_max_iter()
    7.94 +unsigned int Fractal::inc_max_iter()
    7.95     {
    7.96 +   unsigned int t;
    7.97     max_iter++;
    7.98 +   return t;
    7.99     }
   7.100  
   7.101  
   7.102  ////////////////////////////////////////////////////////////////////////////////
   7.103 -void Fractal::dec_max_iter()
   7.104 +unsigned int Fractal::dec_max_iter()
   7.105     {
   7.106 +   unsigned int t;
   7.107     if (max_iter > 0)
   7.108        max_iter--;
   7.109 +   return t;
   7.110     }
   7.111  
   7.112  
   7.113 @@ -87,40 +128,20 @@
   7.114  
   7.115  
   7.116  ////////////////////////////////////////////////////////////////////////////////
   7.117 -double Fractal::get_re_min()
   7.118 +const char * Fractal::get_display_name()
   7.119     {
   7.120 -   return re_min;
   7.121 +   return display_name.c_str();
   7.122     }
   7.123  
   7.124  
   7.125  ////////////////////////////////////////////////////////////////////////////////
   7.126 -double Fractal::get_im_max()
   7.127 +const char * Fractal::get_type_name()
   7.128     {
   7.129 -   return im_max;
   7.130 +   return FRACTAL_TYPE_NAME;
   7.131     }
   7.132  
   7.133  
   7.134  ////////////////////////////////////////////////////////////////////////////////
   7.135 -double Fractal::get_size()
   7.136 -   {
   7.137 -   return size;
   7.138 -   }
   7.139 -
   7.140 -
   7.141 -////////////////////////////////////////////////////////////////////////////////
   7.142 -unsigned int Fractal::get_max_iter()
   7.143 -   {
   7.144 -   return max_iter;
   7.145 -   }
   7.146 -
   7.147 -
   7.148 -////////////////////////////////////////////////////////////////////////////////
   7.149 -const char * Fractal::get_name()
   7.150 -   {
   7.151 -   return name.c_str();
   7.152 -   }
   7.153 -
   7.154 -////////////////////////////////////////////////////////////////////////////////
   7.155  void Fractal::draw_pixel(int x, int y, Uint32 * color)
   7.156     {
   7.157     static char * data;
   7.158 @@ -135,3 +156,10 @@
   7.159     if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
   7.160     }
   7.161  
   7.162 +////////////////////////////////////////////////////////////////////////////////
   7.163 +
   7.164 +std::map <std::string, FractalCreator *> & get_Fractal_map()
   7.165 +   {
   7.166 +   static std::map <std::string, FractalCreator *> the_Fractal_map;
   7.167 +   return the_Fractal_map;
   7.168 +   }
     8.1 --- a/src/Julia.cpp	Fri Oct 22 02:21:52 2010 -0500
     8.2 +++ b/src/Julia.cpp	Sat Oct 23 04:24:48 2010 -0500
     8.3 @@ -9,13 +9,11 @@
     8.4  //
     8.5  ////////////////////////////////////////////////////////////////////////////////
     8.6  
     8.7 -#include <cstdlib>
     8.8 -#include <iostream>
     8.9  #include <string>
    8.10  #include <sstream>
    8.11  
    8.12  #include "Julia.h"
    8.13 -#include "Options.h"
    8.14 +
    8.15  
    8.16  ////////////////////////////////////////////////////////////////////////////////
    8.17  
    8.18 @@ -23,12 +21,13 @@
    8.19     k_re (-0.565072),
    8.20     k_im ( 0.491657)
    8.21     {
    8.22 +   type_name = JULIA_TYPE_NAME;
    8.23     re_min = -2.0;
    8.24     im_max = 2.0;
    8.25     size = 4.0;
    8.26     max_iter = 50;
    8.27 -   set_name();
    8.28     calc_needed = true;
    8.29 +   set_display_name();
    8.30     }
    8.31  
    8.32  
    8.33 @@ -42,8 +41,8 @@
    8.34  
    8.35     if (calc_needed)
    8.36        {
    8.37 -      double re_scale = (size)/(Options::width-1);
    8.38 -      double im_scale = (size)/(Options::height-1);
    8.39 +      double re_scale = (size)/(surface->w-1);
    8.40 +      double im_scale = (size)/(surface->h-1);
    8.41  
    8.42        int r, g, b;
    8.43  
    8.44 @@ -54,10 +53,10 @@
    8.45  
    8.46        unsigned x, y, n;
    8.47  
    8.48 -      for(y = 0; y < Options::height; ++y)
    8.49 +      for(y = 0; y < surface->h; ++y)
    8.50  	 {
    8.51  	 double c_im = im_max - y * im_scale;
    8.52 -	 for(x = 0; x < Options::width; ++x)
    8.53 +	 for(x = 0; x < surface->w; ++x)
    8.54  	    {
    8.55  	    double c_re = re_min + x * re_scale;
    8.56  
    8.57 @@ -119,19 +118,45 @@
    8.58  
    8.59  
    8.60  ////////////////////////////////////////////////////////////////////////////////
    8.61 -void Julia::get_k(double & re, double & im)
    8.62 +bool Julia::get_option(std::string option, void * value)
    8.63     {
    8.64 -   re = k_re;
    8.65 -   im = k_im;
    8.66 +   if (option.compare("k") == 0)
    8.67 +      {
    8.68 +      ((double *)value)[0] = k_re;
    8.69 +      ((double *)value)[0] = k_im;
    8.70 +      }
    8.71 +   else
    8.72 +      {
    8.73 +      return false;
    8.74 +      }
    8.75 +
    8.76 +   return true;
    8.77     }
    8.78  
    8.79  
    8.80  ////////////////////////////////////////////////////////////////////////////////
    8.81 -void Julia::set_k(double re, double im)
    8.82 +bool Julia::set_option(std::string option, void * value)
    8.83     {
    8.84 -   k_re = re;
    8.85 -   k_im = im;
    8.86 -   set_name();
    8.87 +   if (option.compare("k") == 0)
    8.88 +      {
    8.89 +      k_re = ((double *)value)[0];
    8.90 +      k_im = ((double *)value)[1];
    8.91 +      set_display_name();
    8.92 +      }
    8.93 +   else
    8.94 +      {
    8.95 +      return false;
    8.96 +      }
    8.97 +
    8.98 +
    8.99 +   return true;
   8.100 +   }
   8.101 +
   8.102 +
   8.103 +////////////////////////////////////////////////////////////////////////////////
   8.104 +const char * Julia::get_type_name()
   8.105 +   {
   8.106 +   return JULIA_TYPE_NAME;
   8.107     }
   8.108  
   8.109  
   8.110 @@ -144,9 +169,9 @@
   8.111  
   8.112  
   8.113  ////////////////////////////////////////////////////////////////////////////////
   8.114 -void Julia::set_name()
   8.115 +void Julia::set_display_name()
   8.116     {
   8.117     std::stringstream ss;
   8.118 -   ss <<"Julia set K = (" << k_re << "," << k_im << ")";
   8.119 -   name = ss.str();
   8.120 +   ss << "Julia set K = (" << k_re << "," << k_im << ")";
   8.121 +   display_name = ss.str();
   8.122     }
     9.1 --- a/src/Mandelbrot.cpp	Fri Oct 22 02:21:52 2010 -0500
     9.2 +++ b/src/Mandelbrot.cpp	Sat Oct 23 04:24:48 2010 -0500
     9.3 @@ -9,21 +9,22 @@
     9.4  //
     9.5  ////////////////////////////////////////////////////////////////////////////////
     9.6  
     9.7 -#include <iostream>
     9.8  #include <string>
     9.9  
    9.10  #include "Mandelbrot.h"
    9.11 -#include "Options.h"
    9.12 +
    9.13  
    9.14  ////////////////////////////////////////////////////////////////////////////////
    9.15  
    9.16  Mandelbrot::Mandelbrot()
    9.17     {
    9.18 -   name.assign("Mandelbrot set");
    9.19 +   display_name = "Mandelbrot set";
    9.20 +   type_name = MANDELBROT_TYPE_NAME;
    9.21     re_min = -2.5;
    9.22     im_max = 2.5;
    9.23     size = 5.0;
    9.24     max_iter = 50;
    9.25 +   calc_needed = true;
    9.26     }
    9.27  
    9.28  
    9.29 @@ -53,8 +54,8 @@
    9.30  
    9.31     if (calc_needed)
    9.32        {
    9.33 -      double re_scale = (size)/(Options::width-1);
    9.34 -      double im_scale = (size)/(Options::height-1);
    9.35 +      double re_scale = (size)/(surface->w-1);
    9.36 +      double im_scale = (size)/(surface->h-1);
    9.37  
    9.38        int r, g, b;
    9.39  
    9.40 @@ -65,10 +66,10 @@
    9.41  
    9.42        unsigned x, y, n;
    9.43  
    9.44 -      for(y = 0; y < Options::height; ++y)
    9.45 +      for(y = 0; y < surface->h; ++y)
    9.46  	 {
    9.47  	 double c_im = im_max - y * im_scale;
    9.48 -	 for(x = 0; x < Options::width; ++x)
    9.49 +	 for(x = 0; x < surface->w; ++x)
    9.50  	    {
    9.51  	    double c_re = re_min + x * re_scale;
    9.52  
    9.53 @@ -114,8 +115,17 @@
    9.54  
    9.55  
    9.56  ////////////////////////////////////////////////////////////////////////////////
    9.57 +const char * Mandelbrot::get_type_name()
    9.58 +   {
    9.59 +   return MANDELBROT_TYPE_NAME;
    9.60 +   }
    9.61 +
    9.62 +
    9.63 +////////////////////////////////////////////////////////////////////////////////
    9.64  
    9.65  void Mandelbrot::draw_pixel(int x, int y, Uint32 * color)
    9.66     {
    9.67     Fractal::draw_pixel(x, y, color);
    9.68     }
    9.69 +
    9.70 +