Musescore 3 FreeSans bold text rendering is bad

• Jan 11, 2019 - 09:45
Reported version
3.0
Priority
P2 - Medium
Type
Functional
Frequency
Once
Severity
S3 - Major
Reproducibility
Always
Status
closed
Regression
Yes
Workaround
No
Project

Came up in https://musescore.org/en/node/281541

The reason most probably is that we don't package a Bold (nor Italic or BoldItalic) version of FreeSans (but do for FreeSerif) and that converting a normal font to Bold generally gives rather bad results (not so much for Italic, IIRC)

As per https://www.fontspace.com/gnu-freefont/freesans, https://en.wikipedia.org/wiki/GNU_FreeFont and https://www.gnu.org/software/freefont/ there is a FreeSans Bold and a FreeSans Oblique and a FreeSans BoldOblique (Oblique rather than Italic, but seems to be the same thing), and also a Free Mono family.

So the fix would be quite easy(?): add those fonts to the package.


Comments

Regression No Yes

I found an easy way to reproduce this bug using a Kubuntu 18.04.1 live CD/USB image. The bug also happens on my KDE neon installation and probably also happens with Kubuntu 18.10, but I haven't tested this. Here are the steps:

  1. Download Kubuntu 18.04.1 64-bit.
  2. Either create a Kubuntu bootable USB drive and restart your PC to run it, or boot the .iso in VirtualBox.
  3. When prompted, select "Try Kubuntu" rather than installing.
  4. VIRTUALBOX ONLY: Once at the desktop, you may need to increase the screen resolution. Go to the K menu -> System Settings, and then scroll down to "Display and Monitor" where you can increase the screen resolution. While you're there, select "Compositor" on the left and choose "XRender" for the rendering background to speed up the graphics.
  5. Download the MuseScore 3 AppImage, make it executable and run it.
  6. Once you get to where you can edit a score, look at the "Tempo" and "Text" palettes and you will see the bold fonts look correct:
    fonts_correct.png
  7. Close MuseScore.
  8. Open K menu -> System Settings, and then "Fonts" near the top. For "Use anti-aliasing:", choose "Enabled" and hit "Apply".
  9. Launch MuseScore 3 again. Now the bold text is all super-thick and hard to read:
    fonts_messed_up.png

Also note the following:

  • In addition to bold fonts being wonky, font spacing between lines has also increased, as can be compared in the previous screenshots by looking at the palette names. (EDIT: this spacing change appears to be due to MuseScore 3 picking up KDE's default UI font "Noto Sans" after step 8. Previously, MuseScore 3 was using "Sans Serif".)
  • Italic fonts also look different between the screenshots.
  • Reverting the change in step 8 does not fix the wonky fonts issue. The change in step 8 creates ~/.config/fontconfig/fonts.conf, but deleting this file does not restore normal fonts in MuseScore, so perhaps a file elsewhere is also created?
  • The bug occurs in the Flatpak version as well.
  • This bug does not occur in MuseScore 2.

In Windows the problem disappears if freetype is not used as the font rendering engine, i.e. if the lines
[Platforms]
WindowsArguments = fontengine=freetype

are removed from bin/qt.conf (it can be done with any text editor).
These were added to solve #276566: [Windows] underline too close to (lyrics) letters, but apparently freetype engine has some problems for some settings, since the bug appears also under Linux.
Is there maybe a way to disable such setting also under Windows, or to force MuseScore to not use the anti-aliasing for its font drawing?

I found another interesting clue. In my post above, compare the words "arco" and "pizz" between the two screenshots and you'll notice a difference in the italics rendering, particularly with the letters "a" and "z". The first screenshot appears to be using the designated italics glyphs from the font, whereas the second screenshot seems to be creating the italics effect by slanting the standard glyphs. Here is how the FreeSerif font renders in LibreOffice for normal, italics and bold text:
FreeSerif_variations.png
Notice how the italic "a" and "z" have distinctly different style than the normal font.

So, it would appear that this bug is causing a "fake" italic and bold effect to be applied to the font rather than using the style provided by the font.

In reply to by s.chriscollins

So, I think I know what is happening here. The wonky bold text occurs under KDE Plasma desktops in Linux if the ~/.config/kdeglobals file contains a font= line in the [General] section (in my case, the line is "font=Noto Sans,10,-1,5,50,0,0,0,0,0,Regular", which is the Kubuntu default). In a fresh install, this line is not present in ~/.config/kdeglobals, but will be written (along with fixed=, menuFont= lines and a few others) if the user customizes anything in the KDE System Settings fonts panel.

After removing the font= line, MuseScore's fonts again look correct. However, this is not a good workaround, as it might cause issues with visual consistency among other Qt-based applications. Perhaps MuseScore could either ignore by default or at least provide the option to ignore ~/.config/kdeglobals altogether?

Okay, so I found some more information on why this is happening. Check out the following bug reports:

As a workaround, KDE users can edit the following files to remove the text ",Regular" (without quotes, notice the comma) from the end of font definition lines. Just search for and delete all instances of the text ",Regular":

  • ~./config/kdeglobals
  • ~./kde/share/config/kdeglobals

So, for example, the following line:
font=Noto Sans,9,-1,5,50,0,0,0,0,0,Regular

...should be changed to:
font=Noto Sans,9,-1,5,50,0,0,0,0,0

Please note that you will need to repeat this action any time you make changes in the KDE System Settings fonts panel.

I don't know if the Linux one is the same as the Windows bug.
I managed to use the debug version of Qt libraries and found that in the Windows case the different behavior at different scale magnifications is caused by using or not using cached font shapes.
Indeed, the "bad" bold font case has the following backtrace: (line numbers are off by 1 because of using release with forced debug info for the Qt libraries)
Qt5Gui.dll!QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const unsigned int * glyphs, const QFixedPoint * positions, QFontEngine * fontEngine) qpaintengine_raster.cpp(2912)
Qt5Gui.dll!QRasterPaintEngine::drawTextItem(const QPointF & p, const QTextItem & textItem) qpaintengine_raster.cpp(3191)
Qt5Gui.dll!QPainterPrivate::drawTextItem(const QPointF & p, const QTextItem & _ti, QTextEngine * textEngine) qpainter.cpp(6531)
Qt5Gui.dll!QPainter::drawTextItem(const QPointF & p, const QTextItem &) qpainter.cpp(6398)
Qt5Gui.dll!QPainter::drawText(const QPointF & p, const QString & str, int tf, int justificationPadding) qpainter.cpp(5933)
Qt5Gui.dll!QPainter::drawText(const QPointF & p, const QString & str) qpainter.cpp(5710)
MuseScore3.exe!Ms::TextFragment::draw(QPainter * p, const Ms::TextBase * t) musescore\libmscore\textbase.cpp(490)

while in the case of "good" bold font:
Qt5Gui.dll!QPaintEngineEx::drawStaticTextItem(QStaticTextItem * staticTextItem) qpaintengineex.cpp(1062)
Qt5Gui.dll!QRasterPaintEngine::drawTextItem(const QPointF & p, const QTextItem & textItem) qpaintengine_raster.cpp(3218)
Qt5Gui.dll!QPainterPrivate::drawTextItem(const QPointF & p, const QTextItem & _ti, QTextEngine * textEngine) qpainter.cpp(6531)
Qt5Gui.dll!QPainter::drawTextItem(const QPointF & p, const QTextItem &) qpainter.cpp(6398)
Qt5Gui.dll!QPainter::drawText(const QPointF & p, const QString & str, int tf, int justificationPadding) qpainter.cpp(5933)
Qt5Gui.dll!QPainter::drawText(const QPointF & p, const QString & str) qpainter.cpp(5710)
MuseScore3.exe!Ms::TextFragment::draw(QPainter * p, const Ms::TextBase * t) musescore\libmscore\textbase.cpp(490)

The use or not of cached glyphs is determined by function QPaintEngineEx::shouldDrawCachedGlyphs (here: https://code.woboq.org/qt5/qtbase/src/gui/painting/qpaintengineex.cpp.h… ), which ends with these lines:
qreal pixelSize = fontEngine->fontDef.pixelSize;
return (pixelSize * pixelSize * qAbs(m.determinant())) < maxCachedGlyphSizeSquared;

Now, in my system for FreeSans I see:
maxCachedGlyphSizeSquared = 4096
pixelSize = 120
and m is a square 2x2 matrix which for 100% zoom is [0.27974195 0; 0 0.27974195] and it scales accordingly to the zoom level. For these values then the switch between the two behavior happens at zoom value:
sqrt(4096/120^2)/0.27974195*100 ~ 190.65%
which is what I see: for zoom >=191% the bold is good, for zoom <191% the bold is bad.

I tried, but I don't know how to force freetype engine not to use the cached glyphs (or if this is even possible).

Is it possible to somehow rescale the zoom matrix m?

I found that it is possible to reduce the cached glyph size by using an environment variable.
Indeed, in a command line prompt by doing
set QT_MAX_CACHED_GLYPH_SIZE=1
and then launching (from the same command prompt) MuseScore3, no glyph is cached and the bug is apparently solved.
However, this probably introduces a slowing down of text rendering, and it is not clear to me if we can define such env variable when starting MuseScore (maybe with qputenv ?)

probaby with setenv or putenv very early in main before calling the first Qt function or instantiating the first Qt object (which means before constructors of local variables run), but we're not going to require qt 5.12 for a loooong time

Fix version
3.5.0