QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskFunctions.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskFunctions.h"
7
8#include <qfont.h>
9#include <qfontmetrics.h>
10#include <qmath.h>
11
12template< class Rect, class Value >
13static inline Rect qskAlignedRect( const Rect& outerRect,
14 Value width, Value height, Qt::Alignment alignment )
15{
16 Value x = outerRect.x();
17 Value y = outerRect.y();
18
19 switch ( alignment & Qt::AlignHorizontal_Mask )
20 {
21 case Qt::AlignHCenter:
22 x += ( outerRect.width() - width ) / 2;
23 break;
24
25 case Qt::AlignRight:
26 x += outerRect.width() - width;
27 break;
28
29 default:
30 break;
31 }
32
33 switch ( alignment & Qt::AlignVertical_Mask )
34 {
35 case Qt::AlignVCenter:
36 y += ( outerRect.height() - height ) / 2;
37 break;
38
39 case Qt::AlignBottom:
40 y += outerRect.height() - height;
41 break;
42
43 default:
44 break;
45 }
46
47 return Rect( x, y, width, height );
48}
49
50QRect qskAlignedRect( const QRect& outerRect,
51 int width, int height, Qt::Alignment alignment )
52{
53 return qskAlignedRect< QRect, int >( outerRect, width, height, alignment );
54}
55
56QRectF qskAlignedRectF( const QRectF& outerRect,
57 qreal width, qreal height, Qt::Alignment alignment )
58{
59 return qskAlignedRect< QRectF, qreal >( outerRect, width, height, alignment );
60}
61
62QRect qskInnerRect( const QRectF& rect )
63{
64 const int left = qCeil( rect.left() );
65 const int top = qCeil( rect.top() );
66 const int right = qFloor( rect.right() );
67 const int bottom = qFloor( rect.bottom() );
68
69 return QRect( left, top, right - left, bottom - top );
70}
71
72QRectF qskInnerRectF( const QRectF& rect )
73{
74 const qreal left = qCeil( rect.left() );
75 const qreal top = qCeil( rect.top() );
76 const qreal right = qFloor( rect.right() );
77 const qreal bottom = qFloor( rect.bottom() );
78
79 return QRectF( left, top, right - left, bottom - top );
80}
81
82QRectF qskValidOrEmptyInnerRect( const QRectF& rect, const QMarginsF& margins )
83{
84 qreal x, y, h, w;
85
86 if ( rect.width() > 0.0 )
87 {
88 const qreal marginsWidth = margins.left() + margins.right();
89
90 if ( marginsWidth > rect.width() )
91 {
92 x = rect.x() + rect.width() * ( margins.left() / marginsWidth );
93 w = 0.0;
94 }
95 else
96 {
97 x = rect.x() + margins.left();
98 w = rect.width() - marginsWidth;
99 }
100 }
101 else
102 {
103 x = rect.x();
104 w = 0.0;
105 }
106
107 if ( rect.height() > 0.0 )
108 {
109 const qreal marginsHeight = margins.top() + margins.bottom();
110 if ( marginsHeight > rect.height() )
111 {
112 y = rect.y() + rect.height() * ( margins.top() / marginsHeight );
113 h = 0.0;
114 }
115 else
116 {
117 y = rect.y() + margins.top();
118 h = rect.height() - marginsHeight;
119 }
120 }
121 else
122 {
123 y = rect.y();
124 h = 0.0;
125 }
126
127 return QRectF( x, y, w, h );
128}
129
130QRectF qskInterpolatedRect( const QRectF& from, const QRectF& to, qreal progress )
131{
132 if ( progress <= 0.0 )
133 return from;
134
135 if ( progress >= 1.0 )
136 return to;
137
138 const auto x = from.x() + progress * ( to.x() - from.x() );
139 const auto y = from.y() + progress * ( to.y() - from.y() );
140 const auto w = from.width() + progress * ( to.width() - from.width() );
141 const auto h = from.height() + progress * ( to.height() - from.height() );
142
143 return QRectF( x, y, w, h );
144}
145
146QSizeF qskInterpolatedSize( const QSizeF& from, const QSizeF& to, qreal progress )
147{
148 if ( progress <= 0.0 )
149 return from;
150
151 if ( progress >= 1.0 )
152 return to;
153
154 const auto w = from.width() + progress * ( to.width() - from.width() );
155 const auto h = from.height() + progress * ( to.height() - from.height() );
156
157 return QSizeF( w, h );
158}
159
160qreal qskHorizontalAdvance( const QFont& font, const QString& text )
161{
162 return qskHorizontalAdvance( QFontMetricsF( font ), text );
163}
164
165qreal qskHorizontalAdvance( const QFontMetricsF& fontMetrics, const QString& text )
166{
167 return fontMetrics.horizontalAdvance( text );
168}
169
170QSizeF qskTextRenderSize( const QFontMetricsF& fontMetrics, const QString& text )
171{
172 if ( text.isEmpty() )
173 return QSizeF( 0.0, 0.0 );
174
175 QRectF r( 0.0, 0.0, 10e6, 10e6 );
176 r = fontMetrics.boundingRect( r, 0, text );
177
178 return r.size();
179}
180
181qreal qskFuzzyFloor( qreal value, qreal stepSize )
182{
183 const double eps = 1.0e-6 * stepSize;
184
185 value = ( value + eps ) / stepSize;
186 return std::floor( value ) * stepSize;
187}
188
189qreal qskFuzzyCeil( qreal value, qreal stepSize )
190{
191 const double eps = 1.0e-6 * stepSize;
192
193 value = ( value - eps ) / stepSize;
194 return std::ceil( value ) * stepSize;
195}
196
197double qskConstrainedDegrees( double degrees )
198{
199 degrees = fmod( degrees, 360.0 );
200 if ( degrees < 0.0 )
201 degrees += 360.0;
202
203 return degrees;
204}
205
206float qskConstrainedDegrees( float degrees )
207{
208 degrees = fmodf( degrees, 360.0f );
209 if ( degrees < 0.0f )
210 degrees += 360.0f;
211
212 return degrees;
213}
214
215double qskConstrainedRadians( double radians )
216{
217 constexpr double pi2 = 2.0 * M_PI;
218
219 radians = fmod( radians, pi2 );
220 if ( radians < 0.0 )
221 radians += pi2;
222
223 return radians;
224}
225
226float qskConstrainedRadians( float radians )
227{
228 constexpr float pi2 = 2.0f * M_PI;
229
230 radians = fmodf( radians, pi2 );
231 if ( radians < 0.0f )
232 radians += pi2;
233
234 return radians;
235}
236
237// do not export;
238bool qskHasEnvironment( const char* env )
239{
240 bool ok;
241
242 const int value = qEnvironmentVariableIntValue( env, &ok );
243 if ( ok )
244 return value != 0;
245
246 // All other strings are true, apart from "false"
247 auto result = qgetenv( env );
248 return !result.isEmpty() && result != "false";
249}