starting to configure box subcontrols/nodes with
QskBoxColors/QskBorderMetrics
This commit is contained in:
parent
42981403e7
commit
ff9e9ab63c
167
src/common/QskBorderMetrics.cpp
Normal file
167
src/common/QskBorderMetrics.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskBorderMetrics.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
static void qskRegisterBorderMetrics()
|
||||
{
|
||||
qRegisterMetaType< QskBorderMetrics >();
|
||||
}
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( qskRegisterBorderMetrics )
|
||||
|
||||
static inline QSizeF qskInterpolatedSize(
|
||||
const QSizeF& from, const QSizeF& to, qreal ratio )
|
||||
{
|
||||
return from + ( to - from ) * ratio;
|
||||
}
|
||||
|
||||
QskBorderMetrics::QskBorderMetrics( qreal width, qreal radiusX, qreal radiusY ):
|
||||
m_widths( ( width >= 0.0 ) ? width : 0.0 ),
|
||||
m_widthIsRelative( false ),
|
||||
m_radiusIsRelative( false )
|
||||
{
|
||||
setRadius( radiusX, radiusY );
|
||||
}
|
||||
|
||||
QskBorderMetrics::~QskBorderMetrics()
|
||||
{
|
||||
}
|
||||
|
||||
bool QskBorderMetrics::operator==( const QskBorderMetrics& other ) const
|
||||
{
|
||||
if ( m_widthIsRelative != other.m_widthIsRelative )
|
||||
return false;
|
||||
|
||||
if ( m_radiusIsRelative != other.m_radiusIsRelative )
|
||||
return false;
|
||||
|
||||
if ( m_widths != other.m_widths )
|
||||
return false;
|
||||
|
||||
for ( size_t i = 0; i < 4; i++ )
|
||||
{
|
||||
if ( m_radii[i] != other.m_radii[i] )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QskBorderMetrics::setWidthSizeMode( Qt::SizeMode sizeMode )
|
||||
{
|
||||
m_widthIsRelative = ( sizeMode == Qt::RelativeSize );
|
||||
}
|
||||
|
||||
void QskBorderMetrics::setWidths( const QskMargins& widths )
|
||||
{
|
||||
m_widths = widths;
|
||||
}
|
||||
|
||||
void QskBorderMetrics::setWidthAt( Qt::Edges edges, qreal width )
|
||||
{
|
||||
m_widths.setMarginsAt( edges, width );
|
||||
}
|
||||
|
||||
void QskBorderMetrics::setRadiusSizeMode( Qt::SizeMode sizeMode )
|
||||
{
|
||||
m_radiusIsRelative = ( sizeMode == Qt::RelativeSize );
|
||||
}
|
||||
|
||||
void QskBorderMetrics::setRadius(
|
||||
qreal topLeftX, qreal topLeftY, qreal topRightX, qreal topRightY,
|
||||
qreal bottomLeftX, qreal bottomLeftY, qreal bottomRightX, qreal bottomRightY )
|
||||
{
|
||||
m_radii[ Qt::TopLeftCorner ].setWidth( qMax( topLeftX, 0.0 ) );
|
||||
m_radii[ Qt::TopLeftCorner ].setHeight( qMax( topLeftY, 0.0 ) );
|
||||
|
||||
m_radii[ Qt::TopRightCorner ].setWidth( qMax( topRightX, 0.0 ) );
|
||||
m_radii[ Qt::TopRightCorner ].setHeight( qMax( topRightY, 0.0 ) );
|
||||
|
||||
m_radii[ Qt::BottomLeftCorner ].setWidth( qMax( bottomLeftX, 0.0 ) );
|
||||
m_radii[ Qt::BottomLeftCorner ].setHeight( qMax( bottomLeftY, 0.0 ) );
|
||||
|
||||
m_radii[ Qt::BottomRightCorner ].setWidth( qMax( bottomRightX, 0.0 ) );
|
||||
m_radii[ Qt::BottomRightCorner ].setHeight( qMax( bottomRightY, 0.0 ) );
|
||||
}
|
||||
|
||||
void QskBorderMetrics::setRadius( Qt::Corner corner, qreal radiusX, qreal radiusY )
|
||||
{
|
||||
if ( ( corner >= Qt::TopLeftCorner ) && ( corner <= Qt::BottomRightCorner ) )
|
||||
{
|
||||
m_radii[ corner ].setWidth( qMax( radiusX, 0.0 ) );
|
||||
m_radii[ corner ].setHeight( qMax( radiusY, 0.0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
QskBorderMetrics QskBorderMetrics::interpolated(
|
||||
const QskBorderMetrics& to, qreal ratio ) const
|
||||
{
|
||||
if ( *this == to )
|
||||
return to;
|
||||
|
||||
if ( ( m_widthIsRelative != to.m_widthIsRelative )
|
||||
&& ( m_radiusIsRelative != to.m_radiusIsRelative ) )
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
QskMargins widths( to.m_widths );
|
||||
if ( m_widthIsRelative == to.m_widthIsRelative )
|
||||
{
|
||||
widths = m_widths.interpolated( to.m_widths, ratio );
|
||||
}
|
||||
|
||||
if ( m_radiusIsRelative == to.m_radiusIsRelative )
|
||||
{
|
||||
QSizeF radii[4];
|
||||
radii[0] = qskInterpolatedSize( m_radii[0], to.m_radii[0], ratio );
|
||||
radii[1] = qskInterpolatedSize( m_radii[1], to.m_radii[1], ratio );
|
||||
radii[2] = qskInterpolatedSize( m_radii[2], to.m_radii[2], ratio );
|
||||
radii[3] = qskInterpolatedSize( m_radii[3], to.m_radii[3], ratio );
|
||||
|
||||
return QskBorderMetrics( to.m_widthIsRelative, widths,
|
||||
to.m_radiusIsRelative, radii );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QskBorderMetrics( to.m_widthIsRelative, widths,
|
||||
to.m_radiusIsRelative, to.m_radii );
|
||||
}
|
||||
}
|
||||
|
||||
QVariant QskBorderMetrics::interpolate( const QskBorderMetrics& from,
|
||||
const QskBorderMetrics& to, qreal progress )
|
||||
{
|
||||
return QVariant::fromValue( from.interpolated( to, progress ) );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
QDebug operator<<( QDebug debug, const QskBorderMetrics& metrics )
|
||||
{
|
||||
QDebugStateSaver saver( debug );
|
||||
debug.nospace();
|
||||
|
||||
debug << "BorderMetrics" << '(';
|
||||
debug << metrics.widthSizeMode() << metrics.widths();
|
||||
|
||||
debug << metrics.radiusSizeMode();
|
||||
|
||||
for ( int i = Qt::TopLeftCorner; i <= Qt::BottomRightCorner; i++ )
|
||||
{
|
||||
const QSizeF r = metrics.radius( static_cast< Qt::Corner >( i ) );
|
||||
debug << "(" << r.width() << r.height() << ")";
|
||||
}
|
||||
|
||||
debug << ')';
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
183
src/common/QskBorderMetrics.h
Normal file
183
src/common/QskBorderMetrics.h
Normal file
@ -0,0 +1,183 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_BORDER_METRICS_H
|
||||
#define QSK_BORDER_HINTS_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include "QskMargins.h"
|
||||
|
||||
#include <Qt>
|
||||
#include <QMetaType>
|
||||
#include <QSizeF>
|
||||
|
||||
class QDebug;
|
||||
class QVariant;
|
||||
|
||||
class QSK_EXPORT QskBorderMetrics
|
||||
{
|
||||
public:
|
||||
QskBorderMetrics();
|
||||
QskBorderMetrics( qreal width, qreal radius = 0.0 );
|
||||
QskBorderMetrics( qreal width, qreal radiusX, qreal radiusY );
|
||||
|
||||
~QskBorderMetrics();
|
||||
|
||||
bool operator==( const QskBorderMetrics& ) const;
|
||||
bool operator!=( const QskBorderMetrics& ) const;
|
||||
|
||||
void setRadius( qreal radius );
|
||||
void setRadius( qreal radius, Qt::SizeMode );
|
||||
void setRadius( Qt::Corner, qreal radius );
|
||||
|
||||
void setRadius( qreal radiusX, qreal radiusY );
|
||||
void setRadius( const QSizeF& );
|
||||
void setRadius( Qt::Corner, qreal radiusX, qreal radiusY );
|
||||
void setRadius( Qt::Corner, const QSizeF& radius );
|
||||
|
||||
void setRadius( qreal topLeft, qreal topRight,
|
||||
qreal bottomLeft, qreal bottomRight );
|
||||
|
||||
void setRadius( const QSizeF& topLeft, const QSizeF& topRight,
|
||||
const QSizeF& bottomLeft, const QSizeF& bottomRight );
|
||||
|
||||
void setRadius(
|
||||
qreal topLeftX, qreal topLeftY,
|
||||
qreal topRightX, qreal topRightY,
|
||||
qreal bottomLeftX, qreal bottomLeftY,
|
||||
qreal bottomRightX, qreal bottomRightY );
|
||||
|
||||
QSizeF radius( Qt::Corner ) const;
|
||||
|
||||
void setRadiusSizeMode( Qt::SizeMode );
|
||||
Qt::SizeMode radiusSizeMode() const;
|
||||
|
||||
void setWidthAt( Qt::Edges, qreal width );
|
||||
qreal widthAt( Qt::Edge ) const;
|
||||
|
||||
void setWidths( const QskMargins& );
|
||||
const QskMargins& widths() const;
|
||||
|
||||
void setWidthSizeMode( Qt::SizeMode );
|
||||
Qt::SizeMode widthSizeMode() const;
|
||||
|
||||
QskBorderMetrics interpolated( const QskBorderMetrics&, qreal value ) const;
|
||||
|
||||
static QVariant interpolate( const QskBorderMetrics&,
|
||||
const QskBorderMetrics&, qreal progress );
|
||||
|
||||
private:
|
||||
QskBorderMetrics( bool widthIsRelative, const QskMargins& widths,
|
||||
bool radiusIsRelative, const QSizeF radii[4] ):
|
||||
m_widths( widths ),
|
||||
m_radii( { radii[0], radii[1], radii[2], radii[3] } ),
|
||||
m_widthIsRelative( widthIsRelative ),
|
||||
m_radiusIsRelative( radiusIsRelative )
|
||||
{
|
||||
}
|
||||
|
||||
QskMargins m_widths;
|
||||
QSizeF m_radii[ 4 ];
|
||||
|
||||
bool m_widthIsRelative;
|
||||
bool m_radiusIsRelative;
|
||||
};
|
||||
|
||||
inline QskBorderMetrics::QskBorderMetrics():
|
||||
m_widthIsRelative( false ),
|
||||
m_radiusIsRelative( false )
|
||||
{
|
||||
}
|
||||
|
||||
inline QskBorderMetrics::QskBorderMetrics( qreal width, qreal radius ):
|
||||
QskBorderMetrics( width, radius, radius )
|
||||
{
|
||||
}
|
||||
|
||||
inline bool QskBorderMetrics::operator!=( const QskBorderMetrics& other ) const
|
||||
{
|
||||
return !( *this == other );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius( qreal radius )
|
||||
{
|
||||
setRadius( radius, radius );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius( qreal radius, Qt::SizeMode sizeMode )
|
||||
{
|
||||
setRadius( radius );
|
||||
setRadiusSizeMode( sizeMode );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius( qreal radiusX, qreal radiusY )
|
||||
{
|
||||
setRadius( radiusX, radiusY, radiusX, radiusY,
|
||||
radiusX, radiusY, radiusX, radiusY );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius( const QSizeF& radius )
|
||||
{
|
||||
setRadius( radius.width(), radius.height() );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius( Qt::Corner corner, qreal radius )
|
||||
{
|
||||
setRadius( corner, radius, radius );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius( Qt::Corner corner, const QSizeF& radius )
|
||||
{
|
||||
setRadius( corner, radius.width(), radius.height() );
|
||||
}
|
||||
|
||||
inline void QskBorderMetrics::setRadius(
|
||||
const QSizeF& topLeft, const QSizeF& topRight,
|
||||
const QSizeF& bottomLeft, const QSizeF& bottomRight )
|
||||
{
|
||||
setRadius( topLeft.width(), topLeft.height(),
|
||||
topRight.width(), topRight.height(),
|
||||
bottomLeft.width(), bottomLeft.height(),
|
||||
bottomRight.width(), bottomRight.height() );
|
||||
}
|
||||
|
||||
inline QSizeF QskBorderMetrics::radius( Qt::Corner corner ) const
|
||||
{
|
||||
if ( ( corner >= Qt::TopLeftCorner ) && ( corner <= Qt::BottomRightCorner ) )
|
||||
return m_radii[ corner ];
|
||||
|
||||
return QSizeF();
|
||||
}
|
||||
|
||||
inline Qt::SizeMode QskBorderMetrics::radiusSizeMode() const
|
||||
{
|
||||
return m_radiusIsRelative ? Qt::RelativeSize : Qt::AbsoluteSize;
|
||||
}
|
||||
|
||||
inline const QskMargins& QskBorderMetrics::widths() const
|
||||
{
|
||||
return m_widths;
|
||||
}
|
||||
|
||||
inline qreal QskBorderMetrics::widthAt( Qt::Edge edge ) const
|
||||
{
|
||||
return m_widths.marginAt( edge );
|
||||
}
|
||||
|
||||
inline Qt::SizeMode QskBorderMetrics::widthSizeMode() const
|
||||
{
|
||||
return m_widthIsRelative ? Qt::RelativeSize : Qt::AbsoluteSize;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
QSK_EXPORT QDebug operator<<( QDebug, const QskBorderMetrics& );
|
||||
|
||||
#endif
|
||||
|
||||
Q_DECLARE_TYPEINFO( QskBorderMetrics, Q_MOVABLE_TYPE );
|
||||
Q_DECLARE_METATYPE( QskBorderMetrics )
|
||||
|
||||
#endif
|
295
src/common/QskBoxColors.cpp
Normal file
295
src/common/QskBoxColors.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskBoxColors.h"
|
||||
#include "QskRgbValue.h"
|
||||
#include "QskNamespace.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
static void qskRegisterBoxColors()
|
||||
{
|
||||
qRegisterMetaType< QskBoxColors >();
|
||||
}
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( qskRegisterBoxColors )
|
||||
|
||||
static inline void qskMirrorEdges(
|
||||
Qt::Orientations orientations, const QColor* from, QColor* to )
|
||||
{
|
||||
if ( orientations == Qt::Vertical )
|
||||
{
|
||||
to[ Qt::TopLeftCorner ] = from[ Qt::BottomLeftCorner ];
|
||||
to[ Qt::BottomLeftCorner ] = from[ Qt::TopLeftCorner ];
|
||||
to[ Qt::TopRightCorner ] = from[ Qt::BottomRightCorner ];
|
||||
to[ Qt::BottomRightCorner ] = from[ Qt::TopRightCorner ];
|
||||
}
|
||||
else if ( orientations == Qt::Horizontal )
|
||||
{
|
||||
to[ Qt::TopLeftCorner ] = from[ Qt::TopRightCorner ];
|
||||
to[ Qt::BottomLeftCorner ] = from[ Qt::BottomRightCorner ];
|
||||
to[ Qt::TopRightCorner ] = from[ Qt::TopLeftCorner ];
|
||||
to[ Qt::BottomRightCorner ] = from[ Qt::BottomLeftCorner ];
|
||||
}
|
||||
else if ( orientations == ( Qt::Vertical | Qt::Horizontal ) )
|
||||
{
|
||||
to[ Qt::TopLeftCorner ] = from[ Qt::BottomRightCorner ];
|
||||
to[ Qt::BottomLeftCorner ] = from[ Qt::TopRightCorner ];
|
||||
to[ Qt::TopRightCorner ] = from[ Qt::BottomLeftCorner ];
|
||||
to[ Qt::BottomRightCorner ] = from[ Qt::TopLeftCorner ];
|
||||
}
|
||||
else
|
||||
{
|
||||
to[ Qt::TopLeftCorner ] = from[ Qt::TopLeftCorner ];
|
||||
to[ Qt::BottomLeftCorner ] = from[ Qt::BottomLeftCorner ];
|
||||
to[ Qt::TopRightCorner ] = from[ Qt::TopRightCorner ];
|
||||
to[ Qt::BottomRightCorner ] = from[ Qt::BottomRightCorner ];
|
||||
}
|
||||
}
|
||||
|
||||
QskBoxColors::QskBoxColors()
|
||||
{
|
||||
}
|
||||
|
||||
QskBoxColors::QskBoxColors( const QColor& border, const QColor& fill )
|
||||
{
|
||||
setBorderColor( border );
|
||||
setFillColor( fill );
|
||||
}
|
||||
|
||||
QskBoxColors::~QskBoxColors()
|
||||
{
|
||||
}
|
||||
|
||||
bool QskBoxColors::operator==( const QskBoxColors& other ) const
|
||||
{
|
||||
for ( size_t i = 0; i < 4; i++ )
|
||||
{
|
||||
if ( ( m_border[i] != other.m_border[i] )
|
||||
|| ( m_fill[i] != other.m_fill[i] ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QskBoxColors::setBorderColor( const QColor& color )
|
||||
{
|
||||
m_border[ 0 ] = m_border[ 1 ] = m_border[ 2 ] = m_border[ 3 ] = color.toRgb();
|
||||
}
|
||||
|
||||
void QskBoxColors::setBorderColor( const QColor& left, const QColor& top,
|
||||
const QColor& right, const QColor& bottom )
|
||||
{
|
||||
m_border[ Qsk::Left ] = left.toRgb();
|
||||
m_border[ Qsk::Top ] = top.toRgb();
|
||||
m_border[ Qsk::Right ] = right.toRgb();
|
||||
m_border[ Qsk::Bottom ] = bottom.toRgb();
|
||||
}
|
||||
|
||||
void QskBoxColors::setBorderColor( Qt::Edges edges, const QColor& color )
|
||||
{
|
||||
const QColor c = color.toRgb();
|
||||
|
||||
if ( edges & Qt::TopEdge )
|
||||
m_border[ Qsk::Top ] = c;
|
||||
|
||||
if ( edges & Qt::LeftEdge )
|
||||
m_border[ Qsk::Left ] = c;
|
||||
|
||||
if ( edges & Qt::RightEdge )
|
||||
m_border[ Qsk::Right ] = c;
|
||||
|
||||
if ( edges & Qt::BottomEdge )
|
||||
m_border[ Qsk::Bottom ] = c;
|
||||
}
|
||||
|
||||
QColor QskBoxColors::borderColor( Qt::Edge edge ) const
|
||||
{
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::TopEdge:
|
||||
return m_border[ Qsk::Top ];
|
||||
|
||||
case Qt::LeftEdge:
|
||||
return m_border[ Qsk::Left ];
|
||||
|
||||
case Qt::RightEdge:
|
||||
return m_border[ Qsk::Right ];
|
||||
|
||||
case Qt::BottomEdge:
|
||||
return m_border[ Qsk::Bottom ];
|
||||
}
|
||||
|
||||
return QColor();
|
||||
}
|
||||
|
||||
void QskBoxColors::setFillColor( const QColor& color )
|
||||
{
|
||||
m_fill[ 0 ] = m_fill[ 1 ] = m_fill[ 2 ] = m_fill[ 3 ] = color.toRgb();
|
||||
}
|
||||
|
||||
void QskBoxColors::setFillColor(
|
||||
const QColor& topLeft, const QColor& topRight,
|
||||
const QColor& bottomLeft, const QColor& bottomRight )
|
||||
{
|
||||
m_fill[ Qt::TopLeftCorner ] = topLeft.toRgb();
|
||||
m_fill[ Qt::TopRightCorner ] = topRight.toRgb();
|
||||
m_fill[ Qt::BottomLeftCorner ] = bottomLeft.toRgb();
|
||||
m_fill[ Qt::BottomRightCorner ] = bottomRight.toRgb();
|
||||
}
|
||||
|
||||
void QskBoxColors::setFillColor( Qt::Corner corner, const QColor& color )
|
||||
{
|
||||
if ( corner >= 0 && corner < 4 )
|
||||
m_fill[ corner ] = color.toRgb();
|
||||
}
|
||||
|
||||
void QskBoxColors::setFillColor( Qt::Edge edge, const QColor& color )
|
||||
{
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::TopEdge:
|
||||
{
|
||||
m_fill[ Qt::TopLeftCorner ] = color;
|
||||
m_fill[ Qt::TopRightCorner ] = color;
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::LeftEdge:
|
||||
{
|
||||
m_fill[ Qt::TopLeftCorner ] = color;
|
||||
m_fill[ Qt::BottomLeftCorner ] = color;
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::RightEdge:
|
||||
{
|
||||
m_fill[ Qt::TopRightCorner ] = color;
|
||||
m_fill[ Qt::BottomRightCorner ] = color;
|
||||
|
||||
break;
|
||||
}
|
||||
case Qt::BottomEdge:
|
||||
{
|
||||
m_fill[ Qt::BottomLeftCorner ] = color;
|
||||
m_fill[ Qt::BottomRightCorner ] = color;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QColor QskBoxColors::fillColor( Qt::Corner corner ) const
|
||||
{
|
||||
if ( corner >= 0 && corner < 4 )
|
||||
return m_fill[ corner ];
|
||||
|
||||
return QColor();
|
||||
}
|
||||
|
||||
QskBoxColors QskBoxColors::shaded( uint alpha ) const
|
||||
{
|
||||
QskBoxColors colors = *this;
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
colors.m_border[i].setAlpha( alpha );
|
||||
colors.m_fill[i].setAlpha( alpha );
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
QskBoxColors QskBoxColors::mirrored( Qt::Orientations orientations ) const
|
||||
{
|
||||
if ( orientations == 0 )
|
||||
return *this;
|
||||
|
||||
QskBoxColors c;
|
||||
qskMirrorEdges( orientations, m_border, c.m_border );
|
||||
qskMirrorEdges( orientations, m_fill, c.m_fill );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
QskBoxColors QskBoxColors::interpolated( const QskBoxColors& to, qreal ratio ) const
|
||||
{
|
||||
QskBoxColors colors;
|
||||
|
||||
for ( size_t i = 0; i < 4; i++ )
|
||||
{
|
||||
colors.m_border[i] = QskRgbValue::interpolated( m_border[i], to.m_border[i], ratio );
|
||||
colors.m_fill[i] = QskRgbValue::interpolated( m_fill[i], to.m_fill[i], ratio );
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
QVariant QskBoxColors::interpolate(
|
||||
const QskBoxColors& from, const QskBoxColors& to, qreal ratio )
|
||||
{
|
||||
return QVariant::fromValue( from.interpolated( to, ratio ) );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
static inline void qskDebugColor( QDebug debug, const QColor& c )
|
||||
{
|
||||
debug << '('
|
||||
<< c.red() << ','
|
||||
<< c.green() << ','
|
||||
<< c.blue() << ','
|
||||
<< c.alpha() << ')';
|
||||
}
|
||||
|
||||
QDebug operator<<( QDebug debug, const QskBoxColors& colors )
|
||||
{
|
||||
QDebugStateSaver saver( debug );
|
||||
debug.nospace();
|
||||
|
||||
debug << "BoxColors" << '(';
|
||||
|
||||
debug << "\n Border" << '(';
|
||||
|
||||
debug << " L";
|
||||
qskDebugColor( debug, colors.borderColor( Qt::LeftEdge ) );
|
||||
|
||||
debug << ", T";
|
||||
qskDebugColor( debug, colors.borderColor( Qt::TopEdge ) );
|
||||
|
||||
debug << ", R";
|
||||
qskDebugColor( debug, colors.borderColor( Qt::RightEdge ) );
|
||||
|
||||
debug << ", B";
|
||||
qskDebugColor( debug, colors.borderColor( Qt::BottomEdge ) );
|
||||
|
||||
debug << " )";
|
||||
|
||||
debug << "\n Fill" << '(';
|
||||
|
||||
debug << " TL";
|
||||
qskDebugColor( debug, colors.fillColor( Qt::TopLeftCorner ) );
|
||||
|
||||
debug << ", TR";
|
||||
qskDebugColor( debug, colors.fillColor( Qt::TopRightCorner ) );
|
||||
|
||||
debug << ", BL";
|
||||
qskDebugColor( debug, colors.fillColor( Qt::BottomLeftCorner ) );
|
||||
|
||||
debug << ", BR";
|
||||
qskDebugColor( debug, colors.fillColor( Qt::BottomRightCorner ) );
|
||||
|
||||
debug << " )";
|
||||
|
||||
debug << "\n)";
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
72
src/common/QskBoxColors.h
Normal file
72
src/common/QskBoxColors.h
Normal file
@ -0,0 +1,72 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_BOX_COLORS_H
|
||||
#define QSK_BOX_COLORS_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
|
||||
#include <QMarginsF>
|
||||
#include <QColor>
|
||||
#include <Qt>
|
||||
#include <QMetaType>
|
||||
|
||||
class QDebug;
|
||||
|
||||
class QSK_EXPORT QskBoxColors
|
||||
{
|
||||
public:
|
||||
QskBoxColors();
|
||||
QskBoxColors( const QColor& border, const QColor& fill );
|
||||
|
||||
~QskBoxColors();
|
||||
|
||||
bool operator==( const QskBoxColors& ) const;
|
||||
bool operator!=( const QskBoxColors& ) const;
|
||||
|
||||
void setBorderColor( const QColor& );
|
||||
void setBorderColor( Qt::Edges, const QColor& );
|
||||
|
||||
void setBorderColor( const QColor& left, const QColor& top,
|
||||
const QColor& right, const QColor& bottom );
|
||||
|
||||
QColor borderColor( Qt::Edge ) const;
|
||||
|
||||
// will be a QskGradient later
|
||||
void setFillColor( const QColor& );
|
||||
void setFillColor( Qt::Corner, const QColor& );
|
||||
void setFillColor( Qt::Edge, const QColor& );
|
||||
|
||||
void setFillColor( const QColor& topLeft, const QColor& topRight,
|
||||
const QColor& bottomLeft, const QColor& bottomRight );
|
||||
|
||||
QColor fillColor( Qt::Corner ) const;
|
||||
|
||||
QskBoxColors interpolated( const QskBoxColors&, qreal value ) const;
|
||||
QskBoxColors mirrored( Qt::Orientations ) const;
|
||||
QskBoxColors shaded( uint alpha ) const;
|
||||
|
||||
static QVariant interpolate( const QskBoxColors&,
|
||||
const QskBoxColors&, qreal ratio );
|
||||
|
||||
private:
|
||||
QColor m_border[ 4 ];
|
||||
QColor m_fill[ 4 ]; // should be QskGradient later
|
||||
};
|
||||
|
||||
inline bool QskBoxColors::operator!=( const QskBoxColors& other ) const
|
||||
{
|
||||
return !( *this == other );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
QSK_EXPORT QDebug operator<<( QDebug, const QskBoxColors& );
|
||||
|
||||
#endif
|
||||
|
||||
Q_DECLARE_METATYPE( QskBoxColors )
|
||||
|
||||
#endif
|
@ -4,84 +4,29 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskBoxOptions.h"
|
||||
#include <qhashfunctions.h>
|
||||
|
||||
QskBoxOptions::QskBoxOptions():
|
||||
radius( { 0, 0, 0, 0, 0, 0, 0, 0 } ),
|
||||
color( { 0, 0, 0, 0, 0, 0, 0, 0 } )
|
||||
static inline bool qskIsVisible( const QColor& color )
|
||||
{
|
||||
return color.isValid() && color.alpha() > 0;
|
||||
}
|
||||
|
||||
uint QskBoxOptions::metricsHash( uint seed ) const
|
||||
QskBoxOptions::QskBoxOptions()
|
||||
{
|
||||
return qHashBits( this, 2 * sizeof( QMarginsF ) + 8 * sizeof( qreal ), seed );
|
||||
}
|
||||
|
||||
uint QskBoxOptions::colorsHash( uint seed ) const
|
||||
{
|
||||
return qHashBits( &color, 8 * sizeof( QRgb ), seed );
|
||||
}
|
||||
|
||||
void QskBoxOptions::setBorder( qreal width )
|
||||
{
|
||||
borders = QMarginsF( width, width, width, width );
|
||||
}
|
||||
|
||||
void QskBoxOptions::setBorder( qreal left, qreal top, qreal right, qreal bottom )
|
||||
{
|
||||
borders = QMarginsF( left, top, right, bottom );
|
||||
}
|
||||
|
||||
void QskBoxOptions::setRadius( qreal radius )
|
||||
{
|
||||
this->radius = { radius, radius, radius, radius, radius, radius, radius, radius };
|
||||
}
|
||||
|
||||
void QskBoxOptions::setBorderRgb( QRgb rgb )
|
||||
{
|
||||
color.borderLeft = color.borderTop =
|
||||
color.borderRight = color.borderBottom = rgb;
|
||||
}
|
||||
|
||||
void QskBoxOptions::setBorderRgb( QRgb rgbLeft, QRgb rgbTop,
|
||||
QRgb rgbRight, QRgb rgbBottom )
|
||||
{
|
||||
color.borderLeft = rgbLeft;
|
||||
color.borderTop = rgbTop;
|
||||
color.borderRight = rgbRight;
|
||||
color.borderBottom = rgbBottom;
|
||||
}
|
||||
|
||||
void QskBoxOptions::setFillRgb( QRgb rgb )
|
||||
{
|
||||
color.fillTopLeft = color.fillTopRight =
|
||||
color.fillBottomRight = color.fillBottomLeft = rgb;
|
||||
}
|
||||
|
||||
void QskBoxOptions::setFillRgb( QRgb rgbTopLeft, QRgb rgbTopRight,
|
||||
QRgb rgbBottomRight, QRgb rgbBottomLeft )
|
||||
{
|
||||
color.fillTopLeft = rgbTopLeft;
|
||||
color.fillTopRight = rgbTopRight;
|
||||
color.fillBottomRight = rgbBottomRight;
|
||||
color.fillBottomLeft = rgbBottomLeft;
|
||||
}
|
||||
|
||||
bool QskBoxOptions::isVisible() const
|
||||
{
|
||||
if ( qAlpha( color.fillTopLeft ) ||
|
||||
qAlpha( color.fillTopRight ) ||
|
||||
qAlpha( color.fillBottomRight ) ||
|
||||
qAlpha( color.fillBottomLeft ) )
|
||||
if ( qskIsVisible( colors.fillColor( Qt::TopLeftCorner ) )
|
||||
|| qskIsVisible( colors.fillColor( Qt::TopRightCorner ) )
|
||||
|| qskIsVisible( colors.fillColor( Qt::BottomLeftCorner ) )
|
||||
|| qskIsVisible( colors.fillColor( Qt::BottomRightCorner ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ( borders.left() && qAlpha( color.borderLeft ) ) ||
|
||||
( borders.top() && qAlpha( color.borderTop ) ) ||
|
||||
( borders.right() && qAlpha( color.borderRight ) ) ||
|
||||
( borders.bottom() && qAlpha( color.borderBottom ) ) )
|
||||
for ( auto edge : { Qt::LeftEdge, Qt::TopEdge, Qt::RightEdge, Qt::BottomEdge } )
|
||||
{
|
||||
if ( metrics.widthAt( edge ) && qskIsVisible( colors.borderColor( edge ) ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -90,13 +35,16 @@ bool QskBoxOptions::isVisible() const
|
||||
|
||||
QMarginsF QskBoxOptions::padding() const
|
||||
{
|
||||
const qreal left = std::max( radius.topLeftX, radius.bottomLeftX );
|
||||
const qreal top = std::max( radius.topLeftY, radius.topRightY );
|
||||
const qreal right = std::max( radius.topRightX, radius.bottomRightX );
|
||||
const qreal bottom = std::max( radius.bottomRightY, radius.bottomLeftY );
|
||||
const QSizeF topLeft = metrics.radius( Qt::TopLeftCorner );
|
||||
const QSizeF topRight = metrics.radius( Qt::TopRightCorner );
|
||||
const QSizeF bottomLeft = metrics.radius( Qt::BottomLeftCorner );
|
||||
const QSizeF bottomRight = metrics.radius( Qt::BottomRightCorner );
|
||||
|
||||
return QMarginsF( std::max( 0.0, left ), std::max( 0.0, top ),
|
||||
std::max( 0.0, right ), std::max( 0.0, bottom ) );
|
||||
return QMarginsF(
|
||||
std::max( topLeft.width(), bottomLeft.width() ),
|
||||
std::max( topLeft.height(), topRight.height() ),
|
||||
std::max( topRight.width(), bottomRight.width() ),
|
||||
std::max( bottomLeft.height(), bottomRight.height() ) );
|
||||
}
|
||||
|
||||
QMarginsF QskBoxOptions::unitedMargins() const
|
||||
@ -111,5 +59,5 @@ QMarginsF QskBoxOptions::unitedMargins() const
|
||||
std::max( 0.0, pad.bottom() - shadows.bottom() ) + 0.5
|
||||
);
|
||||
|
||||
return borders + shadows + pad + extra;
|
||||
return metrics.widths() + shadows + pad + extra;
|
||||
}
|
||||
|
@ -7,70 +7,26 @@
|
||||
#define QSK_BOX_OPTIONS_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include "QskBoxColors.h"
|
||||
#include "QskBorderMetrics.h"
|
||||
|
||||
#include <QMarginsF>
|
||||
#include <QColor>
|
||||
|
||||
class QSK_EXPORT QskBoxOptions
|
||||
{
|
||||
public:
|
||||
QskBoxOptions();
|
||||
|
||||
void setBorder( qreal width );
|
||||
void setBorder( qreal left, qreal top, qreal right, qreal bottom );
|
||||
|
||||
void setRadius( qreal radius );
|
||||
|
||||
void setBorderRgb( QRgb rgb );
|
||||
void setBorderRgb( QRgb rgbLeft, QRgb rgbTop, QRgb rgbRight, QRgb rgbBottom );
|
||||
|
||||
void setFillRgb( QRgb rgb );
|
||||
void setFillRgb( QRgb rgbTopLeft, QRgb rgbTopRight,
|
||||
QRgb rgbBottomRight, QRgb rgbBottomLeft );
|
||||
|
||||
bool isVisible() const;
|
||||
|
||||
QMarginsF unitedMargins() const;
|
||||
QMarginsF padding() const;
|
||||
|
||||
uint metricsHash( uint seed = 0 ) const;
|
||||
uint colorsHash( uint seed = 0 ) const;
|
||||
|
||||
public:
|
||||
QMarginsF shadows;
|
||||
QMarginsF borders;
|
||||
QskMargins shadows;
|
||||
|
||||
struct Radius
|
||||
{
|
||||
qreal topLeftX;
|
||||
qreal topLeftY;
|
||||
|
||||
qreal topRightX;
|
||||
qreal topRightY;
|
||||
|
||||
qreal bottomRightX;
|
||||
qreal bottomRightY;
|
||||
|
||||
qreal bottomLeftX;
|
||||
qreal bottomLeftY;
|
||||
|
||||
} radius;
|
||||
|
||||
struct Colors
|
||||
{
|
||||
// borders
|
||||
QRgb borderLeft;
|
||||
QRgb borderTop;
|
||||
QRgb borderRight;
|
||||
QRgb borderBottom;
|
||||
|
||||
// background
|
||||
QRgb fillTopLeft;
|
||||
QRgb fillTopRight;
|
||||
QRgb fillBottomRight;
|
||||
QRgb fillBottomLeft;
|
||||
|
||||
} color;
|
||||
QskBorderMetrics metrics;
|
||||
QskBoxColors colors;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -7,12 +7,61 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
inline int value( int from, int to, qreal progress )
|
||||
inline int value( int from, int to, qreal ratio )
|
||||
{
|
||||
return int( from + ( to - from ) * progress );
|
||||
return int( from + ( to - from ) * ratio );
|
||||
}
|
||||
}
|
||||
|
||||
static inline QColor qskInterpolatedColor(
|
||||
const QColor& c1, const QColor& c2, qreal ratio )
|
||||
{
|
||||
switch( c1.spec() )
|
||||
{
|
||||
case QColor::Rgb:
|
||||
{
|
||||
const int r = value( c1.red(), c2.red(), ratio );
|
||||
const int g = value( c1.green(), c2.green(), ratio );
|
||||
const int b = value( c1.blue(), c2.blue(), ratio );
|
||||
const int a = value( c1.alpha(), c2.alpha(), ratio );
|
||||
|
||||
return QColor::fromRgb( r, g, b, a );
|
||||
}
|
||||
case QColor::Hsv:
|
||||
{
|
||||
const int h = value( c1.hue(), c2.hue(), ratio );
|
||||
const int s = value( c1.saturation(), c2.saturation(), ratio );
|
||||
const int v = value( c1.value(), c2.value(), ratio );
|
||||
const int a = value( c1.alpha(), c2.alpha(), ratio );
|
||||
|
||||
return QColor::fromHsv( h, s, v, a );
|
||||
}
|
||||
case QColor::Cmyk:
|
||||
{
|
||||
const int c = value( c1.cyan(), c2.cyan(), ratio );
|
||||
const int m = value( c1.magenta(), c2.magenta(), ratio );
|
||||
const int y = value( c1.yellow(), c2.yellow(), ratio );
|
||||
const int k = value( c1.black(), c2.black(), ratio );
|
||||
const int a = value( c1.alpha(), c2.alpha(), ratio );
|
||||
|
||||
return QColor::fromCmykF( c, m, y, k, a );
|
||||
}
|
||||
case QColor::Hsl:
|
||||
{
|
||||
const int h = value( c1.hue(), c2.hue(), ratio );
|
||||
const int s = value( c1.saturation(), c2.saturation(), ratio );
|
||||
const int l = value( c1.lightness(), c2.lightness(), ratio );
|
||||
const int a = value( c1.alpha(), c2.alpha(), ratio );
|
||||
|
||||
return QColor::fromHsl( h, s, l, a );
|
||||
}
|
||||
case QColor::Invalid:
|
||||
break;
|
||||
}
|
||||
|
||||
return c2;
|
||||
}
|
||||
|
||||
QRgb QskRgbValue::interpolated( QRgb rgb1, QRgb rgb2, qreal ratio )
|
||||
{
|
||||
// interpolating in HSV usually provides better results !!
|
||||
@ -20,8 +69,6 @@ QRgb QskRgbValue::interpolated( QRgb rgb1, QRgb rgb2, qreal ratio )
|
||||
if ( rgb1 == rgb2 )
|
||||
return rgb1;
|
||||
|
||||
ratio = qBound( 0.0, ratio, 1.0 );
|
||||
|
||||
const int r = value( qRed( rgb1 ), qRed( rgb2 ), ratio );
|
||||
const int g = value( qGreen( rgb1 ), qGreen( rgb2 ), ratio );
|
||||
const int b = value( qBlue( rgb1 ), qBlue( rgb2 ), ratio );
|
||||
@ -29,3 +76,16 @@ QRgb QskRgbValue::interpolated( QRgb rgb1, QRgb rgb2, qreal ratio )
|
||||
|
||||
return qRgba( r, g, b, a );
|
||||
}
|
||||
|
||||
QColor QskRgbValue::interpolated( const QColor& c1, const QColor& c2, qreal ratio )
|
||||
{
|
||||
if ( c1 != c2 && c1.isValid() && c2.isValid() )
|
||||
{
|
||||
if ( c1.spec() == c2.spec() )
|
||||
return qskInterpolatedColor( c1, c2, ratio );
|
||||
else
|
||||
return qskInterpolatedColor( c1.convertTo( c2.spec() ), c2, ratio );
|
||||
}
|
||||
|
||||
return c2;
|
||||
}
|
||||
|
@ -434,6 +434,7 @@ QSK_RGB_VALUES
|
||||
#undef RGB
|
||||
|
||||
QRgb interpolated( QRgb rgb1, QRgb rgb2, qreal ratio );
|
||||
QColor interpolated( const QColor& c1, const QColor& c2, qreal ratio );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -249,8 +249,8 @@ QskBoxOptions QskSkinRenderer::boxOptions( const QskSkinnable* skinnable,
|
||||
|
||||
QskBoxOptions options;
|
||||
|
||||
options.borders = qskRotatedMargins(
|
||||
skinnable->borderMetrics( subControl ), rotation );
|
||||
options.metrics.setWidths( qskRotatedMargins(
|
||||
skinnable->borderMetrics( subControl ), rotation ) );
|
||||
|
||||
options.shadows = qskRotatedMargins(
|
||||
skinnable->marginsHint( subControl | Shadow ), rotation );
|
||||
@ -267,26 +267,29 @@ QskBoxOptions QskSkinRenderer::boxOptions( const QskSkinnable* skinnable,
|
||||
const auto bottomLeft = static_cast<Corner>( bottomEdge );
|
||||
|
||||
// corner radii
|
||||
options.radius.topLeftX = qskRadius( skinnable, rect, subControl | RadiusX | topLeft );
|
||||
options.radius.topLeftY = qskRadius( skinnable, rect, subControl | RadiusY | topLeft );
|
||||
options.radius.topRightX = qskRadius( skinnable, rect, subControl | RadiusX | topRight );
|
||||
options.radius.topRightY = qskRadius( skinnable, rect, subControl | RadiusY | topRight );
|
||||
options.radius.bottomRightX = qskRadius( skinnable, rect, subControl | RadiusX | bottomRight );
|
||||
options.radius.bottomRightY = qskRadius( skinnable, rect, subControl | RadiusY | bottomRight );
|
||||
options.radius.bottomLeftX = qskRadius( skinnable, rect, subControl | RadiusX | bottomLeft );
|
||||
options.radius.bottomLeftY = qskRadius( skinnable, rect, subControl | RadiusY | bottomLeft );
|
||||
options.metrics.setRadius(
|
||||
qskRadius( skinnable, rect, subControl | RadiusX | topLeft ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusY | topLeft ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusX | topRight ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusY | topRight ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusX | bottomLeft ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusY | bottomLeft ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusX | bottomRight ),
|
||||
qskRadius( skinnable, rect, subControl | RadiusY | bottomRight ) );
|
||||
|
||||
// border colors
|
||||
options.color.borderLeft = skinnable->color( subControl | Border | leftEdge ).rgba();
|
||||
options.color.borderTop = skinnable->color( subControl | Border | topEdge ).rgba();
|
||||
options.color.borderRight = skinnable->color( subControl | Border | rightEdge ).rgba();
|
||||
options.color.borderBottom = skinnable->color( subControl | Border | bottomEdge ).rgba();
|
||||
options.colors.setBorderColor(
|
||||
skinnable->color( subControl | Border | leftEdge ),
|
||||
skinnable->color( subControl | Border | topEdge ),
|
||||
skinnable->color( subControl | Border | rightEdge ),
|
||||
skinnable->color( subControl | Border | bottomEdge ) );
|
||||
|
||||
// background colors
|
||||
options.color.fillTopLeft = skinnable->color( subControl | leftEdge ).rgba();
|
||||
options.color.fillTopRight = skinnable->color( subControl | topEdge ).rgba();
|
||||
options.color.fillBottomRight = skinnable->color( subControl | rightEdge ).rgba();
|
||||
options.color.fillBottomLeft = skinnable->color( subControl | bottomEdge ).rgba();
|
||||
options.colors.setFillColor(
|
||||
skinnable->color( subControl | topLeft ),
|
||||
skinnable->color( subControl | topRight ),
|
||||
skinnable->color( subControl | bottomLeft ),
|
||||
skinnable->color( subControl | bottomRight ) );
|
||||
|
||||
return options;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "QskVariantAnimator.h"
|
||||
#include "QskColorFilter.h"
|
||||
#include "QskMargins.h"
|
||||
#include "QskBorderMetrics.h"
|
||||
#include "QskBoxColors.h"
|
||||
|
||||
// Even if we don't use the standard Qt animation system we
|
||||
// use its registry of interpolators: why adding our own ...
|
||||
@ -18,6 +20,8 @@ static void qskRegisterInterpolator()
|
||||
{
|
||||
qRegisterAnimationInterpolator<QskColorFilter>( QskColorFilter::interpolate );
|
||||
qRegisterAnimationInterpolator<QskMargins>( QskMargins::interpolate );
|
||||
qRegisterAnimationInterpolator<QskBorderMetrics>( QskBorderMetrics::interpolate );
|
||||
qRegisterAnimationInterpolator<QskBoxColors>( QskBoxColors::interpolate );
|
||||
}
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( qskRegisterInterpolator )
|
||||
|
@ -164,14 +164,19 @@ namespace
|
||||
static QPainterPath qskBorderPath( QMarginsF borders, QMarginsF marginsExtra,
|
||||
const QskBoxOptions& options, bool inner )
|
||||
{
|
||||
qreal topLeftX = options.radius.topLeftX;
|
||||
qreal topRightX = options.radius.topRightX;
|
||||
qreal bottomRightX = options.radius.bottomRightX;
|
||||
qreal bottomLeftX = options.radius.bottomLeftX;
|
||||
qreal topLeftY = options.radius.topLeftY;
|
||||
qreal topRightY = options.radius.topRightY;
|
||||
qreal bottomRightY = options.radius.bottomRightY;
|
||||
qreal bottomLeftY = options.radius.bottomLeftY;
|
||||
const auto& metrics = options.metrics;
|
||||
|
||||
qreal topLeftX = metrics.radius( Qt::TopLeftCorner ).width();
|
||||
qreal topRightX = metrics.radius( Qt::TopRightCorner ).width();
|
||||
|
||||
qreal bottomRightX = metrics.radius( Qt::BottomRightCorner ).width();
|
||||
qreal bottomLeftX = metrics.radius( Qt::BottomLeftCorner ).width();
|
||||
|
||||
qreal topLeftY = metrics.radius( Qt::TopLeftCorner ).height();
|
||||
qreal topRightY = metrics.radius( Qt::TopRightCorner ).height();
|
||||
|
||||
qreal bottomRightY = metrics.radius( Qt::BottomRightCorner ).height();
|
||||
qreal bottomLeftY = metrics.radius( Qt::BottomLeftCorner).height();
|
||||
|
||||
const auto spacingX = marginsExtra.left() + marginsExtra.right();
|
||||
const auto spacingY = marginsExtra.top() + marginsExtra.bottom();
|
||||
@ -288,8 +293,9 @@ namespace
|
||||
|
||||
const QMarginsF allMargins = options.unitedMargins();
|
||||
const QMarginsF padding = options.padding();
|
||||
const QMarginsF borders = options.metrics.widths();
|
||||
|
||||
const QMarginsF extra = allMargins - options.borders - options.shadows - padding;
|
||||
const QMarginsF extra = allMargins - borders - options.shadows - padding;
|
||||
|
||||
const auto width = allMargins.left() + allMargins.right();
|
||||
const auto height = allMargins.top() + allMargins.bottom();
|
||||
@ -299,15 +305,15 @@ namespace
|
||||
const auto translateY = options.shadows.top() + ( size.height() - height ) * 0.5f;
|
||||
|
||||
{
|
||||
auto outerPath = qskBorderPath( options.borders, extra, options, false );
|
||||
auto outerPath = qskBorderPath( borders, extra, options, false );
|
||||
outerPath = outerPath.translated( translateX, translateY );
|
||||
|
||||
paths.append( outerPath );
|
||||
}
|
||||
|
||||
if ( !options.borders.isNull() )
|
||||
if ( !borders.isNull() )
|
||||
{
|
||||
auto innerPath = qskBorderPath( options.borders, extra, options, true );
|
||||
auto innerPath = qskBorderPath( borders, extra, options, true );
|
||||
innerPath = innerPath.translated( translateX, translateY );
|
||||
|
||||
paths.append( innerPath );
|
||||
@ -320,7 +326,7 @@ namespace
|
||||
if ( !options.shadows.isNull() )
|
||||
{
|
||||
auto shadowPath = qskBorderPath(
|
||||
options.borders + options.shadows, extra, options, false );
|
||||
borders + options.shadows, extra, options, false );
|
||||
|
||||
shadowPath = shadowPath.translated( translateX - options.shadows.left(),
|
||||
translateY - options.shadows.top() );
|
||||
@ -440,10 +446,8 @@ bool QskBoxMaterial::isValid() const
|
||||
return m_data != nullptr;
|
||||
}
|
||||
|
||||
void QskBoxMaterial::setBoxOptions( const QskBoxOptions& options )
|
||||
void QskBoxMaterial::setBoxOptions( const QskBoxOptions& options, uint key )
|
||||
{
|
||||
const auto key = options.metricsHash();
|
||||
|
||||
auto it = qskTextureCache.find( key );
|
||||
if ( it != qskTextureCache.cend() )
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
QskBoxMaterial();
|
||||
virtual ~QskBoxMaterial();
|
||||
|
||||
void setBoxOptions( const QskBoxOptions& );
|
||||
void setBoxOptions( const QskBoxOptions&, uint key );
|
||||
|
||||
QSizeF textureSize() const;
|
||||
QRectF textureCoordinates() const;
|
||||
|
@ -76,14 +76,19 @@ namespace
|
||||
static QPainterPath qskBorderPath( QMarginsF borders, QMarginsF marginsExtra,
|
||||
const QskBoxOptions& options, bool inner )
|
||||
{
|
||||
qreal topLeftX = options.radius.topLeftX;
|
||||
qreal topRightX = options.radius.topRightX;
|
||||
qreal bottomRightX = options.radius.bottomRightX;
|
||||
qreal bottomLeftX = options.radius.bottomLeftX;
|
||||
qreal topLeftY = options.radius.topLeftY;
|
||||
qreal topRightY = options.radius.topRightY;
|
||||
qreal bottomRightY = options.radius.bottomRightY;
|
||||
qreal bottomLeftY = options.radius.bottomLeftY;
|
||||
const auto& metrics = options.metrics;
|
||||
|
||||
qreal topLeftX = metrics.radius( Qt::TopLeftCorner ).width();
|
||||
qreal topRightX = metrics.radius( Qt::TopRightCorner ).width();
|
||||
|
||||
qreal bottomRightX = metrics.radius( Qt::BottomRightCorner ).width();
|
||||
qreal bottomLeftX = metrics.radius( Qt::BottomLeftCorner ).width();
|
||||
|
||||
qreal topLeftY = metrics.radius( Qt::TopLeftCorner ).height();
|
||||
qreal topRightY = metrics.radius( Qt::TopRightCorner ).height();
|
||||
|
||||
qreal bottomRightY = metrics.radius( Qt::BottomRightCorner ).height();
|
||||
qreal bottomLeftY = metrics.radius( Qt::BottomLeftCorner).height();
|
||||
|
||||
const auto spacingX = marginsExtra.left() + marginsExtra.right();
|
||||
const auto spacingY = marginsExtra.top() + marginsExtra.bottom();
|
||||
@ -200,8 +205,9 @@ namespace
|
||||
|
||||
const QMarginsF allMargins = options.unitedMargins();
|
||||
const QMarginsF padding = options.padding();
|
||||
const QMarginsF borders = options.metrics.widths();
|
||||
|
||||
const QMarginsF extra = allMargins - options.borders - options.shadows - padding;
|
||||
const QMarginsF extra = allMargins - borders - options.shadows - padding;
|
||||
|
||||
const auto width = allMargins.left() + allMargins.right();
|
||||
const auto height = allMargins.top() + allMargins.bottom();
|
||||
@ -211,15 +217,15 @@ namespace
|
||||
const auto translateY = options.shadows.top() + ( size.height() - height ) * 0.5f;
|
||||
|
||||
{
|
||||
auto outerPath = qskBorderPath( options.borders, extra, options, false );
|
||||
auto outerPath = qskBorderPath( borders, extra, options, false );
|
||||
outerPath = outerPath.translated( translateX, translateY );
|
||||
|
||||
paths.append( outerPath );
|
||||
}
|
||||
|
||||
if ( !options.borders.isNull() )
|
||||
if ( !borders.isNull() )
|
||||
{
|
||||
auto innerPath = qskBorderPath( options.borders, extra, options, true );
|
||||
auto innerPath = qskBorderPath( borders, extra, options, true );
|
||||
innerPath = innerPath.translated( translateX, translateY );
|
||||
|
||||
paths.append( innerPath );
|
||||
@ -232,7 +238,7 @@ namespace
|
||||
if ( !options.shadows.isNull() )
|
||||
{
|
||||
auto shadowPath = qskBorderPath(
|
||||
options.borders + options.shadows, extra, options, false );
|
||||
borders + options.shadows, extra, options, false );
|
||||
|
||||
shadowPath = shadowPath.translated( translateX - options.shadows.left(),
|
||||
translateY - options.shadows.top() );
|
||||
@ -356,11 +362,8 @@ QskBoxMaterialVM::~QskBoxMaterialVM()
|
||||
releaseTextures();
|
||||
}
|
||||
|
||||
void QskBoxMaterialVM::setBoxOptions( const QskBoxOptions& options )
|
||||
void QskBoxMaterialVM::setBoxOptions( const QskBoxOptions& options, uint key )
|
||||
{
|
||||
auto key = options.metricsHash();
|
||||
key = qHash( QOpenGLContext::currentContext(), key );
|
||||
|
||||
auto it = qskTextureCache.find( key );
|
||||
if ( it != qskTextureCache.cend() )
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
QskBoxMaterialVM();
|
||||
virtual ~QskBoxMaterialVM();
|
||||
|
||||
void setBoxOptions( const QskBoxOptions& );
|
||||
void setBoxOptions( const QskBoxOptions&, uint key );
|
||||
|
||||
QSizeF textureSize() const;
|
||||
QRectF textureCoordinates() const;
|
||||
|
@ -7,28 +7,48 @@
|
||||
#include "QskBoxOptions.h"
|
||||
#include "QskAspect.h"
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <qhashfunctions.h>
|
||||
|
||||
static inline Qt::Edge qskAspectToEdge( QskAspect::Edge edge )
|
||||
// hashes based on CRC32 -> not necessarily unique: TODO
|
||||
|
||||
static inline uint qskMetricsHash( const QskBoxOptions& options )
|
||||
{
|
||||
switch ( edge )
|
||||
{
|
||||
case QskAspect::LeftEdge:
|
||||
return Qt::LeftEdge;
|
||||
uint hash = qHash( QOpenGLContext::currentContext() );
|
||||
|
||||
case QskAspect::TopEdge:
|
||||
return Qt::TopEdge;
|
||||
hash = qHashBits( &options.shadows, sizeof( options.shadows ), hash );
|
||||
|
||||
case QskAspect::RightEdge:
|
||||
return Qt::RightEdge;
|
||||
const auto& m = options.metrics;
|
||||
hash = qHashBits( &m.widths(), sizeof( QskMargins ), hash );
|
||||
|
||||
case QskAspect::BottomEdge:
|
||||
return Qt::BottomEdge;
|
||||
QSizeF radius[4];
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
radius[i] = m.radius( static_cast<Qt::Corner>( i ) );
|
||||
|
||||
default:
|
||||
break;
|
||||
hash = qHashBits( radius, sizeof( radius ), hash );
|
||||
|
||||
uint flags[2];
|
||||
flags[0] = m.radiusSizeMode();
|
||||
flags[1] = m.widthSizeMode();
|
||||
|
||||
return qHashBits( flags, sizeof( flags ), hash );
|
||||
}
|
||||
return static_cast< Qt::Edge >( 0 );
|
||||
|
||||
static inline uint qskColorsHash( const QskBoxOptions& options )
|
||||
{
|
||||
const auto& colors = options.colors;
|
||||
|
||||
QRgb rgb[8];
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
const QColor c1 = colors.borderColor( static_cast< Qt::Edge >( i ) );
|
||||
rgb[i] = c1.isValid() ? c1.rgba() : 0;
|
||||
|
||||
const QColor c2 = colors.fillColor( static_cast< Qt::Corner >( i ) );
|
||||
rgb[2*i] = c2.isValid() ? c2.rgba() : 0;
|
||||
}
|
||||
|
||||
return qHashBits( rgb, sizeof( rgb ), 17000 );
|
||||
}
|
||||
|
||||
QskBoxNode::QskBoxNode():
|
||||
@ -51,8 +71,8 @@ void QskBoxNode::setBoxData( const QRectF& rect, const QskBoxOptions& options )
|
||||
{
|
||||
using namespace QskAspect;
|
||||
|
||||
const uint metricsHash = options.metricsHash();
|
||||
const uint colorsHash = options.colorsHash();
|
||||
const uint metricsHash = qskMetricsHash( options );
|
||||
const uint colorsHash = qskColorsHash( options );
|
||||
|
||||
QSGNode::DirtyState dirtyState = 0;
|
||||
|
||||
@ -62,7 +82,7 @@ void QskBoxNode::setBoxData( const QRectF& rect, const QskBoxOptions& options )
|
||||
if ( m_metricsHash > 0 )
|
||||
m_material.release( m_metricsHash );
|
||||
#endif
|
||||
m_material.setBoxOptions( options );
|
||||
m_material.setBoxOptions( options, metricsHash );
|
||||
dirtyState |= QSGNode::DirtyMaterial;
|
||||
}
|
||||
|
||||
@ -79,22 +99,28 @@ void QskBoxNode::setBoxData( const QRectF& rect, const QskBoxOptions& options )
|
||||
|
||||
if ( colorsHash != m_colorsHash )
|
||||
{
|
||||
const auto& c = options.colors;
|
||||
|
||||
m_geometry.setEdgeBackground( Qt::LeftEdge,
|
||||
options.color.fillTopLeft, options.color.fillBottomLeft );
|
||||
c.fillColor( Qt::TopLeftCorner ).rgba(),
|
||||
c.fillColor( Qt::BottomLeftCorner ).rgba() );
|
||||
|
||||
m_geometry.setEdgeBackground( Qt::TopEdge,
|
||||
options.color.fillTopLeft, options.color.fillTopRight );
|
||||
c.fillColor( Qt::TopLeftCorner ).rgba(),
|
||||
c.fillColor( Qt::TopRightCorner ).rgba() );
|
||||
|
||||
m_geometry.setEdgeBackground( Qt::RightEdge,
|
||||
options.color.fillTopRight, options.color.fillBottomRight );
|
||||
c.fillColor( Qt::TopRightCorner ).rgba(),
|
||||
c.fillColor( Qt::BottomRightCorner ).rgba() );
|
||||
|
||||
m_geometry.setEdgeBackground( Qt::BottomEdge,
|
||||
options.color.fillBottomLeft, options.color.fillBottomRight );
|
||||
c.fillColor( Qt::BottomLeftCorner ).rgba(),
|
||||
c.fillColor( Qt::BottomRightCorner ).rgba() );
|
||||
|
||||
m_geometry.setEdgeForeground( qskAspectToEdge( LeftEdge ), options.color.borderLeft );
|
||||
m_geometry.setEdgeForeground( qskAspectToEdge( TopEdge ), options.color.borderTop );
|
||||
m_geometry.setEdgeForeground( qskAspectToEdge( RightEdge ), options.color.borderRight );
|
||||
m_geometry.setEdgeForeground( qskAspectToEdge( BottomEdge ), options.color.borderBottom );
|
||||
m_geometry.setEdgeForeground( Qt::LeftEdge, c.borderColor( Qt::LeftEdge ).rgba() );
|
||||
m_geometry.setEdgeForeground( Qt::TopEdge, c.borderColor( Qt::TopEdge ).rgba() );
|
||||
m_geometry.setEdgeForeground( Qt::RightEdge, c.borderColor( Qt::RightEdge ).rgba() );
|
||||
m_geometry.setEdgeForeground( Qt::BottomEdge, c.borderColor( Qt::BottomEdge ).rgba() );
|
||||
|
||||
dirtyState |= QSGNode::DirtyGeometry;
|
||||
m_colorsHash = colorsHash;
|
||||
|
@ -31,6 +31,8 @@ DEPENDPATH *= $${QSK_SUBDIRS}
|
||||
|
||||
HEADERS += \
|
||||
common/QskAspect.h \
|
||||
common/QskBorderMetrics.h \
|
||||
common/QskBoxColors.h \
|
||||
common/QskBoxOptions.h \
|
||||
common/QskCorner.h \
|
||||
common/QskFlags.h \
|
||||
@ -46,6 +48,8 @@ HEADERS += \
|
||||
|
||||
SOURCES += \
|
||||
common/QskAspect.cpp \
|
||||
common/QskBorderMetrics.cpp \
|
||||
common/QskBoxColors.cpp \
|
||||
common/QskBoxOptions.cpp \
|
||||
common/QskCorner.cpp \
|
||||
common/QskFunctions.cpp \
|
||||
|
Loading…
x
Reference in New Issue
Block a user