import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import '../utils/app_logger.dart'; /// Utility class for loading font assets for libass subtitle rendering. /// /// Extracts font files from Flutter assets to the app's cache directory to ensure /// comprehensive Unicode coverage (including CJK characters) for subtitles. class SubtitleFontLoader { static const String _fontAssetPath = 'assets/go-noto-current-regular.ttf'; static const String _fontName = 'Go Noto Current-Regular'; /// In-memory cache of the resolved font directory. The filesystem work /// (temp dir lookup, existence checks, asset extraction) is idempotent per /// process — caching the result skips ~20ms on every subsequent Player /// instantiation. static Future? _cachedFontDir; /// Loads the subtitle font from assets to the cache directory. /// Returns the directory path containing the font file. static Future loadSubtitleFont() { return _cachedFontDir ??= _loadSubtitleFontOnce(); } static Future _loadSubtitleFontOnce() async { try { // Get the app's cache directory final cacheDir = await getTemporaryDirectory(); final fontDir = Directory(path.join(cacheDir.path, 'subtitle_fonts')); // Create fonts directory if it doesn't exist if (!await fontDir.exists()) { await fontDir.create(recursive: true); } final fontFile = File(path.join(fontDir.path, 'go-noto-current-regular.ttf')); // Load font from assets and write to cache if it doesn't exist if (!await fontFile.exists()) { final fontData = await rootBundle.load(_fontAssetPath); await fontFile.writeAsBytes(fontData.buffer.asUint8List()); } return fontDir.path; } catch (e, st) { // Return null if font loading fails - libass will fall back gracefully appLogger.w('Failed to load subtitle font', error: e, stackTrace: st); return null; } } /// Returns the font name to be used with libass. static String get fontName => _fontName; /// Returns the font asset path. static String get fontAssetPath => _fontAssetPath; }