Sitelet https://github.com/flutter/flutter/pull/180235
Skip to content

Separate ARM64 Linux Desktop and Embedded engine builds to fix CJK and non-ASCII font rendering - #180235

Merged
auto-submit[bot] merged 12 commits into
flutter:masterfrom
krystic:fix-arm64-desktop-fontconfig
Aug 5, 2026
Merged

auto-submit[bot] merged 12 commits into
flutter:masterfrom
krystic:fix-arm64-desktop-fontconfig

Conversation

@krystic

@krystic krystic commented Dec 23, 2025

Copy link
Copy Markdown
Contributor

Separate ARM64 Linux Desktop and Embedded engine builds to fix CJK and non-ASCII font rendering

Problem

On ARM64 Linux desktop environments (GNOME, KDE, etc.), Chinese characters and other non-ASCII text render as squares in Flutter applications. This affects production applications like Ubuntu App Center which uses Flutter on ARM64.

Root Cause

The ARM64 Linux engine builds (linux_arm_host_engine) were missing the --enable-fontconfig flag, unlike x64 Linux builds which have it. Without fontconfig support, the Flutter GTK engine cannot discover and load system fonts properly on desktop Linux distributions.

Why This Wasn't Caught Earlier

The same build configuration was used for both:

  • Desktop environments (GNOME/KDE with GTK) - requires fontconfig
  • Embedded/IoT systems (headless or custom UI) - doesn't need fontconfig

This conflation meant adding fontconfig would unnecessarily bloat embedded deployments.


Solution

This PR separates ARM64 Linux builds into two distinct configurations, following the same architecture pattern as x64 Linux:

1. Desktop Builds (NEW: linux_arm_host_desktop_engine)

  • Target: GNOME/KDE desktop environments
  • Includes: --enable-fontconfig for proper font rendering
  • Builds: flutter_gtk library for profile/debug/release modes
  • Use case: Desktop applications (App Center, desktop Flutter apps)

2. Embedded/IoT Builds (MODIFIED: linux_arm_host_engine)

  • Target: Headless or custom UI embedded systems
  • Excludes: fontconfig dependency (not needed)
  • Builds: embedder library, artifacts, Dart SDK, Impeller SDK
  • Use case: Raspberry Pi, embedded Linux, IoT devices

Changes Made

  1. Created: engine/src/flutter/ci/builders/linux_arm_host_desktop_engine.json

    • New builder configuration for ARM64 desktop
    • Adds --enable-fontconfig to all build modes
    • Produces flutter_gtk libraries
  2. Modified: engine/src/flutter/ci/builders/linux_arm_host_engine.json

    • Now focuses on embedded/IoT builds only
    • Removed flutter_gtk targets (moved to desktop config)
    • Removed --enable-fontconfig (not needed for embedded)
    • Removed profile/release configs (only build embedder in debug)
  3. Modified: engine/src/flutter/.ci.yaml

    • Registered new linux_arm_host_desktop_engine builder
    • Same CI configuration as existing ARM64 builder

Testing & Verification

✅ Manual Testing

  • Platform: Ubuntu 25.10 on ARM64 (Parallels VM on Apple M4)
  • Application: Ubuntu App Center (Snap package)
  • Flutter Version: 3.38.1

Before (Official ARM64 build without fontconfig):

  • Chinese characters display as squares (□□□)
  • All CJK and non-Latin text affected

After (Custom build with fontconfig):

  • Chinese characters render correctly using system fonts
  • All text displays properly

Test Commands Used

# Compile custom engine with fontconfig
./flutter/tools/gn --runtime-mode release --enable-fontconfig \
  --target-os linux --linux-cpu arm64 --no-goma
ninja -C out/linux_release_arm64

# Verify fontconfig linking
readelf -d out/linux_release_arm64/libflutter_linux_gtk.so | grep fontconfig
# Output: libfontconfig.so.1

# Replace engine in App Center snap (via mount)
sudo mount --bind custom_libflutter_linux_gtk.so \
  /snap/snap-store/current/bin/lib/libflutter_linux_gtk.so

# Launch App Center - Chinese text now renders correctly
snap-store

Architecture Benefits

✅ Decoupling: Desktop and embedded builds are now independent
✅ No Breaking Changes: Embedded builds remain unchanged (same targets, no fontconfig)
✅ Transparent: Flutter Tool and VS Code don't need modifications
✅ Consistency: Follows the same pattern as x64 Linux architecture
✅ Minimal Impact: Only adds new builds, doesn't modify existing ones


Downstream Impact

Who Benefits

  • ARM64 Linux desktop users (Ubuntu, Fedora, Debian on ARM)
  • Applications using Flutter GTK on ARM64 (App Center, custom desktop apps)
  • Developers targeting ARM64 desktop environments

Who Is NOT Affected

  • Embedded/IoT users (they continue using linux_arm_host_engine as before)
  • x64 Linux users (already have fontconfig)
  • Mobile platforms (Android, iOS)
  • Windows/macOS platforms

Related Issues

Fixes #139293 #90951


Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above. (Fixes CJK text not showing on arm64 Linux desktop. #139293)
  • I updated/added relevant documentation (comments in JSON files).
  • I added new tests to check the change I am making, or this PR is test-exempt. (CI infrastructure change)
  • All existing and new tests are passing. (JSON syntax verified)

Core Reviewers

@flutter/engine-ci @flutter/linux-desktop


Screenshots

Before (Without Fontconfig)

Chinese text displays as squares in Ubuntu App Center on ARM64:

标题: □□□□□
描述: □□□□□□□□

After (With Fontconfig)

Chinese text renders correctly:

标题: 应用中心
描述: 发现和安装应用程序

(Actual screenshots can be added to the PR after creation)


Additional Context

This issue was discovered while investigating font rendering problems in Ubuntu App Center on ARM64 systems. The fix has been verified to work with Flutter 3.38.1 on Ubuntu 25.10 ARM64.

The architecture follows the principle of separation of concerns: desktop applications need system font integration via fontconfig, while embedded systems typically use bundled fonts and don't need this dependency.

@github-actions github-actions Bot added the engine flutter/engine related. See also e: labels. label Dec 23, 2025

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses the font rendering issue for CJK and non-ASCII characters on ARM64 Linux desktops by separating the engine builds for desktop and embedded systems. The introduction of a new linux_arm_host_desktop_engine with fontconfig enabled is a clean solution. The modifications to the existing linux_arm_host_engine to focus solely on embedded targets are also logical. I have one suggestion to improve the clarity and robustness of the new CI configuration by avoiding potential build name collisions.

Comment on lines +14 to +55
{
"archives": [
{
"name": "ci/linux_profile_arm64",
"type": "gcs",
"base_path": "out/ci/linux_profile_arm64/zip_archives/",
"include_paths": [
"out/ci/linux_profile_arm64/zip_archives/linux-arm64-profile/linux-arm64-flutter-gtk.zip"
],
"realm": "production"
}
],
"drone_dimensions": [
"device_type=none",
"os=Linux"
],
"gclient_variables": {
"download_android_deps": false,
"download_jdk": false,
"use_rbe": true
},
"gn": [
"--target-dir",
"ci/linux_profile_arm64",
"--runtime-mode",
"profile",
"--target-os=linux",
"--linux-cpu=arm64",
"--prebuilt-dart-sdk",
"--no-lto",
"--rbe",
"--no-goma",
"--enable-fontconfig"
],
"name": "ci/linux_profile_arm64",
"description": "Produces profile mode artifacts to target arm64 Linux from a Linux host with fontconfig enabled.",
"ninja": {
"config": "ci/linux_profile_arm64",
"targets": [
"flutter/shell/platform/linux:flutter_gtk"
]
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There's a potential build name collision. The build name "ci/linux_debug_arm64" is used for one of the builds in this file, and it's also used in engine/src/flutter/ci/builders/linux_arm_host_engine.json.

Since these two configurations now build for different targets (desktop vs. embedded), they produce different artifacts. Using the same build name can lead to confusion and potential issues with artifact storage and retrieval in CI, where one build's output might overwrite another's if they are identified by the same name.

To avoid this, it's best to use unique names for the builds in this new desktop-specific configuration. I suggest appending a _desktop suffix to the build names and their corresponding paths and configurations.

This change should be applied to all three builds defined in this file (profile, debug, and release) for consistency. Here is a suggestion for the profile build:

        {
            "archives": [
                {
                    "name": "ci/linux_profile_arm64_desktop",
                    "type": "gcs",
                    "base_path": "out/ci/linux_profile_arm64_desktop/zip_archives/",
                    "include_paths": [
                        "out/ci/linux_profile_arm64_desktop/zip_archives/linux-arm64-profile/linux-arm64-flutter-gtk.zip"
                    ],
                    "realm": "production"
                }
            ],
            "drone_dimensions": [
                "device_type=none",
                "os=Linux"
            ],
            "gclient_variables": {
                "download_android_deps": false,
                "download_jdk": false,
                "use_rbe": true
            },
            "gn": [
                "--target-dir",
                "ci/linux_profile_arm64_desktop",
                "--runtime-mode",
                "profile",
                "--target-os=linux",
                "--linux-cpu=arm64",
                "--prebuilt-dart-sdk",
                "--no-lto",
                "--rbe",
                "--no-goma",
                "--enable-fontconfig"
            ],
            "name": "ci/linux_profile_arm64_desktop",
            "description": "Produces profile mode artifacts to target arm64 Linux from a Linux host with fontconfig enabled.",
            "ninja": {
                "config": "ci/linux_profile_arm64_desktop",
                "targets": [
                    "flutter/shell/platform/linux:flutter_gtk"
                ]
            }
        }

@krystic
krystic force-pushed the fix-arm64-desktop-fontconfig branch 2 times, most recently from 2eb7b14 to 8de35d4 Compare December 23, 2025 19:27
@krystic
krystic force-pushed the fix-arm64-desktop-fontconfig branch from 8de35d4 to e2acdf9 Compare January 6, 2026 15:46
@krystic

krystic commented Jan 6, 2026

Copy link
Copy Markdown
Contributor Author

Hi @dkwingsmt,

Sorry for the ping. I have updated this branch using rebase to stay current with the latest master.

This PR aims to fix the fontconfig issue on Linux ARM64 desktop. Most CI checks are passing, but the Google testing is currently waiting for a maintainer's approval to proceed.

Could you please take a look when you have a moment, or help trigger the internal tests? Thank you for your time and help!

@dkwingsmt
dkwingsmt requested review from dkwingsmt and jtmcdole and removed request for dkwingsmt January 16, 2026 01:11
@dkwingsmt

dkwingsmt commented Jan 16, 2026 •

Copy link
Copy Markdown
Contributor

Thank you for the message. I'm reassigning it to @jtmcdole to evaluate / triage since he's more responsible to infrastructural work like this.

@jtmcdole

Copy link
Copy Markdown
Member

I made a change to make this basically mirror the linux_host_desktop_engine.json - it reduces the diffs between to the two and keeps the order the same. I would have liked to have had the history branched, but that's not a blocker.

@jtmcdole

Copy link
Copy Markdown
Member

Why remove "ci/linux_profile_arm64" and "ci/linux_release_arm64"?

@jtmcdole

Copy link
Copy Markdown
Member

linux_web_engine_tests was flakey, but it looks reolved. Need to pick upstream master.

@flutter-dashboard

Copy link
Copy Markdown

This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@krystic

krystic commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

@jtmcdole Thank you for your review and the improvements! My apologies for the delayed response - I missed the notifications during the Spring Festival holiday period and have been quite busy with work afterwards.

Regarding the removal of ci/linux_profile_arm64 and ci/linux_release_arm64:
Looking at the original linux_arm_host_engine.json, the profile and release builds had empty target lists (no actual build targets specified), while only the debug build had actual targets. Since these builds wouldn't produce any artifacts, I removed them to avoid confusion. However, if you'd prefer to keep them for consistency with the structure, I'm happy to restore them with proper targets mirroring the desktop engine configuration.

I see you've made changes to align the structure with linux_host_desktop_engine.json - this makes a lot of sense for maintainability. I'll rebase on the current upstream master to pick up those changes and the linux_web_engine_tests fix.

Please let me know if there are any other adjustments you'd like me to make!

@LFRon

LFRon commented May 10, 2026

Copy link
Copy Markdown

So when separate ((

@loic-sharma

Copy link
Copy Markdown
Member

cc @jtmcdole This is ready for another review when you're available :)

Bia951 pushed a commit to Bia951/rustdesk that referenced this pull request Jun 16, 2026
…pport

The flutter-elinux engine used for ARM64 Linux is compiled without
--enable-fontconfig, so the Flutter text shaper cannot discover system
fonts, causing CJK characters to render as tofu boxes even when fonts
like Noto Sans CJK are installed. See flutter/flutter#139293.

Fix by loading a CJK font at startup via FontLoader (bypassing fontconfig)
and propagating it through two paths so all text is covered:

1. MyTheme.applyFontFallback() — updates textTheme in both light/dark
   ThemeData so Material components get the fallback via the theme.

2. _mergeCjkFallback() in GetMaterialApp builders — merges the fallback
   into DefaultTextStyle so bare Text() widgets and those with inherit:true
   styles also render CJK correctly.

Font discovery prefers fc-list (fontconfig CLI, available even without
engine fontconfig support), with a hardcoded search-path list as fallback
covering Debian/Ubuntu, Fedora/RHEL, and Arch Linux layouts.

This is an app-level workaround; the engine-level fix is tracked at
flutter/flutter#180235 (open as of 2026-06).

https://claude.ai/code/session_01MhU2orMADdw7M2AdzmJfGh
Bia951 pushed a commit to Bia951/rustdesk that referenced this pull request Jun 16, 2026
The flutter-elinux engine used for ARM64 Linux builds is compiled without
--enable-fontconfig, so Flutter's text shaper cannot discover system fonts.
This causes CJK characters to render as tofu boxes even when fonts such as
Noto Sans CJK are installed. See flutter/flutter#139293.

Fix by loading a CJK font at startup via FontLoader (bypassing fontconfig)
and propagating it through two paths so all text widgets are covered:

1. MyTheme.applyFontFallback() — updates textTheme on both light and dark
   ThemeData so Material components receive the fallback through the theme.

2. _mergeCjkFallback() in GetMaterialApp builders — wraps child widgets in
   DefaultTextStyle.merge so bare Text() widgets and those with inherit:true
   also render CJK characters correctly.

Font discovery first runs `fc-list :lang=zh` (the fontconfig CLI tool is
available system-wide even when the engine has no fontconfig support), then
falls back to a hardcoded search-path list covering Debian/Ubuntu, Fedora/
RHEL, Arch Linux, and WenQuanYi font layouts.

This is an app-level workaround. The engine-level fix is tracked at
flutter/flutter#180235 (open as of 2026-06).

Fixes rustdesk#10666
Bia951 pushed a commit to Bia951/rustdesk that referenced this pull request Jun 16, 2026
The flutter-elinux engine used for ARM64 Linux builds is compiled without
--enable-fontconfig, so Flutter's text shaper cannot discover system fonts.
This causes CJK characters to render as tofu boxes even when fonts such as
Noto Sans CJK are installed. See flutter/flutter#139293.

Fix by loading a CJK font at startup via FontLoader (bypassing fontconfig)
and propagating it through two paths so all text widgets are covered:

1. MyTheme.applyFontFallback() — updates textTheme on both light and dark
   ThemeData so Material components receive the fallback through the theme.

2. _mergeCjkFallback() in GetMaterialApp builders — wraps child widgets in
   DefaultTextStyle.merge so bare Text() widgets and those with inherit:true
   also render CJK characters correctly.

Font discovery first runs `fc-list :lang=zh` (the fontconfig CLI tool is
available system-wide even when the engine has no fontconfig support), then
falls back to a hardcoded search-path list covering Debian/Ubuntu, Fedora/
RHEL, Arch Linux, and WenQuanYi font layouts.

This is an app-level workaround. The engine-level fix is tracked at
flutter/flutter#180235 (open as of 2026-06).

Fixes rustdesk#10666
Bia951 pushed a commit to Bia951/rustdesk that referenced this pull request Jun 17, 2026
The flutter-elinux engine used for ARM64 Linux builds is compiled without
--enable-fontconfig, so Flutter's text shaper cannot discover system fonts.
This causes CJK characters to render as tofu boxes even when fonts such as
Noto Sans CJK are installed. See flutter/flutter#139293.

Fix by loading a CJK font at startup via FontLoader (bypassing fontconfig)
and propagating it through two paths so all text widgets are covered:

1. MyTheme.applyFontFallback() — updates textTheme on both light and dark
   ThemeData so Material components receive the fallback through the theme.

2. _mergeCjkFallback() in GetMaterialApp builders — wraps child widgets in
   DefaultTextStyle.merge so bare Text() widgets and those with inherit:true
   also render CJK characters correctly.

Font discovery first runs `fc-list :lang=zh` (the fontconfig CLI tool is
available system-wide even when the engine has no fontconfig support), then
falls back to a hardcoded search-path list covering Debian/Ubuntu, Fedora/
RHEL, Arch Linux, and WenQuanYi font layouts.

This is an app-level workaround. The engine-level fix is tracked at
flutter/flutter#180235 (open as of 2026-06).

Fixes rustdesk#10666
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Aug 4, 2026
@auto-submit

auto-submit Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/180235, because - The status or check suite Tree_analyze has failed. Please fix the issues identified (or deflake) before re-applying this label.

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Aug 5, 2026
@krystic

krystic commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

Hi @jtmcdole

The branch was updated after the CICD label was added, and flutter-dashboard removed the label on the new head commit. The tree is green now, but the PR is back to Awaiting CICD label.

Could someone please re-apply CICD and then autosubmit when appropriate?

@jason-simmons jason-simmons added the CICD Run CI/CD label Aug 5, 2026
@jtmcdole jtmcdole added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App and removed CICD Run CI/CD labels Aug 5, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Aug 5, 2026
Merged via the queue into flutter:master with commit e4c0224 Aug 5, 2026
35 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Aug 5, 2026
@krystic
krystic deleted the fix-arm64-desktop-fontconfig branch August 5, 2026 19:55
@dbebawy dbebawy mentioned this pull request Aug 11, 2026
6 tasks done
pull Bot pushed a commit to safarmer/flutter that referenced this pull request Aug 11, 2026
flutter#190935)

This builder was recently created in a refactoring of the Linux arm64
builders (see flutter#180235)

The builder was not being scheduled in the merge queue because it is
marked as "bringup: true" (see
flutter#190893)
reancool pushed a commit to flyopensource/rustdesk that referenced this pull request Sep 6, 2026
…15324)

* fix(arm64-linux): fix CJK font rendering on flutter-elinux

The flutter-elinux engine used for ARM64 Linux builds is compiled without
--enable-fontconfig, so Flutter's text shaper cannot discover system fonts.
This causes CJK characters to render as tofu boxes even when fonts such as
Noto Sans CJK are installed. See flutter/flutter#139293.

Fix by loading a CJK font at startup via FontLoader (bypassing fontconfig)
and propagating it through two paths so all text widgets are covered:

1. MyTheme.applyFontFallback() — updates textTheme on both light and dark
   ThemeData so Material components receive the fallback through the theme.

2. _mergeCjkFallback() in GetMaterialApp builders — wraps child widgets in
   DefaultTextStyle.merge so bare Text() widgets and those with inherit:true
   also render CJK characters correctly.

Font discovery queries fc-list for zh, ja, and ko separately, preferring
fonts present in all three sets (true pan-CJK fonts such as NotoSansCJK or
SourceHanSans) over Chinese-only fonts that may lack Japanese kana or Korean
hangul glyphs.  Falls back to a hardcoded search-path list covering
Debian/Ubuntu, Fedora/RHEL, Arch Linux, and WenQuanYi font layouts.

This is an app-level workaround. The engine-level fix is tracked at
flutter/flutter#180235 (open as of 2026-06).

Fixes rustdesk#10666

Signed-off-by: Bia503 <yinwenche189@gmail.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Signed-off-by: Bia503 <yinwenche189@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CJK text not showing on arm64 Linux desktop.

6 participants