2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "QskBoxNode.h"
|
|
|
|
#include "QskBoxOptions.h"
|
|
|
|
#include "QskAspect.h"
|
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
#include <QOpenGLContext>
|
2017-07-21 18:21:34 +02:00
|
|
|
#include <qhashfunctions.h>
|
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
// hashes based on CRC32 -> not necessarily unique: TODO
|
|
|
|
|
|
|
|
static inline uint qskMetricsHash( const QskBoxOptions& options )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-08-28 17:42:11 +02:00
|
|
|
uint hash = qHash( QOpenGLContext::currentContext() );
|
|
|
|
|
|
|
|
hash = qHashBits( &options.shadows, sizeof( options.shadows ), hash );
|
|
|
|
|
|
|
|
const auto& m = options.metrics;
|
|
|
|
hash = qHashBits( &m.widths(), sizeof( QskMargins ), hash );
|
|
|
|
|
|
|
|
QSizeF radius[4];
|
|
|
|
for ( int i = 0; i < 4; i++ )
|
|
|
|
radius[i] = m.radius( static_cast<Qt::Corner>( i ) );
|
|
|
|
|
|
|
|
hash = qHashBits( radius, sizeof( radius ), hash );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
uint flags[2];
|
|
|
|
flags[0] = m.radiusSizeMode();
|
|
|
|
flags[1] = m.widthSizeMode();
|
|
|
|
|
|
|
|
return qHashBits( flags, sizeof( flags ), hash );
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
static inline uint qskColorsHash( const QskBoxOptions& options )
|
|
|
|
{
|
|
|
|
const auto& colors = options.colors;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
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;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
const QColor c2 = colors.fillColor( static_cast< Qt::Corner >( i ) );
|
|
|
|
rgb[2*i] = c2.isValid() ? c2.rgba() : 0;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2017-08-28 17:42:11 +02:00
|
|
|
|
|
|
|
return qHashBits( rgb, sizeof( rgb ), 17000 );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QskBoxNode::QskBoxNode():
|
|
|
|
m_metricsHash( 0 ),
|
|
|
|
m_colorsHash( 0 )
|
|
|
|
{
|
|
|
|
setGeometry( &m_geometry );
|
|
|
|
setMaterial( &m_material );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskBoxNode::~QskBoxNode()
|
|
|
|
{
|
|
|
|
#if VM_SUPPORT
|
|
|
|
if ( m_metricsHash > 0 )
|
|
|
|
m_material.release( m_metricsHash );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskBoxNode::setBoxData( const QRectF& rect, const QskBoxOptions& options )
|
|
|
|
{
|
|
|
|
using namespace QskAspect;
|
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
const uint metricsHash = qskMetricsHash( options );
|
|
|
|
const uint colorsHash = qskColorsHash( options );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
QSGNode::DirtyState dirtyState = 0;
|
|
|
|
|
|
|
|
if ( !m_material.isValid() || ( metricsHash != m_metricsHash ) )
|
|
|
|
{
|
|
|
|
#if VM_SUPPORT
|
|
|
|
if ( m_metricsHash > 0 )
|
|
|
|
m_material.release( m_metricsHash );
|
|
|
|
#endif
|
2017-08-28 17:42:11 +02:00
|
|
|
m_material.setBoxOptions( options, metricsHash );
|
2017-07-21 18:21:34 +02:00
|
|
|
dirtyState |= QSGNode::DirtyMaterial;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ( rect != m_rect ) || ( metricsHash != m_metricsHash ) )
|
|
|
|
{
|
|
|
|
m_geometry.setBorder( rect, options.unitedMargins(),
|
|
|
|
m_material.textureCoordinates(), m_material.textureSize() );
|
|
|
|
|
|
|
|
dirtyState |= QSGNode::DirtyGeometry;
|
|
|
|
|
|
|
|
m_metricsHash = metricsHash;
|
|
|
|
m_rect = rect;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( colorsHash != m_colorsHash )
|
|
|
|
{
|
2017-08-28 17:42:11 +02:00
|
|
|
const auto& c = options.colors;
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
m_geometry.setEdgeBackground( Qt::LeftEdge,
|
2017-08-28 17:42:11 +02:00
|
|
|
c.fillColor( Qt::TopLeftCorner ).rgba(),
|
|
|
|
c.fillColor( Qt::BottomLeftCorner ).rgba() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
m_geometry.setEdgeBackground( Qt::TopEdge,
|
2017-08-28 17:42:11 +02:00
|
|
|
c.fillColor( Qt::TopLeftCorner ).rgba(),
|
|
|
|
c.fillColor( Qt::TopRightCorner ).rgba() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
m_geometry.setEdgeBackground( Qt::RightEdge,
|
2017-08-28 17:42:11 +02:00
|
|
|
c.fillColor( Qt::TopRightCorner ).rgba(),
|
|
|
|
c.fillColor( Qt::BottomRightCorner ).rgba() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
m_geometry.setEdgeBackground( Qt::BottomEdge,
|
2017-08-28 17:42:11 +02:00
|
|
|
c.fillColor( Qt::BottomLeftCorner ).rgba(),
|
|
|
|
c.fillColor( Qt::BottomRightCorner ).rgba() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-08-28 17:42:11 +02:00
|
|
|
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() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
dirtyState |= QSGNode::DirtyGeometry;
|
|
|
|
m_colorsHash = colorsHash;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dirtyState )
|
|
|
|
markDirty( dirtyState );
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskBoxNode::rect() const
|
|
|
|
{
|
|
|
|
return m_rect;
|
|
|
|
}
|