为什么我的 QML CJK 文本呈现为损坏的字形?
Why is my QML CJK text being rendered with corrupt glyphs?
我的应用程序允许用户即时切换语言。我发现大约有 10% 的时间用户切换到中文或日文,UI 文本的字形呈现不正确。
此应用程序在 iMX6 平台上 Linux 下 运行。正在使用 Qt 5.5.0。 QML 用于渲染 UI。损坏的文本正在使用 QML 文本控件呈现。
Example of corrupt font rendering
问题中使用的字体是 Source Hans Sans Regular。我已经尝试使用 QML FontLoader 加载它,并通过在 C++ 端将它加载到应用程序字体数据库中(这两种方法都出现了问题)。我试过使用(诚然非常相关的)Noto 字体;同样的问题。
我从未见过将 Roboto 用于非 CJK 文本时文本渲染损坏,并且如前所述,这对 CJK/Source Hans Sans 更有效。
损坏很有趣,因为它看起来像是在渲染位图级别,而不是字形定义级别(注意一些字形的下半部分是正确的,但上半部分是损坏的)。
腐败有时确实会发展。这让我认为字形位图缓存内存正在被进一步覆盖(只是一个理论,因为我不确定 Qt 如何进行字体渲染)。我认为这可能是 QML 垃圾收集做了一些奇怪的事情,但在 C++ 端加载字体并没有什么不同。
接下来我将尝试使用 'native rendering' 作为 QML 文本控件。
有人以前看过这个吗?任何人都可以确认 FreeType 用于 Qt 5.5.0 下的字体 management/rendering 吗?有没有办法影响字体位图缓存的管理方式?
谢谢!
更新:使用'renderType: Text.NativeRendering'并没有消除问题(尽管损坏的表现略有不同)。而且,考虑到该模式的局限性,最终呈现的文本通常呈现效果不佳(柔和、缩放比例不佳等 - as documented)。
更新 2:我构建 Qt 时(据我所知)禁用了所有字形缓存 -- 在我的本地构建中 shouldDrawCachedGlyphs() returns false对于该调用的四个实例,我能够找到 -- 但仍然遇到字形损坏。
更新 3:尝试通过设置 QMLSCENE_DEVICE=softwarecontext per docs 切换到使用软件(非 OpenGL)Qt Quick 2 渲染器;字形损坏仍然发生。
在这种特殊情况下,我正在使用的平台上的 OpenGL 驱动程序存在错误。它会影响 FBO 回读。在环境中设置 QML_USE_GLYPHCACHE_WORKAROUND=1 会强制 Qt 在 RAM 中保留一个额外的字形缓存副本(因为在添加新字形时无法从图形硬件中读回它)。
这意味着虽然渲染是正确的(因为我们使用的是未损坏的第二个缓存),但性能会略有下降,因为 CPU 上有一个额外的副本并且字形缓存将使用两倍的内存。渲染质量不受影响。
Qt 支持能够为我指明正确的方向并限定与 QML_USE_GLYPHCACHE_WORKAROUND 相关的含义。
我的应用程序允许用户即时切换语言。我发现大约有 10% 的时间用户切换到中文或日文,UI 文本的字形呈现不正确。
此应用程序在 iMX6 平台上 Linux 下 运行。正在使用 Qt 5.5.0。 QML 用于渲染 UI。损坏的文本正在使用 QML 文本控件呈现。
Example of corrupt font rendering
问题中使用的字体是 Source Hans Sans Regular。我已经尝试使用 QML FontLoader 加载它,并通过在 C++ 端将它加载到应用程序字体数据库中(这两种方法都出现了问题)。我试过使用(诚然非常相关的)Noto 字体;同样的问题。
我从未见过将 Roboto 用于非 CJK 文本时文本渲染损坏,并且如前所述,这对 CJK/Source Hans Sans 更有效。
损坏很有趣,因为它看起来像是在渲染位图级别,而不是字形定义级别(注意一些字形的下半部分是正确的,但上半部分是损坏的)。
腐败有时确实会发展。这让我认为字形位图缓存内存正在被进一步覆盖(只是一个理论,因为我不确定 Qt 如何进行字体渲染)。我认为这可能是 QML 垃圾收集做了一些奇怪的事情,但在 C++ 端加载字体并没有什么不同。
接下来我将尝试使用 'native rendering' 作为 QML 文本控件。
有人以前看过这个吗?任何人都可以确认 FreeType 用于 Qt 5.5.0 下的字体 management/rendering 吗?有没有办法影响字体位图缓存的管理方式?
谢谢!
更新:使用'renderType: Text.NativeRendering'并没有消除问题(尽管损坏的表现略有不同)。而且,考虑到该模式的局限性,最终呈现的文本通常呈现效果不佳(柔和、缩放比例不佳等 - as documented)。
更新 2:我构建 Qt 时(据我所知)禁用了所有字形缓存 -- 在我的本地构建中 shouldDrawCachedGlyphs() returns false对于该调用的四个实例,我能够找到 -- 但仍然遇到字形损坏。
更新 3:尝试通过设置 QMLSCENE_DEVICE=softwarecontext per docs 切换到使用软件(非 OpenGL)Qt Quick 2 渲染器;字形损坏仍然发生。
在这种特殊情况下,我正在使用的平台上的 OpenGL 驱动程序存在错误。它会影响 FBO 回读。在环境中设置 QML_USE_GLYPHCACHE_WORKAROUND=1 会强制 Qt 在 RAM 中保留一个额外的字形缓存副本(因为在添加新字形时无法从图形硬件中读回它)。
这意味着虽然渲染是正确的(因为我们使用的是未损坏的第二个缓存),但性能会略有下降,因为 CPU 上有一个额外的副本并且字形缓存将使用两倍的内存。渲染质量不受影响。
Qt 支持能够为我指明正确的方向并限定与 QML_USE_GLYPHCACHE_WORKAROUND 相关的含义。