LCOV - code coverage report
Current view: top level - pencil/include/geometry - geometry_anchor.inl (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 87 87 100.0 %
Date: 2025-09-25 21:07:53 Functions: 13 13 100.0 %

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

Generated by: LCOV version 1.16