moi15moi / fontcollector Goto Github PK
View Code? Open in Web Editor NEWFontCollector for Advanced SubStation Alpha file.
Home Page: https://pypi.org/project/FontCollector/
License: MIT License
FontCollector for Advanced SubStation Alpha file.
Home Page: https://pypi.org/project/FontCollector/
License: MIT License
Currently, FontCollector will always reset the style to the line style.
It should see if there is a style specify after the \r.
If yes, parse it and apply the style, if no, take the line style.
Warning: Need to strip the style only at the end and match exactly the case with the style name. Also, it can not contain "(" or ")".
So I have the following issue. I have a font named SF Pro Display, that has different weight (and italics) options in the same name (see attached screenshots)
In the ass file, I'm using the first one and Aegisub font collector does collect the first one (shown below). So for some reason, this tool collects the italic variant.
(Windows 11)
The current font enumeration method does not find fonts activated by FontBase; even though they should be detected as system fonts considering every app with a font picker can find them.
Potentially could also be causing issues with other apps that utilize the same method as FontBase to activate their fonts.
I've confirmed with other users that they also experience the same issue. One user have testified that FontCollector successfully finds their FontBase fonts though but we couldn't identify the cause—so there might be a configuration change necessary for it to work.
FontCollector is not able to read variable font without AxisValue.
Here is an font that it cannot parse: Inter-VariableFont_slntwght.zip
Here is the STAT table of the font.
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=2 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="270"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
<Axis index="1">
<AxisTag value="slnt"/>
<AxisNameID value="271"/> <!-- Slant -->
<AxisOrdering value="1"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
GDI name this font with 2 value:
1- typo/family name = "Inter"
2- typo/family name + ElidedFallbackNameID = "Inter Regular"
mkvfontvalidator would be a new command to verify if all the font files are muxed to the mkv.
It will automatically detect the muxed fonts and ass file by using the codec id.
To be compatible with mpv, we will use the same codec id as them. Codec id for ass file and codec id for font file.
Finally, mkvfontvalidator should have at least these options
-mkv MKV
The video file to be verified. Must be a Matroska file.
-mkvpropedit MKVPROPEDIT
Path to mkvpropedit.exe if not in variable environments. If -mkv is not specified, it will do
nothing.
--need-draw-fonts
If specified, FontCollector will report a error if a font used in a draw isn't muxed to the mkv. For more detail when this
is usefull, see: https://github.com/libass/libass/issues/617
Please add a logging parameter --logging
-log
.
Example:
--logging OUTPUT, -log OUTPUT
Destination path of log. If OUTPUT isn't specified, it will be the current path.
Helpful when doing large batches to easily search for any errors warnings etc.
You could just have its default log name be something like:
<SYSTEMStartTime>_log.txt
Or something like that it really doesn't matter too much, Or just require the user to declare filename in OUTPUT with DIR.
Thanks!
Windows 95 OSR2.5 (Trad. Chinese)
https://archive.org/details/Win95CCHT
Extract ISO.
Find 3 .cab
files - MINI.CAB, MINI1.CAB, MINI2.CAB (3-parts)
Use 7-Zip, or WinRAR, etc. to extract from MINI.CAB.
You will find what you are looking for.
When someones open a PR, we should run a workflow and run pylint, mypy and pytest to ensure the quality of the code
AssDocument::get_used_style(true)
does not return Arial
in this case. __set_used_styles
gets called for Arial
, but it's not being set as a used style.
[Script Info]
ScriptType: v4.00+
WrapStyle: 0
PlayResX: 1920
PlayResY: 1080
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.709
Video Aspect Ratio: c1.777780
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Sign,Arial,30,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,15,15,15,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:01.10,0:00:10.10,Sign,,0,0,0,,{\pos(1118.334,292.5)\fay-0.6\fnAdobe Gothic Std B\fs15\b1\c&H574942&\blur0.75}Oozuka
The only font collected here is Adobe Gothic Std B
; so Arial
does not end up being muxed into the final output when used in a muxing script.
Playing with mpv and without a font provider, using only the fonts collected by fontcollector, this appears:
mpv --no-config --sub-font-provider=none <path to mkv>
[sub/ass] fontselect: failed to find any fallback with glyph 0x0 for font: (Arial, 400, 0)
FontCollector tries to reproduce what VSFilter does. VSFilter uses GDI to select a font and display it, so we need to emulate it.
We already properly emulate the score for the lfWeight and lfItalic attributes, but we don't emulate the score for lfPitchAndFamily and lfCharSet.
99% of the time, these properties don't affect the font that will be picked up. In general, they can affect the font picked up when the user has two fonts that are the same, but one is TrueType and the other is OpenType.
lfPitchAndFamily score algorithm
font_family = FF_DECORATIVE, FF_DONTCARE, FF_MODERN, FF_ROMAN, FF_SCRIPT or FF_SWISS
requested_family = is it always FF_DONTCARE
requested_charset = Depend on \fe tag or the ass style
if (jMapCharSet == SYMBOL_CHARSET) {
requested_family = font_family
} else if (font_family != FF_DONTCARE) {
requested_family = FF_SWISS // Technically, if the requested font is "Tms Rmn", it will be FF_ROMAN, but I am not sure if we want this behavior
}
if (requested_family != font_family) {
if (font_family == FF_DONTCARE) {
score += 8000;
} else {
if (font_family > FF_MODERN) {
score += 50;
}
score += 9000;
}
}
lfCharSet score algorithm
requested_charset = Depend on \fe tag or the ass style
font_charsets = list of charset
if requested_charset != DEFAULT_CHARSET and requested_charset not in font_charsets:
REJECT the font
I still don't fully understand how GDI sets lfCharSet and lfPitchAndFamily, so I will need to dig deeper before I can implement it.
fontTools allow to create a subset of the font like this:
from fontTools import subset
from fontTools.ttLib.ttFont import TTFont
font = TTFont("font.TTF")
subsetter = subset.Subsetter()
subsetter.populate(text="ABÉé")
subsetter.subset(font)
font.save("font strip.TTF")
In the latest version 2.0.2, the --additional-fonts
function does not work. I get an error every time.
I have the font collections on another disk, I get this error:
C:\Users\xyz\Desktop\Subs>fontcollector -i --additional-fonts D:\Junk\Fonts\
Traceback (most recent call last):
File "C:\Users\xyz\scoop\apps\Python\current\Scripts\fontcollector-script.py", line 33, in <module>
sys.exit(load_entry_point('FontCollector==2.0.2', 'console_scripts', 'fontcollector')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\__main__.py", line 23, in main
) = parse_arguments()
^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\parse_arguments.py", line 121, in parse_arguments
additional_fonts = FontLoader.load_additional_fonts(args.additional_fonts)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\font_loader.py", line 124, in load_additional_fonts
additional_fonts.update(Font.from_font_path(path))
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\font.py", line 72, in from_font_path
axis_value_tables = ParseFont.get_axis_value_from_coordinates(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\parse_font.py", line 132, in get_axis_value_from_coordinates
raise ValueError("Cannot get axis_value since there is no STAT table.")
ValueError: Cannot get axis_value since there is no STAT table.
Also I tested what if the fonts were on the same drive as the subtitles, an error appears interestingly it is different from the first case.
C:\Users\xyz\Desktop\Subs>fontcollector -i --additional-fonts ..\Fonts\
Traceback (most recent call last):
File "C:\Users\xyz\scoop\apps\Python\current\Scripts\fontcollector-script.py", line 33, in <module>
sys.exit(load_entry_point('FontCollector==2.0.2', 'console_scripts', 'fontcollector')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\__main__.py", line 25, in main
font_collection = FontLoader(additional_fonts, use_system_font).fonts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\font_loader.py", line 29, in __init__
self.additional_fonts = FontLoader.load_additional_fonts(additional_fonts_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\xyz\scoop\apps\Python\current\Lib\site-packages\font_collector\font_loader.py", line 120, in load_additional_fonts
if os.path.isfile(font_path):
^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen genericpath>", line 30, in isfile
TypeError: stat: path should be string, bytes, os.PathLike or integer, not Font
\r and \fn can match to string when it should not.
Example:
The \r will match with the r of the tag \frz
{\frz0\alpha&H00&\fn123marker\blur0.5\fscx37\fscy34\pos(963.28,788.5)\c&H071B1E&\3c&H071B1E&}tooth{\clip(m 962 761 l 961 773 961 782 962 793 997 790 997 765)}
fontcollector -i "01.ass"
ERROR - An unknown error occurred while reading the font "C:\Windows\Fonts\bahnschrift.ttf"
Please open an issue on github, share the font and the following error message:
Traceback (most recent call last):
File "C:\Users\leah\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\leah\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "c:\users\leah\.local\bin\fontcollector.exe\__main__.py", line 7, in <module>
File "C:\Users\leah\.local\pipx\venvs\fontcollector\lib\site-packages\font_collector\__main__.py", line 26, in main
font_collection = FontLoader(additional_fonts, use_system_font).fonts
File "C:\Users\leah\.local\pipx\venvs\fontcollector\lib\site-packages\font_collector\font_loader.py", line 25, in __init__
self.system_fonts = FontLoader.load_system_fonts()
File "C:\Users\leah\.local\pipx\venvs\fontcollector\lib\site-packages\font_collector\font_loader.py", line 97, in load_system_fonts
system_fonts.update(Font.from_font_path(font_path))
File "C:\Users\leah\.local\pipx\venvs\fontcollector\lib\site-packages\font_collector\font.py", line 76, in from_font_path
axis_value_tables = FontParser.get_axis_value_from_coordinates(
File "C:\Users\leah\.local\pipx\venvs\fontcollector\lib\site-packages\font_collector\font_parser.py", line 157, in get_axis_value_from_coordinates
axisLimits = AxisLimits(coordinates).populateDefaults(font)
AttributeError: 'AxisLimits' object has no attribute 'populateDefaults'
When attempting to execute fontCollector, I encounter a traceback error. I have the most recent version of fontCollector (1.2.1), so not sure what's going wrong.
D:\Downloads\test>fontCollector -i "animorphs_01.ass" -o
Loaded successfully animorphs_01.ass
Matplotlib is building the font cache; this may take a moment.
Traceback (most recent call last):
File "C:\Users\Animorphs\AppData\Local\Programs\Python\Python39\Scripts\fontCollector-script.py", line 33, in <module>
sys.exit(load_entry_point('fontCollector==1.2.1', 'console_scripts', 'fontCollector')())
File "c:\users\animorphs\appdata\local\programs\python\python39\lib\site-packages\fontCollector.py", line 630, in main
fontCollection = initializeFontCollection(additionalFonts)
File "c:\users\animorphs\appdata\local\programs\python\python39\lib\site-packages\fontCollector.py", line 480, in initializeFontCollection
font = createFont(fontPath)
File "c:\users\animorphs\appdata\local\programs\python\python39\lib\site-packages\fontCollector.py", line 438, in createFont
isItalic = bool(fontTtLib["OS/2"].fsSelection & 1)
File "C:\Users\animorphs\AppData\Roaming\Python\Python39\site-packages\fontTools\ttLib\ttFont.py", line 362, in __getitem__
table = self._readTable(tag)
File "C:\Users\animorphs\AppData\Roaming\Python\Python39\site-packages\fontTools\ttLib\ttFont.py", line 369, in _readTable
data = self.reader[tag]
File "C:\Users\animorphs\AppData\Roaming\Python\Python39\site-packages\fontTools\ttLib\sfnt.py", line 105, in __getitem__
entry = self.tables[Tag(tag)]
KeyError: 'OS/2'
I've also tried it with a very simple ass file just in case, which solely consists of the following, but the same error occurs:
[Script Info]
; Script generated by Aegisub 9213, Daydream Cafe Edition [Shinon]
; http://www.aegisub.org/
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.709
[Aegisub Project Garbage]
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Gandhi Sans,74,&H00FFFFFF,&H000000FF,&H00000000,&HA0000000,-1,0,0,0,100,100,0,0,1,3.6,1.5,2,180,180,56,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:05.00,0:00:10.00,Default,,0,0,0,,Test.
Any help is appreciated, thanks
VSFilter/GDI truncate font name to 31 characters.
Currently, Libass doesn't emulated this behaviour. See: libass/libass#459
Since it doesn't emulated it, this won't be implemente until libass does.
All the test I did was with this font: A-Farzian-2-Regular.zip
I rename the font with different name to see what name GDI would return me:
from fontTools.ttLib.ttFont import TTFont
font = TTFont("A-Farzian-2-Regular.ttf")
names = [
"a"*30 + "😋"
"a"*31 + "😋",
"a"*32,
"😋" * 20,
]
for name in names:
font["name"].setName(name, 1, 3, 1, 0x409)
font.save(f"{name}.TTF")
When running the script with a command:
fontCollector -i "test.ass"
, I get the following error:
ERROR - An unknown error occurred while reading the font "C:\USERS\BEGIJ\FONTBASE\FONTS\MY COLLECTION\BOXED_IN1.TTF"
.
If I remove this specific font, script finishes successfully. I'm on Windows 11 and using 3.0.0c1 of Fontcollector.
I'm attaching this font and test file as a google drive link
Ass and Font
I have a root font folder that contains folders for each font family.
The --additional-fonts
option isn't recursive, so I have to pass a list of all the font family folders on the command line.
It would be very helpful if there was a --font-root
argument that would recursively search one (or more) folders for font files.
In the Install platform-specific requirements (Windows)
step, after installing mkvtoolnix
, you are attempting to run mkvpropedit -h
. The issue here is that the environment variables set or modified in one step are not automatically carried over to the next step.
To address this, you may need to persist the changes to the environment variables
Font example: https://mega.nz/file/S9ERDRpQ#bcPhS06kv-D5jt64aTNDbZVd6gZr6ZfJDYT91yYsoWk
When fontCollector.py decoded the fontName, it returns: f j000 3 1 0
Here is what Aegisub return: Fjイーマ310
Currently, I have no idea how to solve this problem. Here is the documentation about the naming table of fonttools: https://fonttools.readthedocs.io/en/latest/ttLib/tables/_n_a_m_e.html#fontTools.ttLib.tables._n_a_m_e.NameRecord
@matheousse contacted me.
He sent me this .ass and the font that are needed for the .ass file: Font + ass.zip
It take him 1 minute to collec the font which is way to slow.
Seems like FontCollector can't create folders on Windows. When I'm setting an output path to an not existing folder, I get an error. Would be nice if the program could create the named folder instead.
VSFilter can handle duplicate style name by adding an "id" AND if the style name is empty, it rename it to Default
.
FontCollector doesn't replicate this behavior.
Actually, it will even raise an exception: ValueError: Error: Unknown style "Default3" on line 1. You need to correct the .ass file.
Here is a .ass sample that cause problems
[Script Info]
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: None
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Raleway,35,&H00FFFFFF,&H000000FF,&H002C2C2C,&H00000000,-1,0,0,0,100,100,0,0,1,2.5,0,2,0,0,72,1
Style: Default,Jester,35,&H00FFFFFF,&H000000FF,&H002C2C2C,&H00000000,-1,0,0,0,100,100,0,0,1,2.5,0,2,0,0,72,1
Style: ,Arial,35,&H00FFFFFF,&H000000FF,&H002C2C2C,&H00000000,-1,1,0,0,100,100,0,0,1,2.5,0,2,0,0,72,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default3,,0,0,0,,Arial
When the user uninstall the program with pip uninstall FontCollector
, it won't clear the font cache.
To actually clear the cache, the user needs to call FontLoader.discard_system_font_cache() and FontLoader.discard_generated_font_cache().
It seems that it isn't possible to run custom code when the user do a pip uninstall FontCollector
. See Custom code on pip uninstall.
Because of that, I don't really know how I could clear the font cache on uninstall.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.