Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QT5 font rendering different on various platforms

I want to make reproductible tests of some custom widgets renderings. In order to do that, I paint them onto a QImage and save the result as PNG. The output is really different on Windows compared to MacOSX.

I took care of :

  • Selecting the same font on all platform (I provide the "TTF" font file and point the code to it)
  • Drawing onto a QImage and not a QPixmap, as the documentation says QImage painter is supposed to be platform independant
  • I also selected Antialisating and TextAntialiasing hints
  • Requesting the font via QFontDatabase::font() so that pointSize is specified and not pixelSize

How can I make sure the rendering is exactly the same on all platforms so that my test runs are reproductible ? In other words, is it maybe possible to force QT5 to use the same font engine on all platforms (for instance freetype) ?

**

I nailed down the issue to a simple rendering test program. So the code is looks like :

QFontDatabase fontDb;
fontDb.addApplicationFont(".../fonts/Vera.ttf");

QImage   result(width, height, QImage::Format_RGB32);
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);


QBrush background(QColor(205, 205, 205));
painter.fillRect(0, 0, 800, 600, background);

QFont font = fontDb.font("Bitstream Vera Sans", "Normal", 10);
painter.setFont(font);

painter.setPen(QColor(0, 0, 0));
painter.drawText(10, 10, "ABCD abcd 01234567");

The Bitstream Vera font can be downloaded on fontsquirel.com for instance.

See the result on MacOSX (left) and on Win32 (right), which are very different:

enter image description here


Following answer and comments by N1ghtLight below, and after reading the links he suggested, I changed the code to get the font to :

QFont font = fontDb_->font(("Bitstream Vera Sans", "Normal", -1);

qreal screenDPI  = QApplication::primaryScreen()->physicalDotsPerInch();
qreal RENDER_DPI = 72;

int pixelSize = (int)((qreal)10 * screenDPI / RENDER_DPI);
font.setPixelSize(pixelSize);

This seems to mostly solve the problem of the font of very different size. At least on MacOSX, the font is exactly 10 pixels high now. On Windows though the font renders much thinner and a bit smaller too. I'm still lost and confused...

Here is the new result (left MacOSX, right Windows). The white scale indicates true 10 pixels size.

enter image description here


Following answer by G_G below I adapted the code (what about Linux ? Mobile platforms ? This gets very complicated...). Now the fonts are 10 pixels in the output on both Windows and MacOSX, still the rending remains very different (still MacOSX on the left, Windows on the right).

enter image description here

Thanks.

like image 486
Eric Nicolas Avatar asked Sep 10 '14 09:09

Eric Nicolas


2 Answers

your render DPI variable should be 96 for Windows and 72 for OSX

according to: http://www.rfwilmut.clara.net/about/fonts.html

On a Macintosh monitor, the notional resolution is 72 dots-per -inch (dpi), so that a graphic 72 pixels wide would notionally be 1 inch wide - though obviously the actual size would depend on the individual monitor. However it will always print one inch wide.

But on a Windows monitor the resolution is (usually) 96 dpi. This means that though the picture is still 72 pixels wide, it will print at 0.75 inches.

QFont font = fontDb_->font(("Bitstream Vera Sans", "Normal", -1);
qreal screenDPI  = QApplication::primaryScreen()->physicalDotsPerInch();

#ifdef WINDOWS
qreal RENDER_DPI = 96;
#else
qreal RENDER_DPI = 72;
#endif

int pixelSize = (int)((qreal)10 * screenDPI / RENDER_DPI);
font.setPixelSize(pixelSize);
like image 197
Gianluca Ghettini Avatar answered Oct 12 '22 18:10

Gianluca Ghettini


It happens because you set size in pixels. You need to use setPointSize() instead.

From the Qt 5 docs:

void QFont::setPixelSize(int pixelSize)

Sets the font size to pixelSize pixels. Using this function makes the font device dependent. Use setPointSize() or setPointSizeF() to set the size of the font in a device independent manner.

Also, for more info, you can check this post. This difference happens because of different display density on different OSs. I have experienced such problem myself on one OS X, Windows cross platform project.


[Updated] After my additional research, I've found, that current behavior of Qt fonts is just a bug. That's why solution above doesn't work (it worked for Qt 4) Here is described different workarounds to solve this problem. Good luck!

like image 1
Max Go Avatar answered Oct 12 '22 18:10

Max Go