LCOV - code coverage report
Current view: top level - pencil/source/draw - draw_classifier_contour.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.71.2_covts Lines: 27.1 % 458 124
Test Date: 2026-08-22 19:47:36 Functions: 16.7 % 12 2

            Line data    Source code
       1              : /* File: draw_classifier_contour.c; Copyright and License: see below */
       2              : 
       3              : #include "draw/draw_classifier_contour.h"
       4              : #include "draw/draw_classifier_icon.h"
       5              : #include "u8/u8_trace.h"
       6              : #include <stdio.h>
       7              : #include <stdlib.h>
       8              : #include <assert.h>
       9              : #include <math.h>
      10              : 
      11              : /*! where to place the control points of a bezier curve to get a good approximation for a 90 degree curve */
      12              : const static double BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE = 0.552284749831;
      13              : 
      14              : const static double SINUS_OF_45_DEGREE = 0.707106781;
      15              : 
      16          161 : geometry_rectangle_t draw_classifier_contour_calc_inner_area ( const draw_classifier_contour_t *this_,
      17              :                                                                data_classifier_type_t classifier_type,
      18              :                                                                const geometry_rectangle_t *outer_bounds,
      19              :                                                                const pencil_size_t *pencil_size )
      20              : {
      21          161 :     U8_TRACE_BEGIN();
      22          161 :     assert ( NULL != outer_bounds );
      23          161 :     assert ( NULL != pencil_size );
      24              : 
      25              :     geometry_rectangle_t result;
      26          161 :     geometry_rectangle_init_empty( &result );
      27              : 
      28          161 :     double gap = pencil_size_get_standard_object_border( pencil_size );
      29          161 :     double double_gap = 2.0 * gap;  /* a line has the gap distance on both sides to the next object */
      30              : 
      31          161 :     switch ( classifier_type )
      32              :     {
      33            6 :         case DATA_CLASSIFIER_TYPE_USE_CASE:
      34              :         {
      35              :             /* within a use case, space is limited (double_gap is the border on each side): */
      36            6 :             double inner_x_radius = 0.5 * geometry_rectangle_get_width( outer_bounds ) - double_gap;
      37            6 :             double inner_y_radius = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
      38            6 :             double h_offset = (1.0 - SINUS_OF_45_DEGREE) * inner_x_radius;
      39            6 :             double v_offset = (1.0 - SINUS_OF_45_DEGREE) * inner_y_radius;
      40              : 
      41            6 :             geometry_rectangle_replace( &result, outer_bounds );
      42            6 :             geometry_rectangle_expand_4dir( &result, -double_gap - h_offset, -double_gap - v_offset );
      43              :         }
      44            6 :         break;
      45              : 
      46            5 :         case DATA_CLASSIFIER_TYPE_NODE:
      47              :         {
      48              :             /* the 3d border of a node shrinks the space */
      49            5 :             double offset_3d = double_gap;
      50              : 
      51            5 :             geometry_rectangle_replace( &result, outer_bounds );
      52            5 :             geometry_rectangle_enlarge( &result, -2.0 * double_gap - offset_3d, -2.0 * double_gap - offset_3d );
      53            5 :             geometry_rectangle_shift( &result, double_gap, double_gap + offset_3d );
      54              :         }
      55            5 :         break;
      56              : 
      57           45 :         case DATA_CLASSIFIER_TYPE_ACTOR:
      58              :         case DATA_CLASSIFIER_TYPE_DYN_INITIAL_NODE:
      59              :         case DATA_CLASSIFIER_TYPE_DYN_FINAL_NODE:
      60              :         case DATA_CLASSIFIER_TYPE_DYN_FORK_NODE:
      61              :         case DATA_CLASSIFIER_TYPE_DYN_JOIN_NODE:
      62              :         case DATA_CLASSIFIER_TYPE_DYN_SHALLOW_HISTORY:
      63              :         case DATA_CLASSIFIER_TYPE_DYN_DEEP_HISTORY:
      64              :         case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_TIME_EVENT:
      65              :         case DATA_CLASSIFIER_TYPE_IMAGE:
      66              :         {
      67              :             /* the symbol icon height is part of the shape border  */
      68           45 :             double symbol_icon_height = pencil_size_get_classifier_symbol_height( pencil_size );
      69              : 
      70           45 :             geometry_rectangle_replace( &result, outer_bounds );
      71           45 :             geometry_rectangle_enlarge( &result, -2.0 * double_gap, -2.0 * double_gap - symbol_icon_height );
      72           45 :             geometry_rectangle_shift( &result, double_gap, double_gap + symbol_icon_height );
      73              :         }
      74           45 :         break;
      75              : 
      76           20 :         case DATA_CLASSIFIER_TYPE_INTERACTION_USE:  /* and */
      77              :         case DATA_CLASSIFIER_TYPE_INTERACTION:  /* and */
      78              :         case DATA_CLASSIFIER_TYPE_PACKAGE:  /* and */
      79              :         case DATA_CLASSIFIER_TYPE_COMMENT:
      80              :         {
      81           20 :             double top_ornament_height = pencil_size_get_standard_font_size( pencil_size );
      82              : 
      83           20 :             geometry_rectangle_replace( &result, outer_bounds );
      84           20 :             geometry_rectangle_enlarge( &result, -2.0 * double_gap, -2.0 * double_gap - top_ornament_height );
      85           20 :             geometry_rectangle_shift( &result, double_gap, double_gap + top_ornament_height );
      86              :         }
      87           20 :         break;
      88              : 
      89           70 :         case DATA_CLASSIFIER_TYPE_BLOCK:
      90              :         case DATA_CLASSIFIER_TYPE_REQUIREMENT:
      91              :         case DATA_CLASSIFIER_TYPE_SUBSYSTEM:
      92              :         case DATA_CLASSIFIER_TYPE_ACTIVITY:
      93              :         case DATA_CLASSIFIER_TYPE_STATE:
      94              :         case DATA_CLASSIFIER_TYPE_COMPONENT:
      95              :         case DATA_CLASSIFIER_TYPE_PART:
      96              :         case DATA_CLASSIFIER_TYPE_INTERFACE:
      97              :         case DATA_CLASSIFIER_TYPE_CLASS:
      98              :         case DATA_CLASSIFIER_TYPE_OBJECT:
      99              :         case DATA_CLASSIFIER_TYPE_ARTIFACT:
     100              :         case DATA_CLASSIFIER_TYPE_CONSTRAINT_BLOCK:
     101              :         case DATA_CLASSIFIER_TYPE_DYN_INTERRUPTABLE_REGION:
     102              :         case DATA_CLASSIFIER_TYPE_STEREOTYPE:
     103              :         {
     104              :             /* standard size */
     105           70 :             geometry_rectangle_replace( &result, outer_bounds );
     106           70 :             geometry_rectangle_expand_4dir( &result, -double_gap, -double_gap );
     107              :         }
     108           70 :         break;
     109              : 
     110            5 :         case DATA_CLASSIFIER_TYPE_DYN_DECISION_NODE:
     111              :         {
     112              :             /* within a decision rhombus, space is limited by factor 2 per dimension: */
     113            5 :             double half_outer_width = 0.5 * geometry_rectangle_get_width( outer_bounds ) - double_gap;
     114            5 :             double half_outer_height = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
     115            5 :             double h_offset = 0.5 * half_outer_width;
     116            5 :             double v_offset = 0.5 * half_outer_height;
     117              : 
     118            5 :             geometry_rectangle_replace( &result, outer_bounds );
     119            5 :             geometry_rectangle_expand_4dir( &result, -double_gap - h_offset, -double_gap - v_offset );
     120              :         }
     121            5 :         break;
     122              : 
     123            5 :         case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_EVENT :
     124              :         {
     125              :             /* within an accept event, space is limited (double_gap is the border on each side): */
     126            5 :             double half_outer_height = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
     127            5 :             double horizontal_offset = half_outer_height;
     128              : 
     129            5 :             geometry_rectangle_replace( &result, outer_bounds );
     130            5 :             geometry_rectangle_enlarge( &result, -2.0 * double_gap - horizontal_offset, -2.0 * double_gap );
     131            5 :             geometry_rectangle_shift( &result, double_gap + horizontal_offset, double_gap );
     132              :         }
     133            5 :         break;
     134              : 
     135            5 :         case DATA_CLASSIFIER_TYPE_DYN_SEND_SIGNAL:
     136              :         {
     137              :             /* within a send signal, space is limited (double_gap is the border on each side): */
     138            5 :             double half_outer_height = 0.5 * geometry_rectangle_get_height( outer_bounds ) - double_gap;
     139            5 :             double horizontal_offset = half_outer_height;
     140              : 
     141            5 :             geometry_rectangle_replace( &result, outer_bounds );
     142            5 :             geometry_rectangle_enlarge( &result, -2.0 * double_gap - horizontal_offset, -2.0 * double_gap );
     143            5 :             geometry_rectangle_shift( &result, double_gap, double_gap );
     144              :         }
     145            5 :         break;
     146              : 
     147            0 :         default:
     148              :         {
     149              :             /* this case can happen if a model file of a new cfu version is opened with an older version of cfu */
     150            0 :             U8_LOG_ANOMALY("unknown data_classifier_type_t in draw_classifier_contour_calc_inner_area()");
     151              :             /* assume standard size */
     152            0 :             geometry_rectangle_replace( &result, outer_bounds );
     153            0 :             geometry_rectangle_expand_4dir( &result, -double_gap, -double_gap );
     154              :         }
     155            0 :         break;
     156              :     }
     157              : 
     158          161 :     U8_TRACE_END();
     159          161 :     return result;
     160              : }
     161              : 
     162          237 : geometry_rectangle_t draw_classifier_contour_calc_outer_bounds ( const draw_classifier_contour_t *this_,
     163              :                                                                  data_classifier_type_t classifier_type,
     164              :                                                                  const geometry_rectangle_t *inner_area,
     165              :                                                                  const pencil_size_t *pencil_size )
     166              : {
     167          237 :     U8_TRACE_BEGIN();
     168          237 :     assert ( NULL != inner_area );
     169          237 :     assert ( NULL != pencil_size );
     170              : 
     171              :     geometry_rectangle_t result;
     172          237 :     geometry_rectangle_init_empty( &result );
     173              : 
     174          237 :     double gap = pencil_size_get_standard_object_border( pencil_size );
     175          237 :     double double_gap = 2.0 * gap;  /* a line has the gap distance on both sides to the next object */
     176              : 
     177          237 :     switch ( classifier_type )
     178              :     {
     179            9 :         case DATA_CLASSIFIER_TYPE_USE_CASE:
     180              :         {
     181              :             /* within a use case, space is limited (double_gap is the border on each side): */
     182            9 :             double half_inner_width = 0.5 * geometry_rectangle_get_width( inner_area );
     183            9 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     184            9 :             double h_offset = half_inner_width * ( 1.0 / SINUS_OF_45_DEGREE - 1.0  );
     185            9 :             double v_offset = half_inner_height * ( 1.0 / SINUS_OF_45_DEGREE - 1.0  );
     186              : 
     187            9 :             geometry_rectangle_replace( &result, inner_area );
     188            9 :             geometry_rectangle_expand_4dir( &result, +double_gap + h_offset, +double_gap + v_offset );
     189              :         }
     190            9 :         break;
     191              : 
     192            9 :         case DATA_CLASSIFIER_TYPE_NODE:
     193              :         {
     194              :             /* the 3d border of a node shrinks the space */
     195            9 :             double offset_3d = double_gap;
     196              : 
     197            9 :             geometry_rectangle_replace( &result, inner_area );
     198            9 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap + offset_3d, +2.0 * double_gap + offset_3d );
     199            9 :             geometry_rectangle_shift( &result, -double_gap, -double_gap - offset_3d );
     200              :         }
     201            9 :         break;
     202              : 
     203           27 :         case DATA_CLASSIFIER_TYPE_ACTOR:
     204              :         case DATA_CLASSIFIER_TYPE_DYN_INITIAL_NODE:
     205              :         case DATA_CLASSIFIER_TYPE_DYN_FINAL_NODE:
     206              :         case DATA_CLASSIFIER_TYPE_DYN_FORK_NODE:
     207              :         case DATA_CLASSIFIER_TYPE_DYN_JOIN_NODE:
     208              :         case DATA_CLASSIFIER_TYPE_DYN_SHALLOW_HISTORY:
     209              :         case DATA_CLASSIFIER_TYPE_DYN_DEEP_HISTORY:
     210              :         case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_TIME_EVENT:
     211              :         case DATA_CLASSIFIER_TYPE_IMAGE:
     212              :         {
     213              :             /* the symbol icon height is part of the shape border  */
     214           27 :             double symbol_icon_height = pencil_size_get_classifier_symbol_height( pencil_size );
     215              : 
     216           27 :             geometry_rectangle_replace( &result, inner_area );
     217           27 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap, +2.0 * double_gap + symbol_icon_height );
     218           27 :             geometry_rectangle_shift( &result, -double_gap, -double_gap - symbol_icon_height );
     219              :         }
     220           27 :         break;
     221              : 
     222           39 :         case DATA_CLASSIFIER_TYPE_INTERACTION_USE:  /* and */
     223              :         case DATA_CLASSIFIER_TYPE_INTERACTION:  /* and */
     224              :         case DATA_CLASSIFIER_TYPE_PACKAGE:  /* and */
     225              :         case DATA_CLASSIFIER_TYPE_COMMENT:
     226              :         {
     227           39 :             double top_ornament_height = pencil_size_get_standard_font_size( pencil_size );
     228              : 
     229           39 :             geometry_rectangle_replace( &result, inner_area );
     230           39 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap, +2.0 * double_gap + top_ornament_height );
     231           39 :             geometry_rectangle_shift( &result, -double_gap, -double_gap - top_ornament_height );
     232              :         }
     233           39 :         break;
     234              : 
     235          126 :         case DATA_CLASSIFIER_TYPE_BLOCK:
     236              :         case DATA_CLASSIFIER_TYPE_REQUIREMENT:
     237              :         case DATA_CLASSIFIER_TYPE_SUBSYSTEM:
     238              :         case DATA_CLASSIFIER_TYPE_ACTIVITY:
     239              :         case DATA_CLASSIFIER_TYPE_STATE:
     240              :         case DATA_CLASSIFIER_TYPE_COMPONENT:
     241              :         case DATA_CLASSIFIER_TYPE_PART:
     242              :         case DATA_CLASSIFIER_TYPE_INTERFACE:
     243              :         case DATA_CLASSIFIER_TYPE_CLASS:
     244              :         case DATA_CLASSIFIER_TYPE_OBJECT:
     245              :         case DATA_CLASSIFIER_TYPE_ARTIFACT:
     246              :         case DATA_CLASSIFIER_TYPE_CONSTRAINT_BLOCK:
     247              :         case DATA_CLASSIFIER_TYPE_DYN_INTERRUPTABLE_REGION:
     248              :         case DATA_CLASSIFIER_TYPE_STEREOTYPE:
     249              :         {
     250              :             /* standard size */
     251          126 :             geometry_rectangle_replace( &result, inner_area );
     252          126 :             geometry_rectangle_expand_4dir( &result, +double_gap, +double_gap );
     253              :         }
     254          126 :         break;
     255              : 
     256            9 :         case DATA_CLASSIFIER_TYPE_DYN_DECISION_NODE:
     257              :         {
     258              :             /* within a decision rhombus, space is limited by factor 2 per dimension: */
     259            9 :             double half_inner_width = 0.5 * geometry_rectangle_get_width( inner_area );
     260            9 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     261            9 :             double h_offset = half_inner_width;
     262            9 :             double v_offset = half_inner_height;
     263              : 
     264            9 :             geometry_rectangle_replace( &result, inner_area );
     265            9 :             geometry_rectangle_expand_4dir( &result, +double_gap + h_offset, +double_gap + v_offset );
     266              :         }
     267            9 :         break;
     268              : 
     269            9 :         case DATA_CLASSIFIER_TYPE_DYN_ACCEPT_EVENT :
     270              :         {
     271              :             /* within an accept event, space is limited (double_gap is the border on each side): */
     272            9 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     273            9 :             double horizontal_offset = half_inner_height;
     274              : 
     275            9 :             geometry_rectangle_replace( &result, inner_area );
     276            9 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap + horizontal_offset, +2.0 * double_gap );
     277            9 :             geometry_rectangle_shift( &result, -double_gap - horizontal_offset, -double_gap );
     278              :         }
     279            9 :         break;
     280              : 
     281            9 :         case DATA_CLASSIFIER_TYPE_DYN_SEND_SIGNAL:
     282              :         {
     283              :             /* within a send signal, space is limited (double_gap is the border on each side): */
     284            9 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     285            9 :             double horizontal_offset = half_inner_height;
     286              : 
     287            9 :             geometry_rectangle_replace( &result, inner_area );
     288            9 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap + horizontal_offset, +2.0 * double_gap );
     289            9 :             geometry_rectangle_shift( &result, -double_gap, -double_gap );
     290              :         }
     291            9 :         break;
     292              : 
     293            0 :         default:
     294              :         {
     295              :             /* this case can happen if a model file of a new cfu version is opened with an older version of cfu */
     296            0 :             U8_LOG_ANOMALY("unknown data_classifier_type_t in draw_classifier_contour_calc_outer_bounds()");
     297              :             /* assume standard size */
     298            0 :             geometry_rectangle_replace( &result, inner_area );
     299            0 :             geometry_rectangle_expand_4dir( &result, +double_gap, +double_gap );
     300              :         }
     301            0 :         break;
     302              :     }
     303              : 
     304          237 :     U8_TRACE_END();
     305          237 :     return result;
     306              : }
     307              : 
     308            0 : void draw_classifier_contour_draw_rounded_rect ( const draw_classifier_contour_t *this_,
     309              :                                                  const geometry_rectangle_t *outer_bounds,
     310              :                                                  bool dashed_line,
     311              :                                                  const pencil_size_t *pencil_size,
     312              :                                                  cairo_t *cr )
     313              : {
     314            0 :     U8_TRACE_BEGIN();
     315            0 :     assert ( NULL != outer_bounds );
     316            0 :     assert ( NULL != pencil_size );
     317            0 :     assert ( NULL != cr );
     318            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     319            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     320            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     321            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     322            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     323            0 :     const double border_bottom = border_top + border_height;
     324            0 :     const double border_right = border_left + border_width;
     325            0 :     const double corner_radius = 6.0 * gap;
     326            0 :     const double ctrl_offset = corner_radius * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
     327              : 
     328              :     /* set dashes */
     329            0 :     if ( dashed_line )
     330              :     {
     331              :         double dashes[2];
     332            0 :         dashes[0] = 2.0 * pencil_size_get_line_dash_length( pencil_size );
     333            0 :         dashes[1] = 1.0 * pencil_size_get_line_dash_length( pencil_size );
     334            0 :         cairo_set_dash ( cr, dashes, 2, 0.0 );
     335              :     }
     336              : 
     337            0 :     cairo_move_to ( cr, border_right - corner_radius, border_bottom );
     338            0 :     cairo_line_to ( cr, border_left + corner_radius, border_bottom );
     339            0 :     cairo_curve_to ( cr, border_left + ctrl_offset, border_bottom, border_left, border_bottom - ctrl_offset, border_left /* end point x */, border_bottom - corner_radius /* end point y */ );
     340            0 :     cairo_line_to ( cr, border_left, border_top + corner_radius );
     341            0 :     cairo_curve_to ( cr, border_left, border_top + ctrl_offset, border_left + ctrl_offset, border_top, border_left + corner_radius /* end point x */, border_top /* end point y */ );
     342            0 :     cairo_line_to ( cr, border_right - corner_radius, border_top );
     343            0 :     cairo_curve_to ( cr, border_right - ctrl_offset, border_top, border_right, border_top + ctrl_offset, border_right /* end point x */, border_top + corner_radius /* end point y */ );
     344            0 :     cairo_line_to ( cr, border_right, border_bottom - corner_radius );
     345            0 :     cairo_curve_to ( cr, border_right, border_bottom - ctrl_offset, border_right - ctrl_offset, border_bottom, border_right - corner_radius /* end point x */, border_bottom /* end point y */ );
     346            0 :     cairo_stroke (cr);
     347              : 
     348              :     /* reset dashes */
     349            0 :     if ( dashed_line )
     350              :     {
     351            0 :         cairo_set_dash ( cr, NULL, 0, 0.0 );
     352              :     }
     353              : 
     354            0 :     U8_TRACE_END();
     355            0 : }
     356              : 
     357            0 : void draw_classifier_contour_draw_ellipse ( const draw_classifier_contour_t *this_,
     358              :                                             const geometry_rectangle_t *outer_bounds,
     359              :                                             const pencil_size_t *pencil_size,
     360              :                                             cairo_t *cr )
     361              : {
     362            0 :     U8_TRACE_BEGIN();
     363            0 :     assert ( NULL != outer_bounds );
     364            0 :     assert ( NULL != pencil_size );
     365            0 :     assert ( NULL != cr );
     366            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     367            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     368            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     369            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     370            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     371            0 :     const double border_bottom = border_top + border_height;
     372            0 :     const double border_right = border_left + border_width;
     373            0 :     const double half_width = 0.5 * border_width;
     374            0 :     const double half_height = 0.5 * border_height;
     375            0 :     const double center_x = border_left + half_width;
     376            0 :     const double center_y = border_top + half_height;
     377            0 :     const double ctrl_xoffset = half_width * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
     378            0 :     const double ctrl_yoffset = half_height * (1.0-BEZIER_CTRL_POINT_FOR_90_DEGREE_CIRCLE);
     379              : 
     380            0 :     cairo_move_to ( cr, center_x, border_bottom );
     381            0 :     cairo_curve_to ( cr, border_left + ctrl_xoffset, border_bottom, border_left, border_bottom - ctrl_yoffset, border_left /* end point x */, center_y /* end point y */ );
     382            0 :     cairo_curve_to ( cr, border_left, border_top + ctrl_yoffset, border_left + ctrl_xoffset, border_top, center_x /* end point x */, border_top /* end point y */ );
     383            0 :     cairo_curve_to ( cr, border_right - ctrl_xoffset, border_top, border_right, border_top + ctrl_yoffset, border_right /* end point x */, center_y /* end point y */ );
     384            0 :     cairo_curve_to ( cr, border_right, border_bottom - ctrl_yoffset, border_right - ctrl_xoffset, border_bottom, center_x /* end point x */, border_bottom /* end point y */ );
     385            0 :     cairo_stroke (cr);
     386              : 
     387            0 :     U8_TRACE_END();
     388            0 : }
     389              : 
     390            0 : void draw_classifier_contour_draw_rhombus ( const draw_classifier_contour_t *this_,
     391              :                                             const geometry_rectangle_t *outer_bounds,
     392              :                                             const pencil_size_t *pencil_size,
     393              :                                             cairo_t *cr )
     394              : {
     395            0 :     U8_TRACE_BEGIN();
     396            0 :     assert ( NULL != outer_bounds );
     397            0 :     assert ( NULL != pencil_size );
     398            0 :     assert ( NULL != cr );
     399            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     400            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     401            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     402            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     403            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     404            0 :     const double border_bottom = border_top + border_height;
     405            0 :     const double border_right = border_left + border_width;
     406            0 :     const double center_x = geometry_rectangle_get_center_x ( outer_bounds );
     407            0 :     const double center_y = geometry_rectangle_get_center_y ( outer_bounds );
     408              : 
     409            0 :     cairo_move_to ( cr, center_x, border_bottom );
     410            0 :     cairo_line_to ( cr, border_left, center_y );
     411            0 :     cairo_line_to ( cr, center_x, border_top );
     412            0 :     cairo_line_to ( cr, border_right, center_y );
     413            0 :     cairo_line_to ( cr, center_x, border_bottom );
     414            0 :     cairo_stroke (cr);
     415              : 
     416            0 :     U8_TRACE_END();
     417            0 : }
     418              : 
     419            0 : void draw_classifier_contour_draw_3d_box ( const draw_classifier_contour_t *this_,
     420              :                                            const geometry_rectangle_t *outer_bounds,
     421              :                                            const pencil_size_t *pencil_size,
     422              :                                            cairo_t *cr )
     423              : {
     424            0 :     U8_TRACE_BEGIN();
     425            0 :     assert ( NULL != outer_bounds );
     426            0 :     assert ( NULL != pencil_size );
     427            0 :     assert ( NULL != cr );
     428            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     429            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     430            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     431            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     432            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     433            0 :     const double border_bottom = border_top + border_height;
     434            0 :     const double border_right = border_left + border_width;
     435            0 :     const double offset_3d = 2.0*gap;
     436              : 
     437            0 :     cairo_rectangle ( cr, border_left, border_top+offset_3d, border_width-offset_3d, border_height-offset_3d );
     438            0 :     cairo_stroke (cr);
     439              : 
     440            0 :     cairo_move_to ( cr, border_left, border_top+offset_3d );
     441            0 :     cairo_line_to ( cr, border_left+offset_3d, border_top );
     442            0 :     cairo_line_to ( cr, border_right, border_top );
     443            0 :     cairo_line_to ( cr, border_right, border_bottom-offset_3d );
     444            0 :     cairo_line_to ( cr, border_right-offset_3d, border_bottom );
     445            0 :     cairo_stroke (cr);
     446            0 :     cairo_move_to ( cr, border_right, border_top );
     447            0 :     cairo_line_to ( cr, border_right-offset_3d, border_top+offset_3d );
     448            0 :     cairo_stroke (cr);
     449              : 
     450            0 :     U8_TRACE_END();
     451            0 : }
     452              : 
     453            0 : void draw_classifier_contour_draw_accept_event ( const draw_classifier_contour_t *this_,
     454              :                                                  const geometry_rectangle_t *outer_bounds,
     455              :                                                  const pencil_size_t *pencil_size,
     456              :                                                  cairo_t *cr )
     457              : {
     458            0 :     U8_TRACE_BEGIN();
     459            0 :     assert ( NULL != outer_bounds );
     460            0 :     assert ( NULL != pencil_size );
     461            0 :     assert ( NULL != cr );
     462            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     463            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     464            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     465            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     466            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     467            0 :     const double border_bottom = border_top + border_height;
     468            0 :     const double border_right = border_left + border_width;
     469            0 :     const double center_y = geometry_rectangle_get_center_y ( outer_bounds );
     470            0 :     const double x_indent = border_height / 2.0;
     471              : 
     472            0 :     cairo_move_to ( cr, border_right, border_bottom );
     473            0 :     cairo_line_to ( cr, border_right, border_top );
     474            0 :     cairo_line_to ( cr, border_left, border_top );
     475            0 :     cairo_line_to ( cr, border_left + x_indent, center_y );
     476            0 :     cairo_line_to ( cr, border_left, border_bottom );
     477            0 :     cairo_line_to ( cr, border_right, border_bottom );
     478            0 :     cairo_stroke (cr);
     479              : 
     480            0 :     U8_TRACE_END();
     481            0 : }
     482              : 
     483            0 : void draw_classifier_contour_draw_send_signal ( const draw_classifier_contour_t *this_,
     484              :                                                 const geometry_rectangle_t *outer_bounds,
     485              :                                                 const pencil_size_t *pencil_size,
     486              :                                                 cairo_t *cr )
     487              : {
     488            0 :     U8_TRACE_BEGIN();
     489            0 :     assert ( NULL != outer_bounds );
     490            0 :     assert ( NULL != pencil_size );
     491            0 :     assert ( NULL != cr );
     492            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     493            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     494            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     495            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     496            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     497            0 :     const double border_bottom = border_top + border_height;
     498            0 :     const double border_right = border_left + border_width;
     499            0 :     const double center_y = geometry_rectangle_get_center_y ( outer_bounds );
     500            0 :     const double x_indent = border_height / 2.0;
     501              : 
     502            0 :     cairo_move_to ( cr, border_right - x_indent, border_bottom );
     503            0 :     cairo_line_to ( cr, border_right, center_y );
     504            0 :     cairo_line_to ( cr, border_right - x_indent, border_top );
     505            0 :     cairo_line_to ( cr, border_left, border_top );
     506            0 :     cairo_line_to ( cr, border_left, border_bottom );
     507            0 :     cairo_line_to ( cr, border_right - x_indent, border_bottom );
     508            0 :     cairo_stroke (cr);
     509              : 
     510            0 :     U8_TRACE_END();
     511            0 : }
     512              : 
     513            0 : void draw_classifier_contour_draw_package ( const draw_classifier_contour_t *this_,
     514              :                                             const geometry_rectangle_t *outer_bounds,
     515              :                                             const geometry_rectangle_t *label_box,
     516              :                                             const pencil_size_t *pencil_size,
     517              :                                             cairo_t *cr )
     518              : {
     519            0 :     U8_TRACE_BEGIN();
     520            0 :     assert ( NULL != outer_bounds );
     521            0 :     assert ( NULL != pencil_size );
     522            0 :     assert ( NULL != cr );
     523            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     524            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     525            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     526            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     527            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     528              : 
     529              :     double tab_width;
     530              :     double tab_height;
     531            0 :     const bool label_in_tab = ( geometry_rectangle_get_top( label_box ) < ( border_top + gap + gap ) );
     532            0 :     if ( label_in_tab )
     533              :     {
     534            0 :         tab_width = geometry_rectangle_get_width ( label_box ) + gap + gap;
     535            0 :         tab_height = geometry_rectangle_get_height ( label_box ) + gap;
     536              :     }
     537              :     else
     538              :     {
     539            0 :         tab_width = border_width/3.0;
     540            0 :         tab_height = pencil_size_get_standard_font_size( pencil_size );
     541              :     }
     542            0 :     cairo_rectangle ( cr, border_left, border_top, tab_width, tab_height );
     543            0 :     cairo_rectangle ( cr, border_left, border_top+tab_height, border_width, border_height-tab_height );
     544            0 :     cairo_stroke (cr);
     545              : 
     546            0 :     U8_TRACE_END();
     547            0 : }
     548              : 
     549            0 : void draw_classifier_contour_draw_diagram_ref ( const draw_classifier_contour_t *this_,
     550              :                                                 const geometry_rectangle_t *outer_bounds,
     551              :                                                 const pencil_size_t *pencil_size,
     552              :                                                 cairo_t *cr )
     553              : {
     554            0 :     U8_TRACE_BEGIN();
     555            0 :     assert ( NULL != outer_bounds );
     556            0 :     assert ( NULL != pencil_size );
     557            0 :     assert ( NULL != cr );
     558            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     559            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     560            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     561            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     562            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     563            0 :     const double title_corner_height = pencil_size_get_standard_font_size( pencil_size );
     564            0 :     const double title_corner_edge45 = 0.4 * title_corner_height;
     565            0 :     const double title_corner_width = border_width/5.0;
     566              : 
     567            0 :     cairo_rectangle ( cr, border_left, border_top, border_width, border_height );
     568            0 :     cairo_move_to ( cr, border_left, border_top+title_corner_height );
     569            0 :     cairo_line_to ( cr, border_left+title_corner_width - title_corner_edge45, border_top+title_corner_height );
     570            0 :     cairo_line_to ( cr, border_left+title_corner_width, border_top+title_corner_height-title_corner_edge45 );
     571            0 :     cairo_line_to ( cr, border_left+title_corner_width, border_top );
     572            0 :     cairo_stroke (cr);
     573              : 
     574            0 :     U8_TRACE_END();
     575            0 : }
     576              : 
     577            0 : void draw_classifier_contour_draw_comment ( const draw_classifier_contour_t *this_,
     578              :                                             const geometry_rectangle_t *outer_bounds,
     579              :                                             const pencil_size_t *pencil_size,
     580              :                                             cairo_t *cr )
     581              : {
     582            0 :     U8_TRACE_BEGIN();
     583            0 :     assert ( NULL != outer_bounds );
     584            0 :     assert ( NULL != pencil_size );
     585            0 :     assert ( NULL != cr );
     586            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     587            0 :     const double border_left = geometry_rectangle_get_left ( outer_bounds ) + gap;
     588            0 :     const double border_top = geometry_rectangle_get_top ( outer_bounds ) + gap;
     589            0 :     const double border_width = geometry_rectangle_get_width ( outer_bounds ) - gap - gap;
     590            0 :     const double border_height = geometry_rectangle_get_height ( outer_bounds ) - gap - gap;
     591            0 :     const double corner_edge = pencil_size_get_standard_font_size( pencil_size );
     592            0 :     const double border_bottom = border_top + border_height;
     593            0 :     const double border_right = border_left + border_width;
     594              : 
     595            0 :     cairo_move_to ( cr, border_right, border_top + corner_edge );
     596            0 :     cairo_line_to ( cr, border_right - corner_edge, border_top + corner_edge );
     597            0 :     cairo_line_to ( cr, border_right - corner_edge, border_top );
     598            0 :     cairo_line_to ( cr, border_left, border_top );
     599            0 :     cairo_line_to ( cr, border_left, border_bottom );
     600            0 :     cairo_line_to ( cr, border_right, border_bottom );
     601            0 :     cairo_line_to ( cr, border_right, border_top + corner_edge );
     602            0 :     cairo_line_to ( cr, border_right - corner_edge, border_top );
     603            0 :     cairo_stroke (cr);
     604              : 
     605            0 :     U8_TRACE_END();
     606            0 : }
     607              : 
     608            0 : void draw_classifier_contour_draw_compartment_line ( const draw_classifier_contour_t *this_,
     609              :                                                      data_classifier_type_t classifier_type,
     610              :                                                      const geometry_rectangle_t *outer_bounds,
     611              :                                                      double y_coordinate,
     612              :                                                      data_feature_type_t compartment_type,
     613              :                                                      const GdkRGBA *foreground_color,
     614              :                                                      const pencil_size_t *pencil_size,
     615              :                                                      cairo_t *cr )
     616              : {
     617            0 :     U8_TRACE_BEGIN();
     618            0 :     assert ( NULL != outer_bounds );
     619            0 :     assert ( NULL != foreground_color );
     620            0 :     assert ( NULL != pencil_size );
     621            0 :     assert ( NULL != cr );
     622              : 
     623            0 :     const double bounds_left = geometry_rectangle_get_left( outer_bounds );
     624            0 :     const double bounds_width = geometry_rectangle_get_width( outer_bounds );
     625            0 :     const double bounds_height = geometry_rectangle_get_height( outer_bounds );
     626            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     627              : 
     628              :     /* determine left and right coordinates */
     629            0 :     double left = bounds_left + gap;
     630            0 :     double right = bounds_left + bounds_width - gap;
     631            0 :     switch ( classifier_type )
     632              :     {
     633            0 :         case DATA_CLASSIFIER_TYPE_USE_CASE:
     634              :         {
     635            0 :             const double center_x = geometry_rectangle_get_center_x( outer_bounds );
     636            0 :             const double center_y = geometry_rectangle_get_center_y( outer_bounds );
     637            0 :             const double radius_x = ( bounds_width / 2.0 ) - gap; /* there is 1.0*gap around the ellipsis */
     638            0 :             const double radius_y = ( bounds_height / 2.0 ) - gap; /* there is 1.0*gap around the ellipsis */
     639            0 :             const double norm_dy = ( y_coordinate - center_y ) / radius_y;
     640            0 :             const double sqr_norm_dx = 1.0 - ( norm_dy * norm_dy );
     641            0 :             if ( sqr_norm_dx >= 0.0 )
     642              :             {
     643            0 :                 const double dx = sqrt( sqr_norm_dx ) * radius_x;
     644            0 :                 left = center_x - dx;
     645            0 :                 right = center_x + dx;
     646              :             }
     647              :             else
     648              :             {
     649            0 :                 left = bounds_left + gap;
     650            0 :                 right = bounds_left + bounds_width - gap;
     651              :             }
     652              :         }
     653            0 :         break;
     654              : 
     655            0 :         case DATA_CLASSIFIER_TYPE_NODE:
     656              :         {
     657              :             /* the 3d border of a node shrinks the space */
     658            0 :             const double offset_3d = 2.0 * gap;
     659            0 :             left = bounds_left + gap;
     660            0 :             right = bounds_left + bounds_width - offset_3d - gap;
     661              :         }
     662            0 :         break;
     663              : 
     664            0 :         default:
     665              :         {
     666              :             /* for all other cases; this switch is not exhaustive */
     667            0 :             left = bounds_left + gap;
     668            0 :             right = bounds_left + bounds_width - gap;
     669              :         }
     670            0 :         break;
     671              :     }
     672              : 
     673              :     /* draw line */
     674            0 :     cairo_move_to( cr, left, y_coordinate );
     675            0 :     cairo_line_to( cr, right, y_coordinate );
     676            0 :     cairo_stroke( cr );
     677              : 
     678              :     /* draw label */
     679            0 :     const GdkRGBA grey_color = pencil_size_get_gray_out_color( pencil_size );
     680            0 :     cairo_set_source_rgba( cr, grey_color.red, grey_color.green, grey_color.blue, grey_color.alpha );
     681            0 :     const double line_w = pencil_size_get_standard_line_width( pencil_size );
     682            0 :     switch ( compartment_type )
     683              :     {
     684            0 :         case DATA_FEATURE_TYPE_PROPERTY:
     685              :         {
     686            0 :             const double center_x = ( left + right ) / 2.0;
     687              : 
     688            0 :             cairo_move_to( cr, center_x - 1.0 * line_w, y_coordinate + 10.0 * line_w );
     689            0 :             cairo_line_to( cr, center_x - 4.0 * line_w, y_coordinate + 10.0 * line_w );
     690            0 :             cairo_line_to( cr, center_x - 4.0 * line_w, y_coordinate + 2.0 * line_w );
     691            0 :             cairo_line_to( cr, center_x - 1.0 * line_w, y_coordinate + 2.0 * line_w );
     692              : 
     693            0 :             cairo_move_to( cr, center_x + 1.0 * line_w, y_coordinate + 2.0 * line_w );
     694            0 :             cairo_line_to( cr, center_x + 4.0 * line_w, y_coordinate + 2.0 * line_w );
     695            0 :             cairo_line_to( cr, center_x + 4.0 * line_w, y_coordinate + 10.0 * line_w );
     696            0 :             cairo_line_to( cr, center_x + 1.0 * line_w, y_coordinate + 10.0 * line_w );
     697              : 
     698            0 :             cairo_stroke( cr );
     699              :         }
     700            0 :         break;
     701              : 
     702            0 :         case DATA_FEATURE_TYPE_OPERATION:
     703              :         {
     704            0 :             const double center_x = ( left + right ) / 2.0;
     705              : 
     706            0 :             cairo_move_to( cr, center_x - 1.0 * line_w, y_coordinate + 10.0 * line_w );
     707            0 :             cairo_curve_to( cr,
     708            0 :                             center_x - 6.0 * line_w,
     709            0 :                             y_coordinate + 10.0 * line_w,
     710            0 :                             center_x - 6.0 * line_w,
     711            0 :                             y_coordinate + 2.0 * line_w,
     712              :                             center_x - 1.0 * line_w,
     713            0 :                             y_coordinate + 2.0 * line_w
     714              :                           );
     715              : 
     716            0 :             cairo_move_to( cr, center_x + 1.0 * line_w, y_coordinate + 2.0 * line_w );
     717            0 :             cairo_curve_to( cr,
     718            0 :                             center_x + 6.0 * line_w,
     719            0 :                             y_coordinate + 2.0 * line_w,
     720            0 :                             center_x + 6.0 * line_w,
     721            0 :                             y_coordinate + 10.0 * line_w,
     722              :                             center_x + 1.0 * line_w,
     723            0 :                             y_coordinate + 10.0 * line_w
     724              :                           );
     725              : 
     726            0 :             cairo_stroke( cr );
     727              :         }
     728            0 :         break;
     729              : 
     730            0 :         case DATA_FEATURE_TYPE_TAGGED_VALUE:
     731              :         {
     732            0 :             const double center_x = ( left + right ) / 2.0;
     733              : 
     734            0 :             cairo_move_to( cr, center_x - 1.0 * line_w, y_coordinate + 10.0 * line_w );
     735            0 :             cairo_curve_to( cr,
     736            0 :                             center_x - 5.0 * line_w,
     737            0 :                             y_coordinate + 10.0 * line_w,
     738              :                             center_x - 1.0 * line_w,
     739            0 :                             y_coordinate + 6.0 * line_w,
     740            0 :                             center_x - 5.0 * line_w,
     741            0 :                             y_coordinate + 6.0 * line_w
     742              :             );
     743            0 :             cairo_curve_to( cr,
     744              :                             center_x - 1.0 * line_w,
     745            0 :                             y_coordinate + 6.0 * line_w,
     746            0 :                             center_x - 5.0 * line_w,
     747            0 :                             y_coordinate + 2.0 * line_w,
     748              :                             center_x - 1.0 * line_w,
     749            0 :                             y_coordinate + 2.0 * line_w
     750              :                           );
     751              : 
     752            0 :             cairo_move_to( cr, center_x + 1.0 * line_w, y_coordinate + 2.0 * line_w );
     753            0 :             cairo_curve_to( cr,
     754            0 :                             center_x + 5.0 * line_w,
     755            0 :                             y_coordinate + 2.0 * line_w,
     756              :                             center_x + 1.0 * line_w,
     757            0 :                             y_coordinate + 6.0 * line_w,
     758            0 :                             center_x + 5.0 * line_w,
     759            0 :                             y_coordinate + 6.0 * line_w
     760              :                           );
     761            0 :             cairo_curve_to( cr,
     762              :                             center_x + 1.0 * line_w,
     763            0 :                             y_coordinate + 6.0 * line_w,
     764            0 :                             center_x + 5.0 * line_w,
     765            0 :                             y_coordinate + 10.0 * line_w,
     766              :                             center_x + 1.0 * line_w,
     767            0 :                             y_coordinate + 10.0 * line_w
     768              :                           );
     769              : 
     770            0 :             cairo_stroke( cr );
     771              :         }
     772            0 :         break;
     773              : 
     774            0 :         default:
     775              :         {
     776              :             /* for all other cases; this switch is not exhaustive */
     777              :         }
     778            0 :         break;
     779              :     }
     780            0 :     cairo_set_source_rgba( cr, foreground_color->red, foreground_color->green, foreground_color->blue, foreground_color->alpha );
     781              : 
     782            0 :     U8_TRACE_END();
     783            0 : }
     784              : 
     785              : 
     786              : /*
     787              : Copyright 2016-2026 Andreas Warnke
     788              :     http://www.apache.org/licenses/LICENSE-2.0
     789              : 
     790              : Licensed under the Apache License, Version 2.0 (the "License");
     791              : you may not use this file except in compliance with the License.
     792              : You may obtain a copy of the License at
     793              : 
     794              : 
     795              : Unless required by applicable law or agreed to in writing, software
     796              : distributed under the License is distributed on an "AS IS" BASIS,
     797              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     798              : See the License for the specific language governing permissions and
     799              : limitations under the License.
     800              : */
        

Generated by: LCOV version 2.0-1