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 : */
|