LCOV - code coverage report
Current view: top level - pencil/source - pencil_feat_label_layouter.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.71.2_covts Lines: 0.0 % 113 0
Test Date: 2026-08-22 19:47:36 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /* File: pencil_feat_label_layouter.c; Copyright and License: see below */
       2              : 
       3              : #include "pencil_feat_label_layouter.h"
       4              : #include "layout/layout_feature_iter.h"
       5              : #include "u8/u8_trace.h"
       6              : #include "utf8stringbuf/utf8string.h"
       7              : 
       8            0 : void pencil_feat_label_layouter_init( pencil_feat_label_layouter_t *this_,
       9              :                                       layout_visible_set_t *layout_data,
      10              :                                       const data_profile_part_t *profile,
      11              :                                       const pencil_size_t *pencil_size )
      12              : {
      13            0 :     U8_TRACE_BEGIN();
      14            0 :     assert( NULL != layout_data );
      15            0 :     assert( NULL != profile );
      16            0 :     assert( NULL != pencil_size );
      17              : 
      18            0 :     (*this_).layout_data = layout_data;
      19            0 :     (*this_).profile = profile;
      20            0 :     (*this_).pencil_size = pencil_size;
      21            0 :     draw_feature_label_init( &((*this_).draw_feature_label) );
      22            0 :     pencil_floating_label_layouter_init_void( &((*this_).label_floater) );
      23              : 
      24            0 :     U8_TRACE_END();
      25            0 : }
      26              : 
      27            0 : void pencil_feat_label_layouter_reinit( pencil_feat_label_layouter_t *this_,
      28              :                                         layout_visible_set_t *layout_data,
      29              :                                         const data_profile_part_t *profile,
      30              :                                         const pencil_size_t *pencil_size )
      31              : {
      32            0 :     U8_TRACE_BEGIN();
      33            0 :     assert( NULL != layout_data );
      34            0 :     assert( NULL != profile );
      35            0 :     assert( NULL != pencil_size );
      36              : 
      37            0 :     (*this_).layout_data = layout_data;
      38            0 :     (*this_).profile = profile;
      39            0 :     (*this_).pencil_size = pencil_size;
      40            0 :     pencil_floating_label_layouter_init_void( &((*this_).label_floater) );
      41              : 
      42            0 :     U8_TRACE_END();
      43            0 : }
      44              : 
      45            0 : void pencil_feat_label_layouter_destroy( pencil_feat_label_layouter_t *this_ )
      46              : {
      47            0 :     U8_TRACE_BEGIN();
      48              : 
      49            0 :     pencil_floating_label_layouter_destroy ( &((*this_).label_floater) );
      50            0 :     draw_feature_label_destroy( &((*this_).draw_feature_label) );
      51              : 
      52            0 :     U8_TRACE_END();
      53            0 : }
      54              : 
      55            0 : void pencil_feat_label_layouter_do_layout ( pencil_feat_label_layouter_t *this_, PangoLayout *font_layout )
      56              : {
      57            0 :     U8_TRACE_BEGIN();
      58              :     assert ( (unsigned int) UNIVERSAL_ARRAY_INDEX_SORTER_MAX_ARRAY_SIZE >= (unsigned int) LAYOUT_VISIBLE_SET_MAX_FEATURES );
      59            0 :     assert( NULL != font_layout );
      60              : 
      61            0 :     pencil_floating_label_layouter_reinit( &((*this_).label_floater),
      62              :                                            (*this_).layout_data,
      63              :                                            (*this_).profile,
      64              :                                            (*this_).pencil_size,
      65              :                                            font_layout
      66              :                                          );
      67              : 
      68              :     universal_array_index_sorter_t sorted;
      69            0 :     universal_array_index_sorter_init( &sorted );
      70              : 
      71              :     /* sort the features by their label-box layouting needs, drop invisible relations */
      72            0 :     pencil_feat_label_layouter_private_propose_processing_order ( this_, &sorted );
      73              : 
      74              :     /* layout the features label-boxes */
      75              :     layout_feature_iter_t feature_iterator;
      76            0 :     layout_feature_iter_init( &feature_iterator, (*this_).layout_data, &sorted );
      77            0 :     while ( layout_feature_iter_has_next( &feature_iterator ) )
      78              :     {
      79              :         /* determine pointer to feature */
      80            0 :         layout_feature_t *const current_feature = layout_feature_iter_next_ptr( &feature_iterator );
      81            0 :         geometry_point_t feature_middle = layout_feature_get_symbol_middle ( current_feature );
      82              : 
      83              :         /* declaration of list of options */
      84            0 :         uint32_t solutions_count = 0;
      85              :         static const uint32_t SOLUTIONS_MAX = 8;
      86              :         geometry_rectangle_t solution[8];
      87              : 
      88              :         /* propose options */
      89            0 :         pencil_feat_label_layouter_private_propose_solutions( this_,
      90              :                                                               current_feature,
      91              :                                                               font_layout,
      92              :                                                               SOLUTIONS_MAX,
      93              :                                                               solution,
      94              :                                                               &solutions_count
      95              :                                                             );
      96              : 
      97              :         /* select best option */
      98              :         uint32_t index_of_best;
      99            0 :         if ( 1 == solutions_count )
     100              :         {
     101            0 :             index_of_best = 0;
     102              :         }
     103              :         else
     104              :         {
     105            0 :             pencil_floating_label_layouter_select_solution( &((*this_).label_floater),
     106              :                                                             feature_middle,
     107              :                                                             solutions_count,
     108              :                                                             solution,
     109              :                                                             &index_of_best
     110              :                                                           );
     111              :         }
     112              : 
     113              :         /* store best option to (*this_).layout_data */
     114            0 :         layout_feature_set_label_box( current_feature, &(solution[index_of_best]) );
     115              :     }
     116              : 
     117            0 :     layout_feature_iter_destroy( &feature_iterator );
     118            0 :     universal_array_index_sorter_destroy( &sorted );
     119              : 
     120            0 :     pencil_floating_label_layouter_reinit_void( &((*this_).label_floater) );
     121              : 
     122            0 :     U8_TRACE_END();
     123            0 : }
     124              : 
     125            0 : void pencil_feat_label_layouter_private_propose_processing_order ( pencil_feat_label_layouter_t *this_, universal_array_index_sorter_t *out_sorted )
     126              : {
     127            0 :     U8_TRACE_BEGIN();
     128            0 :     assert( NULL != out_sorted );
     129              : 
     130              :     /* sort the features by their label-box: the less simple, the earlier it shall be processed */
     131              :     const uint32_t count_features
     132            0 :         = layout_visible_set_get_feature_count( (*this_).layout_data );
     133            0 :     for ( uint32_t index = 0; index < count_features; index ++ )
     134              :     {
     135              :         const layout_feature_t *const current_feature
     136            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, index );
     137            0 :         const data_feature_t *const feature_data = layout_feature_get_data_const( current_feature );
     138            0 :         assert( NULL != feature_data );
     139            0 :         const data_feature_type_t current_type = data_feature_get_main_type( feature_data );
     140              : 
     141            0 :         int64_t simpleness = 0;
     142              : 
     143              :         /* determine simpleness by length of label */
     144            0 :         simpleness -= utf8string_get_length( data_feature_get_key_const( feature_data ) );
     145            0 :         simpleness -= utf8string_get_length( data_feature_get_value_const( feature_data ) );
     146              : 
     147              :         /* do the properties and operations first, they have a fixed positiion given by the classifier */
     148            0 :         if ( ! data_feature_type_outside_compartment( current_type ) )
     149              :         {
     150            0 :             simpleness = -100000;
     151              :         }
     152              : 
     153              :         /* insert relation to sorted array - except for lifelines which have no label */
     154            0 :         if ( DATA_FEATURE_TYPE_LIFELINE != current_type )
     155              :         {
     156              :             const int insert_error
     157            0 :                 = universal_array_index_sorter_insert( out_sorted, index, simpleness );
     158            0 :             if ( 0 != insert_error )
     159              :             {
     160            0 :                 U8_LOG_WARNING( "not all relationship label-boxes are layouted" );
     161              :             }
     162              :         }
     163              :     }
     164              : 
     165            0 :     U8_TRACE_END();
     166            0 : }
     167              : 
     168            0 : void pencil_feat_label_layouter_private_propose_solutions ( pencil_feat_label_layouter_t *this_,
     169              :                                                             layout_feature_t *current_feature,
     170              :                                                             PangoLayout *font_layout,
     171              :                                                             uint32_t solutions_max,
     172              :                                                             geometry_rectangle_t out_solutions[],
     173              :                                                             uint32_t *out_solutions_count )
     174              : {
     175            0 :     U8_TRACE_BEGIN();
     176            0 :     assert( NULL != current_feature );
     177            0 :     assert( NULL != font_layout );
     178            0 :     assert( NULL != out_solutions );
     179            0 :     assert( NULL != out_solutions_count );
     180              : 
     181            0 :     const data_feature_t *feature_data = layout_feature_get_data_const ( current_feature );
     182            0 :     assert( NULL != feature_data );
     183            0 :     const data_feature_type_t current_type = data_feature_get_main_type( feature_data );
     184              : 
     185            0 :     if ( data_feature_type_inside_compartment( current_type ) )
     186              :     {
     187              :         /* the label-box is already calculated by pencil_feature_layouter_do_layout() */
     188              :         /* which is called before pencil_feat_label_layouter_do_layout() */
     189            0 :         assert( solutions_max >= 1 );
     190            0 :         geometry_rectangle_copy( &(out_solutions[0]), layout_feature_get_label_box_const ( current_feature ) );
     191            0 :         *out_solutions_count = 1;
     192              :     }
     193              :     else
     194              :     {
     195              :         /* key and value dimensions */
     196            0 :         const geometry_dimensions_t label_dim_proposal = {
     197            0 :             .width = 25.0 * pencil_size_get_standard_font_size( (*this_).pencil_size ),
     198            0 :             .height = pencil_size_get_standard_font_size( (*this_).pencil_size )
     199              :         };
     200              :         geometry_dimensions_t preferred_label_dim;
     201            0 :         draw_feature_label_get_key_and_value_dimensions( &((*this_).draw_feature_label),
     202              :                                                          feature_data,
     203              :                                                          (*this_).profile,
     204              :                                                          &label_dim_proposal,
     205              :                                                          (*this_).pencil_size,
     206              :                                                          font_layout,
     207              :                                                          &preferred_label_dim
     208              :                                                        );
     209              : 
     210              :         /* get layout data */
     211            0 :         const double border_gap = pencil_size_get_standard_object_border( (*this_).pencil_size );
     212            0 :         const geometry_rectangle_t *const  bounds = layout_feature_get_symbol_box_const ( current_feature );
     213            0 :         const double left = geometry_rectangle_get_left( bounds );
     214            0 :         const double top = geometry_rectangle_get_top( bounds );
     215            0 :         const double bottom = geometry_rectangle_get_bottom( bounds );
     216            0 :         const double right = geometry_rectangle_get_right( bounds );
     217              : 
     218            0 :         assert( solutions_max >= 8 );
     219              :         /* top-left */
     220              :         {
     221              :             geometry_anchor_t anchor_0;
     222              :             geometry_anchor_t anchor_1;
     223              : 
     224            0 :             geometry_anchor_init( &anchor_0,
     225              :                                   left - border_gap,
     226              :                                   top - border_gap,
     227              :                                   GEOMETRY_H_ALIGN_RIGHT,  /* the reference point is the right side of the label */
     228              :                                   GEOMETRY_V_ALIGN_CENTER
     229              :                                 );
     230            0 :             geometry_anchor_init( &anchor_1,
     231              :                                   left - border_gap,
     232              :                                   top - border_gap,
     233              :                                   GEOMETRY_H_ALIGN_CENTER,
     234              :                                   GEOMETRY_V_ALIGN_BOTTOM  /* the reference point is the bottom side of the label */
     235              :                                 );
     236              : 
     237            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     238              :                                                                   &anchor_0,
     239              :                                                                   &preferred_label_dim,
     240              :                                                                   &((*this_).draw_feature_label),
     241              :                                                                   feature_data,
     242              :                                                                   &(out_solutions[0])
     243              :                                                                 );
     244            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     245              :                                                                   &anchor_1,
     246              :                                                                   &preferred_label_dim,
     247              :                                                                   &((*this_).draw_feature_label),
     248              :                                                                   feature_data,
     249              :                                                                   &(out_solutions[1])
     250              :                                                                 );
     251              :         }
     252              : 
     253              :         /* top-right */
     254              :         {
     255              :             geometry_anchor_t anchor_2;
     256              :             geometry_anchor_t anchor_3;
     257              : 
     258            0 :             geometry_anchor_init( &anchor_2,
     259              :                                   right + border_gap,
     260              :                                   top - border_gap,
     261              :                                   GEOMETRY_H_ALIGN_LEFT,  /* the reference point is the left side of the label */
     262              :                                   GEOMETRY_V_ALIGN_CENTER
     263              :                                 );
     264            0 :             geometry_anchor_init( &anchor_3,
     265              :                                   right + border_gap,
     266              :                                   top - border_gap,
     267              :                                   GEOMETRY_H_ALIGN_CENTER,
     268              :                                   GEOMETRY_V_ALIGN_BOTTOM  /* the reference point is the bottom side of the label */
     269              :                                 );
     270              : 
     271            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     272              :                                                                   &anchor_2,
     273              :                                                                   &preferred_label_dim,
     274              :                                                                   &((*this_).draw_feature_label),
     275              :                                                                   feature_data,
     276              :                                                                   &(out_solutions[2])
     277              :                                                                 );
     278            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     279              :                                                                   &anchor_3,
     280              :                                                                   &preferred_label_dim,
     281              :                                                                   &((*this_).draw_feature_label),
     282              :                                                                   feature_data,
     283              :                                                                   &(out_solutions[3])
     284              :                                                                 );
     285              :         }
     286              : 
     287              :         /* bottom-left */
     288              :         {
     289              :             geometry_anchor_t anchor_4;
     290              :             geometry_anchor_t anchor_5;
     291              : 
     292            0 :             geometry_anchor_init( &anchor_4,
     293              :                                   left - border_gap,
     294              :                                   bottom + border_gap,
     295              :                                   GEOMETRY_H_ALIGN_RIGHT,  /* the reference point is the right side of the label */
     296              :                                   GEOMETRY_V_ALIGN_CENTER
     297              :                                 );
     298            0 :             geometry_anchor_init( &anchor_5,
     299              :                                   left - border_gap,
     300              :                                   bottom + border_gap,
     301              :                                   GEOMETRY_H_ALIGN_CENTER,
     302              :                                   GEOMETRY_V_ALIGN_TOP  /* the reference point is the top side of the label */
     303              :                                 );
     304              : 
     305            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     306              :                                                                   &anchor_4,
     307              :                                                                   &preferred_label_dim,
     308              :                                                                   &((*this_).draw_feature_label),
     309              :                                                                   feature_data,
     310              :                                                                   &(out_solutions[4])
     311              :                                                                 );
     312            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     313              :                                                                   &anchor_5,
     314              :                                                                   &preferred_label_dim,
     315              :                                                                   &((*this_).draw_feature_label),
     316              :                                                                   feature_data,
     317              :                                                                   &(out_solutions[5])
     318              :                                                                 );
     319              :         }
     320              : 
     321              :         /* bottom-right */
     322              :         {
     323              :             geometry_anchor_t anchor_6;
     324              :             geometry_anchor_t anchor_7;
     325              : 
     326            0 :             geometry_anchor_init( &anchor_6,
     327              :                                   right + border_gap,
     328              :                                   bottom + border_gap,
     329              :                                   GEOMETRY_H_ALIGN_LEFT,  /* the reference point is the left side of the label */
     330              :                                   GEOMETRY_V_ALIGN_CENTER
     331              :                                 );
     332            0 :             geometry_anchor_init( &anchor_7,
     333              :                                   right + border_gap,
     334              :                                   bottom + border_gap,
     335              :                                   GEOMETRY_H_ALIGN_CENTER,
     336              :                                   GEOMETRY_V_ALIGN_TOP  /* the reference point is the top side of the label */
     337              :                                 );
     338              : 
     339            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     340              :                                                                   &anchor_6,
     341              :                                                                   &preferred_label_dim,
     342              :                                                                   &((*this_).draw_feature_label),
     343              :                                                                   feature_data,
     344              :                                                                   &(out_solutions[6])
     345              :                                                                 );
     346            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     347              :                                                                   &anchor_7,
     348              :                                                                   &preferred_label_dim,
     349              :                                                                   &((*this_).draw_feature_label),
     350              :                                                                   feature_data,
     351              :                                                                   &(out_solutions[7])
     352              :                                                                 );
     353              :         }
     354              : 
     355            0 :         *out_solutions_count = 8;
     356              :     }
     357              : 
     358            0 :     U8_TRACE_END();
     359            0 : }
     360              : 
     361              : 
     362              : /*
     363              :  * Copyright 2019-2026 Andreas Warnke
     364              :  *
     365              :  * Licensed under the Apache License, Version 2.0 (the "License");
     366              :  * you may not use this file except in compliance with the License.
     367              :  * You may obtain a copy of the License at
     368              :  *
     369              :  *    http://www.apache.org/licenses/LICENSE-2.0
     370              :  *
     371              :  * Unless required by applicable law or agreed to in writing, software
     372              :  * distributed under the License is distributed on an "AS IS" BASIS,
     373              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     374              :  * See the License for the specific language governing permissions and
     375              :  * limitations under the License.
     376              :  */
        

Generated by: LCOV version 2.0-1