LCOV - code coverage report
Current view: top level - pencil/source/draw - draw_diagram_label.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.69.0_covts Lines: 0.0 % 128 0
Test Date: 2026-03-08 20:58:47 Functions: 0.0 % 4 0

            Line data    Source code
       1              :   /* File: draw_diagram_label.c; Copyright and License: see below */
       2              : 
       3              : #include "draw/draw_diagram_label.h"
       4              : #include "u8/u8_trace.h"
       5              : #include "entity/data_classifier.h"
       6              : #include "entity/data_diagramelement.h"
       7              : #include "u8/u8_f64.h"
       8              : #include "utf8stringbuf/utf8stringbuf.h"
       9              : #include "utf8stringbuf/utf8string.h"
      10              : #include <pango/pangocairo.h>
      11              : #include <stdio.h>
      12              : #include <stdlib.h>
      13              : #include <assert.h>
      14              : 
      15              : static const int DRAW_DIAGRAM_PANGO_AUTO_DETECT_LENGTH = -1;
      16              : #define DRAW_DIAGRAM_LEFT_GUILLEMETS "\xc2\xab"
      17              : #define DRAW_DIAGRAM_RIGHT_GUILLEMETS "\xc2\xbb"
      18              : 
      19            0 : void draw_diagram_label_init( draw_diagram_label_t *this_ )
      20              : {
      21            0 :     utf8stream_writemem_init( &((*this_).text_builder), &((*this_).text_buffer), sizeof( (*this_).text_buffer) );
      22            0 :     draw_stereotype_icon_init( &((*this_).image_renderer) );
      23            0 : }
      24              : 
      25            0 : void draw_diagram_label_destroy( draw_diagram_label_t *this_ )
      26              : {
      27            0 :     const u8_error_t text_err = utf8stream_writemem_destroy( &((*this_).text_builder) );
      28            0 :     if ( text_err != U8_ERROR_NONE )
      29              :     {
      30            0 :         U8_LOG_WARNING_HEX( "error at draw/draw_diagram_label: buffer too small", text_err );
      31              :     }
      32            0 :     draw_stereotype_icon_destroy( &((*this_).image_renderer) );
      33            0 : }
      34              : 
      35            0 : void draw_diagram_label_get_type_and_name_dimensions ( draw_diagram_label_t *this_,
      36              :                                                        const data_diagram_t *diagram,
      37              :                                                        const data_profile_part_t *profile,
      38              :                                                        const geometry_dimensions_t *proposed_bounds,
      39              :                                                        const pencil_size_t *pencil_size,
      40              :                                                        PangoLayout *font_layout,
      41              :                                                        geometry_dimensions_t *out_label_dim )
      42              : {
      43            0 :     U8_TRACE_BEGIN();
      44            0 :     assert( NULL != diagram );
      45            0 :     assert( NULL != profile );
      46            0 :     assert( NULL != proposed_bounds );
      47            0 :     assert( NULL != pencil_size );
      48            0 :     assert( NULL != font_layout );
      49            0 :     assert( NULL != out_label_dim );
      50              : 
      51            0 :     if ( data_diagram_is_valid( diagram ) )
      52              :     {
      53              :         /* calc stereotype image bounds */
      54            0 :         const char *const diagram_stereotype = data_diagram_get_stereotype_const( diagram );
      55              :         const bool has_stereotype_image
      56            0 :             = draw_stereotype_icon_exists( &((*this_).image_renderer), diagram_stereotype, profile );
      57            0 :         const geometry_dimensions_t icon_dim
      58              :             = has_stereotype_image
      59            0 :             ? draw_stereotype_icon_get_dimensions( &((*this_).image_renderer), pencil_size )
      60            0 :             : (geometry_dimensions_t){ .width = 0.0, .height = 0.0 };
      61            0 :         const bool has_stereotype_text
      62            0 :             = ( ! has_stereotype_image ) && data_diagram_has_stereotype( diagram );
      63            0 :         const double f_tab_size = pencil_size_get_font_tab_size( pencil_size );
      64              : 
      65              :         /* calc stereotype/type text dimensions (unless has_stereotype_image) */
      66            0 :         int text1_width = 0;
      67            0 :         int text1_height = 0;
      68            0 :         if ( ! has_stereotype_image )
      69              :         {
      70              :             /* prepare text */
      71            0 :             u8_error_t stereotype_err = U8_ERROR_NONE;
      72            0 :             utf8stream_writer_t *to_type = utf8stream_writemem_get_writer( &((*this_).text_builder) );
      73              : 
      74              :             /* build text */
      75            0 :             if ( has_stereotype_text )
      76              :             {
      77            0 :                 stereotype_err |= utf8stream_writer_write_str( to_type, DRAW_DIAGRAM_LEFT_GUILLEMETS );
      78            0 :                 stereotype_err |= utf8stream_writer_write_str( to_type, diagram_stereotype );
      79            0 :                 stereotype_err |= utf8stream_writer_write_str( to_type, DRAW_DIAGRAM_RIGHT_GUILLEMETS );
      80            0 :                 stereotype_err |= utf8stream_writer_flush( to_type );
      81              :             }
      82              :             else
      83              :             {
      84            0 :                 const char *element_kind = data_diagram_type_get_element_kind( data_diagram_get_diagram_type( diagram ) );
      85            0 :                 stereotype_err |= utf8stream_writer_write_str( to_type, element_kind );
      86            0 :                 stereotype_err |= utf8stream_writer_flush( to_type );
      87              :             }
      88            0 :             const utf8stringview_t stereotype_text = utf8stream_writemem_get_view( &((*this_).text_builder) );
      89              : 
      90              :             /* determine text width and height */
      91            0 :             pango_layout_set_font_description( font_layout, pencil_size_get_standard_font_description( pencil_size ) );
      92            0 :             pango_layout_set_text( font_layout,
      93              :                                    utf8stringview_get_start( &stereotype_text ),
      94            0 :                                    utf8stringview_get_length( &stereotype_text )
      95              :                                  );
      96            0 :             pango_layout_get_pixel_size( font_layout, &text1_width, &text1_height );
      97            0 :             text1_height += PENCIL_SIZE_FONT_ALIGN_MARGIN;  /* allow to align font with pixel border */
      98            0 :             text1_width += PENCIL_SIZE_FONT_ALIGN_MARGIN;
      99              : 
     100              :             /* cleanup the text_builder */
     101            0 :             stereotype_err |= utf8stream_writemem_reset( &((*this_).text_builder) );
     102            0 :             if ( stereotype_err != U8_ERROR_NONE )
     103              :             {
     104            0 :                 U8_LOG_WARNING_HEX( "error at get_dim/draw_line_breaker_append", stereotype_err );
     105              :             }
     106              :         }
     107              : 
     108              :         /* calc name text dimensions */
     109              :         /* int proposed_pango_width = geometry_dimensions_get_width( proposed_bounds ); */
     110            0 :         int text2_height = 0;
     111            0 :         int text2_width = 0;
     112            0 :         if ( 0 != utf8string_get_length( data_diagram_get_name_const( diagram ) ))
     113              :         {
     114            0 :             pango_layout_set_font_description( font_layout, pencil_size_get_standard_font_description( pencil_size ) );
     115            0 :             pango_layout_set_text( font_layout,
     116              :                                    data_diagram_get_name_const( diagram ),
     117              :                                    DRAW_DIAGRAM_PANGO_AUTO_DETECT_LENGTH
     118              :                                  );
     119            0 :             pango_layout_get_pixel_size (font_layout, &text2_width, &text2_height);
     120            0 :             text2_height += PENCIL_SIZE_FONT_ALIGN_MARGIN;  /* allow to align font with pixel border */
     121            0 :             text2_width += PENCIL_SIZE_FONT_ALIGN_MARGIN;
     122              :         }
     123              : 
     124            0 :         *out_label_dim = (geometry_dimensions_t) {
     125            0 :             .width = geometry_dimensions_get_width( &icon_dim ) + text1_width + f_tab_size + text2_width + f_tab_size,
     126            0 :             .height = u8_f64_max3( geometry_dimensions_get_height( &icon_dim ), text1_height, text2_height )
     127              :         };
     128              :     }
     129              :     else
     130              :     {
     131            0 :         U8_LOG_ERROR("invalid diagram in draw_diagram_label_get_type_and_name_dimensions()");
     132            0 :         *out_label_dim = (geometry_dimensions_t) { .width = 0.0, .height = 0.0 };
     133              :     }
     134            0 :     U8_TRACE_END();
     135            0 : }
     136              : 
     137            0 : void draw_diagram_label_draw_type_and_name ( draw_diagram_label_t *this_,
     138              :                                              const data_diagram_t *diagram,
     139              :                                              const data_profile_part_t *profile,
     140              :                                              const GdkRGBA *color,
     141              :                                              const geometry_rectangle_t *label_box,
     142              :                                              const pencil_size_t *pencil_size,
     143              :                                              PangoLayout *font_layout,
     144              :                                              cairo_t *cr )
     145              : {
     146            0 :     U8_TRACE_BEGIN();
     147            0 :     assert( NULL != diagram );
     148            0 :     assert( NULL != profile );
     149            0 :     assert( NULL != color );
     150            0 :     assert( NULL != label_box );
     151            0 :     assert( NULL != pencil_size );
     152            0 :     assert( NULL != font_layout );
     153            0 :     assert( NULL != cr );
     154              : 
     155              :     /* calc bounds of stereotype icon */
     156            0 :     const char *const diagram_stereotype = data_diagram_get_stereotype_const( diagram );
     157              :     const bool has_stereotype_image
     158            0 :         = draw_stereotype_icon_exists( &((*this_).image_renderer), diagram_stereotype, profile );
     159            0 :     const geometry_rectangle_t stereotype_box
     160              :         = has_stereotype_image
     161            0 :         ? draw_stereotype_icon_get_bounds( &((*this_).image_renderer),
     162              :                                             geometry_rectangle_get_left( label_box ),
     163              :                                             geometry_rectangle_get_top( label_box ),
     164              :                                             GEOMETRY_H_ALIGN_LEFT,
     165              :                                             GEOMETRY_V_ALIGN_TOP,
     166              :                                             pencil_size
     167              :                                           )
     168            0 :         : (geometry_rectangle_t){ .left = 0.0, .top = 0.0, .width = 0.0, .height = 0.0 };
     169            0 :     const bool has_stereotype_text
     170            0 :         = ( ! has_stereotype_image ) && data_diagram_has_stereotype( diagram );
     171            0 :     const double f_tab_size = pencil_size_get_font_tab_size( pencil_size );
     172              : 
     173              :     /* draw stereotype icon */
     174            0 :     if ( has_stereotype_image )
     175              :     {
     176              :         u8_error_info_t err_info;
     177              :         const u8_error_t stereotype_err
     178            0 :             = draw_stereotype_icon_draw( &((*this_).image_renderer),
     179              :                                           diagram_stereotype,
     180              :                                           profile,
     181              :                                           color,
     182              :                                           &err_info,
     183              :                                           &stereotype_box,
     184              :                                           cr
     185              :                                         );
     186            0 :         if ( u8_error_info_is_error( &err_info ) )
     187              :         {
     188            0 :             U8_LOG_WARNING_INT( "stereotype image: unxpected token in svg path in line",
     189              :                                 u8_error_info_get_line( &err_info )
     190              :                               );
     191              :         }
     192            0 :         else if ( stereotype_err != U8_ERROR_NONE )
     193              :         {
     194            0 :             U8_LOG_WARNING_HEX( "error at drawing stereotype image", stereotype_err );
     195              :         }
     196              :     }
     197              : 
     198              :     /* calc stereotype/type text dimensions (unless has_stereotype_image) */
     199            0 :     int text1_width = 0;
     200            0 :     int text1_height = 0;
     201            0 :     if ( ! has_stereotype_image )
     202              :     {
     203              :         /* prepare text */
     204            0 :         u8_error_t stereotype_err = U8_ERROR_NONE;
     205            0 :         utf8stream_writer_t *to_type = utf8stream_writemem_get_writer( &((*this_).text_builder) );
     206              : 
     207              :         /* build text */
     208            0 :         if ( has_stereotype_text )
     209              :         {
     210            0 :             stereotype_err |= utf8stream_writer_write_str( to_type, DRAW_DIAGRAM_LEFT_GUILLEMETS );
     211            0 :             stereotype_err |= utf8stream_writer_write_str( to_type, diagram_stereotype );
     212            0 :             stereotype_err |= utf8stream_writer_write_str( to_type, DRAW_DIAGRAM_RIGHT_GUILLEMETS );
     213            0 :             stereotype_err |= utf8stream_writer_flush( to_type );
     214              :         }
     215              :         else
     216              :         {
     217            0 :             const char *element_kind = data_diagram_type_get_element_kind( data_diagram_get_diagram_type( diagram ) );
     218            0 :             stereotype_err |= utf8stream_writer_write_str( to_type, element_kind );
     219            0 :             stereotype_err |= utf8stream_writer_flush( to_type );
     220              :         }
     221            0 :         const utf8stringview_t stereotype_text = utf8stream_writemem_get_view( &((*this_).text_builder) );
     222              : 
     223              :         /* determine text width and height */
     224            0 :         pango_layout_set_font_description( font_layout, pencil_size_get_standard_font_description( pencil_size ) );
     225            0 :         pango_layout_set_text( font_layout,
     226              :                                utf8stringview_get_start( &stereotype_text ),
     227            0 :                                utf8stringview_get_length( &stereotype_text )
     228              :                              );
     229            0 :         pango_layout_get_pixel_size( font_layout, &text1_width, &text1_height );
     230            0 :         text1_height += PENCIL_SIZE_FONT_ALIGN_MARGIN;  /* allow to align font with pixel border */
     231            0 :         text1_width += PENCIL_SIZE_FONT_ALIGN_MARGIN;
     232              : 
     233              :         /* draw */
     234            0 :         const GdkRGBA grey_color = pencil_size_get_gray_out_color( pencil_size );
     235            0 :         cairo_set_source_rgba( cr, grey_color.red, grey_color.green, grey_color.blue, grey_color.alpha );
     236            0 :         cairo_move_to( cr,
     237              :                        ceil( geometry_rectangle_get_left( label_box ) ),
     238              :                        ceil( geometry_rectangle_get_top( label_box ) )
     239              :                      );  /* align font with pixel border */
     240            0 :         pango_cairo_show_layout( cr, font_layout );
     241            0 :         const GdkRGBA black_color = pencil_size_get_standard_color( pencil_size );
     242            0 :         cairo_set_source_rgba( cr, black_color.red, black_color.green, black_color.blue, black_color.alpha );
     243              : 
     244              :         /* cleanup the text_builder */
     245            0 :         stereotype_err |= utf8stream_writemem_reset( &((*this_).text_builder) );
     246            0 :         if ( stereotype_err != U8_ERROR_NONE )
     247              :         {
     248            0 :             U8_LOG_WARNING_HEX( "error at get_dim/draw_line_breaker_append", stereotype_err );
     249              :         }
     250              :     }
     251              : 
     252              :     /* define names for input data */
     253            0 :     const double text_left
     254            0 :         = geometry_rectangle_get_left( label_box ) + geometry_rectangle_get_width( &stereotype_box ) + text1_width + f_tab_size;
     255            0 :     const double text_top = geometry_rectangle_get_top( label_box );
     256              : 
     257              :     /* draw name text */
     258            0 :     if ( 0 != utf8string_get_length( data_diagram_get_name_const( diagram ) ))
     259              :     {
     260            0 :         cairo_set_source_rgba( cr, color->red, color->green, color->blue, color->alpha );
     261            0 :         pango_layout_set_font_description (font_layout, pencil_size_get_standard_font_description(pencil_size) );
     262            0 :         pango_layout_set_text( font_layout,
     263              :                                data_diagram_get_name_const( diagram ),
     264              :                                DRAW_DIAGRAM_PANGO_AUTO_DETECT_LENGTH
     265              :                              );
     266              : 
     267              :         /* draw text */
     268            0 :         cairo_move_to ( cr, ceil( text_left ), ceil( text_top ) );  /* align font with pixel border */
     269            0 :         pango_cairo_show_layout (cr, font_layout);
     270              :     }
     271              : 
     272            0 :     U8_TRACE_END();
     273            0 : }
     274              : 
     275              : 
     276              : /*
     277              : Copyright 2017-2026 Andreas Warnke
     278              :     http://www.apache.org/licenses/LICENSE-2.0
     279              : 
     280              : Licensed under the Apache License, Version 2.0 (the "License");
     281              : you may not use this file except in compliance with the License.
     282              : You may obtain a copy of the License at
     283              : 
     284              : 
     285              : Unless required by applicable law or agreed to in writing, software
     286              : distributed under the License is distributed on an "AS IS" BASIS,
     287              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     288              : See the License for the specific language governing permissions and
     289              : limitations under the License.
     290              : */
        

Generated by: LCOV version 2.0-1