Mercurial > MadButterfly
annotate src/coord.c @ 13:ed55009d96d3
refactory for redrawing
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Thu, 31 Jul 2008 08:10:00 +0800 |
parents | 79e9edf4c00a |
children | c2ce186a5c37 |
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> | |
5
9c331ec9e210
SVG path is partially supported
Thinker K.F. Li <thinker@branda.to>
parents:
3
diff
changeset
|
7 #include "mb_types.h" |
1 | 8 |
12 | 9 |
10 #define ASSERT(x) | |
11 | |
3
164162781a7a
Test cairo with Xlib surface
Thinker K.F. Li <thinker@branda.to>
parents:
2
diff
changeset
|
12 /* To keep possibility of changing type of aix */ |
2 | 13 #define MUL(a, b) ((a) * (b)) |
14 #define ADD(a, b) ((a) + (b)) | |
15 #define DIV(a, b) ((a) / (b)) | |
16 #define SUB(a, b) ((a) - (b)) | |
17 | |
18 static void mul_matrix(co_aix *m1, co_aix *m2, co_aix *dst) { | |
19 dst[0] = ADD(MUL(m1[0], m2[0]), MUL(m1[1], m2[3])); | |
20 dst[1] = ADD(MUL(m1[0], m2[1]), MUL(m1[1], m2[4])); | |
21 dst[2] = ADD(ADD(MUL(m1[0], m2[2]), MUL(m1[1], m2[5])), m1[2]); | |
22 dst[3] = ADD(MUL(m1[3], m2[0]), MUL(m1[4], m2[3])); | |
23 dst[4] = ADD(MUL(m1[3], m2[1]), MUL(m1[4], m2[4])); | |
24 dst[5] = ADD(ADD(MUL(m1[3], m2[2]), MUL(m1[4], m2[5])), m1[5]); | |
1 | 25 } |
26 | |
2 | 27 /*! \brief Compute agrregated transform function. |
28 * | |
29 * Base on parent's aggregated matrix if it is existed, or use transform | |
30 * matrix as aggregated matrix. | |
31 */ | |
1 | 32 static void compute_transform_function(coord_t *visit) { |
33 if(visit->parent) | |
34 mul_matrix(visit->parent->aggr_matrix, | |
35 visit->matrix, visit->aggr_matrix); | |
36 else | |
37 memcpy(visit->aggr_matrix, visit->matrix, sizeof(visit->matrix)); | |
38 } | |
39 | |
40 /*! \brief Update aggregate matrices of elements under a sub-tree. | |
41 * | |
42 * A subtree is specified by the root of it. All elements in the subtree | |
43 * are effected by that changes of matrix of the subtree root. | |
44 */ | |
45 void update_aggr_matrix(coord_t *start) { | |
46 coord_t *visit, *child, *next; | |
47 | |
48 compute_transform_function(start); | |
49 | |
50 visit = start; | |
51 while(visit) { | |
12 | 52 child = STAILQ_HEAD(visit->children); |
1 | 53 while(child) { |
54 compute_transform_function(child); | |
12 | 55 child = STAILQ_NEXT(coord_t, sibling, child); |
1 | 56 } |
57 | |
12 | 58 if(STAILQ_HEAD(visit->children)) |
59 visit = STAILQ_HEAD(visit->children); | |
60 else if(STAILQ_NEXT(coord_t, sibling, visit)) | |
61 visit = STAILQ_NEXT(coord_t, sibling, visit); | |
1 | 62 else { |
63 next = NULL; | |
64 while(visit->parent && visit->parent != start) { | |
65 visit = visit->parent; | |
12 | 66 if(STAILQ_NEXT(coord_t, sibling, visit)) { |
67 next = STAILQ_NEXT(coord_t, sibling, visit); | |
1 | 68 break; |
69 } | |
70 } | |
71 visit = next; | |
72 } | |
73 } | |
74 } | |
75 | |
12 | 76 /*! \brief Initialize a coord object. |
77 * | |
78 * The object is cleared and matrix was initialized to ID. | |
79 * The object is be a children of specified parent. | |
80 */ | |
1 | 81 void coord_init(coord_t *co, coord_t *parent) { |
82 memset(co, 0, sizeof(coord_t)); | |
83 if(parent) { | |
12 | 84 /* insert at tail of children list. */ |
1 | 85 co->parent = parent; |
12 | 86 STAILQ_INS_TAIL(parent->children, coord_t, sibling, co); |
1 | 87 } |
88 co->matrix[0] = 1; | |
89 co->matrix[4] = 1; | |
90 } | |
91 | |
2 | 92 void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y) { |
93 co_aix nx, ny; | |
94 | |
95 nx = ADD(ADD(MUL(co->aggr_matrix[0], *x), | |
96 MUL(co->aggr_matrix[1], *y)), | |
97 co->aggr_matrix[2]); | |
98 ny = ADD(ADD(MUL(co->aggr_matrix[3], *x), | |
99 MUL(co->aggr_matrix[4], *y)), | |
100 co->aggr_matrix[5]); | |
101 *x = nx; | |
102 *y = ny; | |
103 } | |
104 | |
13 | 105 coord_t *preorder_coord_subtree(coord_t *root, coord_t *last) { |
12 | 106 coord_t *next; |
107 | |
108 ASSERT(last == NULL); | |
109 | |
110 if(STAILQ_HEAD(last->children)) | |
111 next = STAILQ_HEAD(last->children); | |
112 else { | |
113 next = last; | |
13 | 114 while(next != root && STAILQ_NEXT(coord_t, sibling, next) == NULL) |
12 | 115 next = next->parent; |
13 | 116 if(next == root) |
117 next = NULL; | |
12 | 118 if(next) |
119 next = STAILQ_NEXT(coord_t, sibling, next); | |
120 } | |
121 | |
122 return next; | |
123 } | |
124 | |
125 void sh_attach_coord(shape_t *sh, coord_t *coord) { | |
126 STAILQ_INS_TAIL(coord->members, shape_t, coord_mem_next, sh); | |
127 sh->coord = coord; | |
128 } | |
129 | |
130 void sh_detach_coord(shape_t *sh) { | |
131 STAILQ_REMOVE(sh->coord->members, shape_t, coord_mem_next, sh); | |
132 sh->coord = NULL; | |
133 } | |
134 | |
1 | 135 #ifdef UNITTEST |
136 | |
137 #include <CUnit/Basic.h> | |
138 | |
139 void test_update_aggr_matrix(void) { | |
140 coord_t elms[6]; | |
2 | 141 co_aix x, y; |
1 | 142 |
143 coord_init(elms, NULL); | |
144 coord_init(elms + 1, elms); | |
145 coord_init(elms + 2, elms); | |
146 coord_init(elms + 3, elms + 1); | |
147 coord_init(elms + 4, elms + 1); | |
148 coord_init(elms + 5, elms + 2); | |
149 | |
150 /* | 2 -1 0 | | |
151 * | 0 1 0 | | |
152 * | 0 0 1 | | |
153 */ | |
154 elms[0].matrix[0] = 2; | |
155 elms[0].matrix[1] = -1; | |
156 | |
157 /* | 1 3 0 | | |
158 * | 5 1 0 | | |
159 * | 0 0 1 | | |
160 */ | |
161 elms[1].matrix[1] = 3; | |
162 elms[1].matrix[3] = 5; | |
163 | |
164 update_aggr_matrix(elms); | |
165 | |
166 /* | -3 5 0 | | |
167 * | 5 1 0 | | |
168 * | 0 0 1 | | |
169 */ | |
170 CU_ASSERT(elms[3].aggr_matrix[0] == -3); | |
171 CU_ASSERT(elms[3].aggr_matrix[1] == 5); | |
172 CU_ASSERT(elms[3].aggr_matrix[2] == 0); | |
173 CU_ASSERT(elms[3].aggr_matrix[3] == 5); | |
174 CU_ASSERT(elms[3].aggr_matrix[4] == 1); | |
175 CU_ASSERT(elms[3].aggr_matrix[5] == 0); | |
176 | |
177 CU_ASSERT(elms[4].aggr_matrix[0] == -3); | |
178 CU_ASSERT(elms[4].aggr_matrix[1] == 5); | |
179 CU_ASSERT(elms[4].aggr_matrix[2] == 0); | |
180 CU_ASSERT(elms[4].aggr_matrix[3] == 5); | |
181 CU_ASSERT(elms[4].aggr_matrix[4] == 1); | |
182 CU_ASSERT(elms[4].aggr_matrix[5] == 0); | |
183 | |
184 CU_ASSERT(elms[5].aggr_matrix[0] == 2); | |
185 CU_ASSERT(elms[5].aggr_matrix[1] == -1); | |
186 CU_ASSERT(elms[5].aggr_matrix[2] == 0); | |
187 CU_ASSERT(elms[5].aggr_matrix[3] == 0); | |
188 CU_ASSERT(elms[5].aggr_matrix[4] == 1); | |
189 CU_ASSERT(elms[5].aggr_matrix[5] == 0); | |
2 | 190 |
191 x = 50; | |
192 y = 99; | |
193 coord_trans_pos(elms + 5, &x, &y); | |
194 CU_ASSERT(x == 1); | |
195 CU_ASSERT(y == 99); | |
1 | 196 } |
197 | |
13 | 198 void test_preorder_coord_subtree(void) { |
12 | 199 coord_t elms[6]; |
200 coord_t *last; | |
201 | |
202 coord_init(elms, NULL); | |
203 coord_init(elms + 1, elms); | |
204 coord_init(elms + 2, elms); | |
205 coord_init(elms + 3, elms + 1); | |
206 coord_init(elms + 4, elms + 1); | |
207 coord_init(elms + 5, elms + 2); | |
208 | |
209 last = elms; | |
13 | 210 last = preorder_coord_subtree(elms, last); |
12 | 211 CU_ASSERT(last == elms + 1); |
13 | 212 last = preorder_coord_subtree(elms, last); |
12 | 213 CU_ASSERT(last == elms + 3); |
13 | 214 last = preorder_coord_subtree(elms, last); |
12 | 215 CU_ASSERT(last == elms + 4); |
13 | 216 last = preorder_coord_subtree(elms, last); |
12 | 217 CU_ASSERT(last == elms + 2); |
13 | 218 last = preorder_coord_subtree(elms, last); |
12 | 219 CU_ASSERT(last == elms + 5); |
13 | 220 last = preorder_coord_subtree(elms, last); |
12 | 221 CU_ASSERT(last == NULL); |
222 } | |
223 | |
1 | 224 CU_pSuite get_coord_suite(void) { |
225 CU_pSuite suite; | |
226 | |
227 suite = CU_add_suite("Suite_coord", NULL, NULL); | |
228 CU_ADD_TEST(suite, test_update_aggr_matrix); | |
13 | 229 CU_ADD_TEST(suite, test_preorder_coord_subtree); |
1 | 230 |
231 return suite; | |
232 } | |
233 | |
234 #endif |