2017-07-21 16:21:34 +00:00
|
|
|
#include "QskFunctions.h"
|
|
|
|
|
2020-03-13 12:32:22 +00:00
|
|
|
#include <qfont.h>
|
|
|
|
#include <qfontmetrics.h>
|
2021-12-26 11:57:02 +00:00
|
|
|
#include <qmath.h>
|
2021-05-26 11:06:50 +00:00
|
|
|
|
2017-07-21 16:21:34 +00:00
|
|
|
template< class Rect, class Value >
|
|
|
|
static inline Rect qskAlignedRect( const Rect& outerRect,
|
|
|
|
Value width, Value height, Qt::Alignment alignment )
|
|
|
|
{
|
2019-05-16 06:23:10 +00:00
|
|
|
Value x = outerRect.x();
|
|
|
|
Value y = outerRect.y();
|
2017-07-21 16:21:34 +00:00
|
|
|
|
2018-08-03 06:15:28 +00:00
|
|
|
switch ( alignment & Qt::AlignHorizontal_Mask )
|
2017-07-21 16:21:34 +00:00
|
|
|
{
|
2019-05-16 06:23:10 +00:00
|
|
|
case Qt::AlignHCenter:
|
|
|
|
x += ( outerRect.width() - width ) / 2;
|
2017-07-21 16:21:34 +00:00
|
|
|
break;
|
2019-05-16 06:23:10 +00:00
|
|
|
|
2017-07-21 16:21:34 +00:00
|
|
|
case Qt::AlignRight:
|
2019-05-16 06:23:10 +00:00
|
|
|
x += outerRect.width() - width;
|
2017-07-21 16:21:34 +00:00
|
|
|
break;
|
2019-05-16 06:23:10 +00:00
|
|
|
|
2017-07-21 16:21:34 +00:00
|
|
|
default:
|
2019-05-16 06:23:10 +00:00
|
|
|
break;
|
2017-07-21 16:21:34 +00:00
|
|
|
}
|
|
|
|
|
2018-08-03 06:15:28 +00:00
|
|
|
switch ( alignment & Qt::AlignVertical_Mask )
|
2017-07-21 16:21:34 +00:00
|
|
|
{
|
2019-05-16 06:23:10 +00:00
|
|
|
case Qt::AlignVCenter:
|
|
|
|
y += ( outerRect.height() - height ) / 2;
|
2017-07-21 16:21:34 +00:00
|
|
|
break;
|
2019-05-16 06:23:10 +00:00
|
|
|
|
2017-07-21 16:21:34 +00:00
|
|
|
case Qt::AlignBottom:
|
2019-05-16 06:23:10 +00:00
|
|
|
y += outerRect.height() - height;
|
2017-07-21 16:21:34 +00:00
|
|
|
break;
|
2019-05-16 06:23:10 +00:00
|
|
|
|
2017-07-21 16:21:34 +00:00
|
|
|
default:
|
2019-05-16 06:23:10 +00:00
|
|
|
break;
|
2017-07-21 16:21:34 +00:00
|
|
|
}
|
|
|
|
|
2019-05-16 06:23:10 +00:00
|
|
|
return Rect( x, y, width, height );
|
2017-07-21 16:21:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QRect qskAlignedRect( const QRect& outerRect,
|
|
|
|
int width, int height, Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
return qskAlignedRect< QRect, int >( outerRect, width, height, alignment );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF qskAlignedRectF( const QRectF& outerRect,
|
|
|
|
qreal width, qreal height, Qt::Alignment alignment )
|
|
|
|
{
|
|
|
|
return qskAlignedRect< QRectF, qreal >( outerRect, width, height, alignment );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRect qskInnerRect( const QRectF& rect )
|
|
|
|
{
|
|
|
|
const int left = qCeil( rect.left() );
|
|
|
|
const int top = qCeil( rect.top() );
|
|
|
|
const int right = qFloor( rect.right() );
|
|
|
|
const int bottom = qFloor( rect.bottom() );
|
|
|
|
|
|
|
|
return QRect( left, top, right - left, bottom - top );
|
|
|
|
}
|
|
|
|
|
2019-04-10 17:37:59 +00:00
|
|
|
QRectF qskInnerRectF( const QRectF& rect )
|
|
|
|
{
|
|
|
|
const qreal left = qCeil( rect.left() );
|
|
|
|
const qreal top = qCeil( rect.top() );
|
|
|
|
const qreal right = qFloor( rect.right() );
|
|
|
|
const qreal bottom = qFloor( rect.bottom() );
|
|
|
|
|
|
|
|
return QRectF( left, top, right - left, bottom - top );
|
|
|
|
}
|
|
|
|
|
2017-10-17 15:34:00 +00:00
|
|
|
QRectF qskValidOrEmptyInnerRect( const QRectF& rect, const QMarginsF& margins )
|
|
|
|
{
|
|
|
|
qreal x, y, h, w;
|
|
|
|
|
2019-04-24 06:39:13 +00:00
|
|
|
if ( rect.width() > 0.0 )
|
2017-10-17 15:34:00 +00:00
|
|
|
{
|
2019-04-24 06:39:13 +00:00
|
|
|
const qreal marginsWidth = margins.left() + margins.right();
|
|
|
|
|
|
|
|
if ( marginsWidth > rect.width() )
|
|
|
|
{
|
|
|
|
x = rect.x() + rect.width() * ( margins.left() / marginsWidth );
|
|
|
|
w = 0.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = rect.x() + margins.left();
|
|
|
|
w = rect.width() - marginsWidth;
|
|
|
|
}
|
2018-08-03 06:15:28 +00:00
|
|
|
}
|
2017-10-17 15:34:00 +00:00
|
|
|
else
|
|
|
|
{
|
2019-04-24 06:39:13 +00:00
|
|
|
x = rect.x();
|
|
|
|
w = 0.0;
|
2018-08-03 06:15:28 +00:00
|
|
|
}
|
|
|
|
|
2019-04-24 06:39:13 +00:00
|
|
|
if ( rect.height() > 0.0 )
|
2017-10-17 15:34:00 +00:00
|
|
|
{
|
2019-04-24 06:39:13 +00:00
|
|
|
const qreal marginsHeight = margins.top() + margins.bottom();
|
|
|
|
if ( marginsHeight > rect.height() )
|
|
|
|
{
|
|
|
|
y = rect.y() + rect.height() * ( margins.top() / marginsHeight );
|
|
|
|
h = 0.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y = rect.y() + margins.top();
|
|
|
|
h = rect.height() - marginsHeight;
|
|
|
|
}
|
2018-08-03 06:15:28 +00:00
|
|
|
}
|
2017-10-17 15:34:00 +00:00
|
|
|
else
|
|
|
|
{
|
2019-04-24 06:39:13 +00:00
|
|
|
y = rect.y();
|
|
|
|
h = 0.0;
|
2018-08-03 06:15:28 +00:00
|
|
|
}
|
2017-10-17 15:34:00 +00:00
|
|
|
|
|
|
|
return QRectF( x, y, w, h );
|
2018-08-03 06:15:28 +00:00
|
|
|
}
|
2017-10-17 15:34:00 +00:00
|
|
|
|
2022-03-23 10:54:34 +00:00
|
|
|
QRectF qskInterpolatedRect( const QRectF& from, const QRectF& to, qreal progress )
|
2021-12-29 14:30:44 +00:00
|
|
|
{
|
|
|
|
if ( progress <= 0.0 )
|
|
|
|
return from;
|
|
|
|
|
|
|
|
if ( progress >= 1.0 )
|
|
|
|
return to;
|
|
|
|
|
|
|
|
const auto x = from.x() + progress * ( to.x() - from.x() );
|
|
|
|
const auto y = from.y() + progress * ( to.y() - from.y() );
|
|
|
|
const auto w = from.width() + progress * ( to.width() - from.width() );
|
|
|
|
const auto h = from.height() + progress * ( to.height() - from.height() );
|
|
|
|
|
|
|
|
return QRectF( x, y, w, h );
|
|
|
|
}
|
|
|
|
|
2022-03-23 10:54:34 +00:00
|
|
|
QSizeF qskInterpolatedSize( const QSizeF& from, const QSizeF& to, qreal progress )
|
2022-01-04 12:46:54 +00:00
|
|
|
{
|
|
|
|
if ( progress <= 0.0 )
|
|
|
|
return from;
|
|
|
|
|
|
|
|
if ( progress >= 1.0 )
|
|
|
|
return to;
|
|
|
|
|
|
|
|
const auto w = from.width() + progress * ( to.width() - from.width() );
|
|
|
|
const auto h = from.height() + progress * ( to.height() - from.height() );
|
|
|
|
|
|
|
|
return QSizeF( w, h );
|
|
|
|
}
|
|
|
|
|
2020-03-13 12:32:22 +00:00
|
|
|
qreal qskHorizontalAdvance( const QFont& font, const QString& text )
|
|
|
|
{
|
|
|
|
return qskHorizontalAdvance( QFontMetricsF( font ), text );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal qskHorizontalAdvance( const QFontMetricsF& fontMetrics, const QString& text )
|
|
|
|
{
|
|
|
|
return fontMetrics.horizontalAdvance( text );
|
|
|
|
}
|
|
|
|
|
2021-05-26 11:06:50 +00:00
|
|
|
qreal qskFuzzyFloor( qreal value, qreal stepSize )
|
|
|
|
{
|
2021-07-14 11:29:46 +00:00
|
|
|
const double eps = 1.0e-6 * stepSize;
|
2021-05-26 11:06:50 +00:00
|
|
|
|
2021-07-14 11:29:46 +00:00
|
|
|
value = ( value + eps ) / stepSize;
|
|
|
|
return std::floor( value ) * stepSize;
|
2021-05-26 11:06:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qreal qskFuzzyCeil( qreal value, qreal stepSize )
|
|
|
|
{
|
2021-07-14 11:29:46 +00:00
|
|
|
const double eps = 1.0e-6 * stepSize;
|
2021-05-26 11:06:50 +00:00
|
|
|
|
2021-07-14 11:29:46 +00:00
|
|
|
value = ( value - eps ) / stepSize;
|
|
|
|
return std::ceil( value ) * stepSize;
|
2021-05-26 11:06:50 +00:00
|
|
|
}
|
2023-04-13 07:25:02 +00:00
|
|
|
|
|
|
|
double qskConstrainedDegrees( double degrees )
|
|
|
|
{
|
|
|
|
degrees = fmod( degrees, 360.0 );
|
|
|
|
if ( degrees < 0.0 )
|
|
|
|
degrees += 360.0;
|
|
|
|
|
|
|
|
return degrees;
|
|
|
|
}
|
|
|
|
|
|
|
|
float qskConstrainedDegrees( float degrees )
|
|
|
|
{
|
|
|
|
degrees = fmodf( degrees, 360.0f );
|
|
|
|
if ( degrees < 0.0f )
|
|
|
|
degrees += 360.0f;
|
|
|
|
|
|
|
|
return degrees;
|
|
|
|
}
|
|
|
|
|
|
|
|
double qskConstrainedRadians( double radians )
|
|
|
|
{
|
|
|
|
constexpr double pi2 = 2.0 * M_PI;
|
|
|
|
|
|
|
|
radians = fmod( radians, pi2 );
|
|
|
|
if ( radians < 0.0 )
|
|
|
|
radians += pi2;
|
|
|
|
|
|
|
|
return radians;
|
|
|
|
}
|
|
|
|
|
|
|
|
float qskConstrainedRadians( double float )
|
|
|
|
{
|
|
|
|
constexpr float pi2 = 2.0f * M_PI;
|
|
|
|
|
|
|
|
radians = fmodf( radians, pi2 );
|
|
|
|
if ( radians < 0.0f )
|
|
|
|
radians += pi2;
|
|
|
|
|
|
|
|
return radians;
|
|
|
|
}
|