You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
5.8KB

  1. //
  2. // "$Id: mandelbrot.cxx 7903 2010-11-28 21:06:39Z matt $"
  3. //
  4. // Mandelbrot set demo for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems on the following page:
  24. //
  25. // http://www.fltk.org/str.php
  26. //
  27. #include "mandelbrot_ui.h"
  28. #include <FL/fl_draw.H>
  29. #include <FL/Fl_Button.H>
  30. #include <FL/Fl_Printer.H>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. Drawing_Window mbrot;
  34. Drawing_Window jbrot;
  35. void idle(void*) {
  36. if (!mbrot.d->idle() && !(jbrot.d && jbrot.d->idle())) Fl::remove_idle(idle);
  37. }
  38. void set_idle() {
  39. Fl::add_idle(idle);
  40. }
  41. static void window_callback(Fl_Widget*, void*) {exit(0);}
  42. static void print(Fl_Widget *o, void *data)
  43. {
  44. Fl_Printer printer;
  45. Fl_Window *win = o->window();
  46. if(!win->visible()) return;
  47. win->make_current();
  48. uchar *image_data = fl_read_image(NULL, 0, 0, win->w(), win->h(), 0);
  49. if( printer.start_job(1) ) return;
  50. if( printer.start_page() ) return;
  51. printer.scale(.7,.7);
  52. fl_draw_image(image_data, 0,0, win->w(), win->h());
  53. printer.end_page();
  54. delete image_data;
  55. printer.end_job();
  56. }
  57. int main(int argc, char **argv) {
  58. mbrot.make_window();
  59. mbrot.window->begin();
  60. Fl_Button* o = new Fl_Button(0, 0, 0, 0, NULL);
  61. o->callback(print,NULL);
  62. o->shortcut(FL_CTRL+'p');
  63. mbrot.window->end();
  64. mbrot.d->X = -.75;
  65. mbrot.d->scale = 2.5;
  66. mbrot.update_label();
  67. int i = 0;
  68. if (Fl::args(argc,argv,i) < argc) Fl::fatal(Fl::help);
  69. Fl::visual(FL_RGB);
  70. mbrot.window->callback(window_callback);
  71. mbrot.window->show(argc,argv);
  72. Fl::run();
  73. return 0;
  74. }
  75. void Drawing_Window::update_label() {
  76. char buffer[128];
  77. sprintf(buffer, "%+.10f", d->X); x_input->value(buffer);
  78. sprintf(buffer, "%+.10f", d->Y); y_input->value(buffer);
  79. sprintf(buffer, "%.2g", d->scale); w_input->value(buffer);
  80. }
  81. void Drawing_Area::draw() {
  82. draw_box();
  83. drawn = 0;
  84. set_idle();
  85. }
  86. int Drawing_Area::idle() {
  87. if (!window()->visible()) return 0;
  88. if (drawn < nextline) {
  89. window()->make_current();
  90. int yy = drawn+y()+4;
  91. if (yy >= sy && yy <= sy+sh) erase_box();
  92. fl_draw_image_mono(buffer+drawn*W,x()+3,yy,W,1,1,W);
  93. drawn++;
  94. return 1;
  95. }
  96. if (nextline < H) {
  97. if (!buffer) buffer = new uchar[W*H];
  98. double yy = Y+(H/2-nextline)*scale/W;
  99. double yi = yy; if (julia) yy = jY;
  100. uchar *p = buffer+nextline*W;
  101. for (int xi = 0; xi < W; xi++) {
  102. double xx = X+(xi-W/2)*scale/W;
  103. double wx = xx; double wy = yi;
  104. if (julia) xx = jX;
  105. for (int i=0; ; i++) {
  106. if (i >= iterations) {*p = 0; break;}
  107. double t = wx*wx - wy*wy + xx;
  108. wy = 2*wx*wy + yy;
  109. wx = t;
  110. if (wx*wx + wy*wy > 4) {
  111. wx = t = 1-double(i)/(1<<10);
  112. if (t <= 0) t = 0; else for (i=brightness; i--;) t*=wx;
  113. *p = 255-int(254*t);
  114. break;
  115. }
  116. }
  117. p++;
  118. }
  119. nextline++;
  120. return nextline < H;
  121. }
  122. return 0;
  123. }
  124. void Drawing_Area::erase_box() {
  125. window()->make_current();
  126. fl_overlay_clear();
  127. }
  128. int Drawing_Area::handle(int event) {
  129. static int ix, iy;
  130. static int dragged;
  131. static int button;
  132. int x2,y2;
  133. switch (event) {
  134. case FL_PUSH:
  135. erase_box();
  136. ix = Fl::event_x(); if (ix<x()) ix=x(); if (ix>=x()+w()) ix=x()+w()-1;
  137. iy = Fl::event_y(); if (iy<y()) iy=y(); if (iy>=y()+h()) iy=y()+h()-1;
  138. dragged = 0;
  139. button = Fl::event_button();
  140. return 1;
  141. case FL_DRAG:
  142. dragged = 1;
  143. erase_box();
  144. x2 = Fl::event_x(); if (x2<x()) x2=x(); if (x2>=x()+w()) x2=x()+w()-1;
  145. y2 = Fl::event_y(); if (y2<y()) y2=y(); if (y2>=y()+h()) y2=y()+h()-1;
  146. if (button != 1) {ix = x2; iy = y2; return 1;}
  147. if (ix < x2) {sx = ix; sw = x2-ix;} else {sx = x2; sw = ix-x2;}
  148. if (iy < y2) {sy = iy; sh = y2-iy;} else {sy = y2; sh = iy-y2;}
  149. window()->make_current();
  150. fl_overlay_rect(sx,sy,sw,sh);
  151. return 1;
  152. case FL_RELEASE:
  153. if (button == 1) {
  154. erase_box();
  155. if (dragged && sw > 3 && sh > 3) {
  156. X = X + (sx+sw/2-x()-W/2)*scale/W;
  157. Y = Y + (-sy-sh/2+y()+H/2)*scale/W;
  158. scale = sw*scale/W;
  159. } else if (!dragged) {
  160. scale = 2*scale;
  161. if (julia) {
  162. if (scale >= 4) {
  163. scale = 4;
  164. X = Y = 0;
  165. }
  166. } else {
  167. if (scale >= 2.5) {
  168. scale = 2.5;
  169. X = -.75;
  170. Y = 0;
  171. }
  172. }
  173. } else return 1;
  174. ((Drawing_Window*)(user_data()))->update_label();
  175. new_display();
  176. } else if (!julia) {
  177. if (!jbrot.d) {
  178. jbrot.make_window();
  179. jbrot.d->julia = 1;
  180. jbrot.d->X = 0;
  181. jbrot.d->Y = 0;
  182. jbrot.d->scale = 4;
  183. jbrot.update_label();
  184. }
  185. jbrot.d->jX = X + (ix-x()-W/2)*scale/W;
  186. jbrot.d->jY = Y + (H/2-iy+y())*scale/W;
  187. static char s[128];
  188. sprintf(s, "Julia %.7f %.7f",jbrot.d->jX,jbrot.d->jY);
  189. jbrot.window->label(s);
  190. jbrot.window->show();
  191. jbrot.d->new_display();
  192. }
  193. return 1;
  194. }
  195. return 0;
  196. }
  197. void Drawing_Area::new_display() {
  198. drawn = nextline = 0;
  199. set_idle();
  200. }
  201. void Drawing_Area::resize(int XX,int YY,int WW,int HH) {
  202. if (WW != w() || HH != h()) {
  203. W = WW-6;
  204. H = HH-8;
  205. if (buffer) {delete[] buffer; buffer = 0; new_display();}
  206. }
  207. Fl_Box::resize(XX,YY,WW,HH);
  208. }
  209. //
  210. // End of "$Id: mandelbrot.cxx 7903 2010-11-28 21:06:39Z matt $".
  211. //