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.63.2_covts Lines: 31.6 % 392 124
Test Date: 2025-05-01 10:10:14 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_DIAGRAM_REFERENCE:  /* 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          128 : 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          128 :     U8_TRACE_BEGIN();
     168          128 :     assert ( NULL != inner_area );
     169          128 :     assert ( NULL != pencil_size );
     170              : 
     171              :     geometry_rectangle_t result;
     172          128 :     geometry_rectangle_init_empty( &result );
     173              : 
     174          128 :     double gap = pencil_size_get_standard_object_border( pencil_size );
     175          128 :     double double_gap = 2.0 * gap;  /* a line has the gap distance on both sides to the next object */
     176              : 
     177          128 :     switch ( classifier_type )
     178              :     {
     179            5 :         case DATA_CLASSIFIER_TYPE_USE_CASE:
     180              :         {
     181              :             /* within a use case, space is limited (double_gap is the border on each side): */
     182            5 :             double half_inner_width = 0.5 * geometry_rectangle_get_width( inner_area );
     183            5 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     184            5 :             double h_offset = half_inner_width * ( 1.0 / SINUS_OF_45_DEGREE - 1.0  );
     185            5 :             double v_offset = half_inner_height * ( 1.0 / SINUS_OF_45_DEGREE - 1.0  );
     186              : 
     187            5 :             geometry_rectangle_replace( &result, inner_area );
     188            5 :             geometry_rectangle_expand_4dir( &result, +double_gap + h_offset, +double_gap + v_offset );
     189              :         }
     190            5 :         break;
     191              : 
     192            5 :         case DATA_CLASSIFIER_TYPE_NODE:
     193              :         {
     194              :             /* the 3d border of a node shrinks the space */
     195            5 :             double offset_3d = double_gap;
     196              : 
     197            5 :             geometry_rectangle_replace( &result, inner_area );
     198            5 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap + offset_3d, +2.0 * double_gap + offset_3d );
     199            5 :             geometry_rectangle_shift( &result, -double_gap, -double_gap - offset_3d );
     200              :         }
     201            5 :         break;
     202              : 
     203            9 :         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            9 :             double symbol_icon_height = pencil_size_get_classifier_symbol_height( pencil_size );
     215              : 
     216            9 :             geometry_rectangle_replace( &result, inner_area );
     217            9 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap, +2.0 * double_gap + symbol_icon_height );
     218            9 :             geometry_rectangle_shift( &result, -double_gap, -double_gap - symbol_icon_height );
     219              :         }
     220            9 :         break;
     221              : 
     222           24 :         case DATA_CLASSIFIER_TYPE_DIAGRAM_REFERENCE:  /* and */
     223              :         case DATA_CLASSIFIER_TYPE_INTERACTION:  /* and */
     224              :         case DATA_CLASSIFIER_TYPE_PACKAGE:  /* and */
     225              :         case DATA_CLASSIFIER_TYPE_COMMENT:
     226              :         {
     227           24 :             double top_ornament_height = pencil_size_get_standard_font_size( pencil_size );
     228              : 
     229           24 :             geometry_rectangle_replace( &result, inner_area );
     230           24 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap, +2.0 * double_gap + top_ornament_height );
     231           24 :             geometry_rectangle_shift( &result, -double_gap, -double_gap - top_ornament_height );
     232              :         }
     233           24 :         break;
     234              : 
     235           70 :         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           70 :             geometry_rectangle_replace( &result, inner_area );
     252           70 :             geometry_rectangle_expand_4dir( &result, +double_gap, +double_gap );
     253              :         }
     254           70 :         break;
     255              : 
     256            5 :         case DATA_CLASSIFIER_TYPE_DYN_DECISION_NODE:
     257              :         {
     258              :             /* within a decision rhombus, space is limited by factor 2 per dimension: */
     259            5 :             double half_inner_width = 0.5 * geometry_rectangle_get_width( inner_area );
     260            5 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     261            5 :             double h_offset = half_inner_width;
     262            5 :             double v_offset = half_inner_height;
     263              : 
     264            5 :             geometry_rectangle_replace( &result, inner_area );
     265            5 :             geometry_rectangle_expand_4dir( &result, +double_gap + h_offset, +double_gap + v_offset );
     266              :         }
     267            5 :         break;
     268              : 
     269            5 :         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            5 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     273            5 :             double horizontal_offset = half_inner_height;
     274              : 
     275            5 :             geometry_rectangle_replace( &result, inner_area );
     276            5 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap + horizontal_offset, +2.0 * double_gap );
     277            5 :             geometry_rectangle_shift( &result, -double_gap - horizontal_offset, -double_gap );
     278              :         }
     279            5 :         break;
     280              : 
     281            5 :         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            5 :             double half_inner_height = 0.5 * geometry_rectangle_get_height( inner_area );
     285            5 :             double horizontal_offset = half_inner_height;
     286              : 
     287            5 :             geometry_rectangle_replace( &result, inner_area );
     288            5 :             geometry_rectangle_enlarge( &result, +2.0 * double_gap + horizontal_offset, +2.0 * double_gap );
     289            5 :             geometry_rectangle_shift( &result, -double_gap, -double_gap );
     290              :         }
     291            5 :         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          128 :     U8_TRACE_END();
     305          128 :     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              :                                                      const pencil_size_t *pencil_size,
     613              :                                                      cairo_t *cr )
     614              : {
     615            0 :     U8_TRACE_BEGIN();
     616            0 :     assert ( NULL != outer_bounds );
     617            0 :     assert ( NULL != pencil_size );
     618            0 :     assert ( NULL != cr );
     619              : 
     620            0 :     const double bounds_left = geometry_rectangle_get_left( outer_bounds );
     621            0 :     const double bounds_width = geometry_rectangle_get_width( outer_bounds );
     622            0 :     const double bounds_height = geometry_rectangle_get_height( outer_bounds );
     623            0 :     const double gap = pencil_size_get_standard_object_border( pencil_size );
     624              : 
     625            0 :     double left = bounds_left + gap;
     626            0 :     double right = bounds_left + bounds_width - gap;
     627            0 :     switch ( classifier_type )
     628              :     {
     629            0 :         case DATA_CLASSIFIER_TYPE_USE_CASE:
     630              :         {
     631            0 :             const double center_x = geometry_rectangle_get_center_x( outer_bounds );
     632            0 :             const double center_y = geometry_rectangle_get_center_y( outer_bounds );
     633            0 :             const double radius_x = ( bounds_width / 2.0 ) - gap; /* there is 1.0*gap around the ellipsis */
     634            0 :             const double radius_y = ( bounds_height / 2.0 ) - gap; /* there is 1.0*gap around the ellipsis */
     635            0 :             const double norm_dy = ( y_coordinate - center_y ) / radius_y;
     636            0 :             const double sqr_norm_dx = 1.0 - ( norm_dy * norm_dy );
     637            0 :             if ( sqr_norm_dx >= 0.0 )
     638              :             {
     639            0 :                 const double dx = sqrt( sqr_norm_dx ) * radius_x;
     640            0 :                 left = center_x - dx;
     641            0 :                 right = center_x + dx;
     642              :             }
     643              :             else
     644              :             {
     645            0 :                 left = bounds_left + gap;
     646            0 :                 right = bounds_left + bounds_width - gap;
     647              :             }
     648              :         }
     649            0 :         break;
     650              : 
     651            0 :         case DATA_CLASSIFIER_TYPE_NODE:
     652              :         {
     653              :             /* the 3d border of a node shrinks the space */
     654            0 :             const double offset_3d = 2.0 * gap;
     655            0 :             left = bounds_left + gap;
     656            0 :             right = bounds_left + bounds_width - offset_3d - gap;
     657              :         }
     658            0 :         break;
     659              : 
     660            0 :         default:
     661              :         {
     662              :             /* for all other cases; this switch is not exhaustive */
     663            0 :             left = bounds_left + gap;
     664            0 :             right = bounds_left + bounds_width - gap;
     665              :         }
     666            0 :         break;
     667              :     }
     668              : 
     669            0 :     cairo_move_to ( cr, left, y_coordinate );
     670            0 :     cairo_line_to ( cr, right, y_coordinate );
     671            0 :     cairo_stroke (cr);
     672              : 
     673            0 :     U8_TRACE_END();
     674            0 : }
     675              : 
     676              : 
     677              : /*
     678              : Copyright 2016-2025 Andreas Warnke
     679              :     http://www.apache.org/licenses/LICENSE-2.0
     680              : 
     681              : Licensed under the Apache License, Version 2.0 (the "License");
     682              : you may not use this file except in compliance with the License.
     683              : You may obtain a copy of the License at
     684              : 
     685              : 
     686              : Unless required by applicable law or agreed to in writing, software
     687              : distributed under the License is distributed on an "AS IS" BASIS,
     688              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     689              : See the License for the specific language governing permissions and
     690              : limitations under the License.
     691              : */
        

Generated by: LCOV version 2.0-1