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

            Line data    Source code
       1              : /* File: pencil_feature_layouter.c; Copyright and License: see below */
       2              : 
       3              : #include "pencil_feature_layouter.h"
       4              : #include "u8/u8_f64.h"
       5              : #include "u8/u8_trace.h"
       6              : #include <pango/pangocairo.h>
       7              : #include <stdio.h>
       8              : #include <stdlib.h>
       9              : #include <math.h>
      10              : 
      11            0 : void pencil_feature_layouter_init( pencil_feature_layouter_t *this_,
      12              :                                    layout_visible_set_t *layout_data,
      13              :                                    const data_profile_part_t *profile,
      14              :                                    const pencil_size_t *pencil_size )
      15              : {
      16            0 :     U8_TRACE_BEGIN();
      17            0 :     assert( NULL != layout_data );
      18            0 :     assert( NULL != profile );
      19            0 :     assert( NULL != pencil_size );
      20              : 
      21            0 :     (*this_).layout_data = layout_data;
      22            0 :     (*this_).profile = profile;
      23            0 :     (*this_).pencil_size = pencil_size;
      24            0 :     data_guidelines_init( &((*this_).guidelines) );
      25            0 :     (*this_).label_dimensions_initialized = false;
      26            0 :     draw_feature_label_init( &((*this_).draw_feature_label) );
      27              : 
      28            0 :     U8_TRACE_END();
      29            0 : }
      30              : 
      31            0 : void pencil_feature_layouter_reset( pencil_feature_layouter_t *this_ )
      32              : {
      33            0 :     U8_TRACE_BEGIN();
      34              : 
      35            0 :     (*this_).label_dimensions_initialized = false;
      36              : 
      37            0 :     U8_TRACE_END();
      38            0 : }
      39              : 
      40            0 : void pencil_feature_layouter_destroy( pencil_feature_layouter_t *this_ )
      41              : {
      42            0 :     U8_TRACE_BEGIN();
      43              : 
      44            0 :     draw_feature_label_destroy( &((*this_).draw_feature_label) );
      45            0 :     data_guidelines_destroy( &((*this_).guidelines) );
      46            0 :     (*this_).label_dimensions_initialized = false;
      47              : 
      48            0 :     U8_TRACE_END();
      49            0 : }
      50              : 
      51            0 : void pencil_feature_layouter_do_layout ( pencil_feature_layouter_t *this_, PangoLayout *font_layout )
      52              : {
      53            0 :     U8_TRACE_BEGIN();
      54              :     assert( (unsigned int) UNIVERSAL_ARRAY_INDEX_SORTER_MAX_ARRAY_SIZE >= (unsigned int) LAYOUT_VISIBLE_SET_MAX_FEATURES );
      55              : 
      56              :     /* establish precondition: precalculate the dimensions of labels */
      57            0 :     if ( ! (*this_).label_dimensions_initialized )
      58              :     {
      59            0 :         pencil_feature_layouter_private_init_label_dimensions( this_, font_layout );
      60              :     }
      61              :     /* get diagram draw area */
      62              :     const layout_diagram_t *const diagram_layout
      63            0 :         = layout_visible_set_get_diagram_ptr( (*this_).layout_data );
      64              :     const geometry_rectangle_t *const diagram_draw_area
      65            0 :         = layout_diagram_get_draw_area_const( diagram_layout );
      66              :     const data_diagram_t *const diagram_data
      67            0 :         = layout_diagram_get_data_const ( diagram_layout );
      68              :     const data_diagram_type_t diag_type
      69            0 :         = data_diagram_get_diagram_type ( diagram_data );
      70              : 
      71              :     /* layout the unsorted features */
      72              :     const uint32_t count_features
      73            0 :         = layout_visible_set_get_feature_count ( (*this_).layout_data );
      74            0 :     for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
      75              :     {
      76              :         layout_feature_t *const feature_layout
      77            0 :             = layout_visible_set_get_feature_ptr ( (*this_).layout_data, f_idx );
      78              :         const data_feature_t *const the_feature
      79            0 :             = layout_feature_get_data_const ( feature_layout );
      80              :         const layout_visible_classifier_t *const layout_classifier
      81            0 :             = layout_feature_get_classifier_const ( feature_layout );
      82              :         const data_classifier_t *const classifier
      83            0 :             = layout_visible_classifier_get_classifier_const( layout_classifier );
      84              :         const data_classifier_type_t classifier_type
      85            0 :             = data_classifier_get_main_type( classifier );
      86              : 
      87              :         const geometry_rectangle_t *const c_symbol_box
      88            0 :             = layout_visible_classifier_get_symbol_box_const ( layout_classifier );
      89              :         const geometry_rectangle_t *const c_envelope_box
      90            0 :             = layout_visible_classifier_get_envelope_box_const ( layout_classifier );
      91            0 :         switch ( data_feature_get_main_type (the_feature) )
      92              :         {
      93            0 :             case DATA_FEATURE_TYPE_LIFELINE:
      94              :             {
      95              :                 /* layout lifeline feature next to parent classifier */
      96            0 :                 pencil_feature_layouter_private_layout_lifeline ( this_,
      97              :                                                                   diagram_draw_area,
      98              :                                                                   diag_type,
      99              :                                                                   classifier_type,
     100              :                                                                   c_symbol_box,
     101              :                                                                   c_envelope_box,
     102              :                                                                   feature_layout
     103              :                                                                 );
     104              :             }
     105            0 :             break;
     106              : 
     107            0 :             case DATA_FEATURE_TYPE_PORT:  /* or */
     108              :             case DATA_FEATURE_TYPE_IN_PORT_PIN:  /* or */
     109              :             case DATA_FEATURE_TYPE_OUT_PORT_PIN:  /* or */
     110              :             case DATA_FEATURE_TYPE_ENTRY:  /* or */
     111              :             case DATA_FEATURE_TYPE_EXIT:
     112              :             {
     113              :                 /* layout port feature onto parent classifier box */
     114            0 :                 pencil_feature_layouter_private_layout_port_pin ( this_,
     115              :                                                                   classifier_type,
     116              :                                                                   c_symbol_box,
     117              :                                                                   the_feature,
     118              :                                                                   font_layout,
     119              :                                                                   feature_layout
     120              :                                                                 );
     121              :             }
     122            0 :             break;
     123              : 
     124            0 :             case DATA_FEATURE_TYPE_PROVIDED_INTERFACE:  /* or */
     125              :             case DATA_FEATURE_TYPE_REQUIRED_INTERFACE:
     126              :             {
     127              :                 /* layout interface feature close to parent classifier */
     128            0 :                 pencil_feature_layouter_private_layout_interface ( this_,
     129              :                                                                    c_symbol_box,
     130              :                                                                    the_feature,
     131              :                                                                    font_layout,
     132              :                                                                    feature_layout
     133              :                                                                  );
     134              :             }
     135            0 :             break;
     136              : 
     137            0 :             case DATA_FEATURE_TYPE_PROPERTY:  /* or */
     138              :             case DATA_FEATURE_TYPE_OPERATION:  /* or */
     139              :             case DATA_FEATURE_TYPE_TAGGED_VALUE:
     140              :             {
     141              :                 /* layout property or operation feature within the feature compartments, also the tagged values */
     142              :                 const geometry_rectangle_t *const c_compartments
     143            0 :                     = layout_visible_classifier_get_compartments_const ( layout_classifier );
     144            0 :                 pencil_feature_layouter_private_layout_compartment ( this_,
     145              :                                                                      c_compartments,
     146              :                                                                      font_layout,
     147              :                                                                      feature_layout
     148              :                                                                    );
     149              :             }
     150            0 :             break;
     151              : 
     152            0 :             default:
     153              :             {
     154            0 :                 U8_LOG_ANOMALY("unknown feature type in pencil_feature_layouter_do_layout");
     155              :                 /* this may happen if a new database file has been read by an old program version */
     156              :                 /* layout like property or operation or tagged values */
     157              :                 const geometry_rectangle_t *const c_compartments
     158            0 :                     = layout_visible_classifier_get_compartments_const ( layout_classifier );
     159            0 :                 pencil_feature_layouter_private_layout_compartment ( this_,
     160              :                                                                      c_compartments,
     161              :                                                                      font_layout,
     162              :                                                                      feature_layout
     163              :                                                                    );
     164              :             }
     165            0 :             break;
     166              :         }
     167              :     }
     168              : 
     169            0 :     U8_TRACE_END();
     170            0 : }
     171              : 
     172            0 : void pencil_feature_layouter_calculate_features_dimensions( pencil_feature_layouter_t *this_,
     173              :                                                             data_row_t diagramelement_id,
     174              :                                                             PangoLayout *font_layout,
     175              :                                                             geometry_compartments_t *out_features_dim )
     176              : {
     177            0 :     U8_TRACE_BEGIN();
     178            0 :     assert( NULL != font_layout );
     179            0 :     assert( NULL != out_features_dim );
     180              : 
     181              :     /* establish precondition: precalculate the dimensions of labels */
     182            0 :     if ( ! (*this_).label_dimensions_initialized )
     183              :     {
     184            0 :         pencil_feature_layouter_private_init_label_dimensions( this_, font_layout );
     185              :     }
     186              : 
     187              :     /* init result */
     188            0 :     const double obj_border = pencil_size_get_standard_object_border( (*this_).pencil_size );
     189            0 :     const double gap = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
     190            0 :     geometry_compartments_reinit( out_features_dim, obj_border, gap );
     191              : 
     192              :     /* search all contained features */
     193              :     const uint32_t count_features
     194            0 :         = layout_visible_set_get_feature_count( (*this_).layout_data );
     195            0 :     for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
     196              :     {
     197              :         const layout_feature_t *const feature_layout
     198            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, f_idx );
     199              :         const data_feature_t *const the_feature
     200            0 :             = layout_feature_get_data_const( feature_layout );
     201              :         const layout_visible_classifier_t *const layout_classifier
     202            0 :             = layout_feature_get_classifier_const( feature_layout );
     203            0 :         const data_feature_type_t the_feature_type = data_feature_get_main_type( the_feature );
     204            0 :         const uint32_t list_order = data_feature_get_list_order( the_feature );
     205              : 
     206            0 :         if ( diagramelement_id == layout_visible_classifier_get_diagramelement_id( layout_classifier ) )
     207              :         {
     208              :             const geometry_compartment_type_t compartment
     209            0 :                 = geometry_compartment_type_new( the_feature_type, list_order );
     210              : 
     211            0 :             if ( data_feature_type_inside_compartment( the_feature_type ) )
     212              :             {
     213              :                 /* feature label sizes are already precalculated */
     214            0 :                 assert( (*this_).label_dimensions_initialized );
     215            0 :                 const geometry_rectangle_t *const label_box = layout_feature_get_label_box_const( feature_layout );
     216            0 :                 const geometry_dimensions_t label_dim = geometry_rectangle_get_dimensions( label_box );
     217              : 
     218              :                 /* update compartment dimensions */
     219            0 :                 geometry_compartments_add_feature( out_features_dim,
     220              :                                                    compartment,
     221              :                                                    &label_dim
     222              :                                                  );
     223              :             }
     224              :             else
     225              :             {
     226              :                 /* interface and port icon sizes are based on the standard_font_size: */
     227            0 :                 const double symbol_size = pencil_size_get_standard_font_size( (*this_).pencil_size );
     228            0 :                 const geometry_dimensions_t symbol_dim = geometry_dimensions_new( symbol_size, symbol_size );
     229              : 
     230              :                 /* update compartment dimensions */
     231            0 :                 geometry_compartments_add_feature( out_features_dim,
     232              :                                                    compartment,
     233              :                                                    &symbol_dim
     234              :                                                  );
     235              :             }
     236              :         }
     237              :     }
     238              : 
     239            0 :     U8_TRACE_END();
     240            0 : }
     241              : 
     242            0 : void pencil_feature_layouter_private_init_label_dimensions( pencil_feature_layouter_t *this_,
     243              :                                                             PangoLayout *font_layout
     244              :                                                           )
     245              : {
     246            0 :     U8_TRACE_BEGIN();
     247            0 :     assert ( NULL != font_layout );
     248              : 
     249              :     const uint32_t count_features
     250            0 :         = layout_visible_set_get_feature_count( (*this_).layout_data );
     251            0 :     for ( uint32_t f_idx = 0; f_idx < count_features; f_idx ++ )
     252              :     {
     253              :         layout_feature_t *const feature_layout
     254            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, f_idx );
     255              :         const data_feature_t *const the_feature
     256            0 :             = layout_feature_get_data_const( feature_layout );
     257            0 :         const data_feature_type_t the_feature_type = data_feature_get_main_type( the_feature );
     258              : 
     259            0 :         if ( data_feature_type_inside_compartment( the_feature_type ) )
     260              :         {
     261              :             geometry_dimensions_t min_feature_bounds;
     262            0 :             geometry_dimensions_init_empty( &min_feature_bounds );
     263            0 :             pencil_feature_layouter_private_get_minimum_bounds( this_,
     264              :                                                                 the_feature,
     265              :                                                                 (*this_).profile,
     266              :                                                                 (*this_).pencil_size,
     267              :                                                                 font_layout,
     268              :                                                                 &min_feature_bounds
     269              :                                                               );
     270              : 
     271            0 :             const geometry_rectangle_t label_box = {
     272              :                 .left = 0.0,
     273              :                 .top = 0.0,
     274            0 :                 .width = geometry_dimensions_get_width( &min_feature_bounds ),
     275            0 :                 .height = geometry_dimensions_get_height( &min_feature_bounds ),
     276              :             };
     277            0 :             layout_feature_set_label_box( feature_layout, &label_box );
     278            0 :             geometry_dimensions_destroy( &min_feature_bounds );
     279              :         }
     280              :     }
     281              : 
     282            0 :     (*this_).label_dimensions_initialized = true;
     283            0 :     U8_TRACE_END();
     284            0 : }
     285              : 
     286            0 : void pencil_feature_layouter_private_layout_lifeline ( pencil_feature_layouter_t *this_,
     287              :                                                        const geometry_rectangle_t *diagram_space,
     288              :                                                        data_diagram_type_t diagram_type,
     289              :                                                        data_classifier_type_t classifier_type,
     290              :                                                        const geometry_rectangle_t *classifier_symbol_box,
     291              :                                                        const geometry_rectangle_t *classifier_envelope_box,
     292              :                                                        layout_feature_t *out_feature_layout )
     293              : {
     294            0 :     U8_TRACE_BEGIN();
     295            0 :     assert ( NULL != diagram_space );
     296            0 :     assert ( NULL != classifier_symbol_box );
     297            0 :     assert ( NULL != classifier_envelope_box );
     298            0 :     assert ( NULL != out_feature_layout );
     299              : 
     300              :     /* get preferred object distance */
     301              :     const double obj_dist
     302            0 :         = pencil_size_get_preferred_object_distance( (*this_).pencil_size );
     303            0 :     const double feature_width = obj_dist;
     304              : 
     305              :     const bool lifeline_has_semantics
     306            0 :         = data_guidelines_classifier_has_scenario_semantics( &((*this_).guidelines),
     307              :                                                              diagram_type,
     308              :                                                              classifier_type
     309              :                                                            );
     310              : 
     311            0 :     if (( DATA_DIAGRAM_TYPE_UML_TIMING_DIAGRAM == diagram_type ) && lifeline_has_semantics )
     312            0 :     {
     313            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_RIGHT );
     314            0 :         const double c_right = geometry_rectangle_get_right( classifier_envelope_box );
     315            0 :         const double c_top = geometry_rectangle_get_top( classifier_envelope_box );
     316            0 :         const double c_height = geometry_rectangle_get_height( classifier_envelope_box );
     317            0 :         const double dda_right = geometry_rectangle_get_right ( diagram_space );
     318              :         geometry_rectangle_t lifeline_bounds;
     319            0 :         geometry_rectangle_init ( &lifeline_bounds,
     320              :                                   c_right,
     321            0 :                                   c_top + ( 0.5 * ( c_height - feature_width ) ),
     322            0 :                                   dda_right - c_right - obj_dist,
     323              :                                   feature_width
     324              :                                 );
     325            0 :         layout_feature_set_symbol_box ( out_feature_layout, &lifeline_bounds );
     326            0 :         layout_feature_set_label_box ( out_feature_layout, &lifeline_bounds );
     327              :     }
     328            0 :     else if (( DATA_DIAGRAM_TYPE_UML_SEQUENCE_DIAGRAM == diagram_type ) && lifeline_has_semantics )
     329            0 :     {
     330            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_DOWN );
     331            0 :         const double c_bottom = geometry_rectangle_get_bottom( classifier_envelope_box );
     332            0 :         const double c_left = geometry_rectangle_get_left( classifier_envelope_box );
     333            0 :         const double c_width = geometry_rectangle_get_width( classifier_envelope_box );
     334            0 :         const double dda_bottom = geometry_rectangle_get_bottom ( diagram_space );
     335              :         geometry_rectangle_t lifeline_bounds;
     336            0 :         geometry_rectangle_init ( &lifeline_bounds,
     337            0 :                                   c_left + ( 0.5 * ( c_width - feature_width ) ),
     338              :                                   c_bottom,
     339              :                                   feature_width,
     340            0 :                                   dda_bottom - c_bottom - obj_dist
     341              :                                 );
     342            0 :         layout_feature_set_symbol_box ( out_feature_layout, &lifeline_bounds );
     343            0 :         layout_feature_set_label_box ( out_feature_layout, &lifeline_bounds );
     344              :     }
     345              :     else /*if (( DATA_DIAGRAM_TYPE_UML_COMMUNICATION_DIAGRAM == diagram_type )||( DATA_DIAGRAM_TYPE_INTERACTION_OVERVIEW_DIAGRAM == diagram_type ))*/
     346              :     {
     347            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_CENTER );
     348            0 :         layout_feature_set_symbol_box ( out_feature_layout, classifier_symbol_box );
     349            0 :         layout_feature_set_label_box ( out_feature_layout, classifier_symbol_box );
     350              :     }
     351              : 
     352            0 :     U8_TRACE_END();
     353            0 : }
     354              : 
     355            0 : void pencil_feature_layouter_private_layout_port_pin ( pencil_feature_layouter_t *this_,
     356              :                                                        data_classifier_type_t classifier_type,
     357              :                                                        const geometry_rectangle_t *classifier_symbol_box,
     358              :                                                        const data_feature_t *the_feature,
     359              :                                                        PangoLayout *font_layout,
     360              :                                                        layout_feature_t *out_feature_layout )
     361              : {
     362            0 :     U8_TRACE_BEGIN();
     363            0 :     assert ( NULL != classifier_symbol_box );
     364            0 :     assert ( NULL != the_feature );
     365            0 :     assert ( NULL != font_layout );
     366            0 :     assert ( NULL != out_feature_layout );
     367              : 
     368              :     /* get preferred object distance */
     369              :     const double gap
     370            0 :         = pencil_size_get_standard_object_border( (*this_).pencil_size );
     371              : 
     372              :     const double port_icon_size
     373            0 :         = pencil_size_get_standard_font_size( (*this_).pencil_size );
     374              : 
     375              :     /* determine the coordinates of the box-line */
     376              :     geometry_rectangle_t classifier_box;
     377            0 :     geometry_rectangle_copy( &classifier_box, classifier_symbol_box );
     378            0 :     geometry_rectangle_shift( &classifier_box, gap, gap );
     379            0 :     geometry_rectangle_enlarge( &classifier_box, -2.0*gap, -2.0*gap );
     380              : 
     381              :     const int32_t list_order
     382            0 :         = data_feature_get_list_order( the_feature );
     383              : 
     384              :     /* position the port icon */
     385            0 :     const bool is_sysml_constraint_block = (classifier_type == DATA_CLASSIFIER_TYPE_CONSTRAINT_BLOCK);
     386            0 :     const bool is_behavioral = data_classifier_type_is_behavioral( classifier_type );
     387            0 :     const data_feature_type_t feat_type = data_feature_get_main_type( the_feature );
     388            0 :     const bool is_state_entry_exit
     389            0 :         = (( feat_type == DATA_FEATURE_TYPE_ENTRY )||( feat_type == DATA_FEATURE_TYPE_EXIT ));
     390            0 :     const double outwards_distance
     391            0 :         = is_sysml_constraint_block ? 0.0 : (is_behavioral&&(!is_state_entry_exit)) ? port_icon_size : (0.5*port_icon_size);
     392              :     double port_icon_left;
     393              :     double port_icon_top;
     394            0 :     const double show_arrow_in = ( feat_type == DATA_FEATURE_TYPE_IN_PORT_PIN );
     395            0 :     const double show_arrow_out = ( feat_type == DATA_FEATURE_TYPE_OUT_PORT_PIN );
     396            0 :     geometry_direction_t arrow_dir = GEOMETRY_DIRECTION_CENTER;
     397            0 :     if ( list_order < 0 )
     398              :     {
     399              :         static const int32_t INT32_MIN_HALF = INT32_MIN/2;
     400            0 :         if ( list_order < INT32_MIN_HALF )  /* SHOW ON RIGHT BORDER */
     401              :         {
     402            0 :             const double y_pos_rel
     403            0 :                 = (list_order - INT32_MIN_HALF) / ((double)(INT32_MIN_HALF));
     404            0 :             port_icon_left = geometry_rectangle_get_right( &classifier_box ) - port_icon_size + outwards_distance;
     405            0 :             port_icon_top = geometry_rectangle_get_top( &classifier_box ) + y_pos_rel * ( geometry_rectangle_get_height( &classifier_box ) - port_icon_size );
     406            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_LEFT : show_arrow_out ? GEOMETRY_DIRECTION_RIGHT : GEOMETRY_DIRECTION_CENTER;
     407              :         }
     408              :         else  /* SHOW ON TOP BORDER */
     409              :         {
     410            0 :             const double x_pos_rel
     411            0 :                 = (list_order) / ((double)(INT32_MIN_HALF));
     412            0 :             port_icon_left = geometry_rectangle_get_left( &classifier_box ) + x_pos_rel * ( geometry_rectangle_get_width( &classifier_box ) - port_icon_size );
     413            0 :             port_icon_top = geometry_rectangle_get_top( &classifier_box ) - outwards_distance;
     414            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_DOWN : show_arrow_out ? GEOMETRY_DIRECTION_UP : GEOMETRY_DIRECTION_CENTER;
     415              :         }
     416              :     }
     417              :     else
     418              :     {
     419              :         static const int32_t INT32_MAX_HALF = (INT32_MAX/2)+1;  /* round to ceiling */
     420            0 :         if ( list_order < INT32_MAX_HALF )  /* SHOW ON LEFT BORDER */
     421              :         {
     422            0 :             const double y_pos_rel
     423            0 :                 = (list_order) / ((double)(INT32_MAX_HALF));
     424            0 :             port_icon_left = geometry_rectangle_get_left( &classifier_box ) - outwards_distance;
     425            0 :             port_icon_top = geometry_rectangle_get_top( &classifier_box ) + y_pos_rel * ( geometry_rectangle_get_height( &classifier_box ) - port_icon_size );
     426            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_RIGHT : show_arrow_out ? GEOMETRY_DIRECTION_LEFT : GEOMETRY_DIRECTION_CENTER;
     427              :         }
     428              :         else  /* SHOW ON BOTTOM BORDER */
     429              :         {
     430            0 :             const double x_pos_rel
     431            0 :                 = (list_order - INT32_MAX_HALF) / ((double)(INT32_MAX_HALF));
     432            0 :             port_icon_left = geometry_rectangle_get_left( &classifier_box ) + x_pos_rel * ( geometry_rectangle_get_width( &classifier_box ) - port_icon_size );
     433            0 :             port_icon_top = geometry_rectangle_get_bottom( &classifier_box ) - port_icon_size + outwards_distance;
     434            0 :             arrow_dir = show_arrow_in ? GEOMETRY_DIRECTION_UP : show_arrow_out ? GEOMETRY_DIRECTION_DOWN : GEOMETRY_DIRECTION_CENTER;
     435              :         }
     436              :     }
     437              : 
     438              :     /* set feature bounding box */
     439              :     geometry_rectangle_t f_bounds;
     440            0 :     geometry_rectangle_init ( &f_bounds,
     441              :                               port_icon_left,
     442              :                               port_icon_top,
     443              :                               port_icon_size,
     444              :                               port_icon_size
     445              :                             );
     446            0 :     layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     447            0 :     layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     448            0 :     layout_feature_set_icon_direction ( out_feature_layout, arrow_dir );
     449              : 
     450            0 :     U8_TRACE_END();
     451            0 : }
     452              : 
     453            0 : void pencil_feature_layouter_private_layout_interface ( pencil_feature_layouter_t *this_,
     454              :                                                         const geometry_rectangle_t *classifier_symbol_box,
     455              :                                                         const data_feature_t *the_feature,
     456              :                                                         PangoLayout *font_layout,
     457              :                                                         layout_feature_t *out_feature_layout )
     458              : {
     459            0 :     U8_TRACE_BEGIN();
     460            0 :     assert ( NULL != classifier_symbol_box );
     461            0 :     assert ( NULL != the_feature );
     462            0 :     assert ( NULL != font_layout );
     463            0 :     assert ( NULL != out_feature_layout );
     464              : 
     465              :     /* get preferred object size + distance */
     466            0 :     const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size );
     467            0 :     const double interface_icon_size = pencil_size_get_standard_font_size( (*this_).pencil_size );
     468            0 :     const double interface_distance
     469            0 :         = 2.001 * pencil_size_get_preferred_object_distance( (*this_).pencil_size ) + gap;  /* min dist formula as in relationship layouter */
     470              : 
     471            0 :     const int32_t list_order = data_feature_get_list_order( the_feature );
     472              : 
     473              :     /* position the interface icon */
     474            0 :     if ( list_order < 0 )
     475              :     {
     476              :         static const int32_t INT32_MIN_HALF = INT32_MIN/2;
     477            0 :         if ( list_order < INT32_MIN_HALF )  /* SHOW ON RIGHT BORDER */
     478              :         {
     479            0 :             const double y_pos_rel
     480            0 :                 = (list_order - INT32_MIN_HALF) / ((double)(INT32_MIN_HALF));
     481              :             geometry_rectangle_t f_bounds;
     482            0 :             geometry_rectangle_init ( &f_bounds,
     483            0 :                                       geometry_rectangle_get_right( classifier_symbol_box ) + interface_distance,
     484            0 :                                       geometry_rectangle_get_top( classifier_symbol_box ) + y_pos_rel * ( geometry_rectangle_get_height( classifier_symbol_box ) - interface_icon_size ),
     485              :                                       interface_icon_size,
     486              :                                       interface_icon_size
     487              :                                     );
     488            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     489            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     490            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_RIGHT );
     491              :         }
     492              :         else  /* SHOW ON TOP BORDER */
     493              :         {
     494            0 :             const double x_pos_rel
     495            0 :                 = (list_order) / ((double)(INT32_MIN_HALF));
     496              :             geometry_rectangle_t f_bounds;
     497            0 :             geometry_rectangle_init ( &f_bounds,
     498            0 :                                       geometry_rectangle_get_left( classifier_symbol_box ) + x_pos_rel * ( geometry_rectangle_get_width( classifier_symbol_box ) - interface_icon_size ),
     499            0 :                                       geometry_rectangle_get_top( classifier_symbol_box ) - interface_distance - interface_icon_size,
     500              :                                       interface_icon_size,
     501              :                                       interface_icon_size
     502              :                                     );
     503            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     504            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     505            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_UP );
     506              :         }
     507              :     }
     508              :     else
     509              :     {
     510              :         static const int32_t INT32_MAX_HALF = (INT32_MAX/2)+1;  /* round to ceiling */
     511            0 :         if ( list_order < INT32_MAX_HALF )  /* SHOW ON LEFT BORDER */
     512              :         {
     513            0 :             const double y_pos_rel
     514            0 :                 = (list_order) / ((double)(INT32_MAX_HALF));
     515              :             geometry_rectangle_t f_bounds;
     516            0 :             geometry_rectangle_init ( &f_bounds,
     517            0 :                                       geometry_rectangle_get_left( classifier_symbol_box ) - interface_distance - interface_icon_size,
     518            0 :                                       geometry_rectangle_get_top( classifier_symbol_box ) + y_pos_rel * ( geometry_rectangle_get_height( classifier_symbol_box ) - interface_icon_size ),
     519              :                                       interface_icon_size,
     520              :                                       interface_icon_size
     521              :                                     );
     522            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     523            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     524            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_LEFT );
     525              :         }
     526              :         else  /* SHOW ON BOTTOM BORDER */
     527              :         {
     528            0 :             const double x_pos_rel
     529            0 :                 = (list_order - INT32_MAX_HALF) / ((double)(INT32_MAX_HALF));
     530              :             geometry_rectangle_t f_bounds;
     531            0 :             geometry_rectangle_init ( &f_bounds,
     532            0 :                                       geometry_rectangle_get_left( classifier_symbol_box ) + x_pos_rel * ( geometry_rectangle_get_width( classifier_symbol_box ) - interface_icon_size ),
     533            0 :                                       geometry_rectangle_get_bottom( classifier_symbol_box ) + interface_distance,
     534              :                                       interface_icon_size,
     535              :                                       interface_icon_size
     536              :                                     );
     537            0 :             layout_feature_set_symbol_box ( out_feature_layout, &f_bounds );
     538            0 :             layout_feature_set_label_box ( out_feature_layout, &f_bounds );
     539            0 :             layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_DOWN );
     540              :         }
     541              :     }
     542              : 
     543            0 :     if ( DATA_FEATURE_TYPE_PROVIDED_INTERFACE == data_feature_get_main_type (the_feature) )
     544              :     {
     545              :         /* a provided interface has no direction, it is a circle */
     546            0 :         layout_feature_set_icon_direction ( out_feature_layout, GEOMETRY_DIRECTION_CENTER );
     547              :     }
     548              : 
     549            0 :     U8_TRACE_END();
     550            0 : }
     551              : 
     552            0 : void pencil_feature_layouter_private_layout_compartment ( pencil_feature_layouter_t *this_,
     553              :                                                           const geometry_rectangle_t *compartments_space,
     554              :                                                           PangoLayout *font_layout,
     555              :                                                           layout_feature_t *io_feature_layout )
     556              : {
     557            0 :     U8_TRACE_BEGIN();
     558            0 :     assert( NULL != compartments_space );
     559            0 :     assert( NULL != font_layout );
     560            0 :     assert( NULL != io_feature_layout );
     561              : 
     562              :     /* feature label sizes are already precalculated */
     563            0 :     assert( (*this_).label_dimensions_initialized );
     564              : 
     565              :     /* define names for input data */
     566              :     const layout_visible_classifier_t * const vis_classfy
     567            0 :         = layout_feature_get_classifier_const( io_feature_layout );
     568            0 :     assert( NULL != vis_classfy );
     569            0 :     const data_row_t diagele_id = layout_visible_classifier_get_diagramelement_id( vis_classfy );
     570            0 :     const double gap = pencil_size_get_standard_object_border( (*this_).pencil_size );
     571            0 :     const data_feature_t *const the_feature = layout_feature_get_data_const( io_feature_layout );
     572            0 :     const data_feature_type_t f_type = data_feature_get_main_type (the_feature);
     573              : 
     574              :     /* calculate the feat_top by summing up the heights of the UNORDERED features above */
     575            0 :     double feat_top = geometry_rectangle_get_top( compartments_space );
     576            0 :     bool feat_is_first_in_compartment = true;
     577            0 :     bool compartment_property_above = false;  /* true if a feature of type DATA_FEATURE_TYPE_PROPERTY is above */
     578            0 :     bool compartment_operation_above = false;  /* true if a feature of type DATA_FEATURE_TYPE_OPERATION is above */
     579            0 :     bool compartment_tagged_value_above = false;  /* true if a feature of type DATA_FEATURE_TYPE_TAGGED_VALUE is above */
     580            0 :     const uint32_t num_features = layout_visible_set_get_feature_count( (*this_).layout_data );
     581            0 :     for ( uint32_t f_probe_idx = 0; f_probe_idx < num_features; f_probe_idx ++ )
     582              :     {
     583              :         const layout_feature_t *const f_probe_layout
     584            0 :             = layout_visible_set_get_feature_ptr( (*this_).layout_data, f_probe_idx );
     585            0 :         assert( NULL != f_probe_layout );
     586              :         const layout_visible_classifier_t *const probe_vis_classfy
     587            0 :             = layout_feature_get_classifier_const( f_probe_layout );
     588            0 :         assert( NULL != probe_vis_classfy );
     589              : 
     590              :         /* check if this f_probe_layout has the same diagram element id as the_feature */
     591            0 :         if ( diagele_id == layout_visible_classifier_get_diagramelement_id( probe_vis_classfy ) )
     592              :         {
     593              :             /* this is a feature of the same visible_classifier_t */
     594              :             /* define names for input data */
     595              :             const data_feature_t *f_probe_data;
     596            0 :             f_probe_data = layout_feature_get_data_const( f_probe_layout );
     597            0 :             assert( NULL != f_probe_data );
     598            0 :             const data_feature_type_t f_probe_type = data_feature_get_main_type ( f_probe_data );
     599            0 :             if ( data_feature_type_inside_compartment( f_probe_type ) )
     600              :             {
     601            0 :                 const bool is_above
     602            0 :                     = (( data_feature_get_list_order( f_probe_data ) < data_feature_get_list_order( the_feature ))
     603            0 :                     || (( data_feature_get_list_order( f_probe_data ) == data_feature_get_list_order( the_feature ) )
     604            0 :                     && ( data_feature_get_row( f_probe_data ) < data_feature_get_row( the_feature ) )));
     605            0 :                 if ( is_above )
     606              :                 {
     607              :                     const geometry_rectangle_t *const probe_label_box
     608            0 :                         = layout_feature_get_label_box_const( f_probe_layout );
     609            0 :                     feat_top += geometry_rectangle_get_height( probe_label_box );
     610            0 :                     if ( f_type == f_probe_type )
     611              :                     {
     612            0 :                         feat_is_first_in_compartment = false;
     613              :                     }
     614              :                     compartment_property_above
     615            0 :                         = compartment_property_above || ( f_probe_type == DATA_FEATURE_TYPE_PROPERTY );
     616              :                     compartment_operation_above
     617            0 :                         = compartment_operation_above || ( f_probe_type == DATA_FEATURE_TYPE_OPERATION );
     618              :                     compartment_tagged_value_above
     619            0 :                         = compartment_tagged_value_above || ( f_probe_type == DATA_FEATURE_TYPE_TAGGED_VALUE );
     620              :                 }
     621              :             }
     622              :         }
     623              :     }
     624              : 
     625              :     /* determine compartments above the current */
     626            0 :     feat_top += feat_is_first_in_compartment ? ( 4.0 * gap ) : 0.0;  /* a line for own compartment needed */
     627            0 :     feat_top += compartment_property_above ? ( 4.0 * gap ) : 0.0;  /* 2.0 * gap is reserved for compartment label */
     628            0 :     feat_top += compartment_operation_above ? ( 4.0 * gap ) : 0.0;
     629            0 :     feat_top += compartment_tagged_value_above ? ( 4.0 * gap ) : 0.0;
     630              : 
     631              :     /* determine the bounds of the feature */
     632              :     const geometry_rectangle_t *const feat_label_box
     633            0 :         = layout_feature_get_label_box_const( io_feature_layout );
     634              : 
     635              :     /* layout feature into parent classifier */
     636            0 :     const geometry_rectangle_t label_box = {
     637            0 :         .left = geometry_rectangle_get_left( compartments_space ) + gap,
     638              :         .top = feat_top,
     639            0 :         .width = geometry_rectangle_get_width( feat_label_box ),
     640            0 :         .height = geometry_rectangle_get_height( feat_label_box )
     641              :     };
     642            0 :     const geometry_rectangle_t feat_bounds = {
     643            0 :         .left = geometry_rectangle_get_left( compartments_space ),
     644              :         .top = feat_top,
     645            0 :         .width = geometry_rectangle_get_width( feat_label_box ) + 2.0 * gap,
     646            0 :         .height = geometry_rectangle_get_height( feat_label_box )
     647              :     };
     648              : 
     649            0 :     layout_feature_set_label_box( io_feature_layout, &label_box );
     650            0 :     layout_feature_set_symbol_box( io_feature_layout, &feat_bounds );
     651            0 :     layout_feature_set_icon_direction( io_feature_layout, GEOMETRY_DIRECTION_CENTER );  /* dummy direction */
     652            0 :     layout_feature_set_first_in_compartment( io_feature_layout, feat_is_first_in_compartment );
     653              : 
     654            0 :     U8_TRACE_END();
     655            0 : }
     656              : 
     657            0 : void pencil_feature_layouter_private_get_minimum_bounds( pencil_feature_layouter_t *this_,
     658              :                                                          const data_feature_t *the_feature,
     659              :                                                          const data_profile_part_t *profile,
     660              :                                                          const pencil_size_t *pencil_size,
     661              :                                                          PangoLayout *font_layout,
     662              :                                                          geometry_dimensions_t *out_feature_bounds )
     663              : {
     664            0 :     U8_TRACE_BEGIN();
     665            0 :     assert( NULL != the_feature );
     666            0 :     assert( NULL != profile );
     667            0 :     assert( NULL != pencil_size );
     668            0 :     assert( NULL != font_layout );
     669            0 :     assert( NULL != out_feature_bounds );
     670              : 
     671            0 :     const geometry_dimensions_t label_dim_proposal = {
     672            0 :         .width = 25.0 * pencil_size_get_standard_font_size( pencil_size ),
     673            0 :         .height = pencil_size_get_standard_font_size( pencil_size )
     674              :     };
     675            0 :     draw_feature_label_get_key_and_value_dimensions( &((*this_).draw_feature_label),
     676              :                                                      the_feature,
     677              :                                                      profile,
     678              :                                                      &label_dim_proposal,
     679              :                                                      pencil_size,
     680              :                                                      font_layout,
     681              :                                                      out_feature_bounds
     682              :     );
     683              : 
     684            0 :     U8_TRACE_END();
     685            0 : }
     686              : 
     687              : 
     688              : /*
     689              : Copyright 2017-2026 Andreas Warnke
     690              : 
     691              : Licensed under the Apache License, Version 2.0 (the "License");
     692              : you may not use this file except in compliance with the License.
     693              : You may obtain a copy of the License at
     694              : 
     695              :     http://www.apache.org/licenses/LICENSE-2.0
     696              : 
     697              : Unless required by applicable law or agreed to in writing, software
     698              : distributed under the License is distributed on an "AS IS" BASIS,
     699              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     700              : See the License for the specific language governing permissions and
     701              : limitations under the License.
     702              : */
        

Generated by: LCOV version 2.0-1