-
Notifications
You must be signed in to change notification settings - Fork 19
Add support for font features and variants #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mattt
wants to merge
1
commit into
ManimCommunity:v0
Choose a base branch
from
mattt:mattt/font-features
base: v0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Here's an script you can use to generate example outputs: #!/usr/bin/env python3
"""
Focused test for numeral OpenType features in ManimPango.
"""
import manimpango
import os
def test_numeral_features():
"""Test various numeral-related OpenType features."""
print("=== Testing Numeral Features ===")
# Text with numbers that should show differences
numeral_text = "0123456789"
mixed_text = "Price: $1,234.56 (March 2023)"
numeral_features = {
"default": None,
"oldstyle": "onum=1", # Old-style/text figures
"lining": "lnum=1", # Lining figures
"tabular": "tnum=1", # Tabular (monospaced) figures
"proportional": "pnum=1", # Proportional figures
"tabular_oldstyle": "tnum=1, onum=1",
"tabular_lining": "tnum=1, lnum=1"
}
# Test fonts that are more likely to support numeral features
fonts_to_test = [
"Times New Roman",
"Georgia",
"SF Pro Text",
"Avenir",
]
for font in fonts_to_test:
print(f"\nTesting font: {font}")
for feature_name, features in numeral_features.items():
try:
filename = f"numerals_{font.replace(' ', '_').lower()}_{feature_name}.svg"
result = manimpango.MarkupUtils.text2svg(
text=mixed_text,
font=font,
slant="NORMAL",
weight="NORMAL",
size=48, # Large size to see differences clearly
_=None,
disable_liga=False,
file_name=filename,
START_X=10,
START_Y=60,
width=800,
height=100,
font_features=features
)
print(f" ✓ Created: {filename} ({feature_name})")
except Exception as e:
print(f" ✗ Error with {feature_name}: {e}")
# Also test pure numbers
try:
filename = f"pure_numbers_{font.replace(' ', '_').lower()}.svg"
result = manimpango.MarkupUtils.text2svg(
text=numeral_text,
font=font,
slant="NORMAL",
weight="NORMAL",
size=64,
_=None,
disable_liga=False,
file_name=filename,
START_X=10,
START_Y=80,
width=600,
height=120,
font_features="onum=1" # Test old-style figures
)
print(f" ✓ Created: {filename} (pure numbers with onum)")
except Exception as e:
print(f" ✗ Error with pure numbers: {e}")
def compare_numeral_files():
"""Compare file sizes and content for numeral features."""
print("\n=== Comparing Numeral Files ===")
# Get all numerals files
numeral_files = [f for f in os.listdir(".") if f.startswith("numerals_") and f.endswith(".svg")]
if not numeral_files:
print("No numeral files found to compare")
return
# Group by font
fonts = {}
for f in numeral_files:
parts = f.split("_")
if len(parts) >= 3:
font_key = "_".join(parts[1:-1]) # everything except 'numerals' and feature name
if font_key not in fonts:
fonts[font_key] = {}
feature = parts[-1].replace(".svg", "")
fonts[font_key][feature] = f
for font, files in fonts.items():
print(f"\nFont: {font}")
# Compare file sizes
file_sizes = {}
for feature, filename in files.items():
try:
size = os.path.getsize(filename)
file_sizes[feature] = size
print(f" {feature}: {size} bytes")
except:
print(f" {feature}: file not found")
# Look for size differences (indicating different rendering)
if len(file_sizes) > 1:
sizes = list(file_sizes.values())
if len(set(sizes)) > 1:
print(f" ✓ Size differences detected - features may be working!")
else:
print(f" ? All files same size - features may not be working")
def test_markup_numerals():
"""Test numeral features using markup."""
print("\n=== Testing Numerals in Markup ===")
markup_tests = [
("Default numbers", "Numbers: 0123456789"),
("Old-style figures", "<span font_features='onum=1'>Numbers: 0123456789</span>"),
("Tabular figures", "<span font_features='tnum=1'>123.45 678.90 234.56</span>"),
("Combined features", "<span font_features='onum=1, tnum=1'>Old+Tab: 0123456789</span>"),
]
for name, markup in markup_tests:
try:
# Validate markup first
error = manimpango.MarkupUtils.validate(markup)
if error:
print(f"✗ Markup error for '{name}': {error}")
continue
filename = f"markup_numerals_{name.replace(' ', '_').replace('+', '_').lower()}.svg"
result = manimpango.MarkupUtils.text2svg(
text=markup,
font="Times New Roman",
slant="NORMAL",
weight="NORMAL",
size=36,
_=None,
disable_liga=False,
file_name=filename,
START_X=10,
START_Y=50,
width=600,
height=80
)
print(f"✓ Created: {filename} ({name})")
except Exception as e:
print(f"✗ Error with '{name}': {e}")
def analyze_svg_numerals():
"""Analyze SVG content specifically for numeral differences."""
print("\n=== Analyzing SVG Numeral Content ===")
# Find files to compare
default_file = None
onum_file = None
for f in os.listdir("."):
if "numerals_times_new_roman_default.svg" in f:
default_file = f
elif "numerals_times_new_roman_oldstyle.svg" in f:
onum_file = f
if default_file and onum_file:
try:
with open(default_file, 'r') as f:
default_content = f.read()
with open(onum_file, 'r') as f:
onum_content = f.read()
# Look for differences in glyph usage
default_glyphs = set()
onum_glyphs = set()
# Extract glyph references
import re
glyph_pattern = r'xlink:href="#glyph-\d+-(\d+)"'
default_matches = re.findall(glyph_pattern, default_content)
onum_matches = re.findall(glyph_pattern, onum_content)
print(f"Default file glyphs used: {sorted(set(default_matches))}")
print(f"Old-style file glyphs used: {sorted(set(onum_matches))}")
if set(default_matches) != set(onum_matches):
print("✓ Different glyphs used - numeral features are working!")
else:
print("? Same glyphs used - numeral features may not be working")
# Check file sizes
default_size = len(default_content)
onum_size = len(onum_content)
print(f"File sizes: default={default_size}, oldstyle={onum_size}")
except Exception as e:
print(f"Error analyzing files: {e}")
else:
print("Could not find both default and oldstyle files to compare")
def main():
"""Run all numeral tests."""
print("ManimPango Numeral Features Test")
print("=" * 40)
try:
test_numeral_features()
test_markup_numerals()
compare_numeral_files()
analyze_svg_numerals()
print("\n" + "=" * 40)
print("Numeral test completed!")
print("Check the generated SVG files to see numeral differences.")
print("Look for files with 'oldstyle', 'tabular' variations.")
except Exception as e:
print(f"\nError running numeral tests: {e}")
if __name__ == "__main__":
main() |
3 tasks
Hi @matt, Thanks for your contribution. I'll take a look at this PR later today. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds support for OpenType Font features and font variants using Pango markup attributes.
For example, with the changes in this PR, I can now render proportional and tabular numerals:
Proportional figures (
pnum=1
;default
)Tabular / monospaced figures (
tnum=1
)