Files
IKAR/test/font_file_info_test.dart

122 lines
3.4 KiB
Dart

import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart';
import 'package:ikar/core/config/font_file_info.dart';
typedef _Name = ({int platform, int language, int nameId, List<int> bytes});
List<int> _utf16be(String s) => [
for (final unit in s.codeUnits) ...[unit >> 8, unit & 0xff],
];
Uint8List _nameTable(List<_Name> names) {
final storage = <int>[];
final records = _Bytes();
for (final name in names) {
records
..u16(name.platform)
..u16(name.platform == 3 ? 1 : 0)
..u16(name.language)
..u16(name.nameId)
..u16(name.bytes.length)
..u16(storage.length);
storage.addAll(name.bytes);
}
return (_Bytes()
..u16(0)
..u16(names.length)
..u16(6 + names.length * 12)
..addAll(records.bytes)
..addAll(storage))
.toBytes();
}
Uint8List _font(List<_Name> names, {bool collection = false}) {
final table = _nameTable(names);
final headerSize = collection ? 16 : 0;
final fontOffset = headerSize;
final tableOffset = fontOffset + 12 + 16;
final out = _Bytes();
if (collection) {
out
..u32(0x74746366)
..u32(0x00010000)
..u32(1)
..u32(fontOffset);
}
out
..u32(0x00010000)
..u16(1)
..u16(16)
..u16(0)
..u16(0)
..addAll('name'.codeUnits)
..u32(0)
..u32(tableOffset)
..u32(table.length)
..addAll(table);
return out.toBytes();
}
class _Bytes {
final List<int> bytes = [];
void u16(int v) => bytes.addAll([(v >> 8) & 0xff, v & 0xff]);
void u32(int v) => bytes.addAll([
(v >> 24) & 0xff,
(v >> 16) & 0xff,
(v >> 8) & 0xff,
v & 0xff,
]);
void addAll(Iterable<int> values) => bytes.addAll(values);
Uint8List toBytes() => Uint8List.fromList(bytes);
}
void main() {
test('the typographic family wins over the legacy one', () {
final font = _font([
(platform: 3, language: 0x0409, nameId: 1, bytes: _utf16be('Synth Bold')),
(platform: 3, language: 0x0409, nameId: 16, bytes: _utf16be('Synth')),
]);
expect(FontFileInfo.familyName(font), 'Synth');
});
test('the English Windows name is preferred, others are a fallback', () {
final font = _font([
(platform: 1, language: 0, nameId: 1, bytes: 'Mac Synth'.codeUnits),
(platform: 3, language: 0x0419, nameId: 1, bytes: _utf16be('Синтез')),
(platform: 3, language: 0x0409, nameId: 1, bytes: _utf16be('Synth')),
]);
expect(FontFileInfo.familyName(font), 'Synth');
final onlyRussian = _font([
(platform: 3, language: 0x0419, nameId: 1, bytes: _utf16be('Синтез')),
]);
expect(FontFileInfo.familyName(onlyRussian), 'Синтез');
});
test('a collection is read from its first font', () {
final font = _font([
(platform: 3, language: 0x0409, nameId: 1, bytes: _utf16be('Synth')),
], collection: true);
expect(FontFileInfo.familyName(font), 'Synth');
});
test('garbage has no family name', () {
expect(FontFileInfo.familyName(Uint8List.fromList([1, 2, 3])), isNull);
expect(FontFileInfo.familyName(_font(const [])), isNull);
});
test('the file name loses its style suffix and separators', () {
expect(FontFileInfo.familyFromFileName('/tmp/Synth-Regular.ttf'), 'Synth');
expect(
FontFileInfo.familyFromFileName('Synth_Sans-VariableFont_wght.ttf'),
'Synth Sans',
);
expect(FontFileInfo.familyFromFileName('Mono.otf'), 'Mono');
});
}