LCOV - code coverage report
Current view: top level - pencil/source - pencil_feat_label_layouter.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 0 113 0.0 %
Date: 2025-09-25 21:07:53 Functions: 0 6 0.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 1.16