julia.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2013-2018 K. Lange
  5. *
  6. * julia - Julia Fractal Generator
  7. *
  8. * This is the updated windowed version of the
  9. * julia fractal generator demo.
  10. */
  11. #include <stdio.h>
  12. #include <stdint.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <time.h>
  16. #include <unistd.h>
  17. #include <getopt.h>
  18. #include <toaru/yutani.h>
  19. #include <toaru/graphics.h>
  20. #include <toaru/decorations.h>
  21. #include <toaru/menu.h>
  22. #define GFX_(xpt, ypt) (GFX(ctx,xpt+decor_left_width,ypt+decor_top_height))
  23. /* Pointer to graphics memory */
  24. static yutani_t * yctx;
  25. static yutani_window_t * window = NULL;
  26. static gfx_context_t * ctx = NULL;
  27. /* Julia fractals elements */
  28. float conx = -0.74; /* real part of c */
  29. float cony = 0.1; /* imag part of c */
  30. float Maxx = 2; /* X bounds */
  31. float Minx = -2;
  32. float Maxy = 1; /* Y bounds */
  33. float Miny = -1;
  34. float initer = 1000; /* Iteration levels */
  35. float pixcorx; /* Internal values */
  36. float pixcory;
  37. int newcolor; /* Color we're placing */
  38. int lastcolor; /* Last color we placed */
  39. int no_repeat = 0; /* Repeat colors? */
  40. /*
  41. * Color table
  42. * These are orange/red shades from the Ubuntu platte.
  43. */
  44. int colors[] = {
  45. 0xFFeec73e,
  46. 0xFFf0a513,
  47. 0xFFfb8b00,
  48. 0xFFf44800,
  49. 0xFFffff99,
  50. 0xFFffff00,
  51. 0xFFfdca01,
  52. 0xFF986601,
  53. 0xFFf44800,
  54. 0xFFfd3301,
  55. 0xFFd40000,
  56. 0xFF980101,
  57. };
  58. int left = 40;
  59. int top = 40;
  60. int width = 300;
  61. int height = 300;
  62. void julia(int xpt, int ypt) {
  63. long double x = xpt * pixcorx + Minx;
  64. long double y = Maxy - ypt * pixcory;
  65. long double xnew = 0;
  66. long double ynew = 0;
  67. int k = 0;
  68. for (k = 0; k <= initer; k++) {
  69. xnew = x * x - y * y + conx;
  70. ynew = 2 * x * y + cony;
  71. x = xnew;
  72. y = ynew;
  73. if ((x * x + y * y) > 4)
  74. break;
  75. }
  76. int color;
  77. if (no_repeat) {
  78. color = 12 * k / initer;
  79. } else {
  80. color = k;
  81. if (color > 11) {
  82. color = color % 12;
  83. }
  84. }
  85. if (k >= initer) {
  86. GFX_(xpt,ypt) = rgb(0,0,0);
  87. } else {
  88. GFX_(xpt,ypt) = colors[color];
  89. }
  90. newcolor = color;
  91. }
  92. void usage(char * argv[]) {
  93. printf(
  94. "Julia fractal generator.\n"
  95. "\n"
  96. "usage: %s [-n] [-i \033[3miniter\033[0m] [-x \033[3mminx\033[0m] \n"
  97. " [-X \033[3mmaxx\033[0m] [-c \033[3mconx\033[0m] [-C \033[3mcony\033[0m]\n"
  98. " [-W \033[3mwidth\033[0m] [-H \033[3mheight\033[0m] [-h]\n"
  99. "\n"
  100. " -n --no-repeat \033[3mDo not repeat colors\033[0m\n"
  101. " -i --initer \033[3mInitializer value\033[0m\n"
  102. " -x --minx \033[3mMinimum X value\033[0m\n"
  103. " -X --maxx \033[3mMaximum X value\033[0m\n"
  104. " -c --conx \033[3mcon x\033[0m\n"
  105. " -C --cony \033[3mcon y\033[0m\n"
  106. " -W --width \033[3mWindow width\033[0m\n"
  107. " -H --height \033[3mWindow height\033[0m\n"
  108. " -h --help \033[3mShow this help message.\033[0m\n",
  109. argv[0]);
  110. }
  111. static void decors() {
  112. render_decorations(window, ctx, "Julia Fractals");
  113. }
  114. void redraw() {
  115. printf("initer: %f\n", initer);
  116. printf("X: %f %f\n", Minx, Maxx);
  117. float _x = Maxx - Minx;
  118. float _y = _x / width * height;
  119. Miny = 0 - _y / 2;
  120. Maxy = _y / 2;
  121. printf("Y: %f %f\n", Miny, Maxy);
  122. printf("conx: %f cony: %f\n", conx, cony);
  123. decors();
  124. newcolor = 0;
  125. lastcolor = 0;
  126. pixcorx = (Maxx - Minx) / width;
  127. pixcory = (Maxy - Miny) / height;
  128. int j = 0;
  129. do {
  130. int i = 1;
  131. do {
  132. julia(i,j);
  133. if (lastcolor != newcolor) julia(i-1,j);
  134. else if (i > 0) GFX_(i-1,j) = colors[lastcolor];
  135. newcolor = lastcolor;
  136. i+= 2;
  137. } while ( i < width );
  138. yutani_flip(yctx, window);
  139. ++j;
  140. } while ( j < height );
  141. }
  142. void resize_finish(int w, int h) {
  143. yutani_window_resize_accept(yctx, window, w, h);
  144. reinit_graphics_yutani(ctx, window);
  145. width = w - decor_left_width - decor_right_width;
  146. height = h - decor_top_height - decor_bottom_height;
  147. draw_fill(ctx, rgb(0,0,0));
  148. decors();
  149. yutani_window_resize_done(yctx, window);
  150. redraw();
  151. yutani_flip(yctx, window);
  152. }
  153. int main(int argc, char * argv[]) {
  154. static struct option long_opts[] = {
  155. {"no-repeat", no_argument, 0, 'n'},
  156. {"initer", required_argument, 0, 'i'},
  157. {"minx", required_argument, 0, 'x'},
  158. {"maxx", required_argument, 0, 'X'},
  159. {"conx", required_argument, 0, 'c'},
  160. {"cony", required_argument, 0, 'C'},
  161. {"width", required_argument, 0, 'W'},
  162. {"height", required_argument, 0, 'H'},
  163. {"help", no_argument, 0, 'h'},
  164. {0,0,0,0}
  165. };
  166. if (argc > 1) {
  167. /* Read some arguments */
  168. int index, c;
  169. while ((c = getopt_long(argc, argv, "ni:x:X:c:C:W:H:h", long_opts, &index)) != -1) {
  170. if (!c) {
  171. if (long_opts[index].flag == 0) {
  172. c = long_opts[index].val;
  173. }
  174. }
  175. switch (c) {
  176. case 'n':
  177. no_repeat = 1;
  178. break;
  179. case 'i':
  180. initer = atof(optarg);
  181. break;
  182. case 'x':
  183. Minx = atof(optarg);
  184. break;
  185. case 'X':
  186. Maxx = atof(optarg);
  187. break;
  188. case 'c':
  189. conx = atof(optarg);
  190. break;
  191. case 'C':
  192. cony = atof(optarg);
  193. break;
  194. case 'W':
  195. width = atoi(optarg);
  196. break;
  197. case 'H':
  198. height = atoi(optarg);
  199. break;
  200. case 'h':
  201. usage(argv);
  202. exit(0);
  203. break;
  204. default:
  205. break;
  206. }
  207. }
  208. }
  209. yctx = yutani_init();
  210. if (!yctx) {
  211. fprintf(stderr, "%s: failed to connect to compositor\n", argv[0]);
  212. return 1;
  213. }
  214. init_decorations();
  215. window = yutani_window_create(yctx, width + decor_width(), height + decor_height());
  216. yutani_window_move(yctx, window, left, top);
  217. yutani_window_advertise_icon(yctx, window, "Julia Fractals", "julia");
  218. ctx = init_graphics_yutani(window);
  219. redraw();
  220. yutani_flip(yctx, window);
  221. int playing = 1;
  222. while (playing) {
  223. yutani_msg_t * m = yutani_poll(yctx);
  224. while (m) {
  225. if (menu_process_event(yctx, m)) {
  226. /* just decorations should be fine */
  227. decors();
  228. yutani_flip(yctx, window);
  229. }
  230. switch (m->type) {
  231. case YUTANI_MSG_KEY_EVENT:
  232. {
  233. struct yutani_msg_key_event * ke = (void*)m->data;
  234. if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
  235. playing = 0;
  236. }
  237. }
  238. break;
  239. case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
  240. {
  241. struct yutani_msg_window_focus_change * wf = (void*)m->data;
  242. yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
  243. if (win && win == window) {
  244. win->focused = wf->focused;
  245. decors();
  246. yutani_flip(yctx, window);
  247. }
  248. }
  249. break;
  250. case YUTANI_MSG_RESIZE_OFFER:
  251. {
  252. struct yutani_msg_window_resize * wr = (void*)m->data;
  253. resize_finish(wr->width, wr->height);
  254. }
  255. break;
  256. case YUTANI_MSG_WINDOW_MOUSE_EVENT:
  257. {
  258. struct yutani_msg_window_mouse_event * me = (void*)m->data;
  259. int result = decor_handle_event(yctx, m);
  260. switch (result) {
  261. case DECOR_CLOSE:
  262. playing = 0;
  263. break;
  264. case DECOR_RIGHT:
  265. /* right click in decoration, show appropriate menu */
  266. decor_show_default_menu(window, window->x + me->new_x, window->y + me->new_y);
  267. break;
  268. default:
  269. /* Other actions */
  270. break;
  271. }
  272. }
  273. break;
  274. case YUTANI_MSG_WINDOW_CLOSE:
  275. case YUTANI_MSG_SESSION_END:
  276. playing = 0;
  277. break;
  278. default:
  279. break;
  280. }
  281. free(m);
  282. m = yutani_poll_async(yctx);
  283. }
  284. }
  285. yutani_close(yctx, window);
  286. return 0;
  287. }