summaryrefslogtreecommitdiff
path: root/apps/plugins/fractals/fractal_rect.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/fractals/fractal_rect.c')
-rw-r--r--apps/plugins/fractals/fractal_rect.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/apps/plugins/fractals/fractal_rect.c b/apps/plugins/fractals/fractal_rect.c
new file mode 100644
index 0000000000..af846d3f7a
--- /dev/null
+++ b/apps/plugins/fractals/fractal_rect.c
@@ -0,0 +1,209 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2009 Tomer Shalev
11 *
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "fractal_rect.h"
23
24#define RECT_QUEUE_LEN 32
25
26#define QUEUE_NEXT(i) (((i) + 1) % RECT_QUEUE_LEN)
27#define QUEUE_PREV(i) (((i) - 1) % RECT_QUEUE_LEN)
28#define QUEUE_IS_EMPTY (QUEUE_NEXT(rectq.head) == rectq.tail)
29#define QUEUE_TAIL \
30 (&rectq.rects[rectq.tail]);
31#define QUEUE_ITEM(i) &rectq.rects[(i)]
32
33struct rect_queue
34{
35 struct fractal_rect rects[RECT_QUEUE_LEN];
36 unsigned head;
37 unsigned tail;
38};
39
40static struct rect_queue rectq;
41
42/*#define FRACTAL_RECT_DEBUG*/
43#if defined(FRACTAL_RECT_DEBUG) && defined(SIMULATOR)
44#include <stdio.h>
45
46static void rectq_print(void)
47{
48 unsigned i = rectq.head;
49
50 printf("Rects queue:\n");
51 for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV(i))
52 {
53 printf("\tItem %d/%d; idx %d; (%d,%d),(%d,%d),%svalid%s%s\n",
54 (i - rectq.head + 1) % RECT_QUEUE_LEN,
55 (rectq.head - rectq.tail) % RECT_QUEUE_LEN,
56 i,
57 rectq.rects[(i)].px_min,
58 rectq.rects[(i)].py_min,
59 rectq.rects[(i)].px_max,
60 rectq.rects[(i)].py_max,
61 (rectq.rects[(i)].valid ? "" : "in"),
62 ((i == rectq.head) ? ",head" : ""),
63 ((i == rectq.tail) ? ",tail" : ""));
64 }
65}
66#else
67#define rectq_print(...)
68#endif
69
70static int rects_add(int px_min, int py_min, int px_max, int py_max)
71{
72 struct fractal_rect *rect = &rectq.rects[rectq.tail];
73
74 if (rectq.head == QUEUE_PREV(rectq.tail)) /* queue is full */
75 return 1;
76
77 rect->px_min = px_min;
78 rect->py_min = py_min;
79 rect->px_max = px_max;
80 rect->py_max = py_max;
81 rect->valid = 1;
82 rectq.tail = QUEUE_PREV(rectq.tail);
83
84 return 0;
85}
86
87static void rects_queue_reset(void)
88{
89 rectq.tail = 0;
90 rectq.head = 0;
91}
92
93void rects_queue_init(void)
94{
95 rects_queue_reset();
96 rects_add(0, 0, LCD_WIDTH, LCD_HEIGHT);
97}
98
99void rects_calc_all(int (*calc)(struct fractal_rect *, int (*)(void *), void *),
100 int (*button_yield_cb)(void *), void *ctx)
101{
102 while (rectq.head != rectq.tail) /* queue is not empty */
103 {
104 struct fractal_rect *rect = &rectq.rects[rectq.head];
105
106 rectq_print();
107 if (rect->valid)
108 {
109 if (calc(rect, button_yield_cb, ctx))
110 return; /* interrupted by key-press */
111 }
112
113 rectq.head = QUEUE_PREV(rectq.head); /* dequeue */
114 }
115 rects_queue_reset();
116}
117
118int rects_move_up(void)
119{
120 unsigned i;
121
122 /* move current regions up */
123 for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
124 {
125 struct fractal_rect *rect = QUEUE_ITEM(i);
126
127 rect->py_min -= LCD_SHIFT_Y;
128 rect->py_max -= LCD_SHIFT_Y;
129
130 if (rect->py_min < 0)
131 rect->py_min = 0;
132
133 if (rect->py_max < 0)
134 rect->valid = 0;
135 }
136
137 /* add bottom region */
138 return rects_add(0, LCD_HEIGHT - LCD_SHIFT_Y, LCD_WIDTH, LCD_HEIGHT);
139}
140
141int rects_move_down(void)
142{
143 unsigned i;
144
145 /* move current regions down */
146 for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
147 {
148 struct fractal_rect *rect = QUEUE_ITEM(i);
149
150 rect->py_min += LCD_SHIFT_Y;
151 rect->py_max += LCD_SHIFT_Y;
152
153 if (rect->py_max > LCD_HEIGHT)
154 rect->py_max = LCD_HEIGHT;
155
156 if (LCD_HEIGHT <= rect->py_min)
157 rect->valid = 0;
158 }
159
160 /* add top region */
161 return rects_add(0, 0, LCD_WIDTH, LCD_SHIFT_Y);
162}
163
164int rects_move_left(void)
165{
166 unsigned i;
167
168 /* move current regions left */
169 for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
170 {
171 struct fractal_rect *rect = QUEUE_ITEM(i);
172
173 rect->px_min -= LCD_SHIFT_X;
174 rect->px_max -= LCD_SHIFT_X;
175
176 if (rect->px_min < 0)
177 rect->px_min = 0;
178
179 if (rect->px_max < 0)
180 rect->valid = 0;
181 }
182
183 /* add right region */
184 return rects_add(LCD_WIDTH - LCD_SHIFT_X, 0, LCD_WIDTH, LCD_HEIGHT);
185}
186
187int rects_move_right(void)
188{
189 unsigned i;
190
191 /* move current regions right */
192 for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
193 {
194 struct fractal_rect *rect = QUEUE_ITEM(i);
195
196 rect->px_min += LCD_SHIFT_X;
197 rect->px_max += LCD_SHIFT_X;
198
199 if (rect->px_max > LCD_WIDTH)
200 rect->px_max = LCD_WIDTH;
201
202 if (LCD_WIDTH <= rect->px_min)
203 rect->valid = 0;
204 }
205
206 /* add left region */
207 return rects_add(0, 0, LCD_SHIFT_X, LCD_HEIGHT);
208}
209