Skip to content

Commit dd0cf30

Browse files
committed
apply conversion font smooth
1 parent 0b9adb0 commit dd0cf30

2 files changed

Lines changed: 110 additions & 63 deletions

File tree

lib/screens/player_screen.dart

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ class _PlayerScreenState extends State<PlayerScreen>
348348
bool _autoConvertMissing = false;
349349
Set<String> _favoriteFonts = {};
350350

351+
String? _pendingCycleFont;
352+
String? _pendingCycleConversionType;
353+
bool _pendingCycleReady = false;
354+
351355
Set<String> _favoriteColorPalettes = {};
352356
String _colorFilterMode = 'all';
353357
ColorPaletteFilter _colorFilter = ColorPaletteFilter.all;
@@ -4735,6 +4739,12 @@ class _PlayerScreenState extends State<PlayerScreen>
47354739

47364740
if (_fontCycleActive) {
47374741
_fontCycleCueCounter++;
4742+
4743+
if (_fontCycleInterval > 1 &&
4744+
_fontCycleCueCounter == _fontCycleInterval - 1) {
4745+
unawaited(_preloadNextCycleFont());
4746+
}
4747+
47384748
if (_fontCycleCueCounter >= _fontCycleInterval) {
47394749
_fontCycleCueCounter = 0;
47404750
_navigateFonts(1, fromCycle: true);
@@ -4929,6 +4939,31 @@ class _PlayerScreenState extends State<PlayerScreen>
49294939
}
49304940
}
49314941

4942+
Future<void> _preloadNextCycleFont() async {
4943+
_pendingCycleReady = false;
4944+
final filteredFonts = _getFilteredFonts();
4945+
if (filteredFonts.isEmpty) return;
4946+
4947+
final nextIndex = (_selectedFontIndex + 1) % filteredFonts.length;
4948+
final nextFont = filteredFonts[nextIndex];
4949+
4950+
await CustomFontLoader.loadFonts();
4951+
4952+
String? conversionType;
4953+
if (_autoConvertAlternates && FontAlternatesData.hasFontAlternates(nextFont)) {
4954+
conversionType = 'alternates';
4955+
} else if (_autoConvertMissing) {
4956+
final metadata = FontDatabase.getMetadata(nextFont);
4957+
if (metadata != null && metadata.hasMissingLigatures()) {
4958+
conversionType = 'missing';
4959+
}
4960+
}
4961+
4962+
_pendingCycleFont = nextFont;
4963+
_pendingCycleConversionType = conversionType;
4964+
_pendingCycleReady = true;
4965+
}
4966+
49324967
double _calculateDynamicFontSize(String text, double baseFontSize) {
49334968
final textLength = _getEffectiveTextLength(text);
49344969
double multiplier = 1.0;
@@ -7262,20 +7297,28 @@ class _PlayerScreenState extends State<PlayerScreen>
72627297
});
72637298
_scrollToSelectedFont();
72647299

7265-
if (_autoConvertAlternates &&
7266-
FontAlternatesData.hasFontAlternates(_selectedFont)) {
7267-
setState(() {
7268-
_conversionType = 'alternates';
7269-
});
7270-
await _applyConversion();
7271-
} else if (_autoConvertMissing) {
7272-
final metadata = FontDatabase.getMetadata(_selectedFont);
7273-
if (metadata != null && metadata.hasMissingLigatures()) {
7274-
setState(() {
7275-
_conversionType = 'missing';
7276-
});
7300+
final usePending = fromCycle &&
7301+
_pendingCycleReady &&
7302+
_pendingCycleFont == _selectedFont;
7303+
7304+
if (usePending) {
7305+
if (_pendingCycleConversionType != null) {
7306+
setState(() => _conversionType = _pendingCycleConversionType!);
72777307
await _applyConversion();
72787308
}
7309+
_pendingCycleReady = false;
7310+
} else {
7311+
if (_autoConvertAlternates &&
7312+
FontAlternatesData.hasFontAlternates(_selectedFont)) {
7313+
setState(() => _conversionType = 'alternates');
7314+
await _applyConversion();
7315+
} else if (_autoConvertMissing) {
7316+
final metadata = FontDatabase.getMetadata(_selectedFont);
7317+
if (metadata != null && metadata.hasMissingLigatures()) {
7318+
setState(() => _conversionType = 'missing');
7319+
await _applyConversion();
7320+
}
7321+
}
72797322
}
72807323
}
72817324

@@ -10415,6 +10458,10 @@ class _PlayerScreenState extends State<PlayerScreen>
1041510458

1041610459
setState(() {
1041710460
_subtitles = subtitles;
10461+
if (_currentSubtitleIndex != null &&
10462+
_currentSubtitleIndex! < _subtitles.length) {
10463+
_currentSubtitleText = _subtitles[_currentSubtitleIndex!].text;
10464+
}
1041810465
});
1041910466

1042010467
_updateCurrentSubtitle();

lib/services/font_loader.dart

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class CustomFontLoader {
77
static final Map<String, String> _loadedFonts = {};
88
static final Set<String> _customFonts = {};
99
static final Set<String> _customFonts2 = {};
10-
10+
1111
static List<String> get loadedFonts => _loadedFonts.keys.toList()..sort();
1212
static List<String> get customFonts => _customFonts.toList()..sort();
1313
static List<String> get customFonts2 => _customFonts2.toList()..sort();
@@ -29,7 +29,7 @@ class CustomFontLoader {
2929
try {
3030
final dir = Directory(directory);
3131
final fontFiles = <File>[];
32-
32+
3333
await for (final entity in dir.list(recursive: true)) {
3434
if (entity is File) {
3535
final ext = path.extension(entity.path).toLowerCase();
@@ -38,38 +38,38 @@ class CustomFontLoader {
3838
}
3939
}
4040
}
41-
41+
4242
for (final fontFile in fontFiles) {
4343
try {
4444
final fontName = _extractFontName(fontFile.path);
45-
45+
4646
if (_loadedFonts.containsKey(fontName)) {
4747
continue;
4848
}
49-
49+
5050
final fontLoader = FontLoader(fontName);
5151
final bytes = await fontFile.readAsBytes();
5252
fontLoader.addFont(Future.value(ByteData.view(bytes.buffer)));
5353
await fontLoader.load();
54-
54+
5555
_loadedFonts[fontName] = fontFile.path;
5656
if (slot == 2) {
5757
_customFonts2.add(fontName);
5858
} else {
5959
_customFonts.add(fontName);
6060
}
61-
61+
6262
} catch (e) {
6363
print('Error loading ${path.basename(fontFile.path)}: $e');
6464
}
6565
}
66-
66+
6767
} catch (e) {
6868
print('Error loading custom fonts: $e');
6969
rethrow;
7070
}
7171
}
72-
72+
7373
static void clearCustomFonts({int slot = 1}) {
7474
if (slot == 2) {
7575
for (final fontName in _customFonts2) {
@@ -88,43 +88,43 @@ class CustomFontLoader {
8888
try {
8989
final String manifestJson = await rootBundle.loadString('AssetManifest.bin.json');
9090
final Map<String, dynamic> manifest = json.decode(manifestJson);
91-
91+
9292
final fontPaths = <String>[];
93-
93+
9494
for (final key in manifest.keys) {
95-
if (key.startsWith('assets/fonts/') &&
95+
if (key.startsWith('assets/fonts/') &&
9696
(key.endsWith('.ttf') || key.endsWith('.otf') || key.endsWith('.ttc'))) {
9797
fontPaths.add(key);
9898
}
9999
}
100-
100+
101101
print('Found ${fontPaths.length} font files in assets');
102-
102+
103103
int loaded = 0;
104104
for (final fontPath in fontPaths) {
105105
try {
106106
final fontName = _extractFontName(fontPath);
107-
107+
108108
if (_loadedFonts.containsKey(fontName)) {
109109
continue;
110110
}
111-
111+
112112
final fontLoader = FontLoader(fontName);
113113
final fontData = await rootBundle.load(fontPath);
114114
fontLoader.addFont(Future.value(fontData.buffer.asByteData()));
115115
await fontLoader.load();
116-
116+
117117
_loadedFonts[fontName] = fontPath;
118118
loaded++;
119-
119+
120120
if (loaded % 100 == 0) {
121121
print('Loaded $loaded fonts...');
122122
}
123123
} catch (e) {
124124
print('Error loading font $fontPath: $e');
125125
}
126126
}
127-
127+
128128
print('Successfully loaded $loaded fonts from assets');
129129
} catch (e) {
130130
print('Error loading fonts from assets: $e');
@@ -133,17 +133,17 @@ class CustomFontLoader {
133133

134134
static Future<void> _loadFontsFromFileSystem() async {
135135
String? fontsPath = await _getFontsPath();
136-
136+
137137
if (fontsPath == null) {
138138
print('Fonts directory not found in app bundle');
139139
return;
140140
}
141-
142-
print('Loading fonts from: $fontsPath');
143-
141+
142+
// print('Loading fonts from: $fontsPath');
143+
144144
final fontsDir = Directory(fontsPath);
145145
final fontFiles = <File>[];
146-
146+
147147
await for (final entity in fontsDir.list(recursive: false)) {
148148
if (entity is File) {
149149
final ext = path.extension(entity.path).toLowerCase();
@@ -152,42 +152,42 @@ class CustomFontLoader {
152152
}
153153
}
154154
}
155-
155+
156156
int loaded = 0;
157157
int skipped = 0;
158-
158+
159159
for (final fontFile in fontFiles) {
160160
try {
161161
final fontName = _extractFontName(fontFile.path);
162-
162+
163163
if (_loadedFonts.containsKey(fontName)) {
164164
skipped++;
165165
continue;
166166
}
167-
167+
168168
final fontLoader = FontLoader(fontName);
169169
final bytes = await fontFile.readAsBytes();
170170
fontLoader.addFont(Future.value(ByteData.view(bytes.buffer)));
171171
await fontLoader.load();
172-
172+
173173
_loadedFonts[fontName] = fontFile.path;
174174
loaded++;
175-
175+
176176
if (loaded % 500 == 0) {
177177
}
178178
} catch (e) {
179179
print('Error loading ${path.basename(fontFile.path)}: $e');
180180
}
181181
}
182-
183-
print('Loaded $loaded fonts (skipped $skipped duplicates)');
182+
183+
// print('Loaded $loaded fonts (skipped $skipped duplicates)');
184184
}
185185

186186
static Future<String?> _getFontsPath() async {
187187
if (Platform.isMacOS) {
188188
final executablePath = Platform.resolvedExecutable;
189189
final appDir = Directory(path.dirname(executablePath));
190-
190+
191191
final flutterAssetsDir = Directory(path.join(
192192
appDir.parent.path,
193193
'Frameworks',
@@ -199,70 +199,70 @@ class CustomFontLoader {
199199
'assets',
200200
'fonts'
201201
));
202-
203-
print('DEBUG: Looking for fonts at: ${flutterAssetsDir.path}');
204-
print('DEBUG: Directory exists: ${await flutterAssetsDir.exists()}');
205-
202+
203+
// print('DEBUG: Looking for fonts at: ${flutterAssetsDir.path}');
204+
// print('DEBUG: Directory exists: ${await flutterAssetsDir.exists()}');
205+
206206
if (await flutterAssetsDir.exists()) {
207207
final files = await flutterAssetsDir.list().toList();
208-
print('DEBUG: Found ${files.length} files in fonts directory');
208+
// print('DEBUG: Found ${files.length} files in fonts directory');
209209
return flutterAssetsDir.path;
210210
} else {
211211
print('DEBUG: Fonts directory NOT found!');
212212
}
213213
} else if (Platform.isLinux) {
214214
final executablePath = Platform.resolvedExecutable;
215215
final appDir = path.dirname(executablePath);
216-
216+
217217
var fontsDir = Directory(path.join(appDir, 'data', 'flutter_assets', 'assets', 'fonts'));
218218
if (await fontsDir.exists()) {
219219
return fontsDir.path;
220220
}
221-
221+
222222
fontsDir = Directory(path.join(appDir, 'data', 'flutter_assets', 'fonts'));
223223
if (await fontsDir.exists()) {
224224
return fontsDir.path;
225225
}
226-
226+
227227
fontsDir = Directory(path.join(appDir, '..', 'data', 'fonts'));
228228
if (await fontsDir.exists()) {
229229
return fontsDir.path;
230230
}
231-
231+
232232
fontsDir = Directory(path.join(appDir, 'data', 'fonts'));
233233
if (await fontsDir.exists()) {
234234
return fontsDir.path;
235235
}
236236
} else if (Platform.isWindows) {
237237
final executablePath = Platform.resolvedExecutable;
238238
final appDir = path.dirname(executablePath);
239-
239+
240240
final fontsDir = Directory(path.join(appDir, 'data', 'flutter_assets', 'assets', 'fonts'));
241-
241+
242242
print('Windows fonts path: ${fontsDir.path}');
243243
print('Fonts directory exists: ${await fontsDir.exists()}');
244-
244+
245245
if (await fontsDir.exists()) {
246246
return fontsDir.path;
247247
}
248-
248+
249249
print('ERROR: Fonts directory not found at expected location');
250250
}
251-
251+
252252
return null;
253253
}
254254

255255
static String _extractFontName(String fontPath) {
256256
final fileName = path.basenameWithoutExtension(fontPath);
257-
257+
258258
final decoded = Uri.decodeComponent(fileName);
259-
259+
260260
final cleaned = decoded.trim();
261-
261+
262262
return cleaned.isNotEmpty ? cleaned : fileName;
263263
}
264264

265265
static List<String> getAvailableFonts() {
266266
return loadedFonts;
267267
}
268-
}
268+
}

0 commit comments

Comments
 (0)