Skip to content

Commit

Permalink
Correct variable font and loading font via cmd (#14)
Browse files Browse the repository at this point in the history
New feature:
- Convert legacy weight into "new" weight.

Corrected bugs:
- Families and fullname would use the same set.
- In very specific case, matplotlib.findSystemFonts can return non Font file.
- The font would be considered like a variable font if it contain an fvar table. That was false, it need to contain an fvar table AND a stat table to be considered like a variable font (resolve Option --additional-fonts doesn't work #13)
- Correct overloading fonts with --additional-fonts (resolve Option --additional-fonts doesn't work #13)
  • Loading branch information
moi15moi authored Jan 26, 2023
1 parent 8306fda commit 1493505
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 11 deletions.
2 changes: 1 addition & 1 deletion font_collector/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.0.2"
__version__ = "2.0.3"
8 changes: 3 additions & 5 deletions font_collector/font.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def from_font_path(cls, font_path: str) -> List["Font"]:
exact_names = set()

# If is Variable Font, else "normal" font
if is_var := "fvar" in ttFont:
if is_var := ("fvar" in ttFont and "STAT" in ttFont):

for instance in ttFont["fvar"].instances:
axis_value_tables = ParseFont.get_axis_value_from_coordinates(
Expand All @@ -84,9 +84,7 @@ def from_font_path(cls, font_path: str) -> List["Font"]:

else:
# From https://github.com/fonttools/fonttools/discussions/2619
isTrueType = False
if "glyf" in ttFont:
isTrueType = True
is_truetype = "glyf" in ttFont

families, fullnames = ParseFont.get_font_family_fullname_property(
ttFont["name"].names
Expand All @@ -105,7 +103,7 @@ def from_font_path(cls, font_path: str) -> List["Font"]:
)
continue

if isTrueType:
if is_truetype:
exact_names = fullnames
else:
# If not TrueType, it is OpenType
Expand Down
12 changes: 10 additions & 2 deletions font_collector/font_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ def load_system_fonts() -> Set[Font]:
# Add font that have been installed since last execution
added = fonts_paths.difference(cached_paths)
for font_path in added:
system_fonts.update(Font.from_font_path(font_path))
try:
system_fonts.update(Font.from_font_path(font_path))
except FileExistsError:
# matplotlib can sometimes returns file that aren't font: "C:\WINDOWS\Fonts\desktop.ini"
continue

# If there is a change, update the cache file
if len(added) > 0 or len(removed) > 0:
Expand All @@ -89,7 +93,11 @@ def load_system_fonts() -> Set[Font]:
else:
# Since there is no cache file, load the font
for font_path in fonts_paths:
system_fonts.update(Font.from_font_path(font_path))
try:
system_fonts.update(Font.from_font_path(font_path))
except FileExistsError:
# matplotlib can sometimes returns file that aren't font: "C:\WINDOWS\Fonts\desktop.ini"
continue

# Save the font into the cache file
with open(system_font_cache_file, "wb") as file:
Expand Down
4 changes: 2 additions & 2 deletions font_collector/parse_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def parse_arguments() -> Tuple[
Path,
Union[Path, None],
bool,
Set[Font],
Set[Path],
bool,
]:
"""
Expand Down Expand Up @@ -118,7 +118,7 @@ def parse_arguments() -> Tuple[
delete_fonts = args.delete_fonts

if args.additional_fonts is not None:
additional_fonts = FontLoader.load_additional_fonts(args.additional_fonts)
additional_fonts = args.additional_fonts
else:
additional_fonts = set()

Expand Down
23 changes: 22 additions & 1 deletion font_collector/parse_font.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,26 @@ def get_font_italic_bold_property_with_freetype(
font_path, font_index
)

# See https://github.com/libass/libass/pull/676
if weight == 1:
weight = 100
elif weight == 2:
weight = 200
elif weight == 3:
weight = 300
elif weight == 4:
weight = 350
elif weight == 5:
weight = 400
elif weight == 6:
weight = 600
elif weight == 7:
weight = 700
elif weight == 8:
weight = 800
elif weight == 9:
weight = 900

return is_italic, weight

@staticmethod
Expand All @@ -293,7 +313,8 @@ def get_font_family_fullname_property(

# https://github.com/libass/libass/blob/a2b39cde4ecb74d5e6fccab4a5f7d8ad52b2b1a4/libass/ass_fontselect.c#L258-L344
MAX = 100
families = fullnames = set()
families = set()
fullnames = set()

for name in names:

Expand Down
Binary file added tests/fonts/BRUSHSTP.TTF
Binary file not shown.
Binary file added tests/fonts/Cabin VF Beta Regular.ttf
Binary file not shown.
32 changes: 32 additions & 0 deletions tests/test_font.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import os
from font_collector import Font

dir_path = os.path.dirname(os.path.realpath(__file__))
font_without_os2_table = os.path.join(dir_path, "fonts", "BRUSHSTP.TTF")
font_without_stat_table = os.path.join(dir_path, "fonts", "Cabin VF Beta Regular.ttf")

def test_font_without_os2_table():

font = Font.from_font_path(font_without_os2_table)
assert len(font) == 1
font = font[0]

print(font)

assert font.family_names == set(["brushstroke plain"])
assert font.weight == 400
assert font.italic == False
assert font.exact_names == set()
assert font.is_var == False

def test_font_with_fvar_table_but_without_stat_table():

font = Font.from_font_path(font_without_stat_table)
assert len(font) == 1
font = font[0]

assert font.family_names == set(["cabin vf beta"])
assert font.weight == 400
assert font.italic == False
assert font.exact_names == set(["cabin vf beta regular"])
assert font.is_var == False

0 comments on commit 1493505

Please sign in to comment.