julia.c 8.0 KB

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