diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ea1907e00..58ddc0cb0 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -598,22 +598,6 @@ class MyTheme { } } - /// Applies [fallbacks] as fontFamilyFallback to every text style in both - /// themes. Called once at startup on ARM64 Linux after a CJK font has been - /// loaded via FontLoader (see flutter/flutter#139293). - static void applyFontFallback(List fallbacks) { - lightTheme = lightTheme.copyWith( - textTheme: lightTheme.textTheme.apply(fontFamilyFallback: fallbacks), - primaryTextTheme: - lightTheme.primaryTextTheme.apply(fontFamilyFallback: fallbacks), - ); - darkTheme = darkTheme.copyWith( - textTheme: darkTheme.textTheme.apply(fontFamilyFallback: fallbacks), - primaryTextTheme: - darkTheme.primaryTextTheme.apply(fontFamilyFallback: fallbacks), - ); - } - static ThemeMode currentThemeMode() { final preference = getThemeModePreference(); if (preference == ThemeMode.system) { diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 2812d6b24..9bd68ed60 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -29,8 +29,6 @@ import 'mobile/pages/home_page.dart'; import 'mobile/pages/server_page.dart'; import 'mobile/widgets/deploy_dialog.dart'; import 'models/platform_model.dart'; -import 'native/font_manager.dart' - if (dart.library.html) 'web/font_manager.dart'; import 'package:flutter_hbb/plugin/handlers.dart' if (dart.library.html) 'package:flutter_hbb/web/plugin/handlers.dart'; @@ -39,15 +37,10 @@ import 'package:flutter_hbb/plugin/handlers.dart' int? kWindowId; WindowType? kWindowType; late List kBootArgs; -bool _cjkFontLoaded = false; Future main(List args) async { earlyAssert(); WidgetsFlutterBinding.ensureInitialized(); - _cjkFontLoaded = await loadSystemCJKFonts(); - if (_cjkFontLoaded) { - MyTheme.applyFontFallback([kLinuxCjkFontFamily]); - } debugPrint("launch args: $args"); kBootArgs = List.from(args); @@ -390,7 +383,6 @@ void _runApp( builder: (context, child) { child = _keepScaleBuilder(context, child); child = botToastBuilder(context, child); - if (_cjkFontLoaded) child = _mergeCjkFallback(context, child); return child; }, ), @@ -541,7 +533,6 @@ class _AppState extends State with WidgetsBindingObserver { : (context, child) { child = _keepScaleBuilder(context, child); child = botToastBuilder(context, child); - if (_cjkFontLoaded) child = _mergeCjkFallback(context, child); if ((isDesktop && desktopType == DesktopType.main) || isWebDesktop) { child = keyListenerBuilder(context, child); @@ -595,19 +586,6 @@ _registerEventHandler() { } } -/// Merges the theme's fontFamilyFallback into [DefaultTextStyle] so that -/// bare [Text] widgets (and those with inherit:true styles) also pick up the -/// CJK fallback font loaded on ARM64 Linux. -Widget _mergeCjkFallback(BuildContext context, Widget? child) { - final result = child ?? Container(); - final fallback = Theme.of(context).textTheme.bodyMedium?.fontFamilyFallback; - if (fallback == null || fallback.isEmpty) return result; - return DefaultTextStyle.merge( - style: TextStyle(fontFamilyFallback: fallback), - child: result, - ); -} - Widget keyListenerBuilder(BuildContext context, Widget? child) { return RawKeyboardListener( focusNode: FocusNode(), diff --git a/flutter/lib/native/font_manager.dart b/flutter/lib/native/font_manager.dart deleted file mode 100644 index c714b84f3..000000000 --- a/flutter/lib/native/font_manager.dart +++ /dev/null @@ -1,109 +0,0 @@ -import 'dart:ffi' show Abi; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -/// Font family name registered with [FontLoader] when a system CJK font is -/// successfully loaded on ARM64 Linux. -const kLinuxCjkFontFamily = 'SystemCJK'; - -const _kFontSearchPaths = [ - // Debian / Ubuntu (noto-fonts / fonts-noto-cjk) - '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc', - '/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc', - '/usr/share/fonts/opentype/noto/NotoSansCJKsc-Regular.otf', - // Fedora / RHEL / Rocky (google-noto-sans-cjk-fonts) - '/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc', - '/usr/share/fonts/google-noto-sans-cjk-fonts/NotoSansCJK-Regular.ttc', - // Arch Linux (noto-fonts-cjk) - '/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc', - '/usr/share/fonts/noto-cjk/NotoSansCJKsc-Regular.otf', - // Generic fallback paths - '/usr/share/fonts/noto/NotoSansCJK-Regular.ttc', - '/usr/share/fonts/noto/NotoSansCJKsc-Regular.otf', - // WenQuanYi — commonly pre-installed on CJK-locale systems - '/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', - '/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc', - '/usr/share/fonts/wqy-microhei/wqy-microhei.ttc', - '/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc', -]; - -/// Loads a system CJK font on ARM64 Linux into Flutter's font registry via -/// [FontLoader], working around the missing fontconfig support in the -/// flutter-elinux engine (https://github.com/flutter/flutter/issues/139293). -/// -/// Returns true if a CJK font was successfully loaded; false otherwise. -/// On all other platforms this is a no-op and returns false immediately. -Future loadSystemCJKFonts() async { - if (Abi.current() != Abi.linuxArm64) return false; - - final path = await _findCjkFontPath(); - if (path == null) { - debugPrint('ARM64 Linux: no CJK font found; CJK text may not render'); - return false; - } - - try { - final loader = FontLoader(kLinuxCjkFontFamily); - final bytes = await File(path).readAsBytes(); - loader.addFont(Future.value(ByteData.view(bytes.buffer, bytes.offsetInBytes, bytes.lengthInBytes))); - await loader.load(); - debugPrint('ARM64 Linux: loaded CJK font from $path'); - return true; - } catch (e) { - debugPrint('ARM64 Linux: failed to load CJK font: $e'); - return false; - } -} - -Future _findCjkFontPath() async { - // Query fc-list for each CJK script separately. Fonts present in all three - // sets (zh ∩ ja ∩ ko) are true pan-CJK fonts; prefer them so we don't - // accidentally pick a Chinese-only font that lacks Japanese kana or Korean - // hangul glyphs. fc-list is a fontconfig CLI tool available on most Linux - // systems independent of whether the Flutter engine was built with fontconfig. - final byLang = >{}; - for (final lang in const ['zh', 'ja', 'ko']) { - final paths = {}; - try { - final r = - await Process.run('fc-list', [':lang=$lang', '--format=%{file}\n']); - if (r.exitCode == 0) { - for (final line in r.stdout.toString().split('\n')) { - final p = line.trim(); - if (p.isNotEmpty && File(p).existsSync()) paths.add(p); - } - } - } catch (e) { - debugPrint('ARM64 Linux: fc-list failed for lang=$lang: $e'); - } - byLang[lang] = paths; - } - - final panCjk = byLang['zh']! - .intersection(byLang['ja']!) - .intersection(byLang['ko']!); - final anyCjk = - byLang.values.fold({}, (acc, s) => acc..addAll(s)); - - // Among candidates, prefer well-known pan-CJK font families. - String? pick(Iterable pool) { - const preferred = ['notosanscjk', 'sourcehansans', 'sourcehanserif']; - for (final name in preferred) { - for (final p in pool) { - if (p.toLowerCase().contains(name)) return p; - } - } - return pool.isNotEmpty ? pool.first : null; - } - - final found = pick(panCjk) ?? pick(anyCjk); - if (found != null) return found; - - for (final p in _kFontSearchPaths) { - if (File(p).existsSync()) return p; - } - return null; -} diff --git a/flutter/lib/web/font_manager.dart b/flutter/lib/web/font_manager.dart deleted file mode 100644 index c31d32890..000000000 --- a/flutter/lib/web/font_manager.dart +++ /dev/null @@ -1,8 +0,0 @@ -/// Web stub for `native/font_manager.dart`. -/// -/// The native implementation depends on `dart:io` (Process/File/Platform) to -/// load a system CJK font on ARM64 Linux, which cannot compile for the web -/// target. The web build has no such fontconfig limitation, so this is a no-op. -const kLinuxCjkFontFamily = 'SystemCJK'; - -Future loadSystemCJKFonts() async => false;