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.63.2_covts Lines: 0.0 % 113 0
Test Date: 2025-05-01 10:10:14 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            0 :         const double small_gap = 0.000000001;
     211            0 :         const geometry_rectangle_t *const  bounds = layout_feature_get_symbol_box_const ( current_feature );
     212            0 :         const double left = geometry_rectangle_get_left( bounds );
     213            0 :         const double top = geometry_rectangle_get_top( bounds );
     214            0 :         const double bottom = geometry_rectangle_get_bottom( bounds );
     215            0 :         const double right = geometry_rectangle_get_right( bounds );
     216              : 
     217            0 :         assert( solutions_max >= 8 );
     218              :         /* top-left */
     219              :         {
     220              :             geometry_anchor_t anchor_0;
     221              :             geometry_anchor_t anchor_1;
     222              : 
     223            0 :             geometry_anchor_init( &anchor_0,
     224              :                                   left - small_gap,
     225              :                                   top - small_gap,
     226              :                                   GEOMETRY_H_ALIGN_RIGHT,  /* the reference point is the right side of the label */
     227              :                                   GEOMETRY_V_ALIGN_CENTER
     228              :                                 );
     229            0 :             geometry_anchor_init( &anchor_1,
     230              :                                   left - small_gap,
     231              :                                   top - small_gap,
     232              :                                   GEOMETRY_H_ALIGN_CENTER,
     233              :                                   GEOMETRY_V_ALIGN_BOTTOM  /* the reference point is the bottom side of the label */
     234              :                                 );
     235              : 
     236            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     237              :                                                                   &anchor_0,
     238              :                                                                   &preferred_label_dim,
     239              :                                                                   &((*this_).draw_feature_label),
     240              :                                                                   feature_data,
     241              :                                                                   &(out_solutions[0])
     242              :                                                                 );
     243            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     244              :                                                                   &anchor_1,
     245              :                                                                   &preferred_label_dim,
     246              :                                                                   &((*this_).draw_feature_label),
     247              :                                                                   feature_data,
     248              :                                                                   &(out_solutions[1])
     249              :                                                                 );
     250              :         }
     251              : 
     252              :         /* top-right */
     253              :         {
     254              :             geometry_anchor_t anchor_2;
     255              :             geometry_anchor_t anchor_3;
     256              : 
     257            0 :             geometry_anchor_init( &anchor_2,
     258              :                                   right + small_gap,
     259              :                                   top - small_gap,
     260              :                                   GEOMETRY_H_ALIGN_LEFT,  /* the reference point is the left side of the label */
     261              :                                   GEOMETRY_V_ALIGN_CENTER
     262              :                                 );
     263            0 :             geometry_anchor_init( &anchor_3,
     264              :                                   right + small_gap,
     265              :                                   top - small_gap,
     266              :                                   GEOMETRY_H_ALIGN_CENTER,
     267              :                                   GEOMETRY_V_ALIGN_BOTTOM  /* the reference point is the bottom side of the label */
     268              :                                 );
     269              : 
     270            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     271              :                                                                   &anchor_2,
     272              :                                                                   &preferred_label_dim,
     273              :                                                                   &((*this_).draw_feature_label),
     274              :                                                                   feature_data,
     275              :                                                                   &(out_solutions[2])
     276              :                                                                 );
     277            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     278              :                                                                   &anchor_3,
     279              :                                                                   &preferred_label_dim,
     280              :                                                                   &((*this_).draw_feature_label),
     281              :                                                                   feature_data,
     282              :                                                                   &(out_solutions[3])
     283              :                                                                 );
     284              :         }
     285              : 
     286              :         /* bottom-left */
     287              :         {
     288              :             geometry_anchor_t anchor_4;
     289              :             geometry_anchor_t anchor_5;
     290              : 
     291            0 :             geometry_anchor_init( &anchor_4,
     292              :                                   left - small_gap,
     293              :                                   bottom + small_gap,
     294              :                                   GEOMETRY_H_ALIGN_RIGHT,  /* the reference point is the right side of the label */
     295              :                                   GEOMETRY_V_ALIGN_CENTER
     296              :                                 );
     297            0 :             geometry_anchor_init( &anchor_5,
     298              :                                   left - small_gap,
     299              :                                   bottom + small_gap,
     300              :                                   GEOMETRY_H_ALIGN_CENTER,
     301              :                                   GEOMETRY_V_ALIGN_TOP  /* the reference point is the top side of the label */
     302              :                                 );
     303              : 
     304            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     305              :                                                                   &anchor_4,
     306              :                                                                   &preferred_label_dim,
     307              :                                                                   &((*this_).draw_feature_label),
     308              :                                                                   feature_data,
     309              :                                                                   &(out_solutions[4])
     310              :                                                                 );
     311            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     312              :                                                                   &anchor_5,
     313              :                                                                   &preferred_label_dim,
     314              :                                                                   &((*this_).draw_feature_label),
     315              :                                                                   feature_data,
     316              :                                                                   &(out_solutions[5])
     317              :                                                                 );
     318              :         }
     319              : 
     320              :         /* bottom-right */
     321              :         {
     322              :             geometry_anchor_t anchor_6;
     323              :             geometry_anchor_t anchor_7;
     324              : 
     325            0 :             geometry_anchor_init( &anchor_6,
     326              :                                   right + small_gap,
     327              :                                   bottom + small_gap,
     328              :                                   GEOMETRY_H_ALIGN_LEFT,  /* the reference point is the left side of the label */
     329              :                                   GEOMETRY_V_ALIGN_CENTER
     330              :                                 );
     331            0 :             geometry_anchor_init( &anchor_7,
     332              :                                   right + small_gap,
     333              :                                   bottom + small_gap,
     334              :                                   GEOMETRY_H_ALIGN_CENTER,
     335              :                                   GEOMETRY_V_ALIGN_TOP  /* the reference point is the top side of the label */
     336              :                                 );
     337              : 
     338            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     339              :                                                                   &anchor_6,
     340              :                                                                   &preferred_label_dim,
     341              :                                                                   &((*this_).draw_feature_label),
     342              :                                                                   feature_data,
     343              :                                                                   &(out_solutions[6])
     344              :                                                                 );
     345            0 :             pencil_floating_label_layouter_propose_solution_feat( &((*this_).label_floater),
     346              :                                                                   &anchor_7,
     347              :                                                                   &preferred_label_dim,
     348              :                                                                   &((*this_).draw_feature_label),
     349              :                                                                   feature_data,
     350              :                                                                   &(out_solutions[7])
     351              :                                                                 );
     352              :         }
     353              : 
     354            0 :         *out_solutions_count = 8;
     355              :     }
     356              : 
     357            0 :     U8_TRACE_END();
     358            0 : }
     359              : 
     360              : 
     361              : /*
     362              :  * Copyright 2019-2025 Andreas Warnke
     363              :  *
     364              :  * Licensed under the Apache License, Version 2.0 (the "License");
     365              :  * you may not use this file except in compliance with the License.
     366              :  * You may obtain a copy of the License at
     367              :  *
     368              :  *    http://www.apache.org/licenses/LICENSE-2.0
     369              :  *
     370              :  * Unless required by applicable law or agreed to in writing, software
     371              :  * distributed under the License is distributed on an "AS IS" BASIS,
     372              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     373              :  * See the License for the specific language governing permissions and
     374              :  * limitations under the License.
     375              :  */
        

Generated by: LCOV version 2.0-1