Merge branch 'slider' into features/slider

This commit is contained in:
Uwe Rathmann 2024-11-07 14:13:10 +01:00
commit 1608ef8596
32 changed files with 458 additions and 434 deletions

View File

@ -30,8 +30,6 @@
- Indicator subcontrol might be better than using the border of the selection box
- cell padding unclear
- using qskDpToPixels ?
*/
/*
@ -134,14 +132,17 @@ namespace Fluent2
namespace
{
Q_DECL_UNUSED inline double operator ""_px( long double value )
/*
mapping between px and logical coordinates
*/
inline constexpr double operator ""_px( long double value )
{
return qskPxToPixels( static_cast< qreal >( value ) );
return static_cast< double >( value );
}
Q_DECL_UNUSED inline double operator ""_px( unsigned long long value )
inline constexpr double operator ""_px( unsigned long long value )
{
return qskPxToPixels( value );
return static_cast< double >( value );
}
inline constexpr QRgb rgbGray( int value, qreal opacity = 1.0 )
@ -2073,10 +2074,9 @@ void QskFluent2Skin::initHints()
addTheme( QskAspect::Footer, themeHeader );
}
static inline QFont createFont( int size, int lineHeight, QFont::Weight weight )
static inline QFont createFont( qreal size, int lineHeight, QFont::Weight weight )
{
Q_UNUSED( lineHeight ); // TODO ...
const int pixelSize = qRound( qskPxToPixels( size ) );
QFont font( QStringLiteral( "Segoe UI" ), -1, weight );
@ -2092,7 +2092,8 @@ static inline QFont createFont( int size, int lineHeight, QFont::Weight weight )
checkFont = false;
}
font.setPixelSize( pixelSize );
// px: 1/96 inch, pt: 1/72 inch
font.setPointSizeF( size * 72.0 / 96.0 );
return font;
}
@ -2101,18 +2102,18 @@ void QskFluent2Skin::setupFonts()
{
// see: https://fluent2.microsoft.design/typography ( Windows )
setFont( Fluent2::Caption, createFont( 12, 16, QFont::Normal ) );
setFont( Fluent2::Caption, createFont( 12_px, 16_px, QFont::Normal ) );
setFont( Fluent2::Body, createFont( 14, 20, QFont::Normal ) );
setFont( Fluent2::BodyStrong, createFont( 14, 20, QFont::DemiBold ) );
setFont( Fluent2::BodyStronger, createFont( 18, 24, QFont::Normal ) );
setFont( Fluent2::Body, createFont( 14_px, 20_px, QFont::Normal ) );
setFont( Fluent2::BodyStrong, createFont( 14_px, 20_px, QFont::DemiBold ) );
setFont( Fluent2::BodyStronger, createFont( 18_px, 24_px, QFont::Normal ) );
setFont( Fluent2::Subtitle, createFont( 20, 28, QFont::DemiBold ) );
setFont( Fluent2::Subtitle, createFont( 20_px, 28_px, QFont::DemiBold ) );
setFont( Fluent2::Title, createFont( 28, 36, QFont::Normal ) );
setFont( Fluent2::LargeTitle, createFont( 40, 52, QFont::DemiBold ) );
setFont( Fluent2::Title, createFont( 28_px, 36_px, QFont::Normal ) );
setFont( Fluent2::LargeTitle, createFont( 40_px, 52_px, QFont::DemiBold ) );
setFont( Fluent2::Display, createFont( 68, 92, QFont::DemiBold ) );
setFont( Fluent2::Display, createFont( 68_px, 92_px, QFont::DemiBold ) );
// to have something for the unused roles
QskSkin::completeFontTable();

View File

@ -80,14 +80,17 @@ namespace
}
};
Q_DECL_UNUSED inline double operator ""_dp( long double value )
/*
mapping between px and logical coordinates
*/
inline double operator ""_px( long double value )
{
return qskDpToPixels( static_cast< qreal >( value ) );
return static_cast< double >( value );
}
Q_DECL_UNUSED inline double operator ""_dp( unsigned long long value )
inline double operator ""_px( unsigned long long value )
{
return qskDpToPixels( value );
return static_cast< double >( value );
}
class Editor : private QskSkinHintTableEditor
@ -186,14 +189,14 @@ void Editor::setupCheckBox()
using A = QskAspect;
using P = QPalette;
setSpacing( Q::Panel, 6_dp );
setSpacing( Q::Panel, 6_px );
setStrutSize( Q::Box, 18_dp, 18_dp );
setBoxShape( Q::Box, 2_dp );
setStrutSize( Q::Box, 18_px, 18_px );
setBoxShape( Q::Box, 2_px );
setBoxBorderColors( Q::Box, m_pal.outline );
setBoxBorderColors( Q::Box | Q::Error, m_pal.error );
setBoxBorderMetrics( Q::Box, 1_dp );
setBoxBorderMetrics( Q::Box, 1_px );
#ifdef SHOW_FOCUS
setBoxBorderColors( Q::Box | Q::Focused, m_pal.highlightedOutline,
@ -221,7 +224,7 @@ void Editor::setupCheckBox()
setGraphicRole( Q::Indicator | Q::Disabled, QskFusionSkin::GraphicDisabled );
setGraphicRole( Q::Indicator | Q::Error, QskFusionSkin::GraphicError );
setPadding( Q::Box, 3_dp );
setPadding( Q::Box, 3_px );
const auto checkMark = symbol( "checkMark" );
for ( auto state : { QskAspect::NoState, Q::Disabled } )
@ -251,10 +254,10 @@ void Editor::setupComboBox()
setColor( Q::Text, m_pal.active( P::ButtonText ) );
setColor( Q::Text | Q::Disabled, m_pal.disabled( P::ButtonText ) );
setStrutSize( Q::Panel, -1.0, 32_dp );
setStrutSize( Q::Panel, -1.0, 32_px );
setBoxShape( Q::Panel, 2 );
setBoxBorderMetrics( Q::Panel, 1_dp );
setBoxBorderMetrics( Q::Panel, 1_px );
setBoxBorderColors( Q::Panel, m_pal.outline );
#ifdef SHOW_FOCUS
@ -262,8 +265,8 @@ void Editor::setupComboBox()
Combination( { Q::Hovered, Q::Pressed } ) );
#endif
setPadding( Q::Panel, 8_dp, 4_dp, 8_dp, 4_dp );
setSpacing( Q::Panel, 8_dp );
setPadding( Q::Panel, 8_px, 4_px, 8_px, 4_px );
setSpacing( Q::Panel, 8_px );
// should be similar for QskPushButton
auto rgbFill = m_pal.button;
@ -274,10 +277,10 @@ void Editor::setupComboBox()
setGradient( Q::Panel | Q::Pressed, QskRgb::darker( rgbFill, 110 ) );
setStrutSize( Q::Icon, 20_dp, 20_dp );
setStrutSize( Q::Icon, 20_px, 20_px );
setGraphicRole( Q::Icon | Q::Disabled, QskFusionSkin::GraphicDisabled );
setStrutSize( Q::StatusIndicator, 10_dp, 10_dp );
setStrutSize( Q::StatusIndicator, 10_px, 10_px );
setGraphicRole( Q::StatusIndicator, QskFusionSkin::GraphicIndicator );
setGraphicRole( Q::StatusIndicator | Q::Disabled, QskFusionSkin::GraphicDisabled );
@ -308,8 +311,8 @@ void Editor::setupMenu()
setHint( Q::Overlay | A::Style, true );
setGradient( Q::Overlay, QColor( 220, 220, 220, 100 ) );
setBoxShape( Q::Panel, 4_dp );
setBoxBorderMetrics( Q::Panel, 1_dp );
setBoxShape( Q::Panel, 4_px );
setBoxBorderMetrics( Q::Panel, 1_px );
for ( auto state : { A::NoState, Q::Disabled } )
{
@ -322,8 +325,8 @@ void Editor::setupMenu()
const bool isCascading = qskMaybeDesktopPlatform();
setHint( Q::Panel | A::Style, isCascading );
setMetric( Q::Separator | A::Size, 1_dp );
setMargin( Q::Separator, QskMargins( 5_dp, 2_dp, 5_dp, 2_dp ) );
setMetric( Q::Separator | A::Size, 1_px );
setMargin( Q::Separator, QskMargins( 5_px, 2_px, 5_px, 2_px ) );
setBoxShape( Q::Separator, 0 );
setBoxBorderMetrics( Q::Separator, 0 );
@ -344,7 +347,7 @@ void Editor::setupMenu()
m_pal.color( colorGroup, P::HighlightedText ) );
}
setPadding( Q::Icon, 8_dp );
setPadding( Q::Icon, 8_px );
setGraphicRole( Q::Icon, QskFusionSkin::GraphicNormal );
setGraphicRole( Q::Icon | Q::Disabled, QskFusionSkin::GraphicDisabled );
@ -397,7 +400,7 @@ void Editor::setupTextInput()
}
setBoxBorderMetrics( Q::Panel, 1_dp );
setBoxBorderMetrics( Q::Panel, 1_px );
setBoxBorderColors( Q::Panel, m_pal.outline );
#ifdef SHOW_FOCUS
@ -405,7 +408,7 @@ void Editor::setupTextInput()
#endif
setBoxShape( Q::Panel, 2 );
setPadding( Q::Panel, 4_dp );
setPadding( Q::Panel, 4_px );
}
void Editor::setupProgressBar()
@ -484,17 +487,17 @@ void Editor::setupRadioBox()
using A = QskAspect;
using P = QPalette;
setSpacing( Q::Panel, 10_dp );
setSpacing( Q::Button, 10_dp );
setSpacing( Q::Panel, 10_px );
setSpacing( Q::Button, 10_px );
setStrutSize( Q::CheckIndicatorPanel, 20_dp, 20_dp );
setStrutSize( Q::CheckIndicatorPanel, 20_px, 20_px );
for ( auto subControl : { Q::CheckIndicatorPanel, Q::CheckIndicator } )
setBoxShape( subControl, 100, Qt::RelativeSize ); // circular
setBoxBorderMetrics( Q::CheckIndicatorPanel, 1_dp );
setBoxBorderMetrics( Q::CheckIndicatorPanel, 1_px );
setPadding( Q::CheckIndicatorPanel, 6_dp );
setPadding( Q::CheckIndicatorPanel, 6_px );
setGradient( Q::Button, QskGradient() );
@ -577,15 +580,15 @@ void Editor::setupSegmentedBar()
// Panel
setPadding( Q::Panel, 0 );
setSpacing( Q::Panel, 5_dp );
setSpacing( Q::Panel, 5_px );
setGradient( Q::Panel, m_pal.active( P::Base ) );
setGradient( Q::Panel | Q::Disabled, m_pal.disabled( P::Base ) );
setBoxBorderMetrics( Q::Panel, 1_dp );
setBoxBorderMetrics( Q::Panel, 1_px );
setBoxBorderColors( Q::Panel, m_pal.outline );
const QSizeF strutSize( 100_dp, 16_dp );
const QSizeF strutSize( 100_px, 16_px );
setStrutSize( Q::Panel | A::Horizontal, strutSize );
setStrutSize( Q::Panel | A::Vertical, strutSize.transposed() );
@ -594,7 +597,7 @@ void Editor::setupSegmentedBar()
{
// Segment
setPadding( Q::Segment, QskMargins( 2_dp, 5_dp, 2_dp, 5_dp ) );
setPadding( Q::Segment, QskMargins( 2_px, 5_px, 2_px, 5_px ) );
setGradient( Q::Segment, QskGradient() );
}
@ -633,7 +636,7 @@ void Editor::setupSegmentedBar()
setGraphicRole( Q::Icon | Q::Disabled, QskFusionSkin::GraphicDisabled );
setGraphicRole( Q::Icon | Q::Selected, QskFusionSkin::GraphicHighlighted );
setStrutSize( Q::Icon, -1, 24_dp );
setStrutSize( Q::Icon, -1, 24_px );
}
}
@ -642,7 +645,7 @@ void Editor::setupSeparator()
using Q = QskSeparator;
using A = QskAspect;
setMetric( Q::Panel | A::Size, 2_dp );
setMetric( Q::Panel | A::Size, 2_px );
setBoxShape( Q::Panel, 0 );
setBoxBorderMetrics( Q::Panel, 0 );
setGradient( Q::Panel, QskRgb::lighter( m_pal.outline, 108 ) );
@ -654,7 +657,7 @@ void Editor::setupPageIndicator()
using A = QskAspect;
using P = QPalette;
const auto extent = 8_dp;
const auto extent = 8_px;
setStrutSize( Q::Bullet, extent, extent );
// circles, without border
@ -677,7 +680,7 @@ void Editor::setupPageIndicator()
setAnimation( Q::Bullet | A::Color, 100 );
setSpacing( Q::Panel, 4_dp );
setSpacing( Q::Panel, 4_px );
setGradient( Q::Panel, QskGradient() ); // invisible
}
@ -691,7 +694,7 @@ void Editor::setupPushButton()
using A = QskAspect;
using P = QPalette;
setStrutSize( Q::Panel, 40_dp, 8_dp );
setStrutSize( Q::Panel, 40_px, 8_px );
setPadding( Q::Panel, 4 );
setMetric( Q::Panel | A::Spacing, 4 );
@ -723,7 +726,7 @@ void Editor::setupPushButton()
setGraphicRole( Q::Icon, QskFusionSkin::GraphicNormal );
setGraphicRole( Q::Icon | Q::Disabled, QskFusionSkin::GraphicDisabled );
setStrutSize( Q::Icon, 22_dp, 22_dp );
setStrutSize( Q::Icon, 22_px, 22_px );
}
void Editor::setupDialogButtonBox()
@ -733,7 +736,7 @@ void Editor::setupDialogButtonBox()
setBoxShape( Q::Panel, 0 );
setBoxBorderMetrics( Q::Panel, 0 );
setPadding( Q::Panel, 2_dp, 4_dp, 2_dp, 0_dp );
setPadding( Q::Panel, 2_px, 4_px, 2_px, 0_px );
setGradient( Q::Panel, m_pal.active( P::Base ) );
setGradient( Q::Panel | Q::Disabled, m_pal.disabled( P::Base ) );
@ -772,7 +775,7 @@ void Editor::setupSlider()
using Q = QskSlider;
using P = QPalette;
const qreal extent = 30_dp;
const qreal extent = 30_px;
// Panel
@ -791,9 +794,9 @@ void Editor::setupSlider()
setPadding( subControl, 0 );
setBoxShape( subControl, 0 );
setBoxBorderMetrics( subControl, 1_dp );
setBoxBorderMetrics( subControl, 1_px );
setMetric( subControl | A::Size, 6_dp );
setMetric( subControl | A::Size, 6_px );
}
{
@ -829,7 +832,7 @@ void Editor::setupSlider()
Combination( { Q::Hovered, Q::Pressed } ) );
#endif
setStrutSize( Q::Handle, 16_dp, 16_dp );
setStrutSize( Q::Handle, 16_px, 16_px );
for ( auto state : { A::NoState, Q::Pressed } )
{
@ -854,16 +857,16 @@ void Editor::setupSpinBox()
using P = QPalette;
setHint( Q::Panel | A::Style, Q::UpDownControl );
setSpacing( Q::Panel, 0_dp );
setBoxShape( Q::Panel, 2_dp );
setBoxBorderMetrics( Q::Panel, 0_dp );
setSpacing( Q::Panel, 0_px );
setBoxShape( Q::Panel, 2_px );
setBoxBorderMetrics( Q::Panel, 0_px );
//setBoxBorderColors( Q::Panel, m_pal.outline );
setPadding( Q::TextPanel, 5_dp );
setPadding( Q::TextPanel, 5_px );
setBoxShape( Q::TextPanel, 2, 0, 2, 0 );
setGradient( Q::TextPanel | Q::Disabled, m_pal.disabled( P::Base ) );
setBoxBorderMetrics( Q::TextPanel, 1_dp );
setBoxBorderMetrics( Q::TextPanel, 1_px );
setBoxBorderColors( Q::TextPanel, m_pal.outline );
#ifdef SHOW_FOCUS
@ -875,11 +878,11 @@ void Editor::setupSpinBox()
setColor( Q::Text, m_pal.active( P::Text ) );
setAlignment( Q::Text, Qt::AlignCenter );
setBoxShape( Q::UpPanel, 0, 2_dp, 0, 0 );
setBoxBorderMetrics( Q::UpPanel, 0_dp, 1_dp, 1_dp, 0_dp );
setBoxShape( Q::UpPanel, 0, 2_px, 0, 0 );
setBoxBorderMetrics( Q::UpPanel, 0_px, 1_px, 1_px, 0_px );
setBoxShape( Q::DownPanel, 0, 0, 0, 2_dp );
setBoxBorderMetrics( Q::DownPanel, 0_dp, 0_dp, 1_dp, 1_dp );
setBoxShape( Q::DownPanel, 0, 0, 0, 2_px );
setBoxBorderMetrics( Q::DownPanel, 0_px, 0_px, 1_px, 1_px );
for ( auto subControl : { Q::UpPanel, Q::DownPanel } )
{
@ -926,16 +929,16 @@ void Editor::setupSwitchButton()
using Q = QskSwitchButton;
using P = QPalette;
const qreal h = 22_dp;
const qreal h = 22_px;
const qreal w = 1.25 * h;
setBoxShape( Q::Groove, 2_dp );
setBoxBorderMetrics( Q::Groove, 1_dp );
setBoxShape( Q::Groove, 2_px );
setBoxBorderMetrics( Q::Groove, 1_px );
setStrutSize( Q::Groove | A::Horizontal, 2.0 * w, h );
setStrutSize( Q::Groove | A::Vertical, h, 2.0 * w );
setBoxShape( Q::Handle, 2_dp );
setBoxBorderMetrics( Q::Handle, 1_dp );
setBoxShape( Q::Handle, 2_px );
setBoxBorderMetrics( Q::Handle, 1_px );
setStrutSize( Q::Handle | A::Horizontal, w, h );
setStrutSize( Q::Handle | A::Vertical, h, w );
@ -982,7 +985,7 @@ void Editor::setupTabButton()
using A = QskAspect;
using P = QPalette;
setStrutSize( Q::Panel, 30_dp, 16_dp );
setStrutSize( Q::Panel, 30_px, 16_px );
setColor( Q::Text, m_pal.active( P::Text ) );
setColor( Q::Text | Q::Disabled, m_pal.disabled( P::Text ) );
@ -1198,12 +1201,12 @@ void Editor::setupScrollView()
{
// The scrollbar is expanding, when being hovered/pressed
const auto extent = 8_dp;
const auto extent = 8_px;
setMetric( subControl | A::Size, extent );
setBoxShape( subControl, 100, Qt::RelativeSize );
const qreal padding = extent - 0_dp;
const qreal padding = extent - 0_px;
if ( subControl == Q::HorizontalScrollBar )
setPadding( subControl, 0, padding, 0, 0 );

View File

@ -101,14 +101,47 @@ namespace
namespace
{
Q_DECL_UNUSED inline double operator ""_dp( long double value )
inline constexpr qreal dpToPixels( qreal value )
{
return qskDpToPixels( static_cast< qreal >( value ) );
/*
see: https://en.wikipedia.org/wiki/Device-independent_pixel
https://developer.android.com/training/multiscreen/screendensities
One dp is a virtual pixel unit that's roughly equal to one pixel
on a medium-density screen ( 160 dpi ).
One logical pixel is equivalent to 1/96th of an inch.
*/
/*
For non scalable resources the following density buckets
are recommended:
ldpi: ( 0 -> 140 ) : 120
mdpi: ( 140 -> 200 ): 160
hdpi: ( 140 -> 280 ): 240
xhdpi: ( 280 -> 400 ): 320
xxhdpi: ( 400 -> 560 ): 480
xxxhdpi: ( 560 -> ... ): 640
For some reason the metrics from the Figma model seem to be
too small on our deskop system. Until this has bee understood
we use the ldpi bucket as the density of the logical coordinate
system falls into it.
Need to find out why TODO ...
*/
return value * 96.0 / 120.0;
}
Q_DECL_UNUSED inline double operator ""_dp( unsigned long long value )
Q_DECL_UNUSED inline constexpr double operator ""_dp( long double value )
{
return qskDpToPixels( value );
return dpToPixels( static_cast< qreal >( value ) );
}
Q_DECL_UNUSED inline constexpr double operator ""_dp( unsigned long long value )
{
return dpToPixels( value );
}
class Combination : public QskStateCombination
@ -1569,16 +1602,11 @@ QskMaterial3Skin::~QskMaterial3Skin()
{
}
static inline QFont createFont( int pointSize, int lineHeight,
static inline QFont createFont( qreal size, int lineHeight,
qreal spacing, QFont::Weight weight )
{
Q_UNUSED( lineHeight );
// convert to px according to https://www.w3.org/TR/css3-values/#absolute-lengths :
const double pxSize = pointSize / 72.0 * 96.0;
const int pixelSize = qRound( qskDpToPixels( pxSize ) );
QFont font( QStringLiteral( "Roboto" ), -1, weight );
static bool checkFont = true;
@ -1593,7 +1621,8 @@ static inline QFont createFont( int pointSize, int lineHeight,
checkFont = false;
}
font.setPixelSize( pixelSize );
// px: 1/96 inch, pt: 1/72 inch
font.setPointSize( size * 72.0 / 96.0 );
if ( spacing > 0.0 )
font.setLetterSpacing( QFont::AbsoluteSpacing, spacing );
@ -1603,30 +1632,35 @@ static inline QFont createFont( int pointSize, int lineHeight,
void QskMaterial3Skin::setupFonts()
{
setFont( LabelSmall, createFont( 11, 16, 0.5, QFont::Medium ) );
setFont( LabelMedium, createFont( 12, 16, 0.5, QFont::Medium ) );
setFont( LabelLarge, createFont( 14, 20, 0.1, QFont::Medium ) );
/*
Not sure what units are used for the font sizes in the specs.
From the results on our desktop system we guess they are in pt
- corresponding to the QFont point size.
*/
setFont( LabelSmall, createFont( 11, 16_dp, 0.5, QFont::Medium ) );
setFont( LabelMedium, createFont( 12, 16_dp, 0.5, QFont::Medium ) );
setFont( LabelLarge, createFont( 14, 20_dp, 0.1, QFont::Medium ) );
setFont( BodySmall, createFont( 12, 16, 0.4, QFont::Normal ) );
setFont( BodyMedium, createFont( 14, 20, 0.25, QFont::Normal ) );
setFont( BodyLarge, createFont( 16, 24, 0.5, QFont::Normal ) );
setFont( BodySmall, createFont( 12, 16_dp, 0.4, QFont::Normal ) );
setFont( BodyMedium, createFont( 14, 20_dp, 0.25, QFont::Normal ) );
setFont( BodyLarge, createFont( 16, 24_dp, 0.5, QFont::Normal ) );
setFont( TitleSmall, createFont( 14, 20, 0.1, QFont::Medium ) );
setFont( TitleMedium, createFont( 16, 24, 0.15, QFont::Medium ) );
setFont( TitleLarge, createFont( 22, 28, 0.0, QFont::Normal ) );
setFont( TitleSmall, createFont( 14, 20_dp, 0.1, QFont::Medium ) );
setFont( TitleMedium, createFont( 16, 24_dp, 0.15, QFont::Medium ) );
setFont( TitleLarge, createFont( 22, 28_dp, 0.0, QFont::Normal ) );
setFont( HeadlineSmall, createFont( 24, 32, 0.0, QFont::Normal ) );
setFont( HeadlineMedium, createFont( 28, 36, 0.0, QFont::Medium ) );
setFont( HeadlineLarge, createFont( 32, 40, 0.0, QFont::Medium ) );
setFont( HeadlineSmall, createFont( 24, 32_dp, 0.0, QFont::Normal ) );
setFont( HeadlineMedium, createFont( 28, 36_dp, 0.0, QFont::Medium ) );
setFont( HeadlineLarge, createFont( 32, 40_dp, 0.0, QFont::Medium ) );
setFont( DisplaySmall, createFont( 36, 44, 0.0, QFont::Normal ) );
setFont( DisplayMedium, createFont( 45, 52, 0.0, QFont::Normal ) );
setFont( DisplayLarge, createFont( 57, 64, 0.0, QFont::Normal ) );
setFont( DisplaySmall, createFont( 36, 44_dp, 0.0, QFont::Normal ) );
setFont( DisplayMedium, createFont( 45, 52_dp, 0.0, QFont::Normal ) );
setFont( DisplayLarge, createFont( 57, 64_dp, 0.0, QFont::Normal ) );
// to have something for the unused roles
setFont( { QskFontRole::Subtitle, QskFontRole::Normal },
createFont( 16, 24, 0.0, QFont::Normal ) );
createFont( 16, 24_dp, 0.0, QFont::Normal ) );
QskSkin::completeFontTable();
}

View File

@ -150,7 +150,7 @@ void Frame::updateFrameNode( const QRectF& rect, QskBoxRectangleNode* node )
const QskBoxBorderColors borderColors( c1, c1, c2, c2 );
const qreal radius = effectiveRadius( rect, m_radius );
node->updateBox( rect, radius, m_frameWidth, borderColors, m_color );
node->updateBox( window(), rect, radius, m_frameWidth, borderColors, m_color );
}
#include "moc_Frame.cpp"

View File

@ -133,24 +133,18 @@ namespace
SwitchButtonBox( QQuickItem* parent = nullptr )
: ButtonBox( Qt::Horizontal, parent )
{
setDimension( 6 );
setDimension( 2 );
setSpacing( 20 );
setDefaultAlignment( Qt::AlignCenter );
for ( auto orientation : { Qt::Vertical, Qt::Horizontal } )
{
using Q = QskSwitchButton;
auto button = new QskSwitchButton( orientation, this );
button->setIconMode( QskSwitchButton::ShowIconAlways );
for( auto iconMode : { Q::NoIcon, Q::ShowIconWhenSelected, Q::ShowIconAlways } )
{
auto button = new QskSwitchButton( orientation, this );
button->setIconMode( iconMode );
auto invertedButton = new QskSwitchButton( orientation, this );
invertedButton->setInverted( true );
invertedButton->setChecked( true );
invertedButton->setIconMode( iconMode );
}
auto invertedButton = new QskSwitchButton( orientation, this );
invertedButton->setInverted( true );
invertedButton->setChecked( true );
}
}
};

View File

@ -173,7 +173,7 @@ QSGNode* DiagramSkinlet::updateChartNode( const Diagram* diagram, QSGNode* node
color = diagram->color( barSubcontrol );
const auto shape = diagram->boxShapeHint( barSubcontrol );
barNode->updateFilling( barRect, shape, color );
barNode->updateFilling( diagram->window(), barRect, shape, color );
}
}
else

View File

@ -11,14 +11,11 @@
#include <QskTextLabel.h>
#include <QskSkinHintTableEditor.h>
#include <QskRgbValue.h>
#include <QskPlatform.h>
#include <QskFontRole.h>
static inline QFont qskFont( qreal pointSize )
{
QFont font( "Roboto" );
font.setPointSizeF( pointSize / qskDpToPixels( 1.0 ) );
return font;
return QFont( "Roboto", pointSize );
}
Skin::Skin()
@ -31,9 +28,8 @@ void Skin::initHints()
{
using namespace QskRgb;
setFont( QskFontRole::Caption, qskFont( 8 ) );
setFont( QskFontRole::Body, qskFont( 13 ) );
setFont( QskFontRole::Title, qskFont( 20 ) );
setFont( QskFontRole::Caption, qskFont( 12 ) );
setFont( QskFontRole::Body, qskFont( 16 ) );
const auto rgb1 = qRgb( 1, 16, 27 ); // Maastricht blue
const auto rgb2 = qRgb( 255, 0, 22 ); // Ruddy

View File

@ -166,7 +166,7 @@ QSGNode* GradientView::updatePaintNode(
{
auto node = gradientNode< QskBoxRectangleNode >( oldNode );
node->setHint( QskFillNode::PreferColoredGeometry, false );
node->updateFilling( rect, shape, m_gradient );
node->updateFilling( window(), rect, shape, m_gradient );
return node;
}
@ -174,7 +174,7 @@ QSGNode* GradientView::updatePaintNode(
{
auto node = gradientNode< QskBoxRectangleNode >( oldNode );
node->setHint( QskFillNode::PreferColoredGeometry, true );
node->updateFilling( rect, shape, m_gradient );
node->updateFilling( window(), rect, shape, m_gradient );
return node;
}

View File

@ -111,7 +111,6 @@ list(APPEND HEADERS
nodes/QskBoxMetrics.h
nodes/QskBoxBasicStroker.h
nodes/QskBoxGradientStroker.h
nodes/QskBoxColorMap.h
nodes/QskBoxShadowNode.h
nodes/QskColorRamp.h
nodes/QskFillNode.h
@ -133,6 +132,7 @@ list(APPEND HEADERS
nodes/QskTextRenderer.h
nodes/QskTextureRenderer.h
nodes/QskVertex.h
nodes/QskVertexHelper.h
)
list(APPEND PRIVATE_HEADERS

View File

@ -6,6 +6,7 @@
#include "QskPlatform.h"
#include <qguiapplication.h>
#include <qquickwindow.h>
#include <qscreen.h>
QSK_QT_PRIVATE_BEGIN
@ -51,40 +52,24 @@ QRect qskPlatformScreenGeometry( const QScreen* screen )
return screen->handle()->geometry();
}
static inline qreal qskRoundedDpi( qreal dpi )
{
// see https://developer.android.com/training/multiscreen/screendensities
if( dpi <= 140.0 )
return 120.0; // ldpi
if( dpi <= 200.0 )
return 160.0; // mdpi
if( dpi <= 280.0 )
return 240.0; // hdpi
if( dpi <= 400.0 )
return 320.0; // xhdpi
if( dpi <= 560.0 )
return 480.0; // xxhdpi
return 640.0; // xxxhdpi
}
qreal qskDpToPixelsFactor()
static inline qreal qskWindowDpi( const QWindow* window )
{
if ( const auto screen = QGuiApplication::primaryScreen() )
return qskRoundedDpi( screen->physicalDotsPerInch() ) / 160.0;
QScreen* screen = nullptr;
if ( window )
screen = window->screen();
return 1.0;
if ( screen == nullptr )
screen = QGuiApplication::primaryScreen();
return QHighDpiScaling::logicalDpi( screen ).first;
}
qreal qskPxToPixelsFactor()
qreal qskInchesToPixels( const QQuickWindow* window, qreal inches )
{
if ( const auto screen = QGuiApplication::primaryScreen() )
return screen->physicalDotsPerInch() / 96.0;
return 1.0;
return qskWindowDpi( window ) * inches;
}
qreal qskMMToPixels( const QQuickWindow* window, qreal mm )
{
return qskWindowDpi( window ) * mm / 25.4;
}

View File

@ -12,6 +12,7 @@ class QScreen;
class QPlatformIntegration;
class QPlatformTheme;
class QRect;
class QQuickWindow;
QSK_EXPORT qreal qskGlobalScaleFactor();
@ -21,36 +22,7 @@ QSK_EXPORT QRect qskPlatformScreenGeometry( const QScreen* );
QSK_EXPORT const QPlatformIntegration* qskPlatformIntegration();
QSK_EXPORT const QPlatformTheme* qskPlatformTheme();
/*
see: https://en.wikipedia.org/wiki/Device-independent_pixel
One dp is a virtual pixel unit that's roughly equal to one pixel
on a medium-density screen ( 160 dpi ).
One px is equivalent to 1/96th of an inch.
*/
QSK_EXPORT qreal qskDpToPixelsFactor();
QSK_EXPORT qreal qskPxToPixelsFactor();
inline qreal qskDpToPixels( qreal value )
{
static qreal factor = -1.0;
if ( factor < 0.0 )
factor = qskDpToPixelsFactor();
return value * factor;
}
inline qreal qskPxToPixels( qreal value )
{
static qreal factor = -1.0;
if ( factor < 0.0 )
factor = qskPxToPixelsFactor();
return value * factor;
}
QSK_EXPORT qreal qskInchesToPixels( const QQuickWindow*, qreal mm );
QSK_EXPORT qreal qskMMToPixels( const QQuickWindow*, qreal mm );
#endif

View File

@ -306,30 +306,24 @@ void QskSkin::declareSkinlet( const QMetaObject* metaObject,
}
static inline void qskSetFont( QskSkin* skin,
QskFontRole::Category category, QskFontRole::Emphasis emphasis,
QFont font, QFont::Weight weight )
QskFontRole::Category category, QFont font, qreal pointSize )
{
font.setWeight( weight );
skin->setFont( { category, emphasis }, font );
}
static inline void qskSetNormalFont( QskSkin* skin,
QskFontRole::Category category, QFont font, int pixelSize )
{
font.setPixelSize( qRound( qskDpToPixels( pixelSize ) ) );
qskSetFont( skin, category, QskFontRole::Normal, font, QFont::Normal );
font.setPointSize( pointSize );
skin->setFont( { category, QskFontRole::Normal }, font );
}
void QskSkin::setupFontTable( const QString& family, bool italic )
{
const QFont font( family, -1, -1, italic );
QFont font( family );
font.setItalic( italic );
font.setWeight( QFont::Normal );
qskSetNormalFont( this, QskFontRole::Caption, font, 10 );
qskSetNormalFont( this, QskFontRole::Subtitle, font, 15 );
qskSetNormalFont( this, QskFontRole::Body, font, 20 );
qskSetNormalFont( this, QskFontRole::Title, font, 24 );
qskSetNormalFont( this, QskFontRole::Headline, font, 32 );
qskSetNormalFont( this, QskFontRole::Display, font, 66 );
qskSetFont( this, QskFontRole::Caption, font, 8 );
qskSetFont( this, QskFontRole::Subtitle, font, 10 );
qskSetFont( this, QskFontRole::Body, font, 12 );
qskSetFont( this, QskFontRole::Title, font, 20 );
qskSetFont( this, QskFontRole::Headline, font, 30 );
qskSetFont( this, QskFontRole::Display, font, 48 );
completeFontTable();
}

View File

@ -196,26 +196,37 @@ static inline QskTextColors qskTextColors(
return c;
}
static inline QQuickWindow* qskWindowOfSkinnable( const QskSkinnable* skinnable )
{
if ( auto item = skinnable->owningItem() )
return item->window();
return nullptr;
}
static inline QSGNode* qskUpdateBoxNode(
const QskSkinnable*, QSGNode* node, const QRectF& rect,
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{
if ( rect.isEmpty() )
return nullptr;
if ( !qskIsBoxVisible( borderMetrics, borderColors, gradient )
&& !qskIsShadowVisible( shadowMetrics, shadowColor ) )
if ( !rect.isEmpty() )
{
return nullptr;
if ( qskIsBoxVisible( borderMetrics, borderColors, gradient )
|| qskIsShadowVisible( shadowMetrics, shadowColor ) )
{
if ( auto window = qskWindowOfSkinnable( skinnable ) )
{
auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node );
boxNode->updateNode( window, rect, shape, borderMetrics,
borderColors, gradient, shadowMetrics, shadowColor );
return boxNode;
}
}
}
auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node );
boxNode->updateNode( rect, shape, borderMetrics,
borderColors, gradient, shadowMetrics, shadowColor );
return boxNode;
return nullptr;
}
static inline QSGNode* qskUpdateArcNode(
@ -373,7 +384,7 @@ QSGNode* QskSkinlet::updateBackgroundNode(
return nullptr;
auto rectNode = QskSGNode::ensureNode< QskBoxRectangleNode >( node );
rectNode->updateFilling( rect, gradient );
rectNode->updateFilling( control->window(), rect, gradient );
return rectNode;
}
@ -648,7 +659,8 @@ QSGNode* QskSkinlet::updateBoxClipNode( const QskSkinnable* skinnable,
auto shape = skinnable->boxShapeHint( subControl );
shape = shape.toAbsolute( clipRect.size() );
clipNode->setBox( clipRect, shape, borderMetrics );
const auto window = qskWindowOfSkinnable( skinnable );
clipNode->setBox( window, clipRect, shape, borderMetrics );
}
return clipNode;

View File

@ -5,7 +5,6 @@
#include "QskSubWindow.h"
#include "QskAspect.h"
#include "QskPlatform.h"
#include "QskGraphic.h"
#include "QskGraphicProvider.h"
#include "QskTextOptions.h"
@ -222,10 +221,10 @@ QSizeF QskSubWindow::layoutSizeHint(
{
// should be Minimum Width/Height from the skin hints
if ( hint.width() < 0.0 )
hint.setWidth( qskDpToPixels( 100 ) );
hint.setWidth( 100 );
if ( hint.height() < 0.0 )
hint.setHeight( qskDpToPixels( 80 ) );
hint.setHeight( 80 );
}
return hint;

View File

@ -24,9 +24,10 @@ static void qskUpdateEventFilter( QskSubWindowArea* area )
}
}
static Qt::Edges qskSelectedEdges( const QRectF& rect, const QPointF& pos )
static Qt::Edges qskSelectedEdges( const QskSubWindowArea* area,
const QRectF& rect, const QPointF& pos )
{
const qreal tolerance = qskDpToPixels( 10.0 );
const qreal tolerance = qskMMToPixels( area->window(), 3 );
Qt::Edges edges;
if ( pos.x() <= rect.left() + tolerance )
@ -222,7 +223,7 @@ bool QskSubWindowArea::mouseEventFilter( QskSubWindow* window, const QMouseEvent
if ( doDrag )
{
m_data->isDragging = true;
m_data->draggedEdges = qskSelectedEdges( cr, mousePos );
m_data->draggedEdges = qskSelectedEdges( this, cr, mousePos );
m_data->mousePos = qskMouseScenePosition( event );
setDragging( window, true );

View File

@ -74,7 +74,7 @@ void QskSwipeView::setSwipeDistance( int distance )
void QskSwipeView::resetSwipeDistance()
{
setSwipeDistance( qRound( qskDpToPixels( 40 ) ) );
setSwipeDistance( qRound( qskMMToPixels( window(), 8 ) ) );
}
int QskSwipeView::duration() const

View File

@ -10,10 +10,6 @@
#include "QskLinearBox.h"
#include "QskQuick.h"
#include "QskEvent.h"
#if 1
#include "QskSkin.h"
#include <QskPlatform.h>
#endif
#include <qquickwindow.h>
#include <qpointer.h>
@ -394,7 +390,7 @@ QSizeF QskDialogSubWindow::layoutSizeHint(
if ( which == Qt::MinimumSize )
{
const auto w = qMax( qskDpToPixels( 300.0 ), size.width() );
const auto w = qMax( 300.0, size.width() );
size.setWidth( w );
}

View File

@ -7,7 +7,7 @@
#include "QskArcMetrics.h"
#include "QskGradient.h"
#include "QskVertex.h"
#include "QskBoxColorMap.h"
#include "QskVertexHelper.h"
#include "QskRgbValue.h"
#include <qsggeometry.h>
@ -359,7 +359,7 @@ namespace
void Renderer::renderLines( const LineStroker& lineStroker,
Line* fillLines, Line* borderLines ) const
{
QskBoxRenderer::GradientIterator it;
QskVertex::GradientIterator it;
if ( fillLines )
{

View File

@ -4,7 +4,6 @@
*****************************************************************************/
#include "QskBoxBasicStroker.h"
#include "QskBoxColorMap.h"
namespace
{
@ -144,7 +143,7 @@ namespace
{
public:
inline FillMap( const QskBoxMetrics& metrics,
const QskBoxRenderer::ColorMap& colorMap )
const QskVertex::ColorMap& colorMap )
: m_colorMap( colorMap )
, m_corners( metrics.corners )
{
@ -184,7 +183,7 @@ namespace
m_colorMap.setLine( x1, y1, x2, y2, line );
}
const QskBoxRenderer::ColorMap& m_colorMap;
const QskVertex::ColorMap& m_colorMap;
const QskBoxMetrics::Corner* m_corners;
};
}
@ -379,12 +378,12 @@ QskBoxBasicStroker::QskBoxBasicStroker( const QskBoxMetrics& metrics )
QskBoxBasicStroker::QskBoxBasicStroker( const QskBoxMetrics& metrics,
const QskBoxBorderColors& borderColors )
: QskBoxBasicStroker( metrics, borderColors, QskBoxRenderer::ColorMap() )
: QskBoxBasicStroker( metrics, borderColors, QskVertex::ColorMap() )
{
}
QskBoxBasicStroker::QskBoxBasicStroker( const QskBoxMetrics& metrics,
const QskBoxBorderColors& borderColors, const QskBoxRenderer::ColorMap& colorMap )
const QskBoxBorderColors& borderColors, const QskVertex::ColorMap& colorMap )
: m_metrics( metrics )
, m_borderColors( borderColors )
, m_colorMap( colorMap )

View File

@ -8,7 +8,7 @@
#include "QskBoxMetrics.h"
#include "QskBoxBorderColors.h"
#include "QskBoxColorMap.h"
#include "QskVertexHelper.h"
class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
@ -25,7 +25,7 @@ class QskBoxBasicStroker
QskBoxBasicStroker( const QskBoxMetrics& );
QskBoxBasicStroker( const QskBoxMetrics&, const QskBoxBorderColors& );
QskBoxBasicStroker( const QskBoxMetrics&,
const QskBoxBorderColors&, const QskBoxRenderer::ColorMap& );
const QskBoxBorderColors&, const QskVertex::ColorMap& );
int fillCount() const;
int borderCount() const;
@ -78,7 +78,7 @@ class QskBoxBasicStroker
const QskBoxMetrics& m_metrics;
const QskBoxBorderColors m_borderColors;
const QskBoxRenderer::ColorMap m_colorMap;
const QskVertex::ColorMap m_colorMap;
const GeometryLayout m_geometryLayout;
const bool m_isColored;

View File

@ -9,6 +9,8 @@
#include "QskBoxShapeMetrics.h"
#include "QskFunctions.h"
#include <qquickitem.h>
static inline QskHashValue qskMetricsHash(
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border )
{
@ -29,7 +31,7 @@ QskBoxClipNode::~QskBoxClipNode()
{
}
void QskBoxClipNode::setBox( const QRectF& rect,
void QskBoxClipNode::setBox( const QQuickWindow* window, const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& border )
{
const auto hash = qskMetricsHash( shape, border );
@ -67,7 +69,9 @@ void QskBoxClipNode::setBox( const QRectF& rect,
else
{
setIsRectangular( false );
QskBoxRenderer::setFillLines( rect, shape, border, m_geometry );
QskBoxRenderer renderer( window );
renderer.setFillLines( rect, shape, border, m_geometry );
}
/*

View File

@ -12,13 +12,15 @@
class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
class QQuickWindow;
class QSK_EXPORT QskBoxClipNode : public QSGClipNode
{
public:
QskBoxClipNode();
~QskBoxClipNode() override;
void setBox( const QRectF&,
void setBox( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics& );
private:

View File

@ -5,8 +5,7 @@
#include "QskBoxGradientStroker.h"
#include "QskBoxBasicStroker.h"
#include "QskVertex.h"
#include "QskBoxColorMap.h"
#include "QskVertexHelper.h"
#include "QskBoxMetrics.h"
static inline bool qskCanUseHVFiller(
@ -172,7 +171,7 @@ namespace
qreal m_t0, m_dt;
const QskBoxMetrics::Corner* m_c1, * m_c2, * m_c3;
QskBoxRenderer::GradientIterator m_gradientIterator;
QskVertex::GradientIterator m_gradientIterator;
};
}
@ -528,7 +527,7 @@ namespace
int setLines( const QskGradient& gradient, ColoredLine* lines )
{
ContourIterator it( m_metrics, gradient.linearDirection() );
QskBoxRenderer::GradientIterator gradientIt( gradient.stops() );
QskVertex::GradientIterator gradientIt( gradient.stops() );
ColoredLine* l = lines;
@ -584,7 +583,7 @@ namespace
const qreal y1 = m_metrics.innerRect.top();
const qreal y2 = m_metrics.innerRect.bottom();
QskBoxRenderer::GradientIterator it( gradient.stops() );
QskVertex::GradientIterator it( gradient.stops() );
ColoredLine* l = lines;
const auto dir = gradient.linearDirection();

View File

@ -6,7 +6,7 @@
#include "QskBoxMetrics.h"
#include "QskBoxShapeMetrics.h"
#include "QskBoxBorderMetrics.h"
#include "QskVertex.h"
#include "QskVertexHelper.h"
#include "QskFunctions.h"
QskBoxMetrics::QskBoxMetrics( const QRectF& rect,

View File

@ -60,7 +60,7 @@ QskBoxNode::~QskBoxNode()
{
}
void QskBoxNode::updateNode( const QRectF& rect,
void QskBoxNode::updateNode( const QQuickWindow* window, const QRectF& rect,
const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
@ -100,7 +100,8 @@ void QskBoxNode::updateNode( const QRectF& rect,
{
// QskBoxRectangleNode allows scene graph batching
shadowFillNode = qskNode< QskBoxRectangleNode >( this, ShadowFillRole );
shadowFillNode->updateFilling( shadowRect, shadowShape, shadowColor );
shadowFillNode->updateFilling( window,
shadowRect, shadowShape, shadowColor );
}
else
{
@ -125,13 +126,16 @@ void QskBoxNode::updateNode( const QRectF& rect,
if ( fillNode )
{
rectNode->updateBorder( rect, shapeMetrics, borderMetrics, borderColors );
fillNode->updateFilling( rect, shapeMetrics, borderMetrics, gradient );
rectNode->updateBorder( window, rect,
shapeMetrics, borderMetrics, borderColors );
fillNode->updateFilling( window, rect,
shapeMetrics, borderMetrics, gradient );
}
else
{
rectNode->updateBox( rect, shapeMetrics,
borderMetrics, borderColors, gradient );
rectNode->updateBox( window, rect,
shapeMetrics, borderMetrics, borderColors, gradient );
}
}
}

View File

@ -15,6 +15,7 @@ class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskGradient;
class QskShadowMetrics;
class QQuickWindow;
class QColor;
class QSK_EXPORT QskBoxNode : public QSGNode
@ -23,7 +24,7 @@ class QSK_EXPORT QskBoxNode : public QSGNode
QskBoxNode();
~QskBoxNode() override;
void updateNode( const QRectF&,
void updateNode( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&,
const QskShadowMetrics&, const QColor& shadowColor );

View File

@ -79,21 +79,22 @@ QskBoxRectangleNode::~QskBoxRectangleNode()
{
}
void QskBoxRectangleNode::updateFilling(
void QskBoxRectangleNode::updateFilling( const QQuickWindow* window,
const QRectF& rect, const QskGradient& gradient )
{
updateFilling( rect, QskBoxShapeMetrics(), QskBoxBorderMetrics(), gradient );
updateFilling( window, rect,
QskBoxShapeMetrics(), QskBoxBorderMetrics(), gradient );
}
void QskBoxRectangleNode::updateFilling( const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskGradient& gradient )
void QskBoxRectangleNode::updateFilling( const QQuickWindow* window,
const QRectF& rect, const QskBoxShapeMetrics& shape, const QskGradient& gradient )
{
updateFilling( rect, shape, QskBoxBorderMetrics(), gradient );
updateFilling( window, rect, shape, QskBoxBorderMetrics(), gradient );
}
void QskBoxRectangleNode::updateFilling( const QRectF& rect,
const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskGradient& gradient )
void QskBoxRectangleNode::updateFilling( const QQuickWindow* window,
const QRectF& rect, const QskBoxShapeMetrics& shapeMetrics,
const QskBoxBorderMetrics& borderMetrics, const QskGradient& gradient )
{
Q_D( QskBoxRectangleNode );
@ -117,11 +118,13 @@ void QskBoxRectangleNode::updateFilling( const QRectF& rect,
if ( dirtyGeometry || dirtyMaterial )
{
QskBoxRenderer renderer( window );
if ( coloredGeometry )
{
setColoring( QskFillNode::Polychrome );
QskBoxRenderer::setColoredFillLines( rect, shape,
renderer.setColoredFillLines( rect, shape,
borderMetrics, fillGradient, *geometry() );
markDirty( QSGNode::DirtyGeometry );
@ -132,18 +135,16 @@ void QskBoxRectangleNode::updateFilling( const QRectF& rect,
if ( dirtyGeometry )
{
QskBoxRenderer::setFillLines(
rect, shape, borderMetrics, *geometry() );
renderer.setFillLines( rect, shape, borderMetrics, *geometry() );
markDirty( QSGNode::DirtyGeometry );
}
}
}
}
void QskBoxRectangleNode::updateBorder( const QRectF& rect,
const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors )
void QskBoxRectangleNode::updateBorder( const QQuickWindow* window,
const QRectF& rect, const QskBoxShapeMetrics& shapeMetrics,
const QskBoxBorderMetrics& borderMetrics, const QskBoxBorderColors& borderColors )
{
Q_D( QskBoxRectangleNode );
@ -166,11 +167,13 @@ void QskBoxRectangleNode::updateBorder( const QRectF& rect,
if ( dirtyGeometry || dirtyMaterial )
{
QskBoxRenderer renderer( window );
if ( coloredGeometry )
{
setColoring( QskFillNode::Polychrome );
QskBoxRenderer::setColoredBorderLines( rect, shape,
renderer.setColoredBorderLines( rect, shape,
borderMetrics, borderColors, *geometry() );
markDirty( QSGNode::DirtyGeometry );
@ -181,7 +184,7 @@ void QskBoxRectangleNode::updateBorder( const QRectF& rect,
if ( dirtyGeometry )
{
QskBoxRenderer::setBorderLines( rect, shape,
renderer.setBorderLines( rect, shape,
borderMetrics, *geometry() );
markDirty( QSGNode::DirtyGeometry );
@ -190,7 +193,7 @@ void QskBoxRectangleNode::updateBorder( const QRectF& rect,
}
}
void QskBoxRectangleNode::updateBox( const QRectF& rect,
void QskBoxRectangleNode::updateBox( const QQuickWindow* window, const QRectF& rect,
const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient )
{
@ -228,7 +231,8 @@ void QskBoxRectangleNode::updateBox( const QRectF& rect,
fillGradient.setDirection( QskGradient::Linear );
}
QskBoxRenderer::setColoredBorderAndFillLines( rect, shape, borderMetrics,
QskBoxRenderer renderer( window );
renderer.setColoredBorderAndFillLines( rect, shape, borderMetrics,
borderColors, fillGradient, *geometry() );
markDirty( QSGNode::DirtyGeometry );
@ -236,11 +240,11 @@ void QskBoxRectangleNode::updateBox( const QRectF& rect,
}
else if ( hasFill )
{
updateFilling( rect, shapeMetrics, borderMetrics, gradient );
updateFilling( window, rect, shapeMetrics, borderMetrics, gradient );
}
else if ( hasBorder )
{
updateBorder( rect, shapeMetrics, borderMetrics, borderColors );
updateBorder( window, rect, shapeMetrics, borderMetrics, borderColors );
}
else
{

View File

@ -13,9 +13,10 @@ class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskGradient;
class QskBoxRectangleNodePrivate;
class QQuickWindow;
class QSK_EXPORT QskBoxRectangleNode : public QskFillNode
{
using Inherited = QskFillNode;
@ -24,21 +25,21 @@ class QSK_EXPORT QskBoxRectangleNode : public QskFillNode
QskBoxRectangleNode();
~QskBoxRectangleNode() override;
void updateBox( const QRectF&,
void updateBox( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient& );
void updateBorder( const QRectF&,
void updateBorder( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors& );
void updateFilling( const QRectF& rect, const QskGradient& );
void updateFilling( const QQuickWindow*, const QRectF&, const QskGradient& );
void updateFilling( const QRectF& rect,
void updateFilling( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskGradient& );
void updateFilling( const QRectF& rect, const QskBoxShapeMetrics&,
const QskBoxBorderMetrics&, const QskGradient& );
void updateFilling( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, const QskGradient& );
/*
If true border/filling can be rendered together into the same geometry.

View File

@ -70,6 +70,15 @@ static inline bool qskMaybeSpreading( const QskGradient& gradient )
return true;
}
QskBoxRenderer::QskBoxRenderer( const QQuickWindow* window )
: m_window( window )
{
}
QskBoxRenderer::~QskBoxRenderer()
{
}
bool QskBoxRenderer::isGradientSupported( const QskGradient& gradient )
{
if ( !gradient.isVisible() || gradient.isMonochrome() )
@ -177,7 +186,7 @@ void QskBoxRenderer::setColoredBorderAndFillLines( const QRectF& rect,
const auto effectiveGradient = qskEffectiveGradient( metrics.innerRect, gradient );
if ( metrics.innerRect.isEmpty() ||
QskBoxRenderer::ColorMap::isGradientSupported( effectiveGradient, metrics.innerRect ) )
QskVertex::ColorMap::isGradientSupported( effectiveGradient, metrics.innerRect ) )
{
/*
The gradient can be translated to a QskBoxRenderer::ColorMap and we can do all
@ -193,12 +202,13 @@ void QskBoxRenderer::setColoredBorderAndFillLines( const QRectF& rect,
const int fillCount = stroker.fillCount();
const int borderCount = stroker.borderCount();
auto lines = qskAllocateColoredLines( geometry, borderCount + fillCount );
if ( auto lines = qskAllocateColoredLines( geometry, borderCount + fillCount ) )
{
auto fillLines = fillCount ? lines : nullptr;
auto borderLines = borderCount ? lines + fillCount : nullptr;
auto fillLines = fillCount ? lines : nullptr;
auto borderLines = borderCount ? lines + fillCount : nullptr;
stroker.setBoxLines( borderLines, fillLines );
stroker.setBoxLines( borderLines, fillLines );
}
}
else
{
@ -235,14 +245,14 @@ void QskBoxRenderer::setColoredBorderAndFillLines( const QRectF& rect,
QskGradient QskBoxRenderer::effectiveGradient( const QskGradient& gradient )
{
if ( ( gradient.type() == QskGradient::Stops ) || gradient.isMonochrome() )
{
{
// the shader for linear gradients is the fastest
auto g = gradient;
g.setDirection( QskGradient::Linear );
return g;
}
return gradient;
}

View File

@ -13,11 +13,16 @@ class QskBoxBorderColors;
class QskBoxShapeMetrics;
class QskGradient;
class QQuickWindow;
class QSGGeometry;
class QRectF;
namespace QskBoxRenderer
class QSK_EXPORT QskBoxRenderer
{
public:
QskBoxRenderer( const QQuickWindow* );
~QskBoxRenderer();
/*
Filling the geometry without any color information:
see QSGGeometry::defaultAttributes_Point2D()
@ -26,13 +31,13 @@ namespace QskBoxRenderer
- using shaders setting the color information
*/
QSK_EXPORT void setBorderLines( const QRectF&,
void setBorderLines( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, QSGGeometry& );
QSK_EXPORT void setFillLines( const QRectF&,
void setFillLines( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&, QSGGeometry& );
QSK_EXPORT void setFillLines( const QRectF&,
void setFillLines( const QRectF&,
const QskBoxShapeMetrics&, QSGGeometry& );
/*
@ -41,21 +46,25 @@ namespace QskBoxRenderer
Usually used in combination with QSGVertexColorMaterial
*/
QSK_EXPORT bool isGradientSupported( const QskGradient& );
QSK_EXPORT void setColoredBorderLines( const QRectF&,
void setColoredBorderLines( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, QSGGeometry& );
QSK_EXPORT void setColoredFillLines( const QRectF&,
void setColoredFillLines( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskGradient&, QSGGeometry& );
QSK_EXPORT void setColoredBorderAndFillLines( const QRectF&,
void setColoredBorderAndFillLines( const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&, QSGGeometry& );
QSK_EXPORT QskGradient effectiveGradient( const QskGradient& );
}
static bool isGradientSupported( const QskGradient& );
static QskGradient effectiveGradient( const QskGradient& );
private:
// for adjustments to the target ( f.e devicePixelRatio )
const QQuickWindow* m_window;
};
#endif

View File

@ -11,7 +11,6 @@
#include <qcolor.h>
#include <qsggeometry.h>
#include <qline.h>
#include <qmath.h>
namespace QskVertex
{
@ -216,126 +215,6 @@ namespace QskVertex
}
}
namespace QskVertex
{
class ArcIterator
{
public:
inline ArcIterator() = default;
inline ArcIterator( int stepCount, bool inverted = false )
{
reset( stepCount, inverted );
}
void reset( int stepCount, bool inverted = false )
{
m_inverted = inverted;
if ( inverted )
{
m_cos = 1.0;
m_sin = 0.0;
}
else
{
m_cos = 0.0;
m_sin = 1.0;
}
m_stepIndex = 0;
m_stepCount = stepCount;
const auto angleStep = M_PI_2 / stepCount;
m_cosStep = qFastCos( angleStep );
m_sinStep = qFastSin( angleStep );
}
inline bool isInverted() const { return m_inverted; }
inline qreal cos() const { return m_cos; }
inline qreal sin() const { return m_inverted ? -m_sin : m_sin; }
inline int step() const { return m_stepIndex; }
inline int stepCount() const { return m_stepCount; }
inline bool isDone() const { return m_stepIndex > m_stepCount; }
inline void increment()
{
if ( ++m_stepIndex >= m_stepCount )
{
if ( m_stepIndex == m_stepCount )
{
/*
Doubles are not numerical stable and the small errors,
sum up when iterating in steps. To avoid having to deal with
fuzzy compares we manually fix cos/sin at the end.
*/
if ( m_inverted )
{
m_cos = 0.0;
m_sin = -1.0;
}
else
{
m_cos = 1.0;
m_sin = 0.0;
}
}
}
else
{
const auto cos0 = m_cos;
m_cos = m_cos * m_cosStep + m_sin * m_sinStep;
m_sin = m_sin * m_cosStep - cos0 * m_sinStep;
}
}
inline void decrement()
{
revert();
increment();
revert();
}
inline void operator++() { increment(); }
static int segmentHint( qreal radius )
{
const auto arcLength = radius * M_PI_2;
return qBound( 3, qCeil( arcLength / 3.0 ), 18 ); // every 3 pixels
}
inline void revert()
{
m_inverted = !m_inverted;
m_stepIndex = m_stepCount - m_stepIndex;
m_sin = -m_sin;
}
ArcIterator reverted() const
{
ArcIterator it = *this;
it.revert();
return it;
}
private:
qreal m_cos;
qreal m_sin;
int m_stepIndex;
qreal m_cosStep;
qreal m_sinStep;
int m_stepCount;
bool m_inverted;
};
}
namespace QskVertex
{
void debugGeometry( const QSGGeometry& );

View File

@ -3,14 +3,136 @@
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_BOX_RENDERER_COLOR_MAP_H
#define QSK_BOX_RENDERER_COLOR_MAP_H
#ifndef QSK_VERTEX_HELPER_H
#define QSK_VERTEX_HELPER_H
#include <QskGradient.h>
#include <QskGradientDirection.h>
#include <QskVertex.h>
#include "QskGradient.h"
#include "QskGradientDirection.h"
#include "QskVertex.h"
namespace QskBoxRenderer
#include <qmath.h>
namespace QskVertex
{
class ArcIterator
{
public:
inline ArcIterator() = default;
inline ArcIterator( int stepCount, bool inverted = false )
{
reset( stepCount, inverted );
}
void reset( int stepCount, bool inverted = false )
{
m_inverted = inverted;
if ( inverted )
{
m_cos = 1.0;
m_sin = 0.0;
}
else
{
m_cos = 0.0;
m_sin = 1.0;
}
m_stepIndex = 0;
m_stepCount = stepCount;
const auto angleStep = M_PI_2 / stepCount;
m_cosStep = qFastCos( angleStep );
m_sinStep = qFastSin( angleStep );
}
inline bool isInverted() const { return m_inverted; }
inline qreal cos() const { return m_cos; }
inline qreal sin() const { return m_inverted ? -m_sin : m_sin; }
inline int step() const { return m_stepIndex; }
inline int stepCount() const { return m_stepCount; }
inline bool isDone() const { return m_stepIndex > m_stepCount; }
inline void increment()
{
if ( ++m_stepIndex >= m_stepCount )
{
if ( m_stepIndex == m_stepCount )
{
/*
Doubles are not numerical stable and the small errors,
sum up when iterating in steps. To avoid having to deal with
fuzzy compares we manually fix cos/sin at the end.
*/
if ( m_inverted )
{
m_cos = 0.0;
m_sin = -1.0;
}
else
{
m_cos = 1.0;
m_sin = 0.0;
}
}
}
else
{
const auto cos0 = m_cos;
m_cos = m_cos * m_cosStep + m_sin * m_sinStep;
m_sin = m_sin * m_cosStep - cos0 * m_sinStep;
}
}
inline void decrement()
{
revert();
increment();
revert();
}
inline void operator++() { increment(); }
static int segmentHint( qreal radius )
{
const auto arcLength = radius * M_PI_2;
return qBound( 3, qCeil( arcLength / 3.0 ), 18 ); // every 3 pixels
}
inline void revert()
{
m_inverted = !m_inverted;
m_stepIndex = m_stepCount - m_stepIndex;
m_sin = -m_sin;
}
ArcIterator reverted() const
{
ArcIterator it = *this;
it.revert();
return it;
}
private:
qreal m_cos;
qreal m_sin;
int m_stepIndex;
qreal m_cosStep;
qreal m_sinStep;
int m_stepCount;
bool m_inverted;
};
}
namespace QskVertex
{
class ColorMap
{
@ -101,7 +223,10 @@ namespace QskBoxRenderer
const QskVertex::Color m_color1;
const QskVertex::Color m_color2;
};
}
namespace QskVertex
{
class GradientIterator
{
public: