Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my QML CJK text being rendered with corrupt glyphs?

My application allows the user to switch languages on the fly. I'm seeing that about 10% of the time the user switches to Chinese or Japanese, the glyphs for the UI text are being rendered improperly.

This application is running under Linux on an iMX6 platform. Qt 5.5.0 is being used. QML is used to render the UI. The corrupt text is being rendered using a QML Text control.

Example of corrupt font rendering

The font being used in question is Source Hans Sans Regular. I have tried loading this using a QML FontLoader and by loading it on the C++ side into the application font database (both methods exhibited the problem). I've tried using the (admittedly very strongly related) Noto fonts; same problem.

I have never seen corruption of text rendering when using Roboto for non-CJK text and, as mentioned, this works more often than not for CJK/Source Hans Sans.

The corruption is interesting because it looks like it is at the rendered bitmap level, not the glyph definition level (notice how some glyphs have the lower half correct, but the top half is corrupt).

Corruption does sometimes progress. This leads me to think the glyph bitmap cache memory is being overwritten further (just a theory as I'm not sure how Qt does font rendering). I thought it might be the QML garbage collection doing something odd, but loading the font on the C++ side didn't make a difference.

I'm going to try using 'native rendering' for the QML Text controls next.

Has anyone seen this before? Can anyone confirm FreeType is used for font management/rendering under Qt 5.5.0? Are there ways to influence how that font bitmap cache is managed?

Thanks!

Update: using 'renderType: Text.NativeRendering' did not eliminate the problem (although the corruption manifested slightly differently). And, given the limitations of that mode, just ended up with generally poorly rendered text (soft, poor scaling, etc - as documented).

Update 2: I built Qt with (as far as I know) all of the glyph caches disabled -- shouldDrawCachedGlyphs() returns false in my local build for the four instances of that call I was able to find -- but still encountered glyph corruption.

Update 3: Tried switching to use the software (non-OpenGL) Qt Quick 2 renderer by setting QMLSCENE_DEVICE=softwarecontext per docs; glyph corruption still occurred.

like image 514
Matthew Reynolds Avatar asked Oct 20 '15 16:10

Matthew Reynolds


1 Answers

In this particular case, there is a bug in the OpenGL driver on the platform I'm working with. It affects FBO readbacks. Setting QML_USE_GLYPHCACHE_WORKAROUND=1 in the environment forces Qt to keep an additional copy of the glyph cache in RAM (since it cannot be read back from the graphics hardware when new glyphs are added).

The implication of this is that while rendering will be correct (since we're using a second cache which isn't corrupt) performance will be degraded slightly since there is an extra copy on the CPU and the glyph cache will use twice as much memory. Rendering quality is unaffected.

Qt support was able to point me in the right direction and qualify the implications associated with QML_USE_GLYPHCACHE_WORKAROUND.

like image 116
Matthew Reynolds Avatar answered Oct 04 '22 00:10

Matthew Reynolds