Skip to content

[Bug] UI_TEXT_RENDER_SHARP 的 GDI_CLASSIC 渲染与 NATURAL 度量不匹配 #20

Description

@Hunlongyu

环境

  • Core UI: v1.7.0
  • Windows 11
  • Direct2D / DirectWrite
  • 小字号 UI 文本(约 12–13 DIP)

问题描述

启用 UI_TEXT_RENDER_SHARP 后,小字号文字虽然笔画更锐利,但同一行内会出现局部字距忽宽忽窄的问题。UI_TEXT_RENDER_GRAY_SHARP 也使用相同的 GDI_CLASSIC rendering mode,因此存在同类风险。

问题不是 GDI_CLASSIC 本身,而是 Core UI 只切换了字形的 rendering mode,却仍然使用默认的 natural metrics 创建、测量和布局文字,导致渲染模式与度量模式不匹配。

最小复现

ui_theme_set_text_render_mode(UI_TEXT_RENDER_SHARP);

随后用 12–13 DIP 字号显示一行中英文混排或连续中文,例如:

消息  当前状态  自动滚动  qspin.exe

UI_TEXT_RENDER_CLEARTYPE 对比,SHARP 模式下局部字符间距会显得不均匀。

根因分析

Renderer::ApplyTextRenderMode() 把 SHARP 和 GRAY_SHARP 设置为 DWRITE_RENDERING_MODE_GDI_CLASSIC

https://github.com/ghboke/core-ui/blob/v1.7.0/src/ui/renderer.cpp#L1034-L1070

但核心绘制路径仍统一调用 IDWriteFactory::CreateTextLayout()

https://github.com/ghboke/core-ui/blob/v1.7.0/src/ui/renderer.cpp#L1231-L1283

文字宽度、高度和公开 layout helper 同样使用 CreateTextLayout()

https://github.com/ghboke/core-ui/blob/v1.7.0/src/ui/renderer.cpp#L1286-L1346

微软对 DWRITE_RENDERING_MODE_GDI_CLASSIC 的说明明确要求使用 DWRITE_MEASURING_MODE_GDI_CLASSIC 获取 glyph advances:

https://learn.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_rendering_mode

CreateGdiCompatibleTextLayout(..., useGdiNatural = FALSE, ...) 才会让 text layout 使用对应的 GDI Classic metrics:

https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritefactory-creategdicompatibletextlayout

当前实现只通过 SetTextRenderingParams() 改变 raster rendering,没有同步改变 text layout 的 metrics。

期望行为

选择 UI_TEXT_RENDER_SHARP 时,文字的绘制、宽度测量、换行、ellipsis、caret 和 hit-test 应使用一致的 GDI Classic metrics,避免视觉字距与布局宽度不一致。

建议修复

建议集中封装 text layout 创建逻辑:

  • SMOOTH / CLEARTYPE:继续使用 CreateTextLayout()
  • SHARP / GRAY_SHARP:使用 CreateGdiCompatibleTextLayout()useGdiNatural = FALSE
  • pixelsPerDip 使用当前窗口 DPI,而不是固定 1.0f
  • 绘制、MeasureText、TextArea 缓存布局、caret/hit-test 和 SVG 文字等路径共用同一策略;
  • 文字模式或 DPI 改变时清理相关 layout cache。

建议补充不同 DPI(100% / 125% / 150%)和 11–14 DIP 字号的截图回归测试,并核对 GetMetrics() 与实际绘制 advance 一致。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions