Line data Source code
1 : /* File: pencil_classifier_composer.c; Copyright and License: see below */
2 :
3 : #include "pencil_classifier_composer.h"
4 : #include "u8/u8_trace.h"
5 : #include "u8/u8_f64.h"
6 : #include "utf8stringbuf/utf8stringbuf.h"
7 : #include "utf8stringbuf/utf8string.h"
8 : #include <pango/pangocairo.h>
9 : #include <stdio.h>
10 : #include <stdlib.h>
11 : #include <assert.h>
12 :
13 3 : void pencil_classifier_composer_init( pencil_classifier_composer_t *this_ )
14 : {
15 3 : U8_TRACE_BEGIN();
16 :
17 3 : draw_classifier_icon_init( &((*this_).draw_classifier_icon) );
18 3 : draw_classifier_label_init( &((*this_).draw_classifier_label) );
19 3 : draw_classifier_contour_init( &((*this_).draw_classifier_contour) );
20 3 : draw_stereotype_icon_init( &((*this_).draw_stereotype_icon) );
21 :
22 3 : U8_TRACE_END();
23 3 : }
24 :
25 3 : void pencil_classifier_composer_destroy( pencil_classifier_composer_t *this_ )
26 : {
27 3 : U8_TRACE_BEGIN();
28 :
29 3 : draw_classifier_icon_destroy( &((*this_).draw_classifier_icon) );
30 3 : draw_classifier_label_destroy( &((*this_).draw_classifier_label) );
31 3 : draw_classifier_contour_destroy( &((*this_).draw_classifier_contour) );
32 3 : draw_stereotype_icon_destroy( &((*this_).draw_stereotype_icon) );
33 :
34 3 : U8_TRACE_END();
35 3 : }
36 :
37 128 : int pencil_classifier_composer_expand_space( pencil_classifier_composer_t *this_,
38 : const geometry_rectangle_t *space,
39 : bool shows_contained_children,
40 : const data_profile_part_t *profile,
41 : const pencil_size_t *pencil_size,
42 : PangoLayout *font_layout,
43 : layout_visible_classifier_t *io_classifier_layout )
44 : {
45 128 : U8_TRACE_BEGIN();
46 128 : assert( NULL != space );
47 128 : assert( NULL != pencil_size );
48 128 : assert( NULL != font_layout );
49 128 : assert( NULL != io_classifier_layout );
50 :
51 : /* get data that shall be layouted/composed */
52 : const data_visible_classifier_t *const visible_classifier
53 128 : = layout_visible_classifier_get_data_const( io_classifier_layout );
54 : const data_classifier_t *const classifier
55 128 : = data_visible_classifier_get_classifier_const( visible_classifier );
56 : const data_classifier_type_t classifier_type
57 128 : = data_classifier_get_main_type( classifier );
58 128 : const char *const classifier_stereotype = data_classifier_get_stereotype_const( classifier );
59 : const bool has_stereotype_icon
60 128 : = draw_stereotype_icon_exists( &((*this_).draw_stereotype_icon), classifier_stereotype, profile );
61 :
62 128 : U8_TRACE_INFO_INT("expanding bounds of classifier id:", data_classifier_get_row_id( classifier ) );
63 128 : U8_TRACE_INFO_INT_INT("expanding bounds of classifier type, children:", classifier_type, shows_contained_children?1:0 );
64 :
65 : /* determine border sizes of the main line (label and optionally icon) */
66 : geometry_rectangle_t label_rect;
67 128 : geometry_rectangle_init_empty( &label_rect );
68 : geometry_rectangle_t icon_rect;
69 128 : geometry_rectangle_init_empty( &icon_rect );
70 : geometry_rectangle_t label_compartment;
71 128 : geometry_rectangle_init_empty( &label_compartment );
72 128 : const geometry_rectangle_t *space_and_label_fake = space; /* fake space_and_label to be identical to requested space */
73 : const int area_too_small
74 128 : = pencil_classifier_composer_private_get_label_box( this_,
75 : visible_classifier,
76 : shows_contained_children,
77 : has_stereotype_icon,
78 : space_and_label_fake,
79 : pencil_size,
80 : font_layout,
81 : &label_rect,
82 : &icon_rect,
83 : &label_compartment
84 : );
85 128 : if ( area_too_small != 0 )
86 : {
87 64 : U8_TRACE_INFO("new width is defined by label-and-icon, not by requested inner space" );
88 : }
89 : /* shift the label and icon because space_and_label was a fake; the top side is at space top instead of label top */
90 128 : const double delta_top = geometry_rectangle_get_bottom( &label_compartment ) - geometry_rectangle_get_top( space );
91 128 : geometry_rectangle_set_top( &label_rect, geometry_rectangle_get_top( &label_rect ) - delta_top );
92 128 : geometry_rectangle_set_top( &icon_rect, geometry_rectangle_get_top( &icon_rect ) - delta_top );
93 128 : geometry_rectangle_set_top( &label_compartment, geometry_rectangle_get_top( &label_compartment ) - delta_top );
94 :
95 : /* sizes of geometric objects are determined, */
96 : /* now position the geometric objects */
97 : {
98 : const bool has_contour
99 128 : = draw_classifier_contour_has_contour( &((*this_).draw_classifier_contour), classifier_type );
100 :
101 128 : if ( has_contour )
102 : {
103 92 : U8_TRACE_INFO("calculating symbol box as envelope around label and space..." );
104 :
105 : /* calculate symbol bounds */
106 : geometry_rectangle_t inner_area;
107 92 : if ( area_too_small )
108 : {
109 92 : geometry_rectangle_init( &inner_area,
110 : geometry_rectangle_get_left( &label_compartment ),
111 : geometry_rectangle_get_top( &label_compartment ),
112 : geometry_rectangle_get_width( &label_compartment ),
113 46 : geometry_rectangle_get_height( &label_compartment )
114 46 : + geometry_rectangle_get_height( space )
115 : );
116 : }
117 : else
118 : {
119 46 : geometry_rectangle_copy( &inner_area, space );
120 46 : geometry_rectangle_shift( &inner_area, 0.0, -geometry_rectangle_get_height( &label_compartment ) );
121 46 : geometry_rectangle_enlarge( &inner_area, 0.0, geometry_rectangle_get_height( &label_compartment ) );
122 : }
123 : const geometry_rectangle_t envelope
124 92 : = draw_classifier_contour_calc_outer_bounds( &((*this_).draw_classifier_contour),
125 : classifier_type,
126 : &inner_area,
127 : pencil_size
128 : );
129 92 : layout_visible_classifier_set_symbol_box( io_classifier_layout, &envelope );
130 92 : geometry_rectangle_destroy( &inner_area );
131 : }
132 : else
133 : {
134 36 : U8_TRACE_INFO("calculating symbol box for fixed-sized icon..." );
135 :
136 36 : const double symbol_height = pencil_size_get_classifier_symbol_height( pencil_size );
137 36 : const double symbol_width = symbol_height;
138 :
139 : /* calculate symbol bounds */
140 36 : const geometry_h_align_t H_CENTER = GEOMETRY_H_ALIGN_CENTER;
141 : const double symbol_left
142 36 : = geometry_h_align_get_left( &H_CENTER,
143 : symbol_width,
144 : geometry_rectangle_get_left( space ),
145 : geometry_rectangle_get_width( space )
146 : );
147 36 : const double symbol_top = geometry_rectangle_get_top( &label_compartment ) - symbol_height;
148 : geometry_rectangle_t classifier_symbol_box;
149 36 : geometry_rectangle_init( &classifier_symbol_box, symbol_left, symbol_top, symbol_width, symbol_height );
150 36 : layout_visible_classifier_set_symbol_box( io_classifier_layout, &classifier_symbol_box );
151 36 : geometry_rectangle_destroy( &classifier_symbol_box );
152 : }
153 :
154 : /* calculate label_box */
155 128 : layout_visible_classifier_set_label_box( io_classifier_layout, &label_rect );
156 128 : layout_visible_classifier_set_label_anchor( io_classifier_layout,
157 : GEOMETRY_H_ALIGN_CENTER,
158 : GEOMETRY_V_ALIGN_TOP
159 : );
160 : /* calculate icon_box */
161 128 : layout_visible_classifier_set_icon_box( io_classifier_layout, &icon_rect );
162 :
163 : /* calculate space */
164 : /* get the symbol and label boxes and inner space rectangles to modify */
165 : geometry_rectangle_t classifier_space;
166 128 : geometry_rectangle_init( &classifier_space,
167 : geometry_rectangle_get_left( &label_compartment ),
168 : geometry_rectangle_get_top( space ),
169 : geometry_rectangle_get_width( &label_compartment ),
170 : geometry_rectangle_get_height( space )
171 : );
172 128 : layout_visible_classifier_set_space( io_classifier_layout, &classifier_space );
173 128 : geometry_rectangle_destroy( &classifier_space );
174 : }
175 :
176 128 : U8_TRACE_INFO("==== symbol_box ====" );
177 128 : geometry_rectangle_trace( layout_visible_classifier_get_symbol_box_const( io_classifier_layout ) );
178 128 : U8_TRACE_INFO("==== label_box ====" );
179 128 : geometry_rectangle_trace( &label_rect );
180 128 : U8_TRACE_INFO("==== icon_box ====" );
181 128 : geometry_rectangle_trace( &icon_rect );
182 128 : U8_TRACE_INFO("==== space =====" );
183 128 : geometry_rectangle_trace( layout_visible_classifier_get_space_const( io_classifier_layout ) );
184 :
185 128 : geometry_rectangle_destroy( &label_rect );
186 128 : geometry_rectangle_destroy( &icon_rect );
187 128 : geometry_rectangle_destroy( &label_compartment );
188 :
189 128 : U8_TRACE_END_ERR(area_too_small);
190 128 : return area_too_small;
191 : }
192 :
193 128 : int pencil_classifier_composer_set_envelope_box( pencil_classifier_composer_t *this_,
194 : const geometry_rectangle_t *envelope,
195 : bool shows_contained_children,
196 : const data_profile_part_t *profile,
197 : const pencil_size_t *pencil_size,
198 : PangoLayout *font_layout,
199 : layout_visible_classifier_t *io_classifier_layout )
200 : {
201 128 : U8_TRACE_BEGIN();
202 128 : assert( NULL != envelope );
203 128 : assert( NULL != pencil_size );
204 128 : assert( NULL != font_layout );
205 128 : assert( NULL != io_classifier_layout );
206 :
207 : /* get data that shall be layouted/composed */
208 : const data_visible_classifier_t *const visible_classifier
209 128 : = layout_visible_classifier_get_data_const( io_classifier_layout );
210 : const data_classifier_t *const classifier
211 128 : = data_visible_classifier_get_classifier_const( visible_classifier );
212 : const data_classifier_type_t classifier_type
213 128 : = data_classifier_get_main_type( classifier );
214 128 : const char *const classifier_stereotype = data_classifier_get_stereotype_const( classifier );
215 : const bool has_stereotype_icon
216 128 : = draw_stereotype_icon_exists( &((*this_).draw_stereotype_icon), classifier_stereotype, profile );
217 :
218 128 : U8_TRACE_INFO_INT("calculating bounds of classifier id, type:", data_classifier_get_row_id( classifier ) );
219 128 : U8_TRACE_INFO_INT_INT("calculating bounds of classifier type, children:", classifier_type, shows_contained_children?1:0 );
220 :
221 : /* determine border sizes of the classifier-shape */
222 : const geometry_rectangle_t space_and_label
223 128 : = draw_classifier_contour_calc_inner_area( &((*this_).draw_classifier_contour),
224 : classifier_type,
225 : envelope,
226 : pencil_size
227 : );
228 :
229 : /* determine border sizes of the main line (label and optionally icon) */
230 : geometry_rectangle_t label_rect;
231 128 : geometry_rectangle_init_empty( &label_rect );
232 : geometry_rectangle_t icon_rect;
233 128 : geometry_rectangle_init_empty( &icon_rect );
234 : geometry_rectangle_t label_compartment;
235 128 : geometry_rectangle_init_empty( &label_compartment );
236 : const int area_too_small
237 128 : = pencil_classifier_composer_private_get_label_box( this_,
238 : visible_classifier,
239 : shows_contained_children,
240 : has_stereotype_icon,
241 : &space_and_label,
242 : pencil_size,
243 : font_layout,
244 : &label_rect,
245 : &icon_rect,
246 : &label_compartment
247 : );
248 :
249 : /* if label fits into space_and_label */
250 128 : if ( 0 == area_too_small )
251 : {
252 : const bool has_contour
253 64 : = draw_classifier_contour_has_contour( &((*this_).draw_classifier_contour), classifier_type );
254 :
255 : /* get the symbol and label boxes and inner space rectangles to modify */
256 : geometry_rectangle_t classifier_space;
257 64 : geometry_rectangle_copy( &classifier_space, &space_and_label );
258 :
259 64 : if ( has_contour )
260 : {
261 46 : U8_TRACE_INFO("calculating symbol box as envelope around label and space..." );
262 :
263 : /* calculate symbol bounds */
264 46 : layout_visible_classifier_set_symbol_box( io_classifier_layout, envelope );
265 :
266 : /* calculate space */
267 46 : geometry_rectangle_shift( &classifier_space, 0.0, geometry_rectangle_get_height( &label_compartment ) );
268 46 : geometry_rectangle_enlarge( &classifier_space, 0.0, -geometry_rectangle_get_height( &label_compartment ) );
269 : }
270 : else
271 : {
272 18 : U8_TRACE_INFO("calculating symbol box for fixed-sized icon..." );
273 :
274 18 : const double symbol_height = pencil_size_get_classifier_symbol_height( pencil_size );
275 18 : const double symbol_width = symbol_height;
276 :
277 : /* calculate symbol bounds */
278 18 : const geometry_h_align_t H_CENTER = GEOMETRY_H_ALIGN_CENTER;
279 : const double symbol_left
280 18 : = geometry_h_align_get_left( &H_CENTER,
281 : symbol_width,
282 : geometry_rectangle_get_left( &space_and_label ),
283 : geometry_rectangle_get_width( &space_and_label )
284 : );
285 18 : const double symbol_top = geometry_rectangle_get_top( &label_compartment ) - symbol_height;
286 : geometry_rectangle_t classifier_symbol_box;
287 18 : geometry_rectangle_init( &classifier_symbol_box, symbol_left, symbol_top, symbol_width, symbol_height );
288 18 : layout_visible_classifier_set_symbol_box( io_classifier_layout, &classifier_symbol_box );
289 18 : geometry_rectangle_destroy( &classifier_symbol_box );
290 :
291 : /* calculate space */
292 18 : const double label_and_symbol_height = geometry_rectangle_get_height( &label_compartment ) + symbol_height;
293 18 : geometry_rectangle_shift( &classifier_space, 0.0, label_and_symbol_height );
294 18 : geometry_rectangle_enlarge( &classifier_space, 0.0, -label_and_symbol_height );
295 : }
296 64 : layout_visible_classifier_set_space( io_classifier_layout, &classifier_space );
297 :
298 :
299 : /* calculate label_box */
300 64 : layout_visible_classifier_set_label_box( io_classifier_layout, &label_rect );
301 64 : layout_visible_classifier_set_label_anchor( io_classifier_layout,
302 : GEOMETRY_H_ALIGN_CENTER,
303 : GEOMETRY_V_ALIGN_TOP
304 : );
305 : /* calculate icon_box */
306 64 : layout_visible_classifier_set_icon_box( io_classifier_layout, &icon_rect );
307 :
308 64 : U8_TRACE_INFO("==== symbol_box ====" );
309 64 : geometry_rectangle_trace( layout_visible_classifier_get_symbol_box_const( io_classifier_layout ) );
310 64 : U8_TRACE_INFO("==== label_box ====" );
311 64 : geometry_rectangle_trace( &label_rect );
312 64 : U8_TRACE_INFO("==== icon_box ====" );
313 64 : geometry_rectangle_trace( &icon_rect );
314 64 : U8_TRACE_INFO("==== space =====" );
315 64 : geometry_rectangle_trace( &classifier_space );
316 :
317 64 : geometry_rectangle_destroy( &classifier_space );
318 : }
319 : else
320 : {
321 : geometry_rectangle_t space_guess; /* guess the inner space based on current text height */
322 64 : geometry_rectangle_copy( &space_guess, &space_and_label );
323 64 : geometry_rectangle_shift( &space_guess, 0.0, geometry_rectangle_get_height( &label_compartment ) );
324 64 : geometry_rectangle_enlarge( &space_guess, 0.0, -geometry_rectangle_get_height( &label_compartment ) );
325 64 : U8_TRACE_INFO("==== space_guess====" );
326 64 : geometry_rectangle_trace( &space_guess );
327 64 : pencil_classifier_composer_expand_space( this_,
328 : &space_guess,
329 : shows_contained_children,
330 : profile,
331 : pencil_size,
332 : font_layout,
333 : io_classifier_layout
334 : );
335 64 : geometry_rectangle_destroy( &space_guess );
336 :
337 : /* shift/center to requested position after resizing beyond requested size */
338 : const geometry_rectangle_t current_envelope
339 64 : = layout_visible_classifier_get_envelope_box( io_classifier_layout );
340 64 : const double shift_to_right = geometry_rectangle_get_center_x( envelope ) - geometry_rectangle_get_center_x( ¤t_envelope );
341 64 : const double shift_to_bottom = geometry_rectangle_get_center_y( envelope ) - geometry_rectangle_get_center_y( ¤t_envelope );
342 64 : const geometry_offset_t offset = geometry_offset_new( shift_to_right, shift_to_bottom );
343 64 : layout_visible_classifier_shift( io_classifier_layout, &offset );
344 : }
345 :
346 128 : geometry_rectangle_destroy( &label_rect );
347 128 : geometry_rectangle_destroy( &icon_rect );
348 128 : geometry_rectangle_destroy( &label_compartment );
349 :
350 128 : U8_TRACE_END_ERR( area_too_small );
351 128 : return area_too_small;
352 : }
353 :
354 256 : int pencil_classifier_composer_private_get_label_box( pencil_classifier_composer_t *this_,
355 : const data_visible_classifier_t *visible_classifier,
356 : bool shows_contained_children,
357 : bool has_stereotype_icon,
358 : const geometry_rectangle_t *space_and_label,
359 : const pencil_size_t *pencil_size,
360 : PangoLayout *font_layout,
361 : geometry_rectangle_t *out_label_box,
362 : geometry_rectangle_t *out_icon_box,
363 : geometry_rectangle_t *out_label_compartment )
364 : {
365 256 : U8_TRACE_BEGIN();
366 256 : assert( NULL != visible_classifier );
367 256 : assert( NULL != space_and_label );
368 256 : assert( NULL != pencil_size );
369 256 : assert( NULL != font_layout );
370 256 : assert( NULL != out_label_box );
371 256 : assert( NULL != out_icon_box );
372 256 : assert( NULL != out_label_compartment );
373 :
374 256 : int result = 0;
375 :
376 : /* get classifier type */
377 : const data_classifier_t *const classifier
378 256 : = data_visible_classifier_get_classifier_const( visible_classifier );
379 : const data_classifier_type_t classifier_type
380 256 : = data_classifier_get_main_type( classifier );
381 :
382 : /* get standard gap size */
383 256 : const double gap = pencil_size_get_standard_object_border( pencil_size );
384 :
385 : /* determine icon space */
386 : const geometry_dimensions_t icon_dim
387 : = has_stereotype_icon
388 0 : ? draw_stereotype_icon_get_dimensions( &((*this_).draw_stereotype_icon),
389 : pencil_size
390 : )
391 256 : : draw_classifier_icon_get_icon_dimensions( &((*this_).draw_classifier_icon),
392 : classifier_type,
393 : pencil_size
394 : );
395 :
396 : /* determine stereotype and name dimensions */
397 : geometry_dimensions_t label_dim;
398 : const bool has_contour
399 256 : = draw_classifier_contour_has_contour( &((*this_).draw_classifier_contour), classifier_type );
400 256 : const double icon_gap
401 256 : = ( ! has_contour ) ? 0.0 : ( geometry_dimensions_get_width( &icon_dim ) < 0.000001 ) ? 0.0 : gap;
402 256 : const double proposed_label_width
403 : = has_contour
404 184 : ? geometry_rectangle_get_width( space_and_label ) - geometry_dimensions_get_width( &icon_dim ) - icon_gap
405 440 : : geometry_rectangle_get_width( space_and_label );
406 512 : const geometry_dimensions_t proposed_label_dim
407 256 : = { .width = proposed_label_width, .height = geometry_rectangle_get_height( space_and_label ) };
408 256 : draw_classifier_label_get_stereotype_and_name_dimensions( &((*this_).draw_classifier_label),
409 : visible_classifier,
410 : ( ! has_stereotype_icon ),
411 : &proposed_label_dim,
412 : pencil_size,
413 : font_layout,
414 : &label_dim
415 256 : );
416 256 : const double text_width = geometry_dimensions_get_width( &label_dim );
417 256 : const double text_height = geometry_dimensions_get_height( &label_dim );
418 256 : if ( text_width > (proposed_label_width + 0.0001) )
419 : {
420 128 : U8_TRACE_INFO_INT_INT( "label does not fit to provided width",
421 : (int) text_width,
422 : (int) proposed_label_width
423 : );
424 128 : result = 1;
425 : }
426 256 : const double proposed_label_height = geometry_rectangle_get_height( space_and_label );
427 256 : if ( text_height > (proposed_label_height + 0.0001) )
428 : {
429 128 : U8_TRACE_INFO_INT_INT( "label does not fit to provided height",
430 : (int) text_height,
431 : (int) proposed_label_height
432 : );
433 128 : result = 1;
434 : }
435 :
436 256 : if ( has_contour )
437 : {
438 184 : double top_border = geometry_rectangle_get_top( space_and_label );
439 :
440 : /* calculate label_compartment */
441 184 : const double min_required_width = text_width + icon_gap + geometry_dimensions_get_width( &icon_dim );
442 184 : const double comp_width = u8_f64_max2( min_required_width, geometry_rectangle_get_width( space_and_label ) );
443 184 : const geometry_h_align_t compartment_h_align = GEOMETRY_H_ALIGN_CENTER;
444 184 : const double comp_left = geometry_h_align_get_left( &compartment_h_align,
445 : comp_width,
446 : geometry_rectangle_get_left( space_and_label ),
447 : geometry_rectangle_get_width( space_and_label )
448 : );
449 184 : geometry_rectangle_reinit( out_label_compartment, comp_left, top_border, comp_width, text_height );
450 :
451 : /* calculate label_box and icon_box */
452 184 : const bool is_package_with_contents = (classifier_type == DATA_CLASSIFIER_TYPE_PACKAGE) && shows_contained_children;
453 184 : if ( is_package_with_contents )
454 : {
455 : /* re-calculate the outer bounds (envelope) to see the diff to top of packages, ignore space_and_label */
456 : const geometry_rectangle_t envelope
457 4 : = draw_classifier_contour_calc_outer_bounds( &((*this_).draw_classifier_contour),
458 : classifier_type,
459 : out_label_compartment,
460 : pencil_size
461 : );
462 4 : double comp_top = geometry_rectangle_get_top( &envelope ) + 2.0 * gap;
463 :
464 : /* calculate label_box */
465 4 : geometry_rectangle_reinit( out_label_box,
466 : comp_left,
467 : comp_top,
468 : text_width,
469 : text_height
470 : );
471 : /* calculate icon_box */
472 4 : geometry_rectangle_reinit( out_icon_box,
473 4 : comp_left + text_width + icon_gap,
474 : comp_top,
475 : geometry_dimensions_get_width( &icon_dim ),
476 : geometry_dimensions_get_height( &icon_dim )
477 : );
478 : }
479 : else
480 : {
481 180 : const geometry_h_align_t text_h_align = GEOMETRY_H_ALIGN_CENTER;
482 360 : const double text_left = geometry_h_align_get_left( &text_h_align,
483 : text_width,
484 : geometry_rectangle_get_left( space_and_label ),
485 180 : geometry_rectangle_get_width( space_and_label ) - icon_gap - geometry_dimensions_get_width( &icon_dim )
486 : );
487 : /* calculate label_box */
488 180 : geometry_rectangle_reinit( out_label_box,
489 : text_left,
490 : top_border,
491 : text_width,
492 : text_height
493 : );
494 : /* calculate icon_box */
495 180 : geometry_rectangle_reinit( out_icon_box,
496 180 : comp_left + comp_width - geometry_dimensions_get_width( &icon_dim ),
497 : top_border,
498 : geometry_dimensions_get_width( &icon_dim ),
499 : geometry_dimensions_get_height( &icon_dim )
500 : );
501 : }
502 : }
503 : else
504 : {
505 : /* calculate text position */
506 72 : const geometry_h_align_t h_align_center = GEOMETRY_H_ALIGN_CENTER;
507 72 : const double text_left = geometry_h_align_get_left( &h_align_center,
508 : text_width,
509 : geometry_rectangle_get_left( space_and_label ),
510 : geometry_rectangle_get_width( space_and_label )
511 : );
512 72 : const double text_top = geometry_rectangle_get_top( space_and_label );
513 :
514 : /* calculate label_compartment */
515 72 : const double comp_width = u8_f64_max2( text_width, geometry_rectangle_get_width( space_and_label ) );
516 72 : const geometry_h_align_t compartment_h_align = GEOMETRY_H_ALIGN_CENTER;
517 72 : const double comp_left = geometry_h_align_get_left( &compartment_h_align,
518 : comp_width,
519 : geometry_rectangle_get_left( space_and_label ),
520 : geometry_rectangle_get_width( space_and_label )
521 : );
522 72 : geometry_rectangle_reinit( out_label_compartment, comp_left, text_top, comp_width, text_height );
523 :
524 : /* calculate label_box */
525 72 : geometry_rectangle_reinit( out_label_box, text_left, text_top, text_width, text_height );
526 : /* calculate icon_box */
527 72 : const double icon_left = geometry_h_align_get_left( &h_align_center,
528 : geometry_dimensions_get_width( &icon_dim ),
529 : geometry_rectangle_get_left( space_and_label ),
530 : geometry_rectangle_get_width( space_and_label )
531 : );
532 72 : geometry_rectangle_reinit( out_icon_box,
533 : icon_left,
534 72 : text_top - gap - geometry_dimensions_get_height( &icon_dim ),
535 : geometry_dimensions_get_width( &icon_dim ),
536 : geometry_dimensions_get_height( &icon_dim )
537 : );
538 : }
539 :
540 256 : U8_TRACE_END_ERR( result );
541 256 : return result;
542 : }
543 :
544 :
545 : /*
546 : Copyright 2016-2025 Andreas Warnke
547 : http://www.apache.org/licenses/LICENSE-2.0
548 :
549 : Licensed under the Apache License, Version 2.0 (the "License");
550 : you may not use this file except in compliance with the License.
551 : You may obtain a copy of the License at
552 :
553 :
554 : Unless required by applicable law or agreed to in writing, software
555 : distributed under the License is distributed on an "AS IS" BASIS,
556 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
557 : See the License for the specific language governing permissions and
558 : limitations under the License.
559 : */
|