[SOLVED] Size of text is different on Windows OS and Mac OS



  • My project must run on two platforms: Windows and Mac OS
    Mainly all is working great wihtout trouble except one: the size of text ...

    We use QML to display text - like this simple code:
    @
    Text {
    text: "hello world"
    font.pointSize: 11
    }
    @

    On Mac, the text is written smaller ...
    How to deal witht this ? must I check DPI according the system and calculate the correct "pointSize" to use ? If yes, how t odo it ?
    I prefer to always use font based on "pointSize" since the display is better. But in order to support multi-platform does I need to finally use "pixelSize" instead ?

    I search already on this forum but I found no answer ...

    Thx.



  • At most cases - yes - it's the best way to solve your problem.
    On the other hand you can determine Text.fontSizeMode property. And as the the worst way you can set value depend on platform:
    @
    ...
    font.pointSize: Qt.platform == "windows" ? 10 : 16
    ...
    @



  • For me it's a bug !!
    The point size is a standard unit of measure:
    http://en.wikipedia.org/wiki/Point_(typography)
    So, the physical dimension has to be always the same regardless of the platform and of the device.
    So, I think that if it's physical dimension are different on different platform it's a bug of the underlying qt rendering system.


  • Moderators



  • Roumed:
    About "Text.fontSizeMode" property, there is a known bug -declared as minor an still opened in Qt 5.3 ... :(
    "https://bugreports.qt-project.org/browse/QTBUG-30005":https://bugreports.qt-project.org/browse/QTBUG-30005

    Gianluca:
    Are you sure that it's a bug ?
    The Wikipedia link indicates this:
    "In digital type, letters of a font are designed around an imaginary space called an "em square". When a point size of a font is specified, the font is scaled so that its em square has a side length of that particular length in points. Although the letters of a font usually fit within the font's em square, there is not necessarily any size relationship between the two, so the point size does not necessarily correspond to any measurement of the size of the letters on the printed page"

    I just "google" font window mac" and finally this pb occurs often ...
    I found this link very interesting:
    "http://damieng.com/blog/2007/06/13/font-rendering-philosophies-of-windows-and-mac-os-x":http://damieng.com/blog/2007/06/13/font-rendering-philosophies-of-windows-and-mac-os-x

    And it seems there is not a real easy solution .. :(

    Thank you for your time.
    Regards.



  • One reason I am not using "font.pointSize" for my projects anymore...

    A little sad but to be honest you will have similar problems with other measurements like spacing or size or a simple Rectangle etc where you cannot use pointSize in the first place.

    So my solution, if you want to keep the size of fonts or other QML items the same physical size on all devices, use pixelSize for fonts and calculate the actual size yourself.

    I know that sounds terrible in the first moment, but it is very little overhead if you just multiply a factor to all sizes, QML property binding takes care of most things in my experience.

    Simple example:
    @
    property real globalScaleFactor: Screen.physicalDotsPerInch / 160 // scale factor normalized to 160 DPI

    Text {
    text: "hello world"
    font.pixelSize: 11 * globalScaleFactor
    }

    Rectangle {
    width: 100 * globalScaleFactor
    height: 50 * globalScaleFactor
    }

    ListView {
    spacing: 5 * globalScaleFactor
    }
    @
    So you just apply that factor to all values you want to be scaled to the same physical size, that is it. I use 160 DPI as the default size here, meaning if your screen has 160 DPI a unit of 1 will match 1 pixel, if the device has 320 DPI it will be 2 pixel and so on (pretty simple I guess). In case you are wondering why 160, that is the default value on Android devices, if you have ever created a Android app you have to specify a scale factor like this for all sizes, it is only called "dp" (e.g. 10dp for 10 density independent pixels instead of 10*globalScaleFactor in this case) and "sp" etc, but in the end it's the same principle, only you have to multiply the factor yourself in QML.

    Positive side effect, you can zoom your app at run time by changing the global scale factor, because of the dynamic property binding!
    The scale property in QMl is different than scaling fonts or other QML items, because scale is applied after the layout process I think, so it may overlap with other Items if you use "scale".

    There might be one problem as far as I know, if your device has some weird DPI value the factor might be not that nice, e.g. on windows my monitor "Screen.physicalDotsPerInch" returns 95.98.. instead of 96 DPI, so that will lead to some weird scale factor and be a problem in some cases with sharp edges if you use a non integral value. Of course you can always round the final pixel values, but than it gets messy and more code sadly. Some QML properties are of type "int" so you don't have a problem if you do "property int foo: 1.2123" it should cast the value to "1" anyway, but not if the property is of type "real".

    you can use
    @
    width: (100 * globalScaleFactor).toFixed()
    width: Math.round(100 * globalScaleFactor)
    @
    or something like that, but again that is not that clear to read anymore and also involves function call.

    in my app I actually use the same names as Android does as real global properties set from c++, so it is very fast to write and easy to read I think:
    @
    Text {
    text: "hello world"
    font.pixelSize: 11*sp
    }

    Rectangle {
    width: 100dp
    height: 50
    dp
    }

    ListView {
    spacing: 5*dp
    }
    @
    "dp" and "sp" are global properties defined in my QML context object.
    In case you are wondering "sp" is a variation of "dp" as it adds another factor to scale fonts independently from other sizes just using "dp", so I can scale fonts without the rest of the UI.



  • HI xander,

    You mentioned that "dp" and "sp" are properties defined in your QML context object. I have been looking for the relationship between dp and sp...

    Can you tell me how you defined "sp" please? (My dp is Screen.physicalDotsPerInch / 160.)



  • HI xander,

    You mentioned that "dp" and "sp" are properties defined in your QML context object. I have been looking for the relationship between dp and sp...

    Can you tell me how you defined "sp" please? (My dp is Screen.physicalDotsPerInch / 160.)



  • Hi, as mentioned I have define my "dp" and "sp" values in c++ not QML itself.

    short version is this (my "dip norm" is dynamic per platform, because with a static value of 160 like yours it was not the same size on mobile and desktop platforms sadly.. don't know if that is e feature or bug or whatever):
    @
    #if defined(Q_OS_ANDROID)
    m_dipNorm = 120;
    #elif defined(Q_OS_IOS)
    m_dipNorm = 120; // TODO
    #else
    m_dipNorm = 96;
    #endif

    QScreen *screen = qApp->primaryScreen();
    m_dipScaleFactor = screen->physicalDotsPerInch() / screen->devicePixelRatio() / m_dipNorm; // dp
    

    @

    and "sp" is just a property getter with another factor:
    @
    inline qreal sp() const { return m_dipScaleFactor * m_sipScaleFactor; }
    @
    m_sipScaleFactor defaults to 1.0 ut can be changed at run-time to scale the "sp" value dynamically.

    that is at least how I did it. :)



  • Hi, as mentioned I have define my "dp" and "sp" values in c++ not QML itself.

    short version is this (my "dip norm" is dynamic per platform, because with a static value of 160 like yours it was not the same size on mobile and desktop platforms sadly.. don't know if that is e feature or bug or whatever):
    @
    #if defined(Q_OS_ANDROID)
    m_dipNorm = 120;
    #elif defined(Q_OS_IOS)
    m_dipNorm = 120; // TODO
    #else
    m_dipNorm = 96;
    #endif

    QScreen *screen = qApp->primaryScreen();
    m_dipScaleFactor = screen->physicalDotsPerInch() / screen->devicePixelRatio() / m_dipNorm; // dp
    

    @

    and "sp" is just a property getter with another factor:
    @
    inline qreal sp() const { return m_dipScaleFactor * m_sipScaleFactor; }
    @
    m_sipScaleFactor defaults to 1.0 ut can be changed at run-time to scale the "sp" value dynamically.

    that is at least how I did it. :)



  • Thanks Xander.

    To change the m_sipScaleFactor at run time, are you reading the user's phone font settings (i.e. small, medium, large?)

    If so, how to do that on Android?

    Thanks.



  • Thanks Xander.

    To change the m_sipScaleFactor at run time, are you reading the user's phone font settings (i.e. small, medium, large?)

    If so, how to do that on Android?

    Thanks.



  • I am not sure if you can even do that, certainly not with Qt functions at the moment.
    You have to use your own Java classes and read values from there if that is possible with Android (I guess it is, never tried it myself) and then access it via JNI.. but that is not very easy to do from QML, even with some helper classes Qt provides for JNI support. :/



  • I am not sure if you can even do that, certainly not with Qt functions at the moment.
    You have to use your own Java classes and read values from there if that is possible with Android (I guess it is, never tried it myself) and then access it via JNI.. but that is not very easy to do from QML, even with some helper classes Qt provides for JNI support. :/


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.