fonttools 4.55.6__cp311-cp311-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fonttools might be problematic. Click here for more details.

Files changed (329) hide show
  1. fontTools/__init__.py +8 -0
  2. fontTools/__main__.py +35 -0
  3. fontTools/afmLib.py +439 -0
  4. fontTools/agl.py +5233 -0
  5. fontTools/cffLib/CFF2ToCFF.py +203 -0
  6. fontTools/cffLib/CFFToCFF2.py +305 -0
  7. fontTools/cffLib/__init__.py +3659 -0
  8. fontTools/cffLib/specializer.py +924 -0
  9. fontTools/cffLib/transforms.py +490 -0
  10. fontTools/cffLib/width.py +210 -0
  11. fontTools/colorLib/__init__.py +0 -0
  12. fontTools/colorLib/builder.py +664 -0
  13. fontTools/colorLib/errors.py +2 -0
  14. fontTools/colorLib/geometry.py +143 -0
  15. fontTools/colorLib/table_builder.py +223 -0
  16. fontTools/colorLib/unbuilder.py +81 -0
  17. fontTools/config/__init__.py +75 -0
  18. fontTools/cu2qu/__init__.py +15 -0
  19. fontTools/cu2qu/__main__.py +6 -0
  20. fontTools/cu2qu/benchmark.py +54 -0
  21. fontTools/cu2qu/cli.py +198 -0
  22. fontTools/cu2qu/cu2qu.c +14829 -0
  23. fontTools/cu2qu/cu2qu.cpython-311-x86_64-linux-musl.so +0 -0
  24. fontTools/cu2qu/cu2qu.py +531 -0
  25. fontTools/cu2qu/errors.py +77 -0
  26. fontTools/cu2qu/ufo.py +349 -0
  27. fontTools/designspaceLib/__init__.py +3338 -0
  28. fontTools/designspaceLib/__main__.py +6 -0
  29. fontTools/designspaceLib/split.py +475 -0
  30. fontTools/designspaceLib/statNames.py +253 -0
  31. fontTools/designspaceLib/types.py +147 -0
  32. fontTools/encodings/MacRoman.py +258 -0
  33. fontTools/encodings/StandardEncoding.py +258 -0
  34. fontTools/encodings/__init__.py +1 -0
  35. fontTools/encodings/codecs.py +135 -0
  36. fontTools/feaLib/__init__.py +4 -0
  37. fontTools/feaLib/__main__.py +78 -0
  38. fontTools/feaLib/ast.py +2134 -0
  39. fontTools/feaLib/builder.py +1747 -0
  40. fontTools/feaLib/error.py +22 -0
  41. fontTools/feaLib/lexer.c +17986 -0
  42. fontTools/feaLib/lexer.cpython-311-x86_64-linux-musl.so +0 -0
  43. fontTools/feaLib/lexer.py +287 -0
  44. fontTools/feaLib/location.py +12 -0
  45. fontTools/feaLib/lookupDebugInfo.py +12 -0
  46. fontTools/feaLib/parser.py +2359 -0
  47. fontTools/feaLib/variableScalar.py +113 -0
  48. fontTools/fontBuilder.py +1008 -0
  49. fontTools/help.py +36 -0
  50. fontTools/merge/__init__.py +248 -0
  51. fontTools/merge/__main__.py +6 -0
  52. fontTools/merge/base.py +81 -0
  53. fontTools/merge/cmap.py +141 -0
  54. fontTools/merge/layout.py +526 -0
  55. fontTools/merge/options.py +85 -0
  56. fontTools/merge/tables.py +341 -0
  57. fontTools/merge/unicode.py +78 -0
  58. fontTools/merge/util.py +143 -0
  59. fontTools/misc/__init__.py +1 -0
  60. fontTools/misc/arrayTools.py +424 -0
  61. fontTools/misc/bezierTools.c +41831 -0
  62. fontTools/misc/bezierTools.cpython-311-x86_64-linux-musl.so +0 -0
  63. fontTools/misc/bezierTools.py +1497 -0
  64. fontTools/misc/classifyTools.py +170 -0
  65. fontTools/misc/cliTools.py +53 -0
  66. fontTools/misc/configTools.py +349 -0
  67. fontTools/misc/cython.py +27 -0
  68. fontTools/misc/dictTools.py +83 -0
  69. fontTools/misc/eexec.py +119 -0
  70. fontTools/misc/encodingTools.py +72 -0
  71. fontTools/misc/etree.py +479 -0
  72. fontTools/misc/filenames.py +245 -0
  73. fontTools/misc/fixedTools.py +253 -0
  74. fontTools/misc/intTools.py +25 -0
  75. fontTools/misc/iterTools.py +12 -0
  76. fontTools/misc/lazyTools.py +42 -0
  77. fontTools/misc/loggingTools.py +543 -0
  78. fontTools/misc/macCreatorType.py +56 -0
  79. fontTools/misc/macRes.py +261 -0
  80. fontTools/misc/plistlib/__init__.py +681 -0
  81. fontTools/misc/plistlib/py.typed +0 -0
  82. fontTools/misc/psCharStrings.py +1496 -0
  83. fontTools/misc/psLib.py +398 -0
  84. fontTools/misc/psOperators.py +572 -0
  85. fontTools/misc/py23.py +96 -0
  86. fontTools/misc/roundTools.py +110 -0
  87. fontTools/misc/sstruct.py +231 -0
  88. fontTools/misc/symfont.py +244 -0
  89. fontTools/misc/testTools.py +229 -0
  90. fontTools/misc/textTools.py +154 -0
  91. fontTools/misc/timeTools.py +88 -0
  92. fontTools/misc/transform.py +516 -0
  93. fontTools/misc/treeTools.py +45 -0
  94. fontTools/misc/vector.py +147 -0
  95. fontTools/misc/visitor.py +142 -0
  96. fontTools/misc/xmlReader.py +188 -0
  97. fontTools/misc/xmlWriter.py +204 -0
  98. fontTools/mtiLib/__init__.py +1402 -0
  99. fontTools/mtiLib/__main__.py +5 -0
  100. fontTools/otlLib/__init__.py +1 -0
  101. fontTools/otlLib/builder.py +3221 -0
  102. fontTools/otlLib/error.py +11 -0
  103. fontTools/otlLib/maxContextCalc.py +96 -0
  104. fontTools/otlLib/optimize/__init__.py +53 -0
  105. fontTools/otlLib/optimize/__main__.py +6 -0
  106. fontTools/otlLib/optimize/gpos.py +453 -0
  107. fontTools/pens/__init__.py +1 -0
  108. fontTools/pens/areaPen.py +52 -0
  109. fontTools/pens/basePen.py +475 -0
  110. fontTools/pens/boundsPen.py +98 -0
  111. fontTools/pens/cairoPen.py +26 -0
  112. fontTools/pens/cocoaPen.py +26 -0
  113. fontTools/pens/cu2quPen.py +325 -0
  114. fontTools/pens/explicitClosingLinePen.py +101 -0
  115. fontTools/pens/filterPen.py +241 -0
  116. fontTools/pens/freetypePen.py +462 -0
  117. fontTools/pens/hashPointPen.py +89 -0
  118. fontTools/pens/momentsPen.c +13448 -0
  119. fontTools/pens/momentsPen.cpython-311-x86_64-linux-musl.so +0 -0
  120. fontTools/pens/momentsPen.py +879 -0
  121. fontTools/pens/perimeterPen.py +69 -0
  122. fontTools/pens/pointInsidePen.py +192 -0
  123. fontTools/pens/pointPen.py +600 -0
  124. fontTools/pens/qtPen.py +29 -0
  125. fontTools/pens/qu2cuPen.py +105 -0
  126. fontTools/pens/quartzPen.py +43 -0
  127. fontTools/pens/recordingPen.py +335 -0
  128. fontTools/pens/reportLabPen.py +79 -0
  129. fontTools/pens/reverseContourPen.py +96 -0
  130. fontTools/pens/roundingPen.py +130 -0
  131. fontTools/pens/statisticsPen.py +312 -0
  132. fontTools/pens/svgPathPen.py +310 -0
  133. fontTools/pens/t2CharStringPen.py +68 -0
  134. fontTools/pens/teePen.py +55 -0
  135. fontTools/pens/transformPen.py +115 -0
  136. fontTools/pens/ttGlyphPen.py +335 -0
  137. fontTools/pens/wxPen.py +29 -0
  138. fontTools/qu2cu/__init__.py +15 -0
  139. fontTools/qu2cu/__main__.py +7 -0
  140. fontTools/qu2cu/benchmark.py +56 -0
  141. fontTools/qu2cu/cli.py +125 -0
  142. fontTools/qu2cu/qu2cu.c +16269 -0
  143. fontTools/qu2cu/qu2cu.cpython-311-x86_64-linux-musl.so +0 -0
  144. fontTools/qu2cu/qu2cu.py +405 -0
  145. fontTools/subset/__init__.py +3838 -0
  146. fontTools/subset/__main__.py +6 -0
  147. fontTools/subset/cff.py +184 -0
  148. fontTools/subset/svg.py +253 -0
  149. fontTools/subset/util.py +25 -0
  150. fontTools/svgLib/__init__.py +3 -0
  151. fontTools/svgLib/path/__init__.py +65 -0
  152. fontTools/svgLib/path/arc.py +154 -0
  153. fontTools/svgLib/path/parser.py +322 -0
  154. fontTools/svgLib/path/shapes.py +183 -0
  155. fontTools/t1Lib/__init__.py +648 -0
  156. fontTools/tfmLib.py +460 -0
  157. fontTools/ttLib/__init__.py +26 -0
  158. fontTools/ttLib/__main__.py +109 -0
  159. fontTools/ttLib/macUtils.py +54 -0
  160. fontTools/ttLib/removeOverlaps.py +393 -0
  161. fontTools/ttLib/reorderGlyphs.py +284 -0
  162. fontTools/ttLib/scaleUpem.py +436 -0
  163. fontTools/ttLib/sfnt.py +662 -0
  164. fontTools/ttLib/standardGlyphOrder.py +271 -0
  165. fontTools/ttLib/tables/B_A_S_E_.py +14 -0
  166. fontTools/ttLib/tables/BitmapGlyphMetrics.py +64 -0
  167. fontTools/ttLib/tables/C_B_D_T_.py +113 -0
  168. fontTools/ttLib/tables/C_B_L_C_.py +19 -0
  169. fontTools/ttLib/tables/C_F_F_.py +61 -0
  170. fontTools/ttLib/tables/C_F_F__2.py +26 -0
  171. fontTools/ttLib/tables/C_O_L_R_.py +165 -0
  172. fontTools/ttLib/tables/C_P_A_L_.py +305 -0
  173. fontTools/ttLib/tables/D_S_I_G_.py +158 -0
  174. fontTools/ttLib/tables/D__e_b_g.py +17 -0
  175. fontTools/ttLib/tables/DefaultTable.py +49 -0
  176. fontTools/ttLib/tables/E_B_D_T_.py +835 -0
  177. fontTools/ttLib/tables/E_B_L_C_.py +718 -0
  178. fontTools/ttLib/tables/F_F_T_M_.py +52 -0
  179. fontTools/ttLib/tables/F__e_a_t.py +149 -0
  180. fontTools/ttLib/tables/G_D_E_F_.py +13 -0
  181. fontTools/ttLib/tables/G_M_A_P_.py +148 -0
  182. fontTools/ttLib/tables/G_P_K_G_.py +133 -0
  183. fontTools/ttLib/tables/G_P_O_S_.py +14 -0
  184. fontTools/ttLib/tables/G_S_U_B_.py +13 -0
  185. fontTools/ttLib/tables/G__l_a_t.py +235 -0
  186. fontTools/ttLib/tables/G__l_o_c.py +85 -0
  187. fontTools/ttLib/tables/H_V_A_R_.py +13 -0
  188. fontTools/ttLib/tables/J_S_T_F_.py +13 -0
  189. fontTools/ttLib/tables/L_T_S_H_.py +58 -0
  190. fontTools/ttLib/tables/M_A_T_H_.py +13 -0
  191. fontTools/ttLib/tables/M_E_T_A_.py +352 -0
  192. fontTools/ttLib/tables/M_V_A_R_.py +13 -0
  193. fontTools/ttLib/tables/O_S_2f_2.py +752 -0
  194. fontTools/ttLib/tables/S_I_N_G_.py +99 -0
  195. fontTools/ttLib/tables/S_T_A_T_.py +15 -0
  196. fontTools/ttLib/tables/S_V_G_.py +223 -0
  197. fontTools/ttLib/tables/S__i_l_f.py +1040 -0
  198. fontTools/ttLib/tables/S__i_l_l.py +92 -0
  199. fontTools/ttLib/tables/T_S_I_B_.py +13 -0
  200. fontTools/ttLib/tables/T_S_I_C_.py +14 -0
  201. fontTools/ttLib/tables/T_S_I_D_.py +13 -0
  202. fontTools/ttLib/tables/T_S_I_J_.py +13 -0
  203. fontTools/ttLib/tables/T_S_I_P_.py +13 -0
  204. fontTools/ttLib/tables/T_S_I_S_.py +13 -0
  205. fontTools/ttLib/tables/T_S_I_V_.py +26 -0
  206. fontTools/ttLib/tables/T_S_I__0.py +59 -0
  207. fontTools/ttLib/tables/T_S_I__1.py +166 -0
  208. fontTools/ttLib/tables/T_S_I__2.py +17 -0
  209. fontTools/ttLib/tables/T_S_I__3.py +22 -0
  210. fontTools/ttLib/tables/T_S_I__5.py +49 -0
  211. fontTools/ttLib/tables/T_T_F_A_.py +14 -0
  212. fontTools/ttLib/tables/TupleVariation.py +884 -0
  213. fontTools/ttLib/tables/V_A_R_C_.py +12 -0
  214. fontTools/ttLib/tables/V_D_M_X_.py +249 -0
  215. fontTools/ttLib/tables/V_O_R_G_.py +165 -0
  216. fontTools/ttLib/tables/V_V_A_R_.py +13 -0
  217. fontTools/ttLib/tables/__init__.py +97 -0
  218. fontTools/ttLib/tables/_a_n_k_r.py +15 -0
  219. fontTools/ttLib/tables/_a_v_a_r.py +191 -0
  220. fontTools/ttLib/tables/_b_s_l_n.py +15 -0
  221. fontTools/ttLib/tables/_c_i_d_g.py +24 -0
  222. fontTools/ttLib/tables/_c_m_a_p.py +1578 -0
  223. fontTools/ttLib/tables/_c_v_a_r.py +94 -0
  224. fontTools/ttLib/tables/_c_v_t.py +55 -0
  225. fontTools/ttLib/tables/_f_e_a_t.py +15 -0
  226. fontTools/ttLib/tables/_f_p_g_m.py +60 -0
  227. fontTools/ttLib/tables/_f_v_a_r.py +261 -0
  228. fontTools/ttLib/tables/_g_a_s_p.py +63 -0
  229. fontTools/ttLib/tables/_g_c_i_d.py +13 -0
  230. fontTools/ttLib/tables/_g_l_y_f.py +2311 -0
  231. fontTools/ttLib/tables/_g_v_a_r.py +292 -0
  232. fontTools/ttLib/tables/_h_d_m_x.py +127 -0
  233. fontTools/ttLib/tables/_h_e_a_d.py +130 -0
  234. fontTools/ttLib/tables/_h_h_e_a.py +147 -0
  235. fontTools/ttLib/tables/_h_m_t_x.py +160 -0
  236. fontTools/ttLib/tables/_k_e_r_n.py +289 -0
  237. fontTools/ttLib/tables/_l_c_a_r.py +13 -0
  238. fontTools/ttLib/tables/_l_o_c_a.py +70 -0
  239. fontTools/ttLib/tables/_l_t_a_g.py +72 -0
  240. fontTools/ttLib/tables/_m_a_x_p.py +147 -0
  241. fontTools/ttLib/tables/_m_e_t_a.py +112 -0
  242. fontTools/ttLib/tables/_m_o_r_t.py +14 -0
  243. fontTools/ttLib/tables/_m_o_r_x.py +15 -0
  244. fontTools/ttLib/tables/_n_a_m_e.py +1237 -0
  245. fontTools/ttLib/tables/_o_p_b_d.py +14 -0
  246. fontTools/ttLib/tables/_p_o_s_t.py +317 -0
  247. fontTools/ttLib/tables/_p_r_e_p.py +16 -0
  248. fontTools/ttLib/tables/_p_r_o_p.py +12 -0
  249. fontTools/ttLib/tables/_s_b_i_x.py +129 -0
  250. fontTools/ttLib/tables/_t_r_a_k.py +332 -0
  251. fontTools/ttLib/tables/_v_h_e_a.py +139 -0
  252. fontTools/ttLib/tables/_v_m_t_x.py +19 -0
  253. fontTools/ttLib/tables/asciiTable.py +20 -0
  254. fontTools/ttLib/tables/grUtils.py +92 -0
  255. fontTools/ttLib/tables/otBase.py +1465 -0
  256. fontTools/ttLib/tables/otConverters.py +2065 -0
  257. fontTools/ttLib/tables/otData.py +6400 -0
  258. fontTools/ttLib/tables/otTables.py +2700 -0
  259. fontTools/ttLib/tables/otTraverse.py +162 -0
  260. fontTools/ttLib/tables/sbixGlyph.py +149 -0
  261. fontTools/ttLib/tables/sbixStrike.py +177 -0
  262. fontTools/ttLib/tables/table_API_readme.txt +91 -0
  263. fontTools/ttLib/tables/ttProgram.py +594 -0
  264. fontTools/ttLib/ttCollection.py +125 -0
  265. fontTools/ttLib/ttFont.py +1155 -0
  266. fontTools/ttLib/ttGlyphSet.py +500 -0
  267. fontTools/ttLib/ttVisitor.py +32 -0
  268. fontTools/ttLib/woff2.py +1683 -0
  269. fontTools/ttx.py +467 -0
  270. fontTools/ufoLib/__init__.py +2477 -0
  271. fontTools/ufoLib/converters.py +334 -0
  272. fontTools/ufoLib/errors.py +22 -0
  273. fontTools/ufoLib/etree.py +6 -0
  274. fontTools/ufoLib/filenames.py +291 -0
  275. fontTools/ufoLib/glifLib.py +2022 -0
  276. fontTools/ufoLib/kerning.py +91 -0
  277. fontTools/ufoLib/plistlib.py +47 -0
  278. fontTools/ufoLib/pointPen.py +6 -0
  279. fontTools/ufoLib/utils.py +76 -0
  280. fontTools/ufoLib/validators.py +1186 -0
  281. fontTools/unicode.py +50 -0
  282. fontTools/unicodedata/Blocks.py +802 -0
  283. fontTools/unicodedata/OTTags.py +50 -0
  284. fontTools/unicodedata/ScriptExtensions.py +806 -0
  285. fontTools/unicodedata/Scripts.py +3618 -0
  286. fontTools/unicodedata/__init__.py +298 -0
  287. fontTools/varLib/__init__.py +1511 -0
  288. fontTools/varLib/__main__.py +6 -0
  289. fontTools/varLib/avar.py +260 -0
  290. fontTools/varLib/avarPlanner.py +1004 -0
  291. fontTools/varLib/builder.py +215 -0
  292. fontTools/varLib/cff.py +631 -0
  293. fontTools/varLib/errors.py +219 -0
  294. fontTools/varLib/featureVars.py +689 -0
  295. fontTools/varLib/instancer/__init__.py +1937 -0
  296. fontTools/varLib/instancer/__main__.py +5 -0
  297. fontTools/varLib/instancer/featureVars.py +190 -0
  298. fontTools/varLib/instancer/names.py +388 -0
  299. fontTools/varLib/instancer/solver.py +309 -0
  300. fontTools/varLib/interpolatable.py +1209 -0
  301. fontTools/varLib/interpolatableHelpers.py +396 -0
  302. fontTools/varLib/interpolatablePlot.py +1269 -0
  303. fontTools/varLib/interpolatableTestContourOrder.py +82 -0
  304. fontTools/varLib/interpolatableTestStartingPoint.py +107 -0
  305. fontTools/varLib/interpolate_layout.py +124 -0
  306. fontTools/varLib/iup.c +19154 -0
  307. fontTools/varLib/iup.cpython-311-x86_64-linux-musl.so +0 -0
  308. fontTools/varLib/iup.py +490 -0
  309. fontTools/varLib/merger.py +1717 -0
  310. fontTools/varLib/models.py +642 -0
  311. fontTools/varLib/multiVarStore.py +253 -0
  312. fontTools/varLib/mutator.py +518 -0
  313. fontTools/varLib/mvar.py +40 -0
  314. fontTools/varLib/plot.py +238 -0
  315. fontTools/varLib/stat.py +149 -0
  316. fontTools/varLib/varStore.py +767 -0
  317. fontTools/voltLib/__init__.py +5 -0
  318. fontTools/voltLib/ast.py +448 -0
  319. fontTools/voltLib/error.py +12 -0
  320. fontTools/voltLib/lexer.py +99 -0
  321. fontTools/voltLib/parser.py +656 -0
  322. fontTools/voltLib/voltToFea.py +730 -0
  323. fonttools-4.55.6.data/data/share/man/man1/ttx.1 +225 -0
  324. fonttools-4.55.6.dist-info/LICENSE +21 -0
  325. fonttools-4.55.6.dist-info/METADATA +3413 -0
  326. fonttools-4.55.6.dist-info/RECORD +329 -0
  327. fonttools-4.55.6.dist-info/WHEEL +5 -0
  328. fonttools-4.55.6.dist-info/entry_points.txt +5 -0
  329. fonttools-4.55.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,5 @@
1
+ """fontTools.voltLib -- a package for dealing with Visual OpenType Layout Tool
2
+ (VOLT) files."""
3
+
4
+ # See
5
+ # http://www.microsoft.com/typography/VOLT.mspx
@@ -0,0 +1,448 @@
1
+ from fontTools.voltLib.error import VoltLibError
2
+ from typing import NamedTuple
3
+
4
+
5
+ class Pos(NamedTuple):
6
+ adv: int
7
+ dx: int
8
+ dy: int
9
+ adv_adjust_by: dict
10
+ dx_adjust_by: dict
11
+ dy_adjust_by: dict
12
+
13
+ def __str__(self):
14
+ res = " POS"
15
+ for attr in ("adv", "dx", "dy"):
16
+ value = getattr(self, attr)
17
+ if value is not None:
18
+ res += f" {attr.upper()} {value}"
19
+ adjust_by = getattr(self, f"{attr}_adjust_by", {})
20
+ for size, adjustment in adjust_by.items():
21
+ res += f" ADJUST_BY {adjustment} AT {size}"
22
+ res += " END_POS"
23
+ return res
24
+
25
+
26
+ class Element(object):
27
+ def __init__(self, location=None):
28
+ self.location = location
29
+
30
+ def build(self, builder):
31
+ pass
32
+
33
+ def __str__(self):
34
+ raise NotImplementedError
35
+
36
+
37
+ class Statement(Element):
38
+ pass
39
+
40
+
41
+ class Expression(Element):
42
+ pass
43
+
44
+
45
+ class VoltFile(Statement):
46
+ def __init__(self):
47
+ Statement.__init__(self, location=None)
48
+ self.statements = []
49
+
50
+ def build(self, builder):
51
+ for s in self.statements:
52
+ s.build(builder)
53
+
54
+ def __str__(self):
55
+ return "\n" + "\n".join(str(s) for s in self.statements) + " END\n"
56
+
57
+
58
+ class GlyphDefinition(Statement):
59
+ def __init__(self, name, gid, gunicode, gtype, components, location=None):
60
+ Statement.__init__(self, location)
61
+ self.name = name
62
+ self.id = gid
63
+ self.unicode = gunicode
64
+ self.type = gtype
65
+ self.components = components
66
+
67
+ def __str__(self):
68
+ res = f'DEF_GLYPH "{self.name}" ID {self.id}'
69
+ if self.unicode is not None:
70
+ if len(self.unicode) > 1:
71
+ unicodes = ",".join(f"U+{u:04X}" for u in self.unicode)
72
+ res += f' UNICODEVALUES "{unicodes}"'
73
+ else:
74
+ res += f" UNICODE {self.unicode[0]}"
75
+ if self.type is not None:
76
+ res += f" TYPE {self.type}"
77
+ if self.components is not None:
78
+ res += f" COMPONENTS {self.components}"
79
+ res += " END_GLYPH"
80
+ return res
81
+
82
+
83
+ class GroupDefinition(Statement):
84
+ def __init__(self, name, enum, location=None):
85
+ Statement.__init__(self, location)
86
+ self.name = name
87
+ self.enum = enum
88
+ self.glyphs_ = None
89
+
90
+ def glyphSet(self, groups=None):
91
+ if groups is not None and self.name in groups:
92
+ raise VoltLibError(
93
+ 'Group "%s" contains itself.' % (self.name), self.location
94
+ )
95
+ if self.glyphs_ is None:
96
+ if groups is None:
97
+ groups = set({self.name})
98
+ else:
99
+ groups.add(self.name)
100
+ self.glyphs_ = self.enum.glyphSet(groups)
101
+ return self.glyphs_
102
+
103
+ def __str__(self):
104
+ enum = self.enum and str(self.enum) or ""
105
+ return f'DEF_GROUP "{self.name}"\n{enum}\nEND_GROUP'
106
+
107
+
108
+ class GlyphName(Expression):
109
+ """A single glyph name, such as cedilla."""
110
+
111
+ def __init__(self, glyph, location=None):
112
+ Expression.__init__(self, location)
113
+ self.glyph = glyph
114
+
115
+ def glyphSet(self):
116
+ return (self.glyph,)
117
+
118
+ def __str__(self):
119
+ return f' GLYPH "{self.glyph}"'
120
+
121
+
122
+ class Enum(Expression):
123
+ """An enum"""
124
+
125
+ def __init__(self, enum, location=None):
126
+ Expression.__init__(self, location)
127
+ self.enum = enum
128
+
129
+ def __iter__(self):
130
+ for e in self.glyphSet():
131
+ yield e
132
+
133
+ def glyphSet(self, groups=None):
134
+ glyphs = []
135
+ for element in self.enum:
136
+ if isinstance(element, (GroupName, Enum)):
137
+ glyphs.extend(element.glyphSet(groups))
138
+ else:
139
+ glyphs.extend(element.glyphSet())
140
+ return tuple(glyphs)
141
+
142
+ def __str__(self):
143
+ enum = "".join(str(e) for e in self.enum)
144
+ return f" ENUM{enum} END_ENUM"
145
+
146
+
147
+ class GroupName(Expression):
148
+ """A glyph group"""
149
+
150
+ def __init__(self, group, parser, location=None):
151
+ Expression.__init__(self, location)
152
+ self.group = group
153
+ self.parser_ = parser
154
+
155
+ def glyphSet(self, groups=None):
156
+ group = self.parser_.resolve_group(self.group)
157
+ if group is not None:
158
+ self.glyphs_ = group.glyphSet(groups)
159
+ return self.glyphs_
160
+ else:
161
+ raise VoltLibError(
162
+ 'Group "%s" is used but undefined.' % (self.group), self.location
163
+ )
164
+
165
+ def __str__(self):
166
+ return f' GROUP "{self.group}"'
167
+
168
+
169
+ class Range(Expression):
170
+ """A glyph range"""
171
+
172
+ def __init__(self, start, end, parser, location=None):
173
+ Expression.__init__(self, location)
174
+ self.start = start
175
+ self.end = end
176
+ self.parser = parser
177
+
178
+ def glyphSet(self):
179
+ return tuple(self.parser.glyph_range(self.start, self.end))
180
+
181
+ def __str__(self):
182
+ return f' RANGE "{self.start}" TO "{self.end}"'
183
+
184
+
185
+ class ScriptDefinition(Statement):
186
+ def __init__(self, name, tag, langs, location=None):
187
+ Statement.__init__(self, location)
188
+ self.name = name
189
+ self.tag = tag
190
+ self.langs = langs
191
+
192
+ def __str__(self):
193
+ res = "DEF_SCRIPT"
194
+ if self.name is not None:
195
+ res += f' NAME "{self.name}"'
196
+ res += f' TAG "{self.tag}"\n\n'
197
+ for lang in self.langs:
198
+ res += f"{lang}"
199
+ res += "END_SCRIPT"
200
+ return res
201
+
202
+
203
+ class LangSysDefinition(Statement):
204
+ def __init__(self, name, tag, features, location=None):
205
+ Statement.__init__(self, location)
206
+ self.name = name
207
+ self.tag = tag
208
+ self.features = features
209
+
210
+ def __str__(self):
211
+ res = "DEF_LANGSYS"
212
+ if self.name is not None:
213
+ res += f' NAME "{self.name}"'
214
+ res += f' TAG "{self.tag}"\n\n'
215
+ for feature in self.features:
216
+ res += f"{feature}"
217
+ res += "END_LANGSYS\n"
218
+ return res
219
+
220
+
221
+ class FeatureDefinition(Statement):
222
+ def __init__(self, name, tag, lookups, location=None):
223
+ Statement.__init__(self, location)
224
+ self.name = name
225
+ self.tag = tag
226
+ self.lookups = lookups
227
+
228
+ def __str__(self):
229
+ res = f'DEF_FEATURE NAME "{self.name}" TAG "{self.tag}"\n'
230
+ res += " " + " ".join(f'LOOKUP "{l}"' for l in self.lookups) + "\n"
231
+ res += "END_FEATURE\n"
232
+ return res
233
+
234
+
235
+ class LookupDefinition(Statement):
236
+ def __init__(
237
+ self,
238
+ name,
239
+ process_base,
240
+ process_marks,
241
+ mark_glyph_set,
242
+ direction,
243
+ reversal,
244
+ comments,
245
+ context,
246
+ sub,
247
+ pos,
248
+ location=None,
249
+ ):
250
+ Statement.__init__(self, location)
251
+ self.name = name
252
+ self.process_base = process_base
253
+ self.process_marks = process_marks
254
+ self.mark_glyph_set = mark_glyph_set
255
+ self.direction = direction
256
+ self.reversal = reversal
257
+ self.comments = comments
258
+ self.context = context
259
+ self.sub = sub
260
+ self.pos = pos
261
+
262
+ def __str__(self):
263
+ res = f'DEF_LOOKUP "{self.name}"'
264
+ res += f' {self.process_base and "PROCESS_BASE" or "SKIP_BASE"}'
265
+ if self.process_marks:
266
+ res += " PROCESS_MARKS "
267
+ if self.mark_glyph_set:
268
+ res += f'MARK_GLYPH_SET "{self.mark_glyph_set}"'
269
+ elif isinstance(self.process_marks, str):
270
+ res += f'"{self.process_marks}"'
271
+ else:
272
+ res += "ALL"
273
+ else:
274
+ res += " SKIP_MARKS"
275
+ if self.direction is not None:
276
+ res += f" DIRECTION {self.direction}"
277
+ if self.reversal:
278
+ res += " REVERSAL"
279
+ if self.comments is not None:
280
+ comments = self.comments.replace("\n", r"\n")
281
+ res += f'\nCOMMENTS "{comments}"'
282
+ if self.context:
283
+ res += "\n" + "\n".join(str(c) for c in self.context)
284
+ else:
285
+ res += "\nIN_CONTEXT\nEND_CONTEXT"
286
+ if self.sub:
287
+ res += f"\n{self.sub}"
288
+ if self.pos:
289
+ res += f"\n{self.pos}"
290
+ return res
291
+
292
+
293
+ class SubstitutionDefinition(Statement):
294
+ def __init__(self, mapping, location=None):
295
+ Statement.__init__(self, location)
296
+ self.mapping = mapping
297
+
298
+ def __str__(self):
299
+ res = "AS_SUBSTITUTION\n"
300
+ for src, dst in self.mapping.items():
301
+ src = "".join(str(s) for s in src)
302
+ dst = "".join(str(d) for d in dst)
303
+ res += f"SUB{src}\nWITH{dst}\nEND_SUB\n"
304
+ res += "END_SUBSTITUTION"
305
+ return res
306
+
307
+
308
+ class SubstitutionSingleDefinition(SubstitutionDefinition):
309
+ pass
310
+
311
+
312
+ class SubstitutionMultipleDefinition(SubstitutionDefinition):
313
+ pass
314
+
315
+
316
+ class SubstitutionLigatureDefinition(SubstitutionDefinition):
317
+ pass
318
+
319
+
320
+ class SubstitutionReverseChainingSingleDefinition(SubstitutionDefinition):
321
+ pass
322
+
323
+
324
+ class PositionAttachDefinition(Statement):
325
+ def __init__(self, coverage, coverage_to, location=None):
326
+ Statement.__init__(self, location)
327
+ self.coverage = coverage
328
+ self.coverage_to = coverage_to
329
+
330
+ def __str__(self):
331
+ coverage = "".join(str(c) for c in self.coverage)
332
+ res = f"AS_POSITION\nATTACH{coverage}\nTO"
333
+ for coverage, anchor in self.coverage_to:
334
+ coverage = "".join(str(c) for c in coverage)
335
+ res += f'{coverage} AT ANCHOR "{anchor}"'
336
+ res += "\nEND_ATTACH\nEND_POSITION"
337
+ return res
338
+
339
+
340
+ class PositionAttachCursiveDefinition(Statement):
341
+ def __init__(self, coverages_exit, coverages_enter, location=None):
342
+ Statement.__init__(self, location)
343
+ self.coverages_exit = coverages_exit
344
+ self.coverages_enter = coverages_enter
345
+
346
+ def __str__(self):
347
+ res = "AS_POSITION\nATTACH_CURSIVE"
348
+ for coverage in self.coverages_exit:
349
+ coverage = "".join(str(c) for c in coverage)
350
+ res += f"\nEXIT {coverage}"
351
+ for coverage in self.coverages_enter:
352
+ coverage = "".join(str(c) for c in coverage)
353
+ res += f"\nENTER {coverage}"
354
+ res += "\nEND_ATTACH\nEND_POSITION"
355
+ return res
356
+
357
+
358
+ class PositionAdjustPairDefinition(Statement):
359
+ def __init__(self, coverages_1, coverages_2, adjust_pair, location=None):
360
+ Statement.__init__(self, location)
361
+ self.coverages_1 = coverages_1
362
+ self.coverages_2 = coverages_2
363
+ self.adjust_pair = adjust_pair
364
+
365
+ def __str__(self):
366
+ res = "AS_POSITION\nADJUST_PAIR\n"
367
+ for coverage in self.coverages_1:
368
+ coverage = " ".join(str(c) for c in coverage)
369
+ res += f" FIRST {coverage}"
370
+ res += "\n"
371
+ for coverage in self.coverages_2:
372
+ coverage = " ".join(str(c) for c in coverage)
373
+ res += f" SECOND {coverage}"
374
+ res += "\n"
375
+ for (id_1, id_2), (pos_1, pos_2) in self.adjust_pair.items():
376
+ res += f" {id_1} {id_2} BY{pos_1}{pos_2}\n"
377
+ res += "\nEND_ADJUST\nEND_POSITION"
378
+ return res
379
+
380
+
381
+ class PositionAdjustSingleDefinition(Statement):
382
+ def __init__(self, adjust_single, location=None):
383
+ Statement.__init__(self, location)
384
+ self.adjust_single = adjust_single
385
+
386
+ def __str__(self):
387
+ res = "AS_POSITION\nADJUST_SINGLE"
388
+ for coverage, pos in self.adjust_single:
389
+ coverage = "".join(str(c) for c in coverage)
390
+ res += f"{coverage} BY{pos}"
391
+ res += "\nEND_ADJUST\nEND_POSITION"
392
+ return res
393
+
394
+
395
+ class ContextDefinition(Statement):
396
+ def __init__(self, ex_or_in, left=None, right=None, location=None):
397
+ Statement.__init__(self, location)
398
+ self.ex_or_in = ex_or_in
399
+ self.left = left if left is not None else []
400
+ self.right = right if right is not None else []
401
+
402
+ def __str__(self):
403
+ res = self.ex_or_in + "\n"
404
+ for coverage in self.left:
405
+ coverage = "".join(str(c) for c in coverage)
406
+ res += f" LEFT{coverage}\n"
407
+ for coverage in self.right:
408
+ coverage = "".join(str(c) for c in coverage)
409
+ res += f" RIGHT{coverage}\n"
410
+ res += "END_CONTEXT"
411
+ return res
412
+
413
+
414
+ class AnchorDefinition(Statement):
415
+ def __init__(self, name, gid, glyph_name, component, locked, pos, location=None):
416
+ Statement.__init__(self, location)
417
+ self.name = name
418
+ self.gid = gid
419
+ self.glyph_name = glyph_name
420
+ self.component = component
421
+ self.locked = locked
422
+ self.pos = pos
423
+
424
+ def __str__(self):
425
+ locked = self.locked and " LOCKED" or ""
426
+ return (
427
+ f'DEF_ANCHOR "{self.name}"'
428
+ f" ON {self.gid}"
429
+ f" GLYPH {self.glyph_name}"
430
+ f" COMPONENT {self.component}"
431
+ f"{locked}"
432
+ f" AT {self.pos} END_ANCHOR"
433
+ )
434
+
435
+
436
+ class SettingDefinition(Statement):
437
+ def __init__(self, name, value, location=None):
438
+ Statement.__init__(self, location)
439
+ self.name = name
440
+ self.value = value
441
+
442
+ def __str__(self):
443
+ if self.value is True:
444
+ return f"{self.name}"
445
+ if isinstance(self.value, (tuple, list)):
446
+ value = " ".join(str(v) for v in self.value)
447
+ return f"{self.name} {value}"
448
+ return f"{self.name} {self.value}"
@@ -0,0 +1,12 @@
1
+ class VoltLibError(Exception):
2
+ def __init__(self, message, location):
3
+ Exception.__init__(self, message)
4
+ self.location = location
5
+
6
+ def __str__(self):
7
+ message = Exception.__str__(self)
8
+ if self.location:
9
+ path, line, column = self.location
10
+ return "%s:%d:%d: %s" % (path, line, column, message)
11
+ else:
12
+ return message
@@ -0,0 +1,99 @@
1
+ from fontTools.voltLib.error import VoltLibError
2
+
3
+
4
+ class Lexer(object):
5
+ NUMBER = "NUMBER"
6
+ STRING = "STRING"
7
+ NAME = "NAME"
8
+ NEWLINE = "NEWLINE"
9
+
10
+ CHAR_WHITESPACE_ = " \t"
11
+ CHAR_NEWLINE_ = "\r\n"
12
+ CHAR_DIGIT_ = "0123456789"
13
+ CHAR_UC_LETTER_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
14
+ CHAR_LC_LETTER_ = "abcdefghijklmnopqrstuvwxyz"
15
+ CHAR_UNDERSCORE_ = "_"
16
+ CHAR_PERIOD_ = "."
17
+ CHAR_NAME_START_ = (
18
+ CHAR_UC_LETTER_ + CHAR_LC_LETTER_ + CHAR_PERIOD_ + CHAR_UNDERSCORE_
19
+ )
20
+ CHAR_NAME_CONTINUATION_ = CHAR_NAME_START_ + CHAR_DIGIT_
21
+
22
+ def __init__(self, text, filename):
23
+ self.filename_ = filename
24
+ self.line_ = 1
25
+ self.pos_ = 0
26
+ self.line_start_ = 0
27
+ self.text_ = text
28
+ self.text_length_ = len(text)
29
+
30
+ def __iter__(self):
31
+ return self
32
+
33
+ def next(self): # Python 2
34
+ return self.__next__()
35
+
36
+ def __next__(self): # Python 3
37
+ while True:
38
+ token_type, token, location = self.next_()
39
+ if token_type not in {Lexer.NEWLINE}:
40
+ return (token_type, token, location)
41
+
42
+ def location_(self):
43
+ column = self.pos_ - self.line_start_ + 1
44
+ return (self.filename_ or "<volt>", self.line_, column)
45
+
46
+ def next_(self):
47
+ self.scan_over_(Lexer.CHAR_WHITESPACE_)
48
+ location = self.location_()
49
+ start = self.pos_
50
+ text = self.text_
51
+ limit = len(text)
52
+ if start >= limit:
53
+ raise StopIteration()
54
+ cur_char = text[start]
55
+ next_char = text[start + 1] if start + 1 < limit else None
56
+
57
+ if cur_char == "\n":
58
+ self.pos_ += 1
59
+ self.line_ += 1
60
+ self.line_start_ = self.pos_
61
+ return (Lexer.NEWLINE, None, location)
62
+ if cur_char == "\r":
63
+ self.pos_ += 2 if next_char == "\n" else 1
64
+ self.line_ += 1
65
+ self.line_start_ = self.pos_
66
+ return (Lexer.NEWLINE, None, location)
67
+ if cur_char == '"':
68
+ self.pos_ += 1
69
+ self.scan_until_('"\r\n')
70
+ if self.pos_ < self.text_length_ and self.text_[self.pos_] == '"':
71
+ self.pos_ += 1
72
+ return (Lexer.STRING, text[start + 1 : self.pos_ - 1], location)
73
+ else:
74
+ raise VoltLibError("Expected '\"' to terminate string", location)
75
+ if cur_char in Lexer.CHAR_NAME_START_:
76
+ self.pos_ += 1
77
+ self.scan_over_(Lexer.CHAR_NAME_CONTINUATION_)
78
+ token = text[start : self.pos_]
79
+ return (Lexer.NAME, token, location)
80
+ if cur_char in Lexer.CHAR_DIGIT_:
81
+ self.scan_over_(Lexer.CHAR_DIGIT_)
82
+ return (Lexer.NUMBER, int(text[start : self.pos_], 10), location)
83
+ if cur_char == "-" and next_char in Lexer.CHAR_DIGIT_:
84
+ self.pos_ += 1
85
+ self.scan_over_(Lexer.CHAR_DIGIT_)
86
+ return (Lexer.NUMBER, int(text[start : self.pos_], 10), location)
87
+ raise VoltLibError("Unexpected character: '%s'" % cur_char, location)
88
+
89
+ def scan_over_(self, valid):
90
+ p = self.pos_
91
+ while p < self.text_length_ and self.text_[p] in valid:
92
+ p += 1
93
+ self.pos_ = p
94
+
95
+ def scan_until_(self, stop_at):
96
+ p = self.pos_
97
+ while p < self.text_length_ and self.text_[p] not in stop_at:
98
+ p += 1
99
+ self.pos_ = p