diff --git a/designsystems/fluent2/QskFluent2Skin.cpp b/designsystems/fluent2/QskFluent2Skin.cpp index 5455b3f4..c811bc8f 100644 --- a/designsystems/fluent2/QskFluent2Skin.cpp +++ b/designsystems/fluent2/QskFluent2Skin.cpp @@ -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(); diff --git a/designsystems/fusion/QskFusionSkin.cpp b/designsystems/fusion/QskFusionSkin.cpp index 5feceb48..bad14860 100644 --- a/designsystems/fusion/QskFusionSkin.cpp +++ b/designsystems/fusion/QskFusionSkin.cpp @@ -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 ); diff --git a/designsystems/material3/QskMaterial3Skin.cpp b/designsystems/material3/QskMaterial3Skin.cpp index 74020ffc..117d52cd 100644 --- a/designsystems/material3/QskMaterial3Skin.cpp +++ b/designsystems/material3/QskMaterial3Skin.cpp @@ -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(); } diff --git a/examples/frames/Frame.cpp b/examples/frames/Frame.cpp index 4c89f3d3..88c11bb7 100644 --- a/examples/frames/Frame.cpp +++ b/examples/frames/Frame.cpp @@ -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" diff --git a/examples/gallery/button/ButtonPage.cpp b/examples/gallery/button/ButtonPage.cpp index bc00b4d1..d1658a31 100644 --- a/examples/gallery/button/ButtonPage.cpp +++ b/examples/gallery/button/ButtonPage.cpp @@ -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 ); } } }; diff --git a/examples/iotdashboard/DiagramSkinlet.cpp b/examples/iotdashboard/DiagramSkinlet.cpp index 5e2ab79f..4287bcf1 100644 --- a/examples/iotdashboard/DiagramSkinlet.cpp +++ b/examples/iotdashboard/DiagramSkinlet.cpp @@ -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 diff --git a/playground/dials/Skin.cpp b/playground/dials/Skin.cpp index 760c927e..25e3f381 100644 --- a/playground/dials/Skin.cpp +++ b/playground/dials/Skin.cpp @@ -11,14 +11,11 @@ #include #include #include -#include #include 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 diff --git a/playground/gradients/GradientView.cpp b/playground/gradients/GradientView.cpp index 78d90fed..2804cbbe 100644 --- a/playground/gradients/GradientView.cpp +++ b/playground/gradients/GradientView.cpp @@ -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; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 151ed18f..0c8fa825 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/common/QskPlatform.cpp b/src/common/QskPlatform.cpp index 10fdc86f..935d8452 100644 --- a/src/common/QskPlatform.cpp +++ b/src/common/QskPlatform.cpp @@ -6,6 +6,7 @@ #include "QskPlatform.h" #include +#include #include 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; } diff --git a/src/common/QskPlatform.h b/src/common/QskPlatform.h index e5c9fa83..0381b626 100644 --- a/src/common/QskPlatform.h +++ b/src/common/QskPlatform.h @@ -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 diff --git a/src/controls/QskSkin.cpp b/src/controls/QskSkin.cpp index 61af02a0..76f37577 100644 --- a/src/controls/QskSkin.cpp +++ b/src/controls/QskSkin.cpp @@ -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(); } diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index 7befc837..33a9661f 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -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; diff --git a/src/controls/QskSubWindow.cpp b/src/controls/QskSubWindow.cpp index 5daa8c2b..aae33665 100644 --- a/src/controls/QskSubWindow.cpp +++ b/src/controls/QskSubWindow.cpp @@ -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; diff --git a/src/controls/QskSubWindowArea.cpp b/src/controls/QskSubWindowArea.cpp index 5e7db643..dc632894 100644 --- a/src/controls/QskSubWindowArea.cpp +++ b/src/controls/QskSubWindowArea.cpp @@ -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 ); diff --git a/src/controls/QskSwipeView.cpp b/src/controls/QskSwipeView.cpp index a1e94a09..a25cffdb 100644 --- a/src/controls/QskSwipeView.cpp +++ b/src/controls/QskSwipeView.cpp @@ -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 diff --git a/src/dialogs/QskDialogSubWindow.cpp b/src/dialogs/QskDialogSubWindow.cpp index 3cde7a12..765c805e 100644 --- a/src/dialogs/QskDialogSubWindow.cpp +++ b/src/dialogs/QskDialogSubWindow.cpp @@ -10,10 +10,6 @@ #include "QskLinearBox.h" #include "QskQuick.h" #include "QskEvent.h" -#if 1 -#include "QskSkin.h" -#include -#endif #include #include @@ -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 ); } diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index 02e843f9..72f64440 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -7,7 +7,7 @@ #include "QskArcMetrics.h" #include "QskGradient.h" #include "QskVertex.h" -#include "QskBoxColorMap.h" +#include "QskVertexHelper.h" #include "QskRgbValue.h" #include @@ -359,7 +359,7 @@ namespace void Renderer::renderLines( const LineStroker& lineStroker, Line* fillLines, Line* borderLines ) const { - QskBoxRenderer::GradientIterator it; + QskVertex::GradientIterator it; if ( fillLines ) { diff --git a/src/nodes/QskBoxBasicStroker.cpp b/src/nodes/QskBoxBasicStroker.cpp index b893428a..0221e3b9 100644 --- a/src/nodes/QskBoxBasicStroker.cpp +++ b/src/nodes/QskBoxBasicStroker.cpp @@ -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 ) diff --git a/src/nodes/QskBoxBasicStroker.h b/src/nodes/QskBoxBasicStroker.h index b43e9fbc..f65713dd 100644 --- a/src/nodes/QskBoxBasicStroker.h +++ b/src/nodes/QskBoxBasicStroker.h @@ -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; diff --git a/src/nodes/QskBoxClipNode.cpp b/src/nodes/QskBoxClipNode.cpp index c04d79e2..1006cb81 100644 --- a/src/nodes/QskBoxClipNode.cpp +++ b/src/nodes/QskBoxClipNode.cpp @@ -9,6 +9,8 @@ #include "QskBoxShapeMetrics.h" #include "QskFunctions.h" +#include + 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 ); } /* diff --git a/src/nodes/QskBoxClipNode.h b/src/nodes/QskBoxClipNode.h index 9312334d..1a637792 100644 --- a/src/nodes/QskBoxClipNode.h +++ b/src/nodes/QskBoxClipNode.h @@ -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: diff --git a/src/nodes/QskBoxGradientStroker.cpp b/src/nodes/QskBoxGradientStroker.cpp index ad2537ca..97c444d9 100644 --- a/src/nodes/QskBoxGradientStroker.cpp +++ b/src/nodes/QskBoxGradientStroker.cpp @@ -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(); diff --git a/src/nodes/QskBoxMetrics.cpp b/src/nodes/QskBoxMetrics.cpp index a0cf0cff..4972ad3d 100644 --- a/src/nodes/QskBoxMetrics.cpp +++ b/src/nodes/QskBoxMetrics.cpp @@ -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, diff --git a/src/nodes/QskBoxNode.cpp b/src/nodes/QskBoxNode.cpp index 22cc78c5..89af944d 100644 --- a/src/nodes/QskBoxNode.cpp +++ b/src/nodes/QskBoxNode.cpp @@ -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 ); } } } diff --git a/src/nodes/QskBoxNode.h b/src/nodes/QskBoxNode.h index 999fa58c..8e14d668 100644 --- a/src/nodes/QskBoxNode.h +++ b/src/nodes/QskBoxNode.h @@ -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 ); diff --git a/src/nodes/QskBoxRectangleNode.cpp b/src/nodes/QskBoxRectangleNode.cpp index 62fcb8c5..ce715e1d 100644 --- a/src/nodes/QskBoxRectangleNode.cpp +++ b/src/nodes/QskBoxRectangleNode.cpp @@ -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 { diff --git a/src/nodes/QskBoxRectangleNode.h b/src/nodes/QskBoxRectangleNode.h index 362f1afe..1446bc3e 100644 --- a/src/nodes/QskBoxRectangleNode.h +++ b/src/nodes/QskBoxRectangleNode.h @@ -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. diff --git a/src/nodes/QskBoxRenderer.cpp b/src/nodes/QskBoxRenderer.cpp index eadd6693..f5f039fb 100644 --- a/src/nodes/QskBoxRenderer.cpp +++ b/src/nodes/QskBoxRenderer.cpp @@ -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; } diff --git a/src/nodes/QskBoxRenderer.h b/src/nodes/QskBoxRenderer.h index 9b30eb88..1352ff7c 100644 --- a/src/nodes/QskBoxRenderer.h +++ b/src/nodes/QskBoxRenderer.h @@ -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 diff --git a/src/nodes/QskVertex.h b/src/nodes/QskVertex.h index 967d2382..e8ec9240 100644 --- a/src/nodes/QskVertex.h +++ b/src/nodes/QskVertex.h @@ -11,7 +11,6 @@ #include #include #include -#include 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& ); diff --git a/src/nodes/QskBoxColorMap.h b/src/nodes/QskVertexHelper.h similarity index 63% rename from src/nodes/QskBoxColorMap.h rename to src/nodes/QskVertexHelper.h index 69f04604..742dcf62 100644 --- a/src/nodes/QskBoxColorMap.h +++ b/src/nodes/QskVertexHelper.h @@ -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 -#include -#include +#include "QskGradient.h" +#include "QskGradientDirection.h" +#include "QskVertex.h" -namespace QskBoxRenderer +#include + +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: