HarmonyOS鸿蒙Next中qt下使用鸿蒙字体在x86和arm机器上表现不一致

HarmonyOS鸿蒙Next中qt下使用鸿蒙字体在x86和arm机器上表现不一致 如下图,在arm平台机器和x86上机器同样使用鸿蒙字体的程序截图, 在x86机器上的文字要窄一些。

cke_31083.png

代码都是同一套代码,想知道为什么会有这种差异。使用qt默认自带的字体不会有这个问题。

下面是字体初始化的代码

void Application::Initialize()
{
    {
        // 字体设置
        QFont font;
        font.setFamily(":/font/HarmonyOS_Sans_Medium.ttf");
        font.setPointSize(12);
        font.setWeight(QFont::Normal);                        // 字重
        font.setItalic(false);                                // 斜体
        font.setKerning(true);                                // 字距调整
        font.setStyleStrategy(QFont::PreferAntialias);        // 强制抗锯齿
        font.setHintingPreference(QFont::PreferFullHinting);  // 控制字体边缘的平滑度

        // 应用全局字体
        setFont(font);
    }

    QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, false);
    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
}

更多关于HarmonyOS鸿蒙Next中qt下使用鸿蒙字体在x86和arm机器上表现不一致的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

这个问题解决了,上面  font.setFamily(":/font/HarmonyOS_Sans_Medium.ttf"); 这种方式设置字体只能设置系统自带的字体。而指定设置资源或者路径下的ttf字体,只能使用以下方式:

int fontId = QFontDatabase::addApplicationFont(":/fonts/HarmonyOS_Sans_SC_Regular.ttf");
if (fontId != -1) {
    QString family = QFontDatabase::applicationFontFamilies(fontId).at(0);
    QFont font(family, 12);
    application_->setFont(font);
}

所以之前的代码虽然没报错,但是其实是未成功设置鸿蒙字体。所以在不同机器下,字体表现不一致。

更多关于HarmonyOS鸿蒙Next中qt下使用鸿蒙字体在x86和arm机器上表现不一致的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


还有不同机器上屏幕分辨率,dpi也会影响最终的显示效果,这些都需要统一才能保证最终显示效果一致,

HarmonyOS Sans 本身设计差异
这个字体在不同平台的渲染结果会受 hinting 策略影响更明显,因为它是可变字重(variable font)。
如果 FreeType 在不同 CPU 架构上 fallback 到不同 hinting 方式,就会看到窄/宽的差异。

你好楼主,x86和ARM平台底层图形库的字体度量计算方式不同,可能导致同一字体在不同架构下显示宽度不同,还有鸿蒙字体可能存在针对ARM架构的优化设计,在x86未充分适配,这是我个人猜测。

另外ARM架构可能启用了NEON指令集优化路径,会影响字体缩放算法,而x86架构可能使用不同的浮点运算单元精度设置,影响字体抗锯齿效果。

ARM更依赖字体自带的Hinting信息,而x86平台可能强制应用系统级调整,setHintingPreference在不同平台对矢量字体的微调效果也是可能不同的。总而言之影响因素很多,这也是个人的猜测。。。

楼主可以试试添加字体加载状态检测:

int fontId = QFontDatabase::addApplicationFont(":/font/HarmonyOS_Sans_Medium.ttf");

if(fontId == -1) {
    qWarning() << "Failed to load embedded font";
}

根据架构调整字体参数

#if defined(Q_PROCESSOR_X86)
    font.setHintingPreference(QFont::PreferNoHinting);
    font.setStretch(105); // 略微增加拉伸系数
#elif defined(Q_PROCESSOR_ARM)
    font.setStyleStrategy(QFont::ForceIntegerMetrics);
#endif

观察真仔细,我感觉是屏幕分辨率的原因。

用“Nimbus Sans Narrow”这个字体就没有差异,用鸿蒙字体就有差异。

在HarmonyOS Next中,Qt使用鸿蒙字体时,x86与ARM架构下表现不一致,主要因字体渲染引擎和系统字体库差异导致。x86平台可能依赖通用字体渲染,而ARM平台直接调用鸿蒙原生字体接口。需检查字体文件路径、格式兼容性及Qt字体配置,确保跨架构一致性。建议统一使用鸿蒙系统字体库,并验证Qt字体加载机制。

这个问题通常是由于不同CPU架构(x86 vs ARM)上Qt字体渲染引擎的差异,特别是字体Hinting(微调)处理方式不同导致的。在x86平台上,Qt的字体渲染可能应用了更激进的水平方向Hinting来适应传统的像素网格,导致字形被轻微压缩。

关键点在于您代码中的 setHintingPreference(QFont::PreferFullHinting)。Full Hinting会为了在低分辨率下清晰可读而显著调整字形轮廓,这种调整在不同架构的渲染后端上可能不一致。

建议的排查和解决步骤:

  1. 修改Hinting设置:将 setHintingPreference 改为 QFont::PreferNoHintingQFont::PreferVerticalHinting。这能减少渲染引擎对字形水平方向的干预,使跨平台表现更一致。

    font.setHintingPreference(QFont::PreferNoHinting); // 或 PreferVerticalHinting
    
  2. 检查字体文件:确认嵌入资源的 HarmonyOS_Sans_Medium.ttf 文件是同一版本。不同版本的字形数据可能存在细微差别。

  3. 验证DPI缩放:虽然您已启用高DPI缩放(AA_EnableHighDpiScaling),但请确认两台测试机器的屏幕逻辑DPI是否相同。可以在运行时打印 QScreen::logicalDotsPerInch() 进行对比。不同的DPI值会影响 setPointSize 的实际渲染像素大小。

  4. 使用绝对像素尺寸:作为诊断方法,可以尝试使用 setPixelSize 替代 setPointSize,以消除因DPI计算差异带来的影响。

  5. 检查Qt平台插件:在x86和ARM设备上,Qt可能使用了不同的底层字体渲染引擎(如CoreText、DirectWrite、FreeType)。这可能导致Hinting策略的执行结果存在固有差异。

根本原因分析: 跨架构的字体渲染差异通常并非HarmonyOS Next本身的问题,而是Qt框架为了适配不同硬件和操作系统,在字体微调算法上做出的妥协。使用系统自带字体时,Qt可能采用了更统一的回退策略,因此表现一致。

通过调整Hinting偏好,通常可以显著改善或消除这种不一致性。

回到顶部