Export font.ttf to svg and Import svg to font.ttf

install fontforge and python

sudo apt install fontforge python3-fontforge
sudo apt install python3 python3-pip python3-venv -y
Copied!

export.py

#!/usr/bin/env python3
import fontforge
import os
import sys

# Usage check
if len(sys.argv) < 2:
    print("Usage: python3 export.py <fontfile.ttf> [output_dir]")
    sys.exit(1)

# Path to font file
font_path = sys.argv[1]

# Output directory (default = ./svg)
output_dir = sys.argv[2] if len(sys.argv) > 2 else "./svg"
os.makedirs(output_dir, exist_ok=True)

# Open the font
font = fontforge.open(font_path)

# Export glyphs
for glyph in font.glyphs():
    if glyph.isWorthOutputting():
        export_path = os.path.join(output_dir, f"{glyph.glyphname}.svg")
        glyph.export(export_path)
        print(f"Exported: {export_path}")

font.close()
print("✅ All glyphs exported successfully.")
Copied!

import.py

#!/usr/bin/env fontforge
import fontforge
import os
import sys

# Usage check
if len(sys.argv) < 4:
    print("Usage: fontforge -script export.py <fontfile.ttf> <svg_dir> <output_file.(ttf|sfd)>")
    sys.exit(1)

# Dynamic paths from command line
font_path = sys.argv[1]
svg_dir = sys.argv[2]
output_file = sys.argv[3]

try:
    # Open the base font
    font = fontforge.open(font_path)
    print("✓ Font opened successfully")
    print("Font name:", font.fontname)

    # Collect all SVG files
    svg_files = [f for f in os.listdir(svg_dir) if f.endswith(".svg")]
    if not svg_files:
        print("✗ No SVG files found in", svg_dir)

    # Process each SVG
    for svg_file in svg_files:
        test_svg = os.path.join(svg_dir, svg_file)
        print(f"\nImporting {svg_file}...")

        if not os.path.exists(test_svg):
            print(f"✗ File not found: {test_svg}")
            continue

        expected_glyph_name = svg_file[:-4]
        if not expected_glyph_name.strip():
            print(f"✗ Invalid glyph name from file: {svg_file}")
            continue

        print(f"Looking for glyph: {expected_glyph_name}")

        glyph = None
        if expected_glyph_name.startswith("uni"):
            parts = expected_glyph_name.split('_')
            try:
                if len(parts) == 1 and '.' not in expected_glyph_name:
                    codepoint = int(parts[0][3:], 16)
                    glyph = font[codepoint]
                    print(f"✓ Found base glyph: {glyph.glyphname} (U+{glyph.unicode:04X})")
                else:
                    if expected_glyph_name not in [g.glyphname for g in font.glyphs()]:
                        glyph = font.createChar(-1, expected_glyph_name)
                        print(f"✓ Created new glyph: {expected_glyph_name}")
                    else:
                        glyph = font[expected_glyph_name]
                        print(f"✓ Found existing glyph: {expected_glyph_name}")
            except Exception:
                pass
        else:
            try:
                glyph = font[expected_glyph_name]
            except Exception:
                pass

        if glyph is None:
            print(f"✗ Glyph '{expected_glyph_name}' not found or created")
            continue

        print("  Before import bounding box:", glyph.boundingBox())

        # Save metrics
        original_width = glyph.width
        original_left_bearing = glyph.left_side_bearing
        original_right_bearing = glyph.right_side_bearing

        glyph.clear()
        try:
            glyph.importOutlines(test_svg)
            glyph.round()

            # Restore metrics
            glyph.width = original_width
            glyph.left_side_bearing = original_left_bearing
            glyph.right_side_bearing = original_right_bearing

            print("  After import bounding box:", glyph.boundingBox())
            print("✓ SVG import completed with spacing preserved")
        except Exception as e:
            print(f"✗ Error importing {svg_file}: {e}")

    # Generate output font (TTF or SFD depending on extension)
    print(f"\nGenerating font: {output_file}")
    if output_file.lower().endswith(".ttf"):
        font.generate(output_file, flags=("opentype", "dummy-dsig"))
    elif output_file.lower().endswith(".sfd"):
        font.save(output_file)
    else:
        print("✗ Unsupported output format. Use .ttf or .sfd")
        sys.exit(1)

    print("✓ Font saved as:", output_file)

    if os.path.exists(output_file):
        size = os.path.getsize(output_file)
        print(f"✓ Output file exists, size: {size} bytes")
    else:
        print("✗ Output file was not created!")

    font.close()

except Exception as e:
    print("Error:", e)
    import traceback
    traceback.print_exc()

print("✅ All glyphs import successfully.")
Copied!

feature.py

#!/usr/bin/env python3
import fontforge
import os
import sys

def import_features(font_path, fea_path, output_file):
    try:
        # Normalize output path (absolute)
        output_file = os.path.abspath(output_file)
        output_dir = os.path.dirname(output_file)

        # Ensure output directory exists
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir, exist_ok=True)
            print(f"✓ Created directory: {output_dir}")

        # Open font
        font = fontforge.open(font_path)
        print(f"✓ Opened font: {font.fontname}")

        # Import features
        font.mergeFeature(fea_path)
        print(f"✓ Features merged from {fea_path}")

        # Save
        if output_file.lower().endswith(".ttf"):
            font.generate(output_file, flags=("opentype", "dummy-dsig"))
        elif output_file.lower().endswith(".sfd"):
            font.save(output_file)
        else:
            print("✗ Unsupported output format. Use .ttf or .sfd")
            return

        print(f"✓ New font generated: {output_file}")
        font.close()

    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    if len(sys.argv) < 4:
        print("Usage: python3 feature.py <fontfile.ttf|sfd> <features.fea> <outputfile.ttf|sfd>")
        sys.exit(1)

    font_path = sys.argv[1]
    fea_path = sys.argv[2]
    output_file = sys.argv[3]

    import_features(font_path, fea_path, output_file)

print("✅ All glyphs feature export successfully.")
Copied!

.sfd to .ttf

fontforge -lang=ff -c 'Open("name.sfd"); Generate("name.ttf");'
Copied!