1#include <algorithm>
2
3#include "table.hpp"
4#include "cell.hpp"
5#include "random.hpp"
6
7
8Table::
9Table(const TableParams &params):
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
48void
49Table::
50generate_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
192void
193Table::
194paint_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
276void
277Table::
278pre_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
319void
320Table::
321paint_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