Edit fonts in Python

Introduction

I created a font called M + A1 in Python based on M + FONTS. (https://microraptor.booth.pm/items/2347968) I will explain the procedure to read and write fonts programmatically with the meaning of memorandum and missionary work.

--My environment

Thing you want to do

Since OTF (OpenType) cannot be read suddenly, write it in UFO (Unified Font Object) format and then read the file to create OTF.

What is a UFO? It will be, but it is not difficult. It's just an xml file. The control points of the Bezier curves that make up the font data are exported as xml.

OTF -> UFO Create a Font object with defcon and write it to OTF-> UFO with extractUFO.


import defcon
import extractor

IMPORT_FILE = r'C:\example\abc.otf'
EXPORT_FILE = r'C:\example\abc_ufo'
font = defcon.Font()
extractor.extractUFO(IMPORT_FILE, font)
font.save(EXPORT_FILE)

Exporting is done in a few seconds for Western typefaces and in a few minutes for Japanese typefaces.

Output result

lib.plist and contents.plist are similar files, so you can refer to either one. (Lib.plist does not have a font name and font file associated with each other, but the font name is also written in each .gilf. Contents.plist exists in a large number of .gilf, so it is troublesome to find it. I think it doesn't matter which one.)

UFO -> OTF

import os
import defcon
import ufo2ft
from xml.etree import ElementTree as ET

# Const
UFO_FILE = r'C:\example\abc_ufo'
GLIF_PATH = os.path.join(UFO_FILE, 'glyphs')

font = defcon.Font()

#Select the character to edit
glif_root = ET.parse(os.path.join(GLIF_PATH, 'a.glif'))
glyph = font.newGlyph('a')
glyph.unicode = int(glif_root.find('.//unicode').attrib['hex'], 16)
contour_list = glif_root.findall('.//contour')

#From glif file<contour>Subordinate<point>Read tags sequentially
for tag_contour in contour_list:
    contour = defcon.Contour()
    point_list = tag_contour.findall('./point')

    for k, v in enumerate(point_list):
        # <point>None if type is not defined in
        _type = v.attrib['type'] if 'type' in v.attrib else None
        #Set points
        contour.appendPoint(
            defcon.Point(
                (int(v.attrib['x']), int(v.attrib['y'])),
                segmentType=_type,
            )
        )
    #Set the contour for one lap
    glyph.appendContour(contour)

#Export to OTF
otf = ufo2ft.compileOTF(font)
otf.save('new_font.otf')

This will output a font file with only "a" set. You can create an original font by manipulating the path and then writing.

Reference / reference material

UFO Official: https://unifiedfontobject.org/ DEFCON : https://defcon.robotools.dev/en/latest/ https://qiita.com/irori/items/5518c242e0244838783b https://blog.hgrs.me/20190806022544 https://irori.github.io/wapuro-mincho/

Recommended Posts

Edit fonts in Python
Edit videos in Python using MoviePy
Quadtree in Python --2
Python in optimization
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python
Sorted list in Python
Daily AtCoder # 36 in Python
Daily AtCoder # 2 in Python
Implement Enigma in python
Daily AtCoder # 32 in Python
Daily AtCoder # 18 in Python
Singleton pattern in Python
File operations in Python
Read DXF in python
Daily AtCoder # 53 in Python
Key input in Python
Use config.ini in Python
Daily AtCoder # 33 in Python
Solve ABC168D in Python
Logistic distribution in Python
Daily AtCoder # 7 in Python
LU decomposition in Python