1 | #include <algorithm> |
2 | |
3 | #include "table.hpp" |
4 | #include "cell.hpp" |
5 | #include "random.hpp" |
6 | |
7 | |
8 | Table:: |
9 | Table(const TableParams ¶ms): |
10 | CellGroup(nullptr), |
11 | m_rotating(false), |
12 | m_params(params), |
13 | m_first_draw(true) |
14 | { |
15 | m_dimensions = m_params.m_wh; |
16 | m_clipped = false; |
17 | m_params.m_cell_count.x() = std::max(1, m_params.m_cell_count.x()); |
18 | m_params.m_cell_count.y() = std::max(1, m_params.m_cell_count.y()); |
19 | |
20 | if (m_params.m_text_colors.empty()) |
21 | { |
22 | m_params.m_text_colors.push_back(vec4(1.0f, 1.0f, 1.0f, 1.0f)); |
23 | } |
24 | |
25 | if (m_params.m_background_colors.empty()) |
26 | { |
27 | m_params.m_background_colors.push_back(vec4(0.0f, 0.0f, 1.0f, 1.0f)); |
28 | } |
29 | |
30 | if (m_params.m_texts.empty()) |
31 | { |
32 | m_params.m_texts.push_back("Lonely Text" ); |
33 | } |
34 | |
35 | if (m_params.m_images.empty()) |
36 | { |
37 | m_params.m_images.push_back(named_image(reference_counted_ptr<const Image>(), |
38 | "nullptr" )); |
39 | } |
40 | |
41 | if (m_params.m_rect_colors.empty()) |
42 | { |
43 | m_params.m_rect_colors.push_back(vec4(1.0f, 1.0f, 1.0f, 1.0f)); |
44 | } |
45 | |
46 | } |
47 | |
48 | void |
49 | Table:: |
50 | generate_children_in_group(const reference_counted_ptr<Painter> &painter, |
51 | CellGroup *g, int &J, |
52 | const ivec2 &xy, |
53 | int count_x, int count_y, |
54 | std::vector<PainterData::brush_value > &txt, |
55 | std::vector<PainterData::brush_value > &bg, |
56 | std::vector<PainterData::brush_value > &im) |
57 | { |
58 | g->m_bb_min = (vec2(xy) ) * m_cell_sz; |
59 | g->m_bb_max = (vec2(xy) + vec2(count_x, count_y) ) * m_cell_sz; |
60 | |
61 | if (count_x > m_params.m_max_cell_group_size || count_y > m_params.m_max_cell_group_size) |
62 | { |
63 | int cx1, cx2, cy1, cy2; |
64 | |
65 | if (count_x > m_params.m_max_cell_group_size) |
66 | { |
67 | cx1 = count_x / 2; |
68 | cx2 = count_x - cx1; |
69 | } |
70 | else |
71 | { |
72 | cx1 = count_x; |
73 | cx2 = 0; |
74 | } |
75 | |
76 | if (count_y > m_params.m_max_cell_group_size) |
77 | { |
78 | cy1 = count_y / 2; |
79 | cy2 = count_y - cy1; |
80 | } |
81 | else |
82 | { |
83 | cy1 = count_y; |
84 | cy2 = 0; |
85 | } |
86 | |
87 | CellGroup *p; |
88 | p = FASTUIDRAWnew CellGroup(g); |
89 | generate_children_in_group(painter, p, J, xy, cx1, cy1, txt, bg, im); |
90 | |
91 | if (cx2 > 0) |
92 | { |
93 | p = FASTUIDRAWnew CellGroup(g); |
94 | generate_children_in_group(painter, p, J, ivec2(xy.x() + cx1, xy.y()), |
95 | cx2, cy1, txt, bg, im); |
96 | } |
97 | |
98 | if (cy2 > 0) |
99 | { |
100 | p = FASTUIDRAWnew CellGroup(g); |
101 | generate_children_in_group(painter, p, J, ivec2(xy.x(), xy.y() + cy1), |
102 | cx1, cy2, txt, bg, im); |
103 | } |
104 | |
105 | if (cx2 > 0 && cy2 > 0) |
106 | { |
107 | p = FASTUIDRAWnew CellGroup(g); |
108 | generate_children_in_group(painter, p, J, ivec2(xy.x() + cx1, xy.y() + cy1), |
109 | cx2, cy2, txt, bg, im); |
110 | } |
111 | } |
112 | else |
113 | { |
114 | int x, y; |
115 | vec2 pt; |
116 | for(y = 0, pt.y() = float(xy.y()) * m_cell_sz.y(); y < count_y; ++y, pt.y() += m_cell_sz.y()) |
117 | { |
118 | for(x = 0, pt.x() = float(xy.x()) * m_cell_sz.x(); x < count_x; ++x, pt.x() += m_cell_sz.x(), ++J) |
119 | { |
120 | int txtJ, bgJ, imJ; |
121 | |
122 | txtJ = J % txt.size(); |
123 | bgJ = J % bg.size(); |
124 | imJ = J % im.size(); |
125 | |
126 | if (!txt[txtJ].packed()) |
127 | { |
128 | PainterBrush brush(m_params.m_text_colors[txtJ]); |
129 | txt[txtJ] = painter->packed_value_pool().create_packed_brush(brush); |
130 | } |
131 | |
132 | if (!bg[bgJ].packed()) |
133 | { |
134 | PainterBrush brush(m_params.m_background_colors[bgJ]); |
135 | bg[bgJ] = painter->packed_value_pool().create_packed_brush(brush); |
136 | } |
137 | |
138 | if (!im[imJ].packed()) |
139 | { |
140 | int image, color; |
141 | |
142 | image = imJ % m_params.m_images.size(); |
143 | color = imJ % m_params.m_rect_colors.size(); |
144 | |
145 | PainterBrush brush; |
146 | if (m_params.m_images[image].first) |
147 | { |
148 | brush.image(m_params.m_images[image].first, |
149 | m_params.m_image_filter, |
150 | m_params.m_image_mipmapping); |
151 | } |
152 | |
153 | brush.color(m_params.m_rect_colors[color]); |
154 | im[imJ] = painter->packed_value_pool().create_packed_brush(brush); |
155 | } |
156 | |
157 | CellParams params; |
158 | params.m_font_database = m_params.m_font_database; |
159 | params.m_glyph_cache = m_params.m_glyph_cache; |
160 | params.m_font = m_params.m_font; |
161 | params.m_background_brush = bg[bgJ]; |
162 | params.m_image_brush = im[imJ]; |
163 | params.m_image = m_params.m_images[imJ % m_params.m_images.size()].first.get(); |
164 | params.m_text_brush = txt[txtJ]; |
165 | params.m_text = m_params.m_texts[J % m_params.m_texts.size()]; |
166 | params.m_pixels_per_ms = random_value(m_params.m_min_speed, m_params.m_max_speed) / 1000.0f; |
167 | params.m_degrees_per_s = (int)random_value(m_params.m_min_degrees_per_s, m_params.m_max_degrees_per_s); |
168 | params.m_pixel_size = m_params.m_pixel_size; |
169 | params.m_size = m_cell_sz; |
170 | params.m_table_pos = ivec2(x, y) + xy; |
171 | if (m_params.m_draw_image_name) |
172 | { |
173 | params.m_image_name = m_params.m_images[imJ].second; |
174 | } |
175 | else |
176 | { |
177 | params.m_image_name = "" ; |
178 | } |
179 | params.m_line_brush = m_line_brush; |
180 | params.m_state = m_params.m_cell_state; |
181 | params.m_timer_based_animation = m_params.m_timer_based_animation; |
182 | |
183 | Cell *cell; |
184 | cell = FASTUIDRAWnew Cell(g, params); |
185 | cell->m_parent_matrix_this = float3x3(float2x2(), pt); |
186 | } |
187 | } |
188 | } |
189 | } |
190 | |
191 | |
192 | void |
193 | Table:: |
194 | paint_pre_children(const reference_counted_ptr<Painter> &painter) |
195 | { |
196 | if (m_first_draw) |
197 | { |
198 | vec2 cell_loc; |
199 | int x, y, J; |
200 | std::vector<PainterData::brush_value > txt, bg, im; |
201 | |
202 | txt.resize(m_params.m_text_colors.size()); |
203 | bg.resize(m_params.m_background_colors.size()); |
204 | im.resize(m_params.m_images.size() * m_params.m_rect_colors.size()); |
205 | m_cell_sz = m_dimensions / vec2(m_params.m_cell_count); |
206 | |
207 | m_params.m_cell_state->m_path << vec2(0.0f, 0.0f) |
208 | << vec2(m_cell_sz.x(), 0.0f) |
209 | << vec2(m_cell_sz.x(), m_cell_sz.y()) |
210 | << vec2(0.0f, m_cell_sz.y()) |
211 | << Path::contour_close(); |
212 | |
213 | |
214 | m_grid_path << vec2(0.0f, 0.0f) |
215 | << vec2(m_params.m_wh.x(), 0.0f) |
216 | << vec2(m_params.m_wh.x(), m_params.m_wh.y()) |
217 | << vec2(0.0f, m_params.m_wh.y()) |
218 | << Path::contour_close(); |
219 | |
220 | for(x = 1, cell_loc.x() = m_cell_sz.x(); x < m_params.m_cell_count.x(); ++x, cell_loc.x() += m_cell_sz.x()) |
221 | { |
222 | m_grid_path << Path::contour_start(cell_loc.x(), 0.0f) |
223 | << vec2(cell_loc.x(), m_params.m_wh.y()); |
224 | |
225 | } |
226 | |
227 | for(y = 1, cell_loc.y() = m_cell_sz.y(); y < m_params.m_cell_count.y(); ++y, cell_loc.y() += m_cell_sz.y()) |
228 | { |
229 | m_grid_path << Path::contour_start(0.0f, cell_loc.y()) |
230 | << vec2(m_params.m_wh.x(), cell_loc.y()); |
231 | } |
232 | |
233 | m_line_brush = painter->packed_value_pool().create_packed_brush(m_params.m_line_color); |
234 | |
235 | J = 0; |
236 | generate_children_in_group(painter, this, J, ivec2(0, 0), |
237 | m_params.m_cell_count.x(), m_params.m_cell_count.y(), |
238 | txt, bg, im); |
239 | m_first_draw = false; |
240 | m_time.restart(); |
241 | m_thousandths_degrees_rotation = 0; |
242 | } |
243 | else |
244 | { |
245 | uint32_t ms; |
246 | if (m_params.m_timer_based_animation) |
247 | { |
248 | ms = m_time.restart(); |
249 | } |
250 | else |
251 | { |
252 | ms = 16; |
253 | } |
254 | |
255 | if (m_params.m_cell_state->m_pause) |
256 | { |
257 | ms = 0; |
258 | } |
259 | |
260 | m_thousandths_degrees_rotation += m_params.m_table_rotate_degrees_per_s * ms; |
261 | if (m_thousandths_degrees_rotation >= 360 * 1000) |
262 | { |
263 | m_thousandths_degrees_rotation = m_thousandths_degrees_rotation % (360 * 1000); |
264 | } |
265 | |
266 | if (!m_rotating) |
267 | { |
268 | m_thousandths_degrees_rotation = 0; |
269 | } |
270 | } |
271 | |
272 | m_rotation_radians = |
273 | static_cast<float>(FASTUIDRAW_PI) * static_cast<float>(m_thousandths_degrees_rotation) / (1000.0f * 180.0f); |
274 | } |
275 | |
276 | void |
277 | Table:: |
278 | pre_paint() |
279 | { |
280 | m_bb_min = m_params.m_zoomer->transformation().apply_inverse_to_point(m_bb_min); |
281 | m_bb_max = m_params.m_zoomer->transformation().apply_inverse_to_point(m_bb_max); |
282 | |
283 | if (m_rotating) |
284 | { |
285 | m_parent_matrix_this.reset(); |
286 | m_parent_matrix_this.translate(m_dimensions * 0.5f); |
287 | m_parent_matrix_this.rotate(m_rotation_radians); |
288 | m_parent_matrix_this.translate(-m_dimensions * 0.5f); |
289 | |
290 | /* |
291 | screen_pt = zoomer * parent_matrix_this * table_pt |
292 | becomes: |
293 | table_pt = inverse(parent_matrix_this) * inverse(zoomer) * screen_pt |
294 | */ |
295 | |
296 | float3x3 inverse; |
297 | vec3 p0, p1, p2, p3; |
298 | m_parent_matrix_this.inverse(inverse); |
299 | |
300 | p0 = inverse * vec3(m_bb_min.x(), m_bb_min.y(), 1.0f); |
301 | p1 = inverse * vec3(m_bb_min.x(), m_bb_max.y(), 1.0f); |
302 | p2 = inverse * vec3(m_bb_max.x(), m_bb_max.y(), 1.0f); |
303 | p3 = inverse * vec3(m_bb_max.x(), m_bb_min.y(), 1.0f); |
304 | |
305 | for(int i = 0; i < 2; ++i) |
306 | { |
307 | m_bb_min[i] = std::min(std::min(p0[i], p1[i]), std::min(p2[i], p3[i])); |
308 | m_bb_max[i] = std::max(std::max(p0[i], p1[i]), std::max(p2[i], p3[i])); |
309 | } |
310 | } |
311 | else |
312 | { |
313 | m_parent_matrix_this.reset(); |
314 | } |
315 | CellGroup::pre_paint(); |
316 | } |
317 | |
318 | |
319 | void |
320 | Table:: |
321 | paint_post_children(const reference_counted_ptr<Painter> &painter) |
322 | { |
323 | if (!m_params.m_cell_state->m_rotating && m_params.m_cell_state->m_stroke_width > 0.0f) |
324 | { |
325 | PainterStrokeParams st; |
326 | |
327 | st.miter_limit(-1.0f); |
328 | st.width(m_params.m_cell_state->m_stroke_width); |
329 | |
330 | painter->stroke_path(PainterData(m_line_brush, &st), |
331 | m_grid_path, |
332 | StrokingStyle() |
333 | .cap_style(Painter::flat_caps) |
334 | .join_style(Painter::rounded_joins), |
335 | m_params.m_cell_state->m_anti_alias_stroking); |
336 | } |
337 | } |
338 | |