File: dump-cursive.py

package info (click to toggle)
python-fontfeatures 1.9.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,096 kB
  • sloc: python: 9,112; makefile: 22
file content (91 lines) | stat: -rw-r--r-- 3,004 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Parse a GPOS ttx dump and output a cursive attachment .fea
import xml.etree.cElementTree as et
from fontTools.feaLib.ast import *

tree = et.parse("cursive.xml")
doc = tree.getroot()
glyphs = [x.attrib["value"] for x in tree.findall("Coverage/Glyph")]
recs = tree.findall("EntryExitRecord")

droplist = []
poslist = []
for i,rec in enumerate(recs):
  entries = rec.findall("EntryAnchor")
  exits   = rec.findall("ExitAnchor")
  if len(entries) > 0:
    entryY = int(entries[0].find("YCoordinate").attrib["value"])
    entryX = int(entries[0].find("XCoordinate").attrib["value"])
    entryAnchor = Anchor(entryX, entryY)
  else:
    entryY = 0
    entryAnchor = Anchor(0,0,name="NULL")

  if len(exits) > 0:
    exitY = int(exits[0].find("YCoordinate").attrib["value"])
    exitX = int(exits[0].find("XCoordinate").attrib["value"])
    exitAnchor = Anchor(exitX, exitY)
  else:
    exitY = 0
    exitAnchor = Anchor(0,0,name="NULL")

  drop = entryY - exitY
  droplist.append((glyphs[i],drop))
  poslist.append(CursivePosStatement(GlyphName(glyphs[i]), entryAnchor, exitAnchor))

droplist = sorted(droplist, key = lambda x:x[1])

import numpy as np

def groupByDrop(droplist, classname, bincount=10):
  relevant = list(filter(lambda x: classname in x[0] , droplist))
  dropValues = [ x[1] for x in relevant ]
  edges = np.histogram_bin_edges(dropValues, bins = bincount)
  middles = list((edges[0:-1] + edges[1:] ) /2)
  groups = np.digitize(dropValues, edges) -1

  binnedGlyphs = {}
  for i,group in enumerate(groups):
    if not group in binnedGlyphs:
      binnedGlyphs[group] = []
    binnedGlyphs[group].append(relevant[i][0])
  middles.append(edges[-1])
  classes = []
  for k,v in binnedGlyphs.items():
    classes.append(GlyphClassDefinition("%s_%i" % (classname,k), GlyphClass(v)))
    classes.append(Comment("# average drop = %i\n" % middles[k]))

  return binnedGlyphs, middles, classes

binnedMeds, medMiddles, medClasses = groupByDrop(droplist, "Med")
for x in medClasses:
  print(x.asFea())
binnedInis, iniMiddles, iniClasses = groupByDrop(droplist, "Ini")
for x in iniClasses:
  print(x.asFea())

binnedFins, finMiddles, finClasses = groupByDrop(droplist, "Fin")
for x in finClasses:
  print(x.asFea())

print("feature curs {\n")
print("lookupflag IgnoreMarks;\n")
for x in poslist:
  print(x.asFea())
print("} curs;")

# print("feature kern {\n")
# print("lookupflag IgnoreMarks;\n")

# for i in binnedInis.keys():
#   for m1 in binnedMeds.keys():
#     for f in binnedFins.keys():
#       totalDrop = (iniMiddles[i] + medMiddles[m1] + finMiddles[f])
#       print("\tposition @Ini_%i' <0 %i 0 0> @Med_%i @Fin_%i;" % (i, totalDrop, m1,f))

# for i in binnedInis.keys():
#   for m1 in binnedMeds.keys():
#     for m2 in binnedMeds.keys():
#       for f in binnedFins.keys():
#         totalDrop = (iniMiddles[i] + medMiddles[m1] + medMiddles[m2] + finMiddles[f])
#         print("\tposition @Ini_%i' <0 %i 0 0> @Med_%i  @Med_%i  @Fin_%i;" % (i, totalDrop, m1,m2,f))
#   print("} kern;")