LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_anchor.inl (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.71.2_covts Lines: 97.4 % 78 76
Test Date: 2026-08-22 19:47:36 Functions: 100.0 % 13 13

            Line data    Source code
       1              : /* File: geometry_anchor.inl; Copyright and License: see below */
       2              : 
       3              : #include "u8/u8_trace.h"
       4              : #include "u8/u8_log.h"
       5              : #include "u8/u8_f64.h"
       6              : #include <assert.h>
       7              : #include <math.h>
       8              : 
       9            3 : static inline void geometry_anchor_init( geometry_anchor_t *this_,
      10              :                                          double x,
      11              :                                          double y,
      12              :                                          geometry_h_align_t x_align,
      13              :                                          geometry_v_align_t y_align )
      14              : {
      15            3 :     geometry_point_init( &((*this_).reference_point), x, y );
      16            3 :     (*this_).x_align = x_align;
      17            3 :     (*this_).y_align = y_align;
      18            3 : }
      19              : 
      20            1 : static inline void geometry_anchor_copy( geometry_anchor_t *this_, const geometry_anchor_t *original )
      21              : {
      22            1 :     assert( NULL != original );
      23            1 :     (*this_) = (*original);
      24            1 : }
      25              : 
      26            1 : static inline void geometry_anchor_replace( geometry_anchor_t *this_, const geometry_anchor_t *original )
      27              : {
      28            1 :     assert( NULL != original );
      29            1 :     (*this_) = (*original);
      30            1 : }
      31              : 
      32            3 : static inline void geometry_anchor_destroy( geometry_anchor_t *this_ )
      33              : {
      34            3 :     geometry_point_destroy( &((*this_).reference_point) );
      35            3 : }
      36              : 
      37            1 : static inline double geometry_anchor_get_x( const geometry_anchor_t *this_ )
      38              : {
      39            1 :     return geometry_point_get_x( &((*this_).reference_point) );
      40              : }
      41              : 
      42            1 : static inline double geometry_anchor_get_y( const geometry_anchor_t *this_ )
      43              : {
      44            1 :     return geometry_point_get_y( &((*this_).reference_point) );
      45              : }
      46              : 
      47            1 : static inline geometry_h_align_t geometry_anchor_get_x_align( const geometry_anchor_t *this_ )
      48              : {
      49            1 :     return (*this_).x_align;
      50              : }
      51              : 
      52            1 : static inline geometry_v_align_t geometry_anchor_get_y_align( const geometry_anchor_t *this_ )
      53              : {
      54            1 :     return (*this_).y_align;
      55              : }
      56              : 
      57            1 : static inline const geometry_point_t * geometry_anchor_get_point_const( const geometry_anchor_t *this_ )
      58              : {
      59            1 :     return &((*this_).reference_point);
      60              : }
      61              : 
      62            1 : static inline geometry_rectangle_t geometry_anchor_align_rect( const geometry_anchor_t *this_,
      63              :                                                                const geometry_rectangle_t *unaligned )
      64              : {
      65            1 :     assert( unaligned != NULL );
      66              : 
      67              :     geometry_rectangle_t result;
      68              : 
      69            1 :     const double width = geometry_rectangle_get_width( unaligned );
      70            1 :     const double height = geometry_rectangle_get_height( unaligned );
      71              : 
      72            1 :     const double left = geometry_h_align_get_left( &((*this_).x_align),
      73              :                                                    width,
      74              :                                                    geometry_point_get_x( &((*this_).reference_point) ),
      75              :                                                    0.0 /* reference_width is zero, the reference is a point */
      76              :                                                  );
      77            1 :     const double top = geometry_v_align_get_top( &((*this_).y_align),
      78              :                                                  height,
      79              :                                                  geometry_point_get_y( &((*this_).reference_point) ),
      80              :                                                  0.0 /* reference_height is zero, the reference is a point */
      81              :                                                );
      82              : 
      83            1 :     geometry_rectangle_init( &result, left, top, width, height );
      84            1 :     return result;
      85              : }
      86              : 
      87            1 : static inline geometry_rectangle_t geometry_anchor_align_dim ( const geometry_anchor_t *this_,
      88              :                                                                const geometry_dimensions_t *unaligned )
      89              : {
      90            1 :     assert( unaligned != NULL );
      91              : 
      92              :     geometry_rectangle_t result;
      93              : 
      94            1 :     const double width = geometry_dimensions_get_width( unaligned );
      95            1 :     const double height = geometry_dimensions_get_height( unaligned );
      96              : 
      97            1 :     const double left = geometry_h_align_get_left( &((*this_).x_align),
      98              :                                                    width,
      99              :                                                    geometry_point_get_x( &((*this_).reference_point) ),
     100              :                                                    0.0 /* reference_width is zero, the reference is a point */
     101              :                                                  );
     102            1 :     const double top = geometry_v_align_get_top( &((*this_).y_align),
     103              :                                                  height,
     104              :                                                  geometry_point_get_y( &((*this_).reference_point) ),
     105              :                                                  0.0 /* reference_height is zero, the reference is a point */
     106              :                                                );
     107              : 
     108            1 :     geometry_rectangle_init( &result, left, top, width, height );
     109            1 :     return result;
     110              : }
     111              : 
     112            8 : static inline geometry_rectangle_t geometry_anchor_align_dim_closest( const geometry_anchor_t *this_,
     113              :                                                                       const geometry_dimensions_t *unaligned,
     114              :                                                                       const geometry_rectangle_t *permitted_area )
     115              : {
     116            8 :     assert( unaligned != NULL );
     117            8 :     assert( permitted_area != NULL );
     118              : 
     119              :     geometry_rectangle_t result;
     120              : 
     121            8 :     const double width = geometry_dimensions_get_width( unaligned );
     122            8 :     const double height = geometry_dimensions_get_height( unaligned );
     123              : 
     124            8 :     const double left = geometry_h_align_get_left( &((*this_).x_align),
     125              :                                                    width,
     126              :                                                    geometry_point_get_x( &((*this_).reference_point) ),
     127              :                                                    0.0 /* reference_width is zero, the reference is a point */
     128              :                                                  );
     129            8 :     const double top = geometry_v_align_get_top( &((*this_).y_align),
     130              :                                                  height,
     131              :                                                  geometry_point_get_y( &((*this_).reference_point) ),
     132              :                                                  0.0 /* reference_height is zero, the reference is a point */
     133              :                                                );
     134              : 
     135              :     /* force the result into permitted_area */
     136            8 :     const double right = left + width;
     137            8 :     const double bottom = top + height;
     138            8 :     const double permitted_left = geometry_rectangle_get_left( permitted_area );
     139            8 :     const double permitted_top = geometry_rectangle_get_top( permitted_area );
     140            8 :     const double permitted_right = geometry_rectangle_get_right( permitted_area );
     141            8 :     const double permitted_bottom = geometry_rectangle_get_bottom( permitted_area );
     142            8 :     double new_left = left;
     143            8 :     double new_top = top;
     144            8 :     if ( left < permitted_left )
     145              :     {
     146            3 :         if ( right > permitted_right )
     147              :         {
     148            0 :             U8_TRACE_INFO( "geometry_anchor_align_dim_closest cannot fit dim-x into permitted_area" );
     149              :         }
     150              :         else
     151              :         {
     152              :             /* move the unaligned area either till right side is at limit or till left side is fitting */
     153            3 :             new_left = u8_f64_min2( permitted_right - width, permitted_left );
     154              :         }
     155              :     }
     156              :     else
     157              :     {
     158            5 :         if ( right > permitted_right )
     159              :         {
     160              :             /* move the unaligned area either till left side is at limit or till right side is fitting */
     161            3 :             new_left = u8_f64_max2( permitted_right - width, permitted_left );
     162              :         }
     163              :         else
     164              :         {
     165              :             /* rectangle is fitting, no move */
     166              :         }
     167              :     }
     168            8 :     if ( top < permitted_top )
     169              :     {
     170            4 :         if ( bottom > permitted_bottom )
     171              :         {
     172            0 :             U8_TRACE_INFO( "geometry_anchor_align_dim_closest cannot fit dim-y into permitted_area" );
     173              :         }
     174              :         else
     175              :         {
     176              :             /* move the unaligned area either till bottom side is at limit or till top side is fitting */
     177            4 :             new_top = u8_f64_min2( permitted_bottom - height, permitted_top );
     178              :         }
     179              :     }
     180              :     else
     181              :     {
     182            4 :         if ( bottom > permitted_bottom )
     183              :         {
     184              :             /* move the unaligned area either till top side is at limit or till bottom side is fitting */
     185            3 :             new_top = u8_f64_max2( permitted_bottom - height, permitted_top );
     186              :         }
     187              :         else
     188              :         {
     189              :             /* rectangle is fitting, no move */
     190              :         }
     191              :     }
     192              : 
     193              : #if 0
     194              :     /* in case of center, allow small moves */
     195              :     if ( (*this_).x_align == GEOMETRY_H_ALIGN_CENTER )
     196              :     {
     197              :         /* if left/top position exceeds preferred_location, then move */
     198              :         const double min_x = geometry_rectangle_get_left( preferred_location );
     199              :         const double max_x = geometry_rectangle_get_right( preferred_location );
     200              :         const double max_width = geometry_rectangle_get_width( preferred_location );
     201              :         if ( left < min_x )
     202              :         {
     203              :             if ( width <= max_width )
     204              :             {
     205              :                 /* left/top position is too far left, but can fit if moved */
     206              :                 left = min_x;
     207              :             }
     208              :             else
     209              :             {
     210              :                 /* unaligned does not fit to preferred_location, simply center the result */
     211              :                 left = geometry_rectangle_get_center_x( preferred_location ) - 0.5 * width;
     212              :             }
     213              :         }
     214              :         else if ( left + width > max_x )
     215              :         {
     216              :             if ( width <= max_width )
     217              :             {
     218              :                 /* left/top position is too far left, but can fit if moved */
     219              :                 left = max_x - width;
     220              :             }
     221              :             else
     222              :             {
     223              :                 /* unaligned does not fit to preferred_location, simply center the result */
     224              :                 left = geometry_rectangle_get_center_x( preferred_location ) - 0.5 * width;
     225              :             }
     226              :         }
     227              :         /* if result moved too far, pull it back to anchor */
     228              :         const double reference_x = geometry_point_get_x( &((*this_).reference_point) );
     229              :         if ( left + width < reference_x )
     230              :         {
     231              :             left = reference_x - width;
     232              :         }
     233              :         if ( left > reference_x )
     234              :         {
     235              :             left = reference_x;
     236              :         }
     237              :     }
     238              :     if ( (*this_).y_align == GEOMETRY_V_ALIGN_CENTER )
     239              :     {
     240              :         /* if left/top position exceeds preferred_location, then move */
     241              :         const double min_y = geometry_rectangle_get_top( preferred_location );
     242              :         const double max_y = geometry_rectangle_get_bottom( preferred_location );
     243              :         const double max_height = geometry_rectangle_get_height( preferred_location );
     244              :         if ( top < min_y )
     245              :         {
     246              :             if ( height <= max_height )
     247              :             {
     248              :                 /* left/top position is too far left, but can fit if moved */
     249              :                 top = min_y;
     250              :             }
     251              :             else
     252              :             {
     253              :                 /* unaligned does not fit to preferred_location, simply center the result */
     254              :                 top = geometry_rectangle_get_center_y( preferred_location ) - 0.5 * height;
     255              :             }
     256              :         }
     257              :         else if ( top + height > max_y )
     258              :         {
     259              :             if ( height <= max_height )
     260              :             {
     261              :                 /* left/top position is too far left, but can fit if moved */
     262              :                 top = max_y - height;
     263              :             }
     264              :             else
     265              :             {
     266              :                 /* unaligned does not fit to preferred_location, simply center the result */
     267              :                 top = geometry_rectangle_get_center_y( preferred_location ) - 0.5 * height;
     268              :             }
     269              :         }
     270              :         /* if result moved too far, pull it back to anchor */
     271              :         const double reference_y = geometry_point_get_y( &((*this_).reference_point) );
     272              :         if ( top + height < reference_y )
     273              :         {
     274              :             top = reference_y - height;
     275              :         }
     276              :         if ( top > reference_y )
     277              :         {
     278              :             top = reference_y;
     279              :         }
     280              :     }
     281              : #endif
     282              : 
     283            8 :     geometry_rectangle_init( &result, new_left, new_top, width, height );
     284            8 :     return result;
     285              : }
     286              : 
     287            1 : static inline void geometry_anchor_trace( const geometry_anchor_t *this_ )
     288              : {
     289            1 :     U8_TRACE_INFO( "geometry_anchor_t" );
     290            1 :     U8_TRACE_INFO_INT( "- x:", geometry_point_get_x( &((*this_).reference_point) ) );
     291            1 :     U8_TRACE_INFO_INT( "- y:", geometry_point_get_y( &((*this_).reference_point) ) );
     292            1 :     U8_TRACE_INFO_INT( "- x_align:", (*this_).x_align );
     293            1 :     U8_TRACE_INFO_INT( "- y_align:", (*this_).y_align );
     294            1 : }
     295              : 
     296              : 
     297              : /*
     298              : Copyright 2021-2026 Andreas Warnke
     299              : 
     300              : Licensed under the Apache License, Version 2.0 (the "License");
     301              : you may not use this file except in compliance with the License.
     302              : You may obtain a copy of the License at
     303              : 
     304              :     http://www.apache.org/licenses/LICENSE-2.0
     305              : 
     306              : Unless required by applicable law or agreed to in writing, software
     307              : distributed under the License is distributed on an "AS IS" BASIS,
     308              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     309              : See the License for the specific language governing permissions and
     310              : limitations under the License.
     311              : */
        

Generated by: LCOV version 2.0-1