LCOV - code coverage report
Current view: top level - pencil/source/draw - draw_feature_label.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 0 80 0.0 %
Date: 2024-04-07 11:14:42 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /* File: draw_feature_label.c; Copyright and License: see below */
       2             : 
       3             : #include "draw/draw_feature_label.h"
       4             : #include "u8/u8_trace.h"
       5             : #include "data_classifier.h"
       6             : #include "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_FEATURE_PANGO_UNLIMITED_WIDTH = -1;
      16             : static const int DRAW_LABEL_PANGO_AUTO_DETECT_LENGTH = -1;
      17             : 
      18           0 : void draw_feature_label_get_key_and_value_dimensions ( const draw_feature_label_t *this_,
      19             :                                                        const data_feature_t *feature,
      20             :                                                        const data_profile_part_t *profile,
      21             :                                                        const geometry_dimensions_t *proposed_bounds,
      22             :                                                        const pencil_size_t *pencil_size,
      23             :                                                        PangoLayout *font_layout,
      24             :                                                        geometry_dimensions_t *out_label_dim )
      25             : {
      26           0 :     U8_TRACE_BEGIN();
      27           0 :     assert( NULL != feature );
      28           0 :     assert( NULL != profile );
      29           0 :     assert( NULL != proposed_bounds );
      30           0 :     assert( NULL != pencil_size );
      31           0 :     assert( NULL != font_layout );
      32           0 :     assert( NULL != out_label_dim );
      33             : 
      34           0 :     if ( data_feature_is_valid( feature ) )
      35             :     {
      36             :         /* calc stereotype image bounds */
      37           0 :         const char *const feature_stereotype = data_feature_get_value_const( feature );
      38             :         const bool has_stereotype_image
      39           0 :             = draw_stereotype_image_exists( &((*this_).image_renderer), feature_stereotype, profile );
      40           0 :         const geometry_dimensions_t icon_dim
      41             :             = has_stereotype_image
      42           0 :             ? draw_stereotype_image_get_dimensions( &((*this_).image_renderer), pencil_size )
      43           0 :             : (geometry_dimensions_t){ .width = 0.0, .height = 0.0 };
      44           0 :         const double icon_gap = has_stereotype_image ? pencil_size_get_standard_object_border( pencil_size ) : 0.0;
      45             : 
      46             :         /* draw text - except for lifelines */
      47           0 :         int proposed_pango_width = geometry_dimensions_get_width( proposed_bounds );
      48           0 :         int text_width = 0;
      49           0 :         int text_height = 0;
      50           0 :         if ( DATA_FEATURE_TYPE_LIFELINE != data_feature_get_main_type (feature) )
      51             :         {
      52             :             /* prepare text */
      53             :             char label_text[DATA_FEATURE_MAX_KEY_SIZE + DATA_FEATURE_MAX_VALUE_SIZE + 2 ];
      54           0 :             utf8stringbuf_t label_buf = UTF8STRINGBUF(label_text);
      55           0 :             utf8stringbuf_copy_str( label_buf, data_feature_get_key_const( feature ) );
      56           0 :             if ( data_feature_has_value( feature ) && ( ! has_stereotype_image ) )
      57             :             {
      58           0 :                 utf8stringbuf_append_str( label_buf, ": " );
      59           0 :                 utf8stringbuf_append_str( label_buf, data_feature_get_value_const( feature ) );
      60             :             }
      61             : 
      62             :             /* determine text width and height */
      63           0 :             pango_layout_set_font_description (font_layout, pencil_size_get_standard_font_description(pencil_size) );
      64           0 :             pango_layout_set_text (font_layout, utf8stringbuf_get_string( label_buf ), DRAW_LABEL_PANGO_AUTO_DETECT_LENGTH );
      65           0 :             pango_layout_set_width(font_layout, proposed_pango_width * PANGO_SCALE );
      66           0 :             pango_layout_get_pixel_size (font_layout, &text_width, &text_height);
      67           0 :             text_height += PENCIL_SIZE_FONT_ALIGN_MARGIN;  /* allow to align font with pixel border */
      68           0 :             text_width += PENCIL_SIZE_FONT_ALIGN_MARGIN;
      69             :             /* restore pango context */
      70           0 :             pango_layout_set_width(font_layout, DRAW_FEATURE_PANGO_UNLIMITED_WIDTH);
      71             :         }
      72             : 
      73           0 :         *out_label_dim = (geometry_dimensions_t) {
      74           0 :             .width = geometry_dimensions_get_width( &icon_dim ) + icon_gap + text_width,
      75           0 :             .height = u8_f64_max2( geometry_dimensions_get_height( &icon_dim ), text_height )
      76             :         };
      77             :     }
      78             :     else
      79             :     {
      80           0 :         U8_LOG_ERROR("invalid feature in draw_feature_label_get_key_and_value_dimensions()");
      81           0 :         *out_label_dim = (geometry_dimensions_t) { .width = 0.0, .height = 0.0 };
      82             :     }
      83           0 :     U8_TRACE_END();
      84           0 : }
      85             : 
      86           0 : void draw_feature_label_draw_key_and_value ( const draw_feature_label_t *this_,
      87             :                                              const data_feature_t *feature,
      88             :                                              const data_profile_part_t *profile,
      89             :                                              const GdkRGBA *color,
      90             :                                              const geometry_rectangle_t *label_box,
      91             :                                              const pencil_size_t *pencil_size,
      92             :                                              PangoLayout *font_layout,
      93             :                                              cairo_t *cr )
      94             : {
      95           0 :     U8_TRACE_BEGIN();
      96           0 :     assert( NULL != feature );
      97           0 :     assert( NULL != profile );
      98           0 :     assert( NULL != color );
      99           0 :     assert( NULL != label_box );
     100           0 :     assert( NULL != pencil_size );
     101           0 :     assert( NULL != font_layout );
     102           0 :     assert( NULL != cr );
     103             : 
     104             :     /* calc bounds of stereotype icon */
     105           0 :     const char *const feature_stereotype = data_feature_get_value_const( feature );
     106             :     const bool has_stereotype_image
     107           0 :         = draw_stereotype_image_exists( &((*this_).image_renderer), feature_stereotype, profile );
     108           0 :     const geometry_rectangle_t stereotype_box
     109             :         = has_stereotype_image
     110           0 :         ? draw_stereotype_image_get_bounds( &((*this_).image_renderer),
     111             :                                             geometry_rectangle_get_left( label_box ),
     112             :                                             geometry_rectangle_get_top( label_box ),
     113             :                                             GEOMETRY_H_ALIGN_LEFT,
     114             :                                             GEOMETRY_V_ALIGN_TOP,
     115             :                                             pencil_size
     116             :                                           )
     117           0 :         : (geometry_rectangle_t){ .left = 0.0, .top = 0.0, .width = 0.0, .height = 0.0 };
     118           0 :     const double icon_gap = has_stereotype_image ? pencil_size_get_standard_object_border( pencil_size ) : 0.0;
     119             : 
     120             :     /* draw stereotype icon */
     121           0 :     if ( has_stereotype_image )
     122             :     {
     123             :         u8_error_info_t err_info;
     124             :         const u8_error_t stereotype_err
     125           0 :             = draw_stereotype_image_draw( &((*this_).image_renderer),
     126             :                                           feature_stereotype,
     127             :                                           profile,
     128             :                                           color,
     129             :                                           &err_info,
     130             :                                           &stereotype_box,
     131             :                                           cr
     132             :                                         );
     133           0 :         if ( u8_error_info_is_error( &err_info ) )
     134             :         {
     135           0 :             U8_LOG_WARNING_INT( "stereotype image: unxpected token in svg path in line",
     136             :                                 u8_error_info_get_line( &err_info )
     137             :                               );
     138             :         }
     139           0 :         else if ( stereotype_err != U8_ERROR_NONE )
     140             :         {
     141           0 :             U8_LOG_WARNING_HEX( "error at drawing stereotype image", stereotype_err );
     142             :         }
     143             :     }
     144             : 
     145             :     /* define names for input data: */
     146           0 :     const double text_left
     147           0 :         = geometry_rectangle_get_left( label_box ) + geometry_rectangle_get_width( &stereotype_box ) + icon_gap;
     148           0 :     const double text_top = geometry_rectangle_get_top( label_box );
     149           0 :     const double text_width
     150           0 :         = geometry_rectangle_get_width( label_box ) - geometry_rectangle_get_width( &stereotype_box ) - icon_gap;
     151             : 
     152             :     /* draw text - except for lifelines */
     153           0 :     if ( DATA_FEATURE_TYPE_LIFELINE != data_feature_get_main_type (feature) )
     154             :     {
     155             :         /* prepare text */
     156             :         char label_text[DATA_FEATURE_MAX_KEY_SIZE + DATA_FEATURE_MAX_VALUE_SIZE + 2 ];
     157           0 :         utf8stringbuf_t label_buf = UTF8STRINGBUF(label_text);
     158           0 :         utf8stringbuf_copy_str( label_buf, data_feature_get_key_const( feature ) );
     159           0 :         if ( data_feature_has_value( feature ) && ( ! has_stereotype_image ) )
     160             :         {
     161           0 :             utf8stringbuf_append_str( label_buf, ": " );
     162           0 :             utf8stringbuf_append_str( label_buf, data_feature_get_value_const( feature ) );
     163             :         }
     164             : 
     165           0 :         const double f_size = pencil_size_get_standard_font_size( pencil_size );
     166           0 :         cairo_set_source_rgba( cr, color->red, color->green, color->blue, color->alpha );
     167           0 :         pango_layout_set_font_description (font_layout, pencil_size_get_standard_font_description(pencil_size) );
     168           0 :         pango_layout_set_text (font_layout, utf8stringbuf_get_string( label_buf ), DRAW_LABEL_PANGO_AUTO_DETECT_LENGTH);
     169           0 :         pango_layout_set_width(font_layout, (text_width+f_size) * PANGO_SCALE );  /* add gap to avoid line breaks by rounding errors and whitespace character widths */
     170             : 
     171             :         /* draw text */
     172           0 :         cairo_move_to ( cr, ceil( text_left ), ceil( text_top ) );  /* align font with pixel border */
     173           0 :         pango_cairo_show_layout (cr, font_layout);
     174             : 
     175             :         /* restore pango context */
     176           0 :         pango_layout_set_width(font_layout, DRAW_FEATURE_PANGO_UNLIMITED_WIDTH);
     177             :     }
     178             : 
     179           0 :     U8_TRACE_END();
     180           0 : }
     181             : 
     182             : 
     183             : /*
     184             : Copyright 2017-2024 Andreas Warnke
     185             :     http://www.apache.org/licenses/LICENSE-2.0
     186             : 
     187             : Licensed under the Apache License, Version 2.0 (the "License");
     188             : you may not use this file except in compliance with the License.
     189             : You may obtain a copy of the License at
     190             : 
     191             : 
     192             : Unless required by applicable law or agreed to in writing, software
     193             : distributed under the License is distributed on an "AS IS" BASIS,
     194             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     195             : See the License for the specific language governing permissions and
     196             : limitations under the License.
     197             : */

Generated by: LCOV version 1.16