Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Fabric text is drawn with ClearType onto transparent composition surfaces, fringing thin glyphs

未关闭 适合新手
#16,340 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 2 天内回复

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
82/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
冷清
技术栈
cpp
领域
desktop

调研方向

从 TextDrawing.cpp 开始,重点查看 RenderText 以及其中现有的 GetAntialiasMode/SetAntialiasMode/restore 惯用模式;检查 ParagraphComponentView.cpp、ScrollViewComponentView.cpp 和 TextInput/WindowsTextInputComponentView.cpp 中列出的 DrawTextLayout 位置。运行可用的 RNW 构建或检查,并在透明表面上的文本使用显式灰度抗锯齿且不改变周围设备上下文状态时,视为工作完成。

由索引模型根据 Issue 内容生成。

描述

Needs: Triage :mag:
Problem Description

On the new architecture, RenderText — the single function every <Text> render goes through —
calls ID2D1RenderTarget::DrawTextLayout without ever setting a text antialias mode, so the draw
inherits the device context's default. On a normal Windows machine that default is ClearType
subpixel antialiasing.

The surface it draws onto is transparent:

  • ParagraphComponentView::updateVisualBrush creates it as
    CreateDrawingSurfaceBrush(surfaceSize, DirectXPixelFormat::B8G8R8A8UIntNormalized, DirectXAlphaMode::Premultiplied)
    (vnext/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp, ~L367-370).
  • ParagraphComponentView::DrawText clears it to D2D1::ColorF(D2D1::ColorF::Black, 0.0f) —
    transparent black — whenever the view has no backgroundColor (same file, ~L521-523).
  • The surface is composited by the visual tree afterwards, possibly under an opacity or a transform.

ClearType computes independent R/G/B coverage and needs an opaque, known background to filter
against. There is none here, so that per-channel coverage lands in the surface's colour channels and
shows up as dark or colour-tinted fringes along thin glyph stems once the surface is composited.
D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE is the documented mode for transparent render targets.

The gap is repo-wide, not local: at c69cf55f67f9b03f467502dac1007ac2d9ebe209, neither
SetTextAntialiasMode nor D2D1_TEXT_ANTIALIAS_MODE appears anywhere in the tree. The other two
DrawTextLayout call sites have the same omission —
ScrollViewComponentView.cpp ~L529 (scrollbar arrow glyphs) and
TextInput/WindowsTextInputComponentView.cpp ~L1870 (placeholder text).

Confidence, stated honestly. The missing call is a fact — the source is quoted above and the
repo-wide search returned zero hits. The visual claim is a source-level diagnosis that I have not
captured as before/after pixels: I have not built or run RNW main, and I cannot rule out that D2D
already coerces toward grayscale on some premultiplied targets, in which case the practical effect
of setting it explicitly is determinism (no dependence on the user's font-smoothing setting) rather
than a pixel change. I did not want to file a "verified" claim I had not measured.

Steps To Reproduce
  1. New-arch RNW app, default <Text> (no backgroundColor), light background behind it.
  2. Use thin glyph strokes — a light font weight, a small icon font, or hairline separators — at a
    fractional/high display scale (we see it clearly at 250%).
  3. Zoom a screenshot to the pixel level along vertical stems.
  4. Observe coloured/dark fringing rather than clean grayscale edges.

Control: set D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE on the device context immediately before the
DrawTextLayout in RenderText and repeat.

Expected Results

Text on the new architecture is antialiased in grayscale, matching what other frameworks do for text
on transparent composition surfaces, and does not depend on the machine's ClearType setting.

Fix

PR attached: save / set D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE / restore around the DrawTextLayout
call in RenderText, matching the GetAntialiasMode/SetAntialiasMode/restore and
GetDpi/SetDpi/restore idioms already present in that same function. One file, twelve added
lines, no signature or header changes. Not compiled and not run — lint/format/build gates are unrun.

CLI version

18.0.0

Environment
System:
  OS: Windows 11 10.0.26200 (ARM64 device; app builds and runs ARM64)
  CPU: (6) x64 Apple Silicon (Windows-on-ARM)
  Memory: 6.49 GB / 15.99 GB
Binaries:
  Node: 22.15.0
  Yarn: 4.5.1
  npm: 10.9.2
SDKs:
  Windows SDK versions: 10.0.19041.0, 10.0.22621.0, 10.0.26100.0
IDEs:
  Visual Studio: 18.6.11822.322 (Community 2026), 17.14.37314.3 (Community 2022)
npmPackages (yarn 4 workspaces — `cli info` reports Not Found in-workspace):
  react-native: 0.83.2
  react-native-windows: 0.83.2 (New Architecture / Fabric composition)
  Microsoft.WindowsAppSDK: 1.8

Source analysis above is against main at c69cf55f67f9b03f467502dac1007ac2d9ebe209, not 0.83.2 —
the code in question is unchanged between them as far as this function is concerned.

Community Modules

None involved. Core <Text> on the Composition/Fabric path.

Target React Native Architecture

New Architecture (WinAppSDK) Only

Target Platform Version

10.0.22621

Visual Studio Version

Visual Studio 2026

Build Configuration

Debug

Snack, code example, screenshot, or link to a repository

The decisive artifact is the source itself — TextDrawing.cpp L171-172 has no antialias-mode call
and D2D1_TEXT_ANTIALIAS_MODE occurs nowhere in the repo. Happy to produce zoomed before/after
captures from our app once we have the patched build, and to test any alternative the team prefers
(e.g. conditional grayscale only when the paragraph has no opaque background).

Context: found during a Windows hardening pass of a production RNW app (Facilitron FIT — RNW 0.83.2
new-arch, Windows 11 ARM64, WinAppSDK 1.8, 250% display scale). Related font-path issues from the
same investigation: #16306, #16308. Sibling PRs: #16302, #16303, #16304.

主要语言
C++
星标
17.4k
派生
1.2k
平均合并
2 天 23 小时
30 天内合并 PR
16

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

microsoft/react-native-windows 的其他 Issue

查看 microsoft/react-native-windows 的全部 Issue

相似的 Issue

更多 C++ Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。