[OpenFontFormat] Add table order files
This commit is contained in:
		
							parent
							
								
									7d5c90bd17
								
							
						
					
					
						commit
						8fe052ed17
					
				
							
								
								
									
										3
									
								
								OpenFontFormat/table-order/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								OpenFontFormat/table-order/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
*.txt
 | 
			
		||||
*.svg
 | 
			
		||||
*.dot
 | 
			
		||||
							
								
								
									
										2
									
								
								OpenFontFormat/table-order/fonts.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2
									
								
								OpenFontFormat/table-order/fonts.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
find $1 -type f -name "*.tt[$2]"
 | 
			
		||||
# TODO: Parse other fonts that are not tt[fc]
 | 
			
		||||
							
								
								
									
										105
									
								
								OpenFontFormat/table-order/tables.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										105
									
								
								OpenFontFormat/table-order/tables.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
from os import system as run
 | 
			
		||||
import os
 | 
			
		||||
from subprocess import check_output as run_and_read
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Dict, Set
 | 
			
		||||
 | 
			
		||||
def get_vendor(file: str) -> str:
 | 
			
		||||
	command = f"otfinfo -i {file} | grep 'Vendor ID' | awk '{{print $3}}'"
 | 
			
		||||
	return run_and_read(command, shell=True).decode(encoding='ascii').rstrip('\n')
 | 
			
		||||
 | 
			
		||||
def get_tables(file: str) -> list[str]:
 | 
			
		||||
	command = f"otfinfo -t {file} | awk '{{print $2}}'"
 | 
			
		||||
	return run_and_read(command, shell=True).decode(encoding='ascii').rstrip('\n').split('\n')
 | 
			
		||||
 | 
			
		||||
FILENAME = os.path.join(os.path.dirname(__file__), "tables")
 | 
			
		||||
 | 
			
		||||
graph: Dict[str, Set[str]] = {}
 | 
			
		||||
 | 
			
		||||
def verify_node(tag: str):
 | 
			
		||||
	if tag not in graph: graph[tag] = set()
 | 
			
		||||
 | 
			
		||||
def add_edge(tag1: str, tag2: str):
 | 
			
		||||
	verify_node(tag1)
 | 
			
		||||
	verify_node(tag2)
 | 
			
		||||
	graph[tag1].add(tag2)
 | 
			
		||||
 | 
			
		||||
MODE = None
 | 
			
		||||
if not sys.stdin.isatty():
 | 
			
		||||
	MODE = 'direct' if '--direct' in sys.argv else 'before'
 | 
			
		||||
	accumulator: Dict[tuple[str, str], int] = {} # acc[(tag1, tag2)] is number of times tag1 occured before tag2
 | 
			
		||||
	for file in sys.stdin:
 | 
			
		||||
		file = file.rstrip('\n')
 | 
			
		||||
		print(f"{get_vendor(file):<4} {file}")
 | 
			
		||||
		tables = get_tables(file)
 | 
			
		||||
 | 
			
		||||
		def add_to_acc(tag1: str, tag2: str):
 | 
			
		||||
			accumulator[(tag1, tag2)] = accumulator.get((tag1, tag2), 0)+1
 | 
			
		||||
		match MODE:
 | 
			
		||||
			case 'before':
 | 
			
		||||
				for i, tag1 in enumerate(tables):
 | 
			
		||||
					for tag2 in tables[i+1:]:
 | 
			
		||||
						add_to_acc(tag1, tag2)
 | 
			
		||||
			case 'direct':
 | 
			
		||||
				for i, tag1 in enumerate(tables[:-1]):
 | 
			
		||||
					tag2 = tables[i+1]
 | 
			
		||||
					add_to_acc(tag1, tag2)
 | 
			
		||||
			case _:
 | 
			
		||||
				assert False, f"Invalid mode: '{MODE}'"
 | 
			
		||||
 | 
			
		||||
	with open(f"{FILENAME}.txt", 'w') as f:
 | 
			
		||||
		f.write(f"mode: {MODE}\n")
 | 
			
		||||
		for (tag1, tag2) in accumulator:
 | 
			
		||||
			f.write(f"'{tag1:<4}', '{tag2:<4}', {accumulator[(tag1, tag2)]}\n")
 | 
			
		||||
 | 
			
		||||
	for (tag1, tag2) in accumulator: add_edge(tag1, tag2)
 | 
			
		||||
 | 
			
		||||
else:
 | 
			
		||||
	with open(f"{FILENAME}.txt", 'r') as f:
 | 
			
		||||
		for i, line in enumerate(f.readlines()):
 | 
			
		||||
			if i == 0:
 | 
			
		||||
				MODE = line[6:-1]
 | 
			
		||||
				continue
 | 
			
		||||
			tag1, tag2 = line[1:5], line[9:13]
 | 
			
		||||
			add_edge(tag1, tag2)
 | 
			
		||||
assert MODE, "Unreachable"
 | 
			
		||||
 | 
			
		||||
UNTRANSITIVITY = '--untrans' in sys.argv
 | 
			
		||||
def untransitivity():
 | 
			
		||||
	to_remove: Dict[str, Set[str]] = {tag: set() for tag in graph}
 | 
			
		||||
	for tag1 in graph:
 | 
			
		||||
		for tag2 in graph[tag1]:
 | 
			
		||||
			for tag3 in graph[tag2]:
 | 
			
		||||
				if tag3 in graph[tag1]: # find a->b, b->c where a->c
 | 
			
		||||
					to_remove[tag1].add(tag3)
 | 
			
		||||
 | 
			
		||||
	# to_remove = {
 | 
			
		||||
	# 	tag1: {tag3 for tag3 in graph[tag2] for tag2 in graph[tag1] if tag3 in graph[tag1]}
 | 
			
		||||
	# 	for tag1 in graph
 | 
			
		||||
	# }
 | 
			
		||||
 | 
			
		||||
	for tag1 in to_remove:
 | 
			
		||||
		for tag3 in to_remove[tag1]:
 | 
			
		||||
			graph[tag1].remove(tag3)
 | 
			
		||||
 | 
			
		||||
if UNTRANSITIVITY: untransitivity()
 | 
			
		||||
 | 
			
		||||
GENERATE = '--svg' in sys.argv
 | 
			
		||||
def generate_svg() -> int:
 | 
			
		||||
	def node_name(tag: str) -> str:
 | 
			
		||||
		return '"'+tag+'"'
 | 
			
		||||
 | 
			
		||||
	with open(f"{FILENAME}.dot", 'w') as f:
 | 
			
		||||
		f.write("digraph {\n")
 | 
			
		||||
		for node in graph:
 | 
			
		||||
			for neighbour in graph[node]:
 | 
			
		||||
				f.write(f"\t{node_name(node)} -> {node_name(neighbour)};\n")
 | 
			
		||||
		f.write("}")
 | 
			
		||||
 | 
			
		||||
	return run(f"dot -Tsvg {FILENAME}.dot > {FILENAME}.svg")
 | 
			
		||||
 | 
			
		||||
if GENERATE: generate_svg()
 | 
			
		||||
 | 
			
		||||
print(f"{MODE = }\n{UNTRANSITIVITY = }\n{GENERATE = }")
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user