Mercurial > MadButterfly
annotate src/coord.c @ 151:d11aa8fc06c7
Fix bug of tanks do not show at right places.
Since we avoid to dirty a subtree if root of a subtree have been dirty or
hidden, it make children that was added into coord tree after a coord be
dirty do not be marked with COF_DIRTY flag. To fix it, when a new coord
is created, the parent is checked and mark new coord with COF_DIRTY flag
if the parent is dirty. It forces new coords to be cleaned and transformed
to right places.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Fri, 26 Sep 2008 17:42:16 +0800 |
parents | 0de8fd11271e |
children | c7e5b8779bb5 |
rev | line source |
---|---|
2 | 1 /*! \brief Implement coordination tranform mechanism. |
2 * \file | |
3 * This file implements coordination transforming for containers. | |
4 */ | |
1 | 5 #include <stdio.h> |
6 #include <string.h> | |
31
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
7 #include <math.h> |
5
9c331ec9e210
SVG path is partially supported
Thinker K.F. Li <thinker@branda.to>
parents:
3
diff
changeset
|
8 #include "mb_types.h" |
1 | 9 |
12 | 10 |
11 #define ASSERT(x) | |
12 | |
3
164162781a7a
Test cairo with Xlib surface
Thinker K.F. Li <thinker@branda.to>
parents:
2
diff
changeset
|
13 /* To keep possibility of changing type of aix */ |
2 | 14 #define MUL(a, b) ((a) * (b)) |
15 #define ADD(a, b) ((a) + (b)) | |
16 #define DIV(a, b) ((a) / (b)) | |
17 #define SUB(a, b) ((a) - (b)) | |
18 | |
19 static void mul_matrix(co_aix *m1, co_aix *m2, co_aix *dst) { | |
20 dst[0] = ADD(MUL(m1[0], m2[0]), MUL(m1[1], m2[3])); | |
21 dst[1] = ADD(MUL(m1[0], m2[1]), MUL(m1[1], m2[4])); | |
22 dst[2] = ADD(ADD(MUL(m1[0], m2[2]), MUL(m1[1], m2[5])), m1[2]); | |
23 dst[3] = ADD(MUL(m1[3], m2[0]), MUL(m1[4], m2[3])); | |
24 dst[4] = ADD(MUL(m1[3], m2[1]), MUL(m1[4], m2[4])); | |
25 dst[5] = ADD(ADD(MUL(m1[3], m2[2]), MUL(m1[4], m2[5])), m1[5]); | |
1 | 26 } |
27 | |
2 | 28 /*! \brief Compute agrregated transform function. |
29 * | |
30 * Base on parent's aggregated matrix if it is existed, or use transform | |
31 * matrix as aggregated matrix. | |
32 */ | |
1 | 33 static void compute_transform_function(coord_t *visit) { |
34 if(visit->parent) | |
35 mul_matrix(visit->parent->aggr_matrix, | |
36 visit->matrix, visit->aggr_matrix); | |
37 else | |
38 memcpy(visit->aggr_matrix, visit->matrix, sizeof(visit->matrix)); | |
39 } | |
40 | |
16
e17e12b112c4
A simple animation using rdman_redraw_changed().
Thinker K.F. Li <thinker@branda.to>
parents:
15
diff
changeset
|
41 void compute_aggr_of_coord(coord_t *coord) { |
e17e12b112c4
A simple animation using rdman_redraw_changed().
Thinker K.F. Li <thinker@branda.to>
parents:
15
diff
changeset
|
42 compute_transform_function(coord); |
e17e12b112c4
A simple animation using rdman_redraw_changed().
Thinker K.F. Li <thinker@branda.to>
parents:
15
diff
changeset
|
43 } |
e17e12b112c4
A simple animation using rdman_redraw_changed().
Thinker K.F. Li <thinker@branda.to>
parents:
15
diff
changeset
|
44 |
1 | 45 /*! \brief Update aggregate matrices of elements under a sub-tree. |
46 * | |
47 * A subtree is specified by the root of it. All elements in the subtree | |
48 * are effected by that changes of matrix of the subtree root. | |
49 */ | |
50 void update_aggr_matrix(coord_t *start) { | |
51 coord_t *visit, *child, *next; | |
52 | |
53 compute_transform_function(start); | |
54 | |
55 visit = start; | |
56 while(visit) { | |
12 | 57 child = STAILQ_HEAD(visit->children); |
1 | 58 while(child) { |
59 compute_transform_function(child); | |
12 | 60 child = STAILQ_NEXT(coord_t, sibling, child); |
1 | 61 } |
62 | |
12 | 63 if(STAILQ_HEAD(visit->children)) |
64 visit = STAILQ_HEAD(visit->children); | |
65 else if(STAILQ_NEXT(coord_t, sibling, visit)) | |
66 visit = STAILQ_NEXT(coord_t, sibling, visit); | |
1 | 67 else { |
68 next = NULL; | |
69 while(visit->parent && visit->parent != start) { | |
70 visit = visit->parent; | |
12 | 71 if(STAILQ_NEXT(coord_t, sibling, visit)) { |
72 next = STAILQ_NEXT(coord_t, sibling, visit); | |
1 | 73 break; |
74 } | |
75 } | |
76 visit = next; | |
77 } | |
78 } | |
79 } | |
80 | |
12 | 81 /*! \brief Initialize a coord object. |
82 * | |
83 * The object is cleared and matrix was initialized to ID. | |
84 * The object is be a children of specified parent. | |
85 */ | |
1 | 86 void coord_init(coord_t *co, coord_t *parent) { |
87 memset(co, 0, sizeof(coord_t)); | |
88 if(parent) { | |
12 | 89 /* insert at tail of children list. */ |
1 | 90 co->parent = parent; |
12 | 91 STAILQ_INS_TAIL(parent->children, coord_t, sibling, co); |
1 | 92 } |
93 co->matrix[0] = 1; | |
94 co->matrix[4] = 1; | |
17
41f0907b27ac
Unittest for rdman_redraw_changed().
Thinker K.F. Li <thinker@branda.to>
parents:
16
diff
changeset
|
95 co->aggr_matrix[0] = 1; |
41f0907b27ac
Unittest for rdman_redraw_changed().
Thinker K.F. Li <thinker@branda.to>
parents:
16
diff
changeset
|
96 co->aggr_matrix[4] = 1; |
15
c2ce186a5c37
X_main uses rdman_redraw_all()
Thinker K.F. Li <thinker@branda.to>
parents:
13
diff
changeset
|
97 co->cur_area = &co->areas[0]; |
c2ce186a5c37
X_main uses rdman_redraw_all()
Thinker K.F. Li <thinker@branda.to>
parents:
13
diff
changeset
|
98 co->last_area = &co->areas[1]; |
1 | 99 } |
100 | |
2 | 101 void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y) { |
102 co_aix nx, ny; | |
103 | |
104 nx = ADD(ADD(MUL(co->aggr_matrix[0], *x), | |
105 MUL(co->aggr_matrix[1], *y)), | |
106 co->aggr_matrix[2]); | |
107 ny = ADD(ADD(MUL(co->aggr_matrix[3], *x), | |
108 MUL(co->aggr_matrix[4], *y)), | |
109 co->aggr_matrix[5]); | |
110 *x = nx; | |
111 *y = ny; | |
112 } | |
113 | |
31
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
114 co_aix coord_trans_size(coord_t *co, co_aix sz) { |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
115 co_aix x, y; |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
116 |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
117 x = MUL(co->aggr_matrix[0], sz); |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
118 y = MUL(co->aggr_matrix[3], sz); |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
119 |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
120 return sqrt(x * x + y * y); |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
121 } |
da770188a44d
resize font size for changige of coord.
Thinker K.F. Li <thinker@branda.to>
parents:
17
diff
changeset
|
122 |
151
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
123 /*! |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
124 * \note Coords, marked with COF_SKIP_TRIVAL (for temporary), and |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
125 * descendants of them will not be trivaled and the flag with be removed |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
126 * after skipping them. |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
127 */ |
13 | 128 coord_t *preorder_coord_subtree(coord_t *root, coord_t *last) { |
151
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
129 coord_t *next = NULL; |
12 | 130 |
138
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
131 ASSERT(last != NULL); |
12 | 132 |
151
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
133 if((!(last->flags & COF_SKIP_TRIVAL)) && |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
134 STAILQ_HEAD(last->children)) { |
12 | 135 next = STAILQ_HEAD(last->children); |
151
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
136 if(!(next->flags & COF_SKIP_TRIVAL)) |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
137 return next; |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
138 } else { |
12 | 139 next = last; |
151
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
140 } |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
141 |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
142 do { |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
143 next->flags &= ~COF_SKIP_TRIVAL; |
13 | 144 while(next != root && STAILQ_NEXT(coord_t, sibling, next) == NULL) |
12 | 145 next = next->parent; |
13 | 146 if(next == root) |
151
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
147 return NULL; |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
148 next = STAILQ_NEXT(coord_t, sibling, next); |
d11aa8fc06c7
Fix bug of tanks do not show at right places.
Thinker K.F. Li <thinker@branda.to>
parents:
140
diff
changeset
|
149 } while(next->flags & COF_SKIP_TRIVAL); |
12 | 150 |
151 return next; | |
152 } | |
153 | |
138
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
154 coord_t *postorder_coord_subtree(coord_t *root, coord_t *last) { |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
155 coord_t *next; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
156 |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
157 if(root == last) |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
158 return NULL; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
159 |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
160 if(last == NULL) { |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
161 /* Go most left leaf. */ |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
162 next = root; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
163 while(STAILQ_HEAD(next->children)) |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
164 next = STAILQ_HEAD(next->children); |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
165 return next; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
166 } |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
167 |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
168 next = last; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
169 if(STAILQ_NEXT(coord_t, sibling, next) == NULL) /* most right */ |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
170 return next->parent; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
171 |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
172 /* Go most left leaf of right sibling sub-tree. */ |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
173 next = STAILQ_NEXT(coord_t, sibling, next); |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
174 while(STAILQ_HEAD(next->children)) |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
175 next = STAILQ_HEAD(next->children); |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
176 |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
177 return next; |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
178 } |
9f4fc9ecfd1f
Make shapes and coords drawed in post-order of tree.
Thinker K.F. Li <thinker@branda.to>
parents:
31
diff
changeset
|
179 |
1 | 180 #ifdef UNITTEST |
181 | |
182 #include <CUnit/Basic.h> | |
183 | |
184 void test_update_aggr_matrix(void) { | |
185 coord_t elms[6]; | |
2 | 186 co_aix x, y; |
1 | 187 |
188 coord_init(elms, NULL); | |
189 coord_init(elms + 1, elms); | |
190 coord_init(elms + 2, elms); | |
191 coord_init(elms + 3, elms + 1); | |
192 coord_init(elms + 4, elms + 1); | |
193 coord_init(elms + 5, elms + 2); | |
194 | |
195 /* | 2 -1 0 | | |
196 * | 0 1 0 | | |
197 * | 0 0 1 | | |
198 */ | |
199 elms[0].matrix[0] = 2; | |
200 elms[0].matrix[1] = -1; | |
201 | |
202 /* | 1 3 0 | | |
203 * | 5 1 0 | | |
204 * | 0 0 1 | | |
205 */ | |
206 elms[1].matrix[1] = 3; | |
207 elms[1].matrix[3] = 5; | |
208 | |
209 update_aggr_matrix(elms); | |
210 | |
211 /* | -3 5 0 | | |
212 * | 5 1 0 | | |
213 * | 0 0 1 | | |
214 */ | |
215 CU_ASSERT(elms[3].aggr_matrix[0] == -3); | |
216 CU_ASSERT(elms[3].aggr_matrix[1] == 5); | |
217 CU_ASSERT(elms[3].aggr_matrix[2] == 0); | |
218 CU_ASSERT(elms[3].aggr_matrix[3] == 5); | |
219 CU_ASSERT(elms[3].aggr_matrix[4] == 1); | |
220 CU_ASSERT(elms[3].aggr_matrix[5] == 0); | |
221 | |
222 CU_ASSERT(elms[4].aggr_matrix[0] == -3); | |
223 CU_ASSERT(elms[4].aggr_matrix[1] == 5); | |
224 CU_ASSERT(elms[4].aggr_matrix[2] == 0); | |
225 CU_ASSERT(elms[4].aggr_matrix[3] == 5); | |
226 CU_ASSERT(elms[4].aggr_matrix[4] == 1); | |
227 CU_ASSERT(elms[4].aggr_matrix[5] == 0); | |
228 | |
229 CU_ASSERT(elms[5].aggr_matrix[0] == 2); | |
230 CU_ASSERT(elms[5].aggr_matrix[1] == -1); | |
231 CU_ASSERT(elms[5].aggr_matrix[2] == 0); | |
232 CU_ASSERT(elms[5].aggr_matrix[3] == 0); | |
233 CU_ASSERT(elms[5].aggr_matrix[4] == 1); | |
234 CU_ASSERT(elms[5].aggr_matrix[5] == 0); | |
2 | 235 |
236 x = 50; | |
237 y = 99; | |
238 coord_trans_pos(elms + 5, &x, &y); | |
239 CU_ASSERT(x == 1); | |
240 CU_ASSERT(y == 99); | |
1 | 241 } |
242 | |
13 | 243 void test_preorder_coord_subtree(void) { |
12 | 244 coord_t elms[6]; |
245 coord_t *last; | |
246 | |
247 coord_init(elms, NULL); | |
248 coord_init(elms + 1, elms); | |
249 coord_init(elms + 2, elms); | |
250 coord_init(elms + 3, elms + 1); | |
251 coord_init(elms + 4, elms + 1); | |
252 coord_init(elms + 5, elms + 2); | |
253 | |
254 last = elms; | |
13 | 255 last = preorder_coord_subtree(elms, last); |
12 | 256 CU_ASSERT(last == elms + 1); |
13 | 257 last = preorder_coord_subtree(elms, last); |
12 | 258 CU_ASSERT(last == elms + 3); |
13 | 259 last = preorder_coord_subtree(elms, last); |
12 | 260 CU_ASSERT(last == elms + 4); |
13 | 261 last = preorder_coord_subtree(elms, last); |
12 | 262 CU_ASSERT(last == elms + 2); |
13 | 263 last = preorder_coord_subtree(elms, last); |
12 | 264 CU_ASSERT(last == elms + 5); |
13 | 265 last = preorder_coord_subtree(elms, last); |
12 | 266 CU_ASSERT(last == NULL); |
267 } | |
268 | |
1 | 269 CU_pSuite get_coord_suite(void) { |
270 CU_pSuite suite; | |
271 | |
272 suite = CU_add_suite("Suite_coord", NULL, NULL); | |
273 CU_ADD_TEST(suite, test_update_aggr_matrix); | |
13 | 274 CU_ADD_TEST(suite, test_preorder_coord_subtree); |
1 | 275 |
276 return suite; | |
277 } | |
278 | |
279 #endif |