Mercurial > MadButterfly
annotate src/coord.c @ 3:164162781a7a
Test cairo with Xlib surface
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Fri, 25 Jul 2008 10:09:53 +0800 |
parents | 31402929c587 |
children | 9c331ec9e210 |
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> | |
7 | |
2 | 8 typedef float co_aix; |
9 /*! \brief A coordination system. | |
10 * | |
11 * It have a transform function defined by matrix to transform | |
12 * coordination from source space to target space. | |
13 * Source space is where the contained is drawed, and target space | |
14 * is where the coordination of parent container of the element | |
15 * represented by this coord object. | |
16 */ | |
1 | 17 typedef struct coord { |
18 int seq; | |
2 | 19 co_aix matrix[6]; |
20 co_aix aggr_matrix[6]; | |
1 | 21 struct coord *parent; |
22 struct coord *children, *sibling; | |
23 } coord_t; | |
24 | |
3
164162781a7a
Test cairo with Xlib surface
Thinker K.F. Li <thinker@branda.to>
parents:
2
diff
changeset
|
25 /* To keep possibility of changing type of aix */ |
2 | 26 #define MUL(a, b) ((a) * (b)) |
27 #define ADD(a, b) ((a) + (b)) | |
28 #define DIV(a, b) ((a) / (b)) | |
29 #define SUB(a, b) ((a) - (b)) | |
30 | |
31 static void mul_matrix(co_aix *m1, co_aix *m2, co_aix *dst) { | |
32 dst[0] = ADD(MUL(m1[0], m2[0]), MUL(m1[1], m2[3])); | |
33 dst[1] = ADD(MUL(m1[0], m2[1]), MUL(m1[1], m2[4])); | |
34 dst[2] = ADD(ADD(MUL(m1[0], m2[2]), MUL(m1[1], m2[5])), m1[2]); | |
35 dst[3] = ADD(MUL(m1[3], m2[0]), MUL(m1[4], m2[3])); | |
36 dst[4] = ADD(MUL(m1[3], m2[1]), MUL(m1[4], m2[4])); | |
37 dst[5] = ADD(ADD(MUL(m1[3], m2[2]), MUL(m1[4], m2[5])), m1[5]); | |
1 | 38 } |
39 | |
2 | 40 /*! \brief Compute agrregated transform function. |
41 * | |
42 * Base on parent's aggregated matrix if it is existed, or use transform | |
43 * matrix as aggregated matrix. | |
44 */ | |
1 | 45 static void compute_transform_function(coord_t *visit) { |
46 if(visit->parent) | |
47 mul_matrix(visit->parent->aggr_matrix, | |
48 visit->matrix, visit->aggr_matrix); | |
49 else | |
50 memcpy(visit->aggr_matrix, visit->matrix, sizeof(visit->matrix)); | |
51 } | |
52 | |
53 /*! \brief Update aggregate matrices of elements under a sub-tree. | |
54 * | |
55 * A subtree is specified by the root of it. All elements in the subtree | |
56 * are effected by that changes of matrix of the subtree root. | |
57 */ | |
58 void update_aggr_matrix(coord_t *start) { | |
59 coord_t *visit, *child, *next; | |
60 | |
61 compute_transform_function(start); | |
62 | |
63 visit = start; | |
64 while(visit) { | |
65 child = visit->children; | |
66 while(child) { | |
67 compute_transform_function(child); | |
68 child = child->sibling; | |
69 } | |
70 | |
71 if(visit->children) | |
72 visit = visit->children; | |
73 else if(visit->sibling) | |
74 visit = visit->sibling; | |
75 else { | |
76 next = NULL; | |
77 while(visit->parent && visit->parent != start) { | |
78 visit = visit->parent; | |
79 if(visit->sibling) { | |
80 next = visit->sibling; | |
81 break; | |
82 } | |
83 } | |
84 visit = next; | |
85 } | |
86 } | |
87 } | |
88 | |
89 void coord_init(coord_t *co, coord_t *parent) { | |
90 memset(co, 0, sizeof(coord_t)); | |
91 if(parent) { | |
92 co->parent = parent; | |
93 co->sibling = parent->children; | |
94 parent->children = co; | |
95 } | |
96 co->matrix[0] = 1; | |
97 co->matrix[4] = 1; | |
98 } | |
99 | |
2 | 100 void coord_trans_pos(coord_t *co, co_aix *x, co_aix *y) { |
101 co_aix nx, ny; | |
102 | |
103 nx = ADD(ADD(MUL(co->aggr_matrix[0], *x), | |
104 MUL(co->aggr_matrix[1], *y)), | |
105 co->aggr_matrix[2]); | |
106 ny = ADD(ADD(MUL(co->aggr_matrix[3], *x), | |
107 MUL(co->aggr_matrix[4], *y)), | |
108 co->aggr_matrix[5]); | |
109 *x = nx; | |
110 *y = ny; | |
111 } | |
112 | |
1 | 113 #ifdef UNITTEST |
114 | |
115 #include <CUnit/Basic.h> | |
116 | |
117 void test_update_aggr_matrix(void) { | |
118 coord_t elms[6]; | |
2 | 119 co_aix x, y; |
1 | 120 |
121 coord_init(elms, NULL); | |
122 coord_init(elms + 1, elms); | |
123 coord_init(elms + 2, elms); | |
124 coord_init(elms + 3, elms + 1); | |
125 coord_init(elms + 4, elms + 1); | |
126 coord_init(elms + 5, elms + 2); | |
127 | |
128 /* | 2 -1 0 | | |
129 * | 0 1 0 | | |
130 * | 0 0 1 | | |
131 */ | |
132 elms[0].matrix[0] = 2; | |
133 elms[0].matrix[1] = -1; | |
134 | |
135 /* | 1 3 0 | | |
136 * | 5 1 0 | | |
137 * | 0 0 1 | | |
138 */ | |
139 elms[1].matrix[1] = 3; | |
140 elms[1].matrix[3] = 5; | |
141 | |
142 update_aggr_matrix(elms); | |
143 | |
144 /* | -3 5 0 | | |
145 * | 5 1 0 | | |
146 * | 0 0 1 | | |
147 */ | |
148 CU_ASSERT(elms[3].aggr_matrix[0] == -3); | |
149 CU_ASSERT(elms[3].aggr_matrix[1] == 5); | |
150 CU_ASSERT(elms[3].aggr_matrix[2] == 0); | |
151 CU_ASSERT(elms[3].aggr_matrix[3] == 5); | |
152 CU_ASSERT(elms[3].aggr_matrix[4] == 1); | |
153 CU_ASSERT(elms[3].aggr_matrix[5] == 0); | |
154 | |
155 CU_ASSERT(elms[4].aggr_matrix[0] == -3); | |
156 CU_ASSERT(elms[4].aggr_matrix[1] == 5); | |
157 CU_ASSERT(elms[4].aggr_matrix[2] == 0); | |
158 CU_ASSERT(elms[4].aggr_matrix[3] == 5); | |
159 CU_ASSERT(elms[4].aggr_matrix[4] == 1); | |
160 CU_ASSERT(elms[4].aggr_matrix[5] == 0); | |
161 | |
162 CU_ASSERT(elms[5].aggr_matrix[0] == 2); | |
163 CU_ASSERT(elms[5].aggr_matrix[1] == -1); | |
164 CU_ASSERT(elms[5].aggr_matrix[2] == 0); | |
165 CU_ASSERT(elms[5].aggr_matrix[3] == 0); | |
166 CU_ASSERT(elms[5].aggr_matrix[4] == 1); | |
167 CU_ASSERT(elms[5].aggr_matrix[5] == 0); | |
2 | 168 |
169 x = 50; | |
170 y = 99; | |
171 coord_trans_pos(elms + 5, &x, &y); | |
172 CU_ASSERT(x == 1); | |
173 CU_ASSERT(y == 99); | |
1 | 174 } |
175 | |
176 CU_pSuite get_coord_suite(void) { | |
177 CU_pSuite suite; | |
178 | |
179 suite = CU_add_suite("Suite_coord", NULL, NULL); | |
180 CU_ADD_TEST(suite, test_update_aggr_matrix); | |
181 | |
182 return suite; | |
183 } | |
184 | |
185 #endif |