using point sizes for fonts and metrics in logical coordinates

This commit is contained in:
Uwe Rathmann 2024-10-31 13:30:06 +01:00
parent d33c556a7b
commit a2719b4ccd
6 changed files with 98 additions and 136 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 ""_px( 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 ""_px( unsigned long long value )
inline double operator ""_px( unsigned long long value )
{
return qskDpToPixels( value );
return static_cast< double >( value );
}
class Editor : private QskSkinHintTableEditor

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
@ -1536,16 +1569,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;
@ -1560,7 +1588,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 );
@ -1570,30 +1599,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

@ -52,44 +52,6 @@ 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()
{
if ( const auto screen = QGuiApplication::primaryScreen() )
return qskRoundedDpi( screen->physicalDotsPerInch() ) / 160.0;
return 1.0;
}
qreal qskPxToPixelsFactor()
{
if ( const auto screen = QGuiApplication::primaryScreen() )
return screen->physicalDotsPerInch() / 96.0;
return 1.0;
}
static inline qreal qskWindowDpi( const QWindow* window )
{
QScreen* screen = nullptr;

View File

@ -22,39 +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();
QSK_EXPORT qreal qskInchesToPixels( const QQuickWindow*, qreal mm );
QSK_EXPORT qreal qskMMToPixels( const QQuickWindow*, qreal mm );
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;
}
#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();
}