fonttools 4.58.3__cp310-cp310-manylinux2014_x86_64.manylinux_2_17_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 (334) 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 +3694 -0
  8. fontTools/cffLib/specializer.py +927 -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 +90 -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 +15545 -0
  23. fontTools/cu2qu/cu2qu.cpython-310-x86_64-linux-gnu.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 +260 -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 +2142 -0
  39. fontTools/feaLib/builder.py +1796 -0
  40. fontTools/feaLib/error.py +22 -0
  41. fontTools/feaLib/lexer.c +17336 -0
  42. fontTools/feaLib/lexer.cpython-310-x86_64-linux-gnu.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 +2379 -0
  47. fontTools/feaLib/variableScalar.py +113 -0
  48. fontTools/fontBuilder.py +1014 -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 +173 -0
  54. fontTools/merge/layout.py +526 -0
  55. fontTools/merge/options.py +85 -0
  56. fontTools/merge/tables.py +352 -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 +40136 -0
  62. fontTools/misc/bezierTools.cpython-310-x86_64-linux-gnu.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 +456 -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 +242 -0
  89. fontTools/misc/testTools.py +233 -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 +1400 -0
  99. fontTools/mtiLib/__main__.py +5 -0
  100. fontTools/otlLib/__init__.py +1 -0
  101. fontTools/otlLib/builder.py +3435 -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 +439 -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 +13459 -0
  119. fontTools/pens/momentsPen.cpython-310-x86_64-linux-gnu.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 +609 -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 +88 -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 +16738 -0
  143. fontTools/qu2cu/qu2cu.cpython-310-x86_64-linux-gnu.so +0 -0
  144. fontTools/qu2cu/qu2cu.py +405 -0
  145. fontTools/subset/__init__.py +3929 -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 +30 -0
  158. fontTools/ttLib/__main__.py +148 -0
  159. fontTools/ttLib/macUtils.py +54 -0
  160. fontTools/ttLib/removeOverlaps.py +393 -0
  161. fontTools/ttLib/reorderGlyphs.py +285 -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 +35 -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_V_A_R_.py +5 -0
  186. fontTools/ttLib/tables/G__l_a_t.py +235 -0
  187. fontTools/ttLib/tables/G__l_o_c.py +85 -0
  188. fontTools/ttLib/tables/H_V_A_R_.py +13 -0
  189. fontTools/ttLib/tables/J_S_T_F_.py +13 -0
  190. fontTools/ttLib/tables/L_T_S_H_.py +58 -0
  191. fontTools/ttLib/tables/M_A_T_H_.py +13 -0
  192. fontTools/ttLib/tables/M_E_T_A_.py +352 -0
  193. fontTools/ttLib/tables/M_V_A_R_.py +13 -0
  194. fontTools/ttLib/tables/O_S_2f_2.py +752 -0
  195. fontTools/ttLib/tables/S_I_N_G_.py +99 -0
  196. fontTools/ttLib/tables/S_T_A_T_.py +15 -0
  197. fontTools/ttLib/tables/S_V_G_.py +223 -0
  198. fontTools/ttLib/tables/S__i_l_f.py +1040 -0
  199. fontTools/ttLib/tables/S__i_l_l.py +92 -0
  200. fontTools/ttLib/tables/T_S_I_B_.py +13 -0
  201. fontTools/ttLib/tables/T_S_I_C_.py +14 -0
  202. fontTools/ttLib/tables/T_S_I_D_.py +13 -0
  203. fontTools/ttLib/tables/T_S_I_J_.py +13 -0
  204. fontTools/ttLib/tables/T_S_I_P_.py +13 -0
  205. fontTools/ttLib/tables/T_S_I_S_.py +13 -0
  206. fontTools/ttLib/tables/T_S_I_V_.py +26 -0
  207. fontTools/ttLib/tables/T_S_I__0.py +70 -0
  208. fontTools/ttLib/tables/T_S_I__1.py +166 -0
  209. fontTools/ttLib/tables/T_S_I__2.py +17 -0
  210. fontTools/ttLib/tables/T_S_I__3.py +22 -0
  211. fontTools/ttLib/tables/T_S_I__5.py +60 -0
  212. fontTools/ttLib/tables/T_T_F_A_.py +14 -0
  213. fontTools/ttLib/tables/TupleVariation.py +884 -0
  214. fontTools/ttLib/tables/V_A_R_C_.py +12 -0
  215. fontTools/ttLib/tables/V_D_M_X_.py +249 -0
  216. fontTools/ttLib/tables/V_O_R_G_.py +165 -0
  217. fontTools/ttLib/tables/V_V_A_R_.py +13 -0
  218. fontTools/ttLib/tables/__init__.py +98 -0
  219. fontTools/ttLib/tables/_a_n_k_r.py +15 -0
  220. fontTools/ttLib/tables/_a_v_a_r.py +191 -0
  221. fontTools/ttLib/tables/_b_s_l_n.py +15 -0
  222. fontTools/ttLib/tables/_c_i_d_g.py +24 -0
  223. fontTools/ttLib/tables/_c_m_a_p.py +1591 -0
  224. fontTools/ttLib/tables/_c_v_a_r.py +94 -0
  225. fontTools/ttLib/tables/_c_v_t.py +57 -0
  226. fontTools/ttLib/tables/_f_e_a_t.py +15 -0
  227. fontTools/ttLib/tables/_f_p_g_m.py +62 -0
  228. fontTools/ttLib/tables/_f_v_a_r.py +261 -0
  229. fontTools/ttLib/tables/_g_a_s_p.py +63 -0
  230. fontTools/ttLib/tables/_g_c_i_d.py +13 -0
  231. fontTools/ttLib/tables/_g_l_y_f.py +2312 -0
  232. fontTools/ttLib/tables/_g_v_a_r.py +337 -0
  233. fontTools/ttLib/tables/_h_d_m_x.py +127 -0
  234. fontTools/ttLib/tables/_h_e_a_d.py +130 -0
  235. fontTools/ttLib/tables/_h_h_e_a.py +147 -0
  236. fontTools/ttLib/tables/_h_m_t_x.py +160 -0
  237. fontTools/ttLib/tables/_k_e_r_n.py +289 -0
  238. fontTools/ttLib/tables/_l_c_a_r.py +13 -0
  239. fontTools/ttLib/tables/_l_o_c_a.py +70 -0
  240. fontTools/ttLib/tables/_l_t_a_g.py +72 -0
  241. fontTools/ttLib/tables/_m_a_x_p.py +147 -0
  242. fontTools/ttLib/tables/_m_e_t_a.py +112 -0
  243. fontTools/ttLib/tables/_m_o_r_t.py +14 -0
  244. fontTools/ttLib/tables/_m_o_r_x.py +15 -0
  245. fontTools/ttLib/tables/_n_a_m_e.py +1237 -0
  246. fontTools/ttLib/tables/_o_p_b_d.py +14 -0
  247. fontTools/ttLib/tables/_p_o_s_t.py +320 -0
  248. fontTools/ttLib/tables/_p_r_e_p.py +16 -0
  249. fontTools/ttLib/tables/_p_r_o_p.py +12 -0
  250. fontTools/ttLib/tables/_s_b_i_x.py +129 -0
  251. fontTools/ttLib/tables/_t_r_a_k.py +332 -0
  252. fontTools/ttLib/tables/_v_h_e_a.py +139 -0
  253. fontTools/ttLib/tables/_v_m_t_x.py +19 -0
  254. fontTools/ttLib/tables/asciiTable.py +20 -0
  255. fontTools/ttLib/tables/grUtils.py +92 -0
  256. fontTools/ttLib/tables/otBase.py +1466 -0
  257. fontTools/ttLib/tables/otConverters.py +2068 -0
  258. fontTools/ttLib/tables/otData.py +6400 -0
  259. fontTools/ttLib/tables/otTables.py +2708 -0
  260. fontTools/ttLib/tables/otTraverse.py +163 -0
  261. fontTools/ttLib/tables/sbixGlyph.py +149 -0
  262. fontTools/ttLib/tables/sbixStrike.py +177 -0
  263. fontTools/ttLib/tables/table_API_readme.txt +91 -0
  264. fontTools/ttLib/tables/ttProgram.py +594 -0
  265. fontTools/ttLib/ttCollection.py +125 -0
  266. fontTools/ttLib/ttFont.py +1157 -0
  267. fontTools/ttLib/ttGlyphSet.py +490 -0
  268. fontTools/ttLib/ttVisitor.py +32 -0
  269. fontTools/ttLib/woff2.py +1683 -0
  270. fontTools/ttx.py +479 -0
  271. fontTools/ufoLib/__init__.py +2477 -0
  272. fontTools/ufoLib/converters.py +398 -0
  273. fontTools/ufoLib/errors.py +30 -0
  274. fontTools/ufoLib/etree.py +6 -0
  275. fontTools/ufoLib/filenames.py +346 -0
  276. fontTools/ufoLib/glifLib.py +2029 -0
  277. fontTools/ufoLib/kerning.py +121 -0
  278. fontTools/ufoLib/plistlib.py +47 -0
  279. fontTools/ufoLib/pointPen.py +6 -0
  280. fontTools/ufoLib/utils.py +79 -0
  281. fontTools/ufoLib/validators.py +1186 -0
  282. fontTools/unicode.py +50 -0
  283. fontTools/unicodedata/Blocks.py +801 -0
  284. fontTools/unicodedata/Mirrored.py +446 -0
  285. fontTools/unicodedata/OTTags.py +50 -0
  286. fontTools/unicodedata/ScriptExtensions.py +826 -0
  287. fontTools/unicodedata/Scripts.py +3617 -0
  288. fontTools/unicodedata/__init__.py +302 -0
  289. fontTools/varLib/__init__.py +1517 -0
  290. fontTools/varLib/__main__.py +6 -0
  291. fontTools/varLib/avar.py +260 -0
  292. fontTools/varLib/avarPlanner.py +1004 -0
  293. fontTools/varLib/builder.py +215 -0
  294. fontTools/varLib/cff.py +631 -0
  295. fontTools/varLib/errors.py +219 -0
  296. fontTools/varLib/featureVars.py +695 -0
  297. fontTools/varLib/hvar.py +113 -0
  298. fontTools/varLib/instancer/__init__.py +1946 -0
  299. fontTools/varLib/instancer/__main__.py +5 -0
  300. fontTools/varLib/instancer/featureVars.py +190 -0
  301. fontTools/varLib/instancer/names.py +388 -0
  302. fontTools/varLib/instancer/solver.py +309 -0
  303. fontTools/varLib/interpolatable.py +1209 -0
  304. fontTools/varLib/interpolatableHelpers.py +396 -0
  305. fontTools/varLib/interpolatablePlot.py +1269 -0
  306. fontTools/varLib/interpolatableTestContourOrder.py +82 -0
  307. fontTools/varLib/interpolatableTestStartingPoint.py +107 -0
  308. fontTools/varLib/interpolate_layout.py +124 -0
  309. fontTools/varLib/iup.c +19830 -0
  310. fontTools/varLib/iup.cpython-310-x86_64-linux-gnu.so +0 -0
  311. fontTools/varLib/iup.py +490 -0
  312. fontTools/varLib/merger.py +1717 -0
  313. fontTools/varLib/models.py +642 -0
  314. fontTools/varLib/multiVarStore.py +253 -0
  315. fontTools/varLib/mutator.py +518 -0
  316. fontTools/varLib/mvar.py +40 -0
  317. fontTools/varLib/plot.py +238 -0
  318. fontTools/varLib/stat.py +149 -0
  319. fontTools/varLib/varStore.py +739 -0
  320. fontTools/voltLib/__init__.py +5 -0
  321. fontTools/voltLib/__main__.py +206 -0
  322. fontTools/voltLib/ast.py +452 -0
  323. fontTools/voltLib/error.py +12 -0
  324. fontTools/voltLib/lexer.py +99 -0
  325. fontTools/voltLib/parser.py +664 -0
  326. fontTools/voltLib/voltToFea.py +911 -0
  327. fonttools-4.58.3.data/data/share/man/man1/ttx.1 +225 -0
  328. fonttools-4.58.3.dist-info/METADATA +2133 -0
  329. fonttools-4.58.3.dist-info/RECORD +334 -0
  330. fonttools-4.58.3.dist-info/WHEEL +6 -0
  331. fonttools-4.58.3.dist-info/entry_points.txt +5 -0
  332. fonttools-4.58.3.dist-info/licenses/LICENSE +21 -0
  333. fonttools-4.58.3.dist-info/licenses/LICENSE.external +359 -0
  334. fonttools-4.58.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,142 @@
1
+ """Generic visitor pattern implementation for Python objects."""
2
+
3
+ import enum
4
+
5
+
6
+ class Visitor(object):
7
+ defaultStop = False
8
+
9
+ @classmethod
10
+ def _register(celf, clazzes_attrs):
11
+ assert celf != Visitor, "Subclass Visitor instead."
12
+ if "_visitors" not in celf.__dict__:
13
+ celf._visitors = {}
14
+
15
+ def wrapper(method):
16
+ assert method.__name__ == "visit"
17
+ for clazzes, attrs in clazzes_attrs:
18
+ if type(clazzes) != tuple:
19
+ clazzes = (clazzes,)
20
+ if type(attrs) == str:
21
+ attrs = (attrs,)
22
+ for clazz in clazzes:
23
+ _visitors = celf._visitors.setdefault(clazz, {})
24
+ for attr in attrs:
25
+ assert attr not in _visitors, (
26
+ "Oops, class '%s' has visitor function for '%s' defined already."
27
+ % (clazz.__name__, attr)
28
+ )
29
+ _visitors[attr] = method
30
+ return None
31
+
32
+ return wrapper
33
+
34
+ @classmethod
35
+ def register(celf, clazzes):
36
+ if type(clazzes) != tuple:
37
+ clazzes = (clazzes,)
38
+ return celf._register([(clazzes, (None,))])
39
+
40
+ @classmethod
41
+ def register_attr(celf, clazzes, attrs):
42
+ clazzes_attrs = []
43
+ if type(clazzes) != tuple:
44
+ clazzes = (clazzes,)
45
+ if type(attrs) == str:
46
+ attrs = (attrs,)
47
+ for clazz in clazzes:
48
+ clazzes_attrs.append((clazz, attrs))
49
+ return celf._register(clazzes_attrs)
50
+
51
+ @classmethod
52
+ def register_attrs(celf, clazzes_attrs):
53
+ return celf._register(clazzes_attrs)
54
+
55
+ @classmethod
56
+ def _visitorsFor(celf, thing, _default={}):
57
+ typ = type(thing)
58
+
59
+ for celf in celf.mro():
60
+ _visitors = getattr(celf, "_visitors", None)
61
+ if _visitors is None:
62
+ break
63
+
64
+ for base in typ.mro():
65
+ m = celf._visitors.get(base, None)
66
+ if m is not None:
67
+ return m
68
+
69
+ return _default
70
+
71
+ def visitObject(self, obj, *args, **kwargs):
72
+ """Called to visit an object. This function loops over all non-private
73
+ attributes of the objects and calls any user-registered (via
74
+ @register_attr() or @register_attrs()) visit() functions.
75
+
76
+ If there is no user-registered visit function, of if there is and it
77
+ returns True, or it returns None (or doesn't return anything) and
78
+ visitor.defaultStop is False (default), then the visitor will proceed
79
+ to call self.visitAttr()"""
80
+
81
+ keys = sorted(vars(obj).keys())
82
+ _visitors = self._visitorsFor(obj)
83
+ defaultVisitor = _visitors.get("*", None)
84
+ for key in keys:
85
+ if key[0] == "_":
86
+ continue
87
+ value = getattr(obj, key)
88
+ visitorFunc = _visitors.get(key, defaultVisitor)
89
+ if visitorFunc is not None:
90
+ ret = visitorFunc(self, obj, key, value, *args, **kwargs)
91
+ if ret == False or (ret is None and self.defaultStop):
92
+ continue
93
+ self.visitAttr(obj, key, value, *args, **kwargs)
94
+
95
+ def visitAttr(self, obj, attr, value, *args, **kwargs):
96
+ """Called to visit an attribute of an object."""
97
+ self.visit(value, *args, **kwargs)
98
+
99
+ def visitList(self, obj, *args, **kwargs):
100
+ """Called to visit any value that is a list."""
101
+ for value in obj:
102
+ self.visit(value, *args, **kwargs)
103
+
104
+ def visitDict(self, obj, *args, **kwargs):
105
+ """Called to visit any value that is a dictionary."""
106
+ for value in obj.values():
107
+ self.visit(value, *args, **kwargs)
108
+
109
+ def visitLeaf(self, obj, *args, **kwargs):
110
+ """Called to visit any value that is not an object, list,
111
+ or dictionary."""
112
+ pass
113
+
114
+ def visit(self, obj, *args, **kwargs):
115
+ """This is the main entry to the visitor. The visitor will visit object
116
+ obj.
117
+
118
+ The visitor will first determine if there is a registered (via
119
+ @register()) visit function for the type of object. If there is, it
120
+ will be called, and (visitor, obj, *args, **kwargs) will be passed to
121
+ the user visit function.
122
+
123
+ If there is no user-registered visit function, of if there is and it
124
+ returns True, or it returns None (or doesn't return anything) and
125
+ visitor.defaultStop is False (default), then the visitor will proceed
126
+ to dispatch to one of self.visitObject(), self.visitList(),
127
+ self.visitDict(), or self.visitLeaf() (any of which can be overriden in
128
+ a subclass)."""
129
+
130
+ visitorFunc = self._visitorsFor(obj).get(None, None)
131
+ if visitorFunc is not None:
132
+ ret = visitorFunc(self, obj, *args, **kwargs)
133
+ if ret == False or (ret is None and self.defaultStop):
134
+ return
135
+ if hasattr(obj, "__dict__") and not isinstance(obj, enum.Enum):
136
+ self.visitObject(obj, *args, **kwargs)
137
+ elif isinstance(obj, list):
138
+ self.visitList(obj, *args, **kwargs)
139
+ elif isinstance(obj, dict):
140
+ self.visitDict(obj, *args, **kwargs)
141
+ else:
142
+ self.visitLeaf(obj, *args, **kwargs)
@@ -0,0 +1,188 @@
1
+ from fontTools import ttLib
2
+ from fontTools.misc.textTools import safeEval
3
+ from fontTools.ttLib.tables.DefaultTable import DefaultTable
4
+ import sys
5
+ import os
6
+ import logging
7
+
8
+
9
+ log = logging.getLogger(__name__)
10
+
11
+
12
+ class TTXParseError(Exception):
13
+ pass
14
+
15
+
16
+ BUFSIZE = 0x4000
17
+
18
+
19
+ class XMLReader(object):
20
+ def __init__(
21
+ self, fileOrPath, ttFont, progress=None, quiet=None, contentOnly=False
22
+ ):
23
+ if fileOrPath == "-":
24
+ fileOrPath = sys.stdin
25
+ if not hasattr(fileOrPath, "read"):
26
+ self.file = open(fileOrPath, "rb")
27
+ self._closeStream = True
28
+ else:
29
+ # assume readable file object
30
+ self.file = fileOrPath
31
+ self._closeStream = False
32
+ self.ttFont = ttFont
33
+ self.progress = progress
34
+ if quiet is not None:
35
+ from fontTools.misc.loggingTools import deprecateArgument
36
+
37
+ deprecateArgument("quiet", "configure logging instead")
38
+ self.quiet = quiet
39
+ self.root = None
40
+ self.contentStack = []
41
+ self.contentOnly = contentOnly
42
+ self.stackSize = 0
43
+
44
+ def read(self, rootless=False):
45
+ if rootless:
46
+ self.stackSize += 1
47
+ if self.progress:
48
+ self.file.seek(0, 2)
49
+ fileSize = self.file.tell()
50
+ self.progress.set(0, fileSize // 100 or 1)
51
+ self.file.seek(0)
52
+ self._parseFile(self.file)
53
+ if self._closeStream:
54
+ self.close()
55
+ if rootless:
56
+ self.stackSize -= 1
57
+
58
+ def close(self):
59
+ self.file.close()
60
+
61
+ def _parseFile(self, file):
62
+ from xml.parsers.expat import ParserCreate
63
+
64
+ parser = ParserCreate()
65
+ parser.StartElementHandler = self._startElementHandler
66
+ parser.EndElementHandler = self._endElementHandler
67
+ parser.CharacterDataHandler = self._characterDataHandler
68
+
69
+ pos = 0
70
+ while True:
71
+ chunk = file.read(BUFSIZE)
72
+ if not chunk:
73
+ parser.Parse(chunk, 1)
74
+ break
75
+ pos = pos + len(chunk)
76
+ if self.progress:
77
+ self.progress.set(pos // 100)
78
+ parser.Parse(chunk, 0)
79
+
80
+ def _startElementHandler(self, name, attrs):
81
+ if self.stackSize == 1 and self.contentOnly:
82
+ # We already know the table we're parsing, skip
83
+ # parsing the table tag and continue to
84
+ # stack '2' which begins parsing content
85
+ self.contentStack.append([])
86
+ self.stackSize = 2
87
+ return
88
+ stackSize = self.stackSize
89
+ self.stackSize = stackSize + 1
90
+ subFile = attrs.get("src")
91
+ if subFile is not None:
92
+ if hasattr(self.file, "name"):
93
+ # if file has a name, get its parent directory
94
+ dirname = os.path.dirname(self.file.name)
95
+ else:
96
+ # else fall back to using the current working directory
97
+ dirname = os.getcwd()
98
+ subFile = os.path.join(dirname, subFile)
99
+ if not stackSize:
100
+ if name != "ttFont":
101
+ raise TTXParseError("illegal root tag: %s" % name)
102
+ if self.ttFont.reader is None and not self.ttFont.tables:
103
+ sfntVersion = attrs.get("sfntVersion")
104
+ if sfntVersion is not None:
105
+ if len(sfntVersion) != 4:
106
+ sfntVersion = safeEval('"' + sfntVersion + '"')
107
+ self.ttFont.sfntVersion = sfntVersion
108
+ self.contentStack.append([])
109
+ elif stackSize == 1:
110
+ if subFile is not None:
111
+ subReader = XMLReader(subFile, self.ttFont, self.progress)
112
+ subReader.read()
113
+ self.contentStack.append([])
114
+ return
115
+ tag = ttLib.xmlToTag(name)
116
+ msg = "Parsing '%s' table..." % tag
117
+ if self.progress:
118
+ self.progress.setLabel(msg)
119
+ log.info(msg)
120
+ if tag == "GlyphOrder":
121
+ tableClass = ttLib.GlyphOrder
122
+ elif "ERROR" in attrs or ("raw" in attrs and safeEval(attrs["raw"])):
123
+ tableClass = DefaultTable
124
+ else:
125
+ tableClass = ttLib.getTableClass(tag)
126
+ if tableClass is None:
127
+ tableClass = DefaultTable
128
+ if tag == "loca" and tag in self.ttFont:
129
+ # Special-case the 'loca' table as we need the
130
+ # original if the 'glyf' table isn't recompiled.
131
+ self.currentTable = self.ttFont[tag]
132
+ else:
133
+ self.currentTable = tableClass(tag)
134
+ self.ttFont[tag] = self.currentTable
135
+ self.contentStack.append([])
136
+ elif stackSize == 2 and subFile is not None:
137
+ subReader = XMLReader(subFile, self.ttFont, self.progress, contentOnly=True)
138
+ subReader.read()
139
+ self.contentStack.append([])
140
+ self.root = subReader.root
141
+ elif stackSize == 2:
142
+ self.contentStack.append([])
143
+ self.root = (name, attrs, self.contentStack[-1])
144
+ else:
145
+ l = []
146
+ self.contentStack[-1].append((name, attrs, l))
147
+ self.contentStack.append(l)
148
+
149
+ def _characterDataHandler(self, data):
150
+ if self.stackSize > 1:
151
+ # parser parses in chunks, so we may get multiple calls
152
+ # for the same text node; thus we need to append the data
153
+ # to the last item in the content stack:
154
+ # https://github.com/fonttools/fonttools/issues/2614
155
+ if (
156
+ data != "\n"
157
+ and self.contentStack[-1]
158
+ and isinstance(self.contentStack[-1][-1], str)
159
+ and self.contentStack[-1][-1] != "\n"
160
+ ):
161
+ self.contentStack[-1][-1] += data
162
+ else:
163
+ self.contentStack[-1].append(data)
164
+
165
+ def _endElementHandler(self, name):
166
+ self.stackSize = self.stackSize - 1
167
+ del self.contentStack[-1]
168
+ if not self.contentOnly:
169
+ if self.stackSize == 1:
170
+ self.root = None
171
+ elif self.stackSize == 2:
172
+ name, attrs, content = self.root
173
+ self.currentTable.fromXML(name, attrs, content, self.ttFont)
174
+ self.root = None
175
+
176
+
177
+ class ProgressPrinter(object):
178
+ def __init__(self, title, maxval=100):
179
+ print(title)
180
+
181
+ def set(self, val, maxval=None):
182
+ pass
183
+
184
+ def increment(self, val=1):
185
+ pass
186
+
187
+ def setLabel(self, text):
188
+ print(text)
@@ -0,0 +1,204 @@
1
+ """xmlWriter.py -- Simple XML authoring class"""
2
+
3
+ from fontTools.misc.textTools import byteord, strjoin, tobytes, tostr
4
+ import sys
5
+ import os
6
+ import string
7
+
8
+ INDENT = " "
9
+
10
+
11
+ class XMLWriter(object):
12
+ def __init__(
13
+ self,
14
+ fileOrPath,
15
+ indentwhite=INDENT,
16
+ idlefunc=None,
17
+ encoding="utf_8",
18
+ newlinestr="\n",
19
+ ):
20
+ if encoding.lower().replace("-", "").replace("_", "") != "utf8":
21
+ raise Exception("Only UTF-8 encoding is supported.")
22
+ if fileOrPath == "-":
23
+ fileOrPath = sys.stdout
24
+ if not hasattr(fileOrPath, "write"):
25
+ self.filename = fileOrPath
26
+ self.file = open(fileOrPath, "wb")
27
+ self._closeStream = True
28
+ else:
29
+ self.filename = None
30
+ # assume writable file object
31
+ self.file = fileOrPath
32
+ self._closeStream = False
33
+
34
+ # Figure out if writer expects bytes or unicodes
35
+ try:
36
+ # The bytes check should be first. See:
37
+ # https://github.com/fonttools/fonttools/pull/233
38
+ self.file.write(b"")
39
+ self.totype = tobytes
40
+ except TypeError:
41
+ # This better not fail.
42
+ self.file.write("")
43
+ self.totype = tostr
44
+ self.indentwhite = self.totype(indentwhite)
45
+ if newlinestr is None:
46
+ self.newlinestr = self.totype(os.linesep)
47
+ else:
48
+ self.newlinestr = self.totype(newlinestr)
49
+ self.indentlevel = 0
50
+ self.stack = []
51
+ self.needindent = 1
52
+ self.idlefunc = idlefunc
53
+ self.idlecounter = 0
54
+ self._writeraw('<?xml version="1.0" encoding="UTF-8"?>')
55
+ self.newline()
56
+
57
+ def __enter__(self):
58
+ return self
59
+
60
+ def __exit__(self, exception_type, exception_value, traceback):
61
+ self.close()
62
+
63
+ def close(self):
64
+ if self._closeStream:
65
+ self.file.close()
66
+
67
+ def write(self, string, indent=True):
68
+ """Writes text."""
69
+ self._writeraw(escape(string), indent=indent)
70
+
71
+ def writecdata(self, string):
72
+ """Writes text in a CDATA section."""
73
+ self._writeraw("<![CDATA[" + string + "]]>")
74
+
75
+ def write8bit(self, data, strip=False):
76
+ """Writes a bytes() sequence into the XML, escaping
77
+ non-ASCII bytes. When this is read in xmlReader,
78
+ the original bytes can be recovered by encoding to
79
+ 'latin-1'."""
80
+ self._writeraw(escape8bit(data), strip=strip)
81
+
82
+ def write_noindent(self, string):
83
+ """Writes text without indentation."""
84
+ self._writeraw(escape(string), indent=False)
85
+
86
+ def _writeraw(self, data, indent=True, strip=False):
87
+ """Writes bytes, possibly indented."""
88
+ if indent and self.needindent:
89
+ self.file.write(self.indentlevel * self.indentwhite)
90
+ self.needindent = 0
91
+ s = self.totype(data, encoding="utf_8")
92
+ if strip:
93
+ s = s.strip()
94
+ self.file.write(s)
95
+
96
+ def newline(self):
97
+ self.file.write(self.newlinestr)
98
+ self.needindent = 1
99
+ idlecounter = self.idlecounter
100
+ if not idlecounter % 100 and self.idlefunc is not None:
101
+ self.idlefunc()
102
+ self.idlecounter = idlecounter + 1
103
+
104
+ def comment(self, data):
105
+ data = escape(data)
106
+ lines = data.split("\n")
107
+ self._writeraw("<!-- " + lines[0])
108
+ for line in lines[1:]:
109
+ self.newline()
110
+ self._writeraw(" " + line)
111
+ self._writeraw(" -->")
112
+
113
+ def simpletag(self, _TAG_, *args, **kwargs):
114
+ attrdata = self.stringifyattrs(*args, **kwargs)
115
+ data = "<%s%s/>" % (_TAG_, attrdata)
116
+ self._writeraw(data)
117
+
118
+ def begintag(self, _TAG_, *args, **kwargs):
119
+ attrdata = self.stringifyattrs(*args, **kwargs)
120
+ data = "<%s%s>" % (_TAG_, attrdata)
121
+ self._writeraw(data)
122
+ self.stack.append(_TAG_)
123
+ self.indent()
124
+
125
+ def endtag(self, _TAG_):
126
+ assert self.stack and self.stack[-1] == _TAG_, "nonmatching endtag"
127
+ del self.stack[-1]
128
+ self.dedent()
129
+ data = "</%s>" % _TAG_
130
+ self._writeraw(data)
131
+
132
+ def dumphex(self, data):
133
+ linelength = 16
134
+ hexlinelength = linelength * 2
135
+ chunksize = 8
136
+ for i in range(0, len(data), linelength):
137
+ hexline = hexStr(data[i : i + linelength])
138
+ line = ""
139
+ white = ""
140
+ for j in range(0, hexlinelength, chunksize):
141
+ line = line + white + hexline[j : j + chunksize]
142
+ white = " "
143
+ self._writeraw(line)
144
+ self.newline()
145
+
146
+ def indent(self):
147
+ self.indentlevel = self.indentlevel + 1
148
+
149
+ def dedent(self):
150
+ assert self.indentlevel > 0
151
+ self.indentlevel = self.indentlevel - 1
152
+
153
+ def stringifyattrs(self, *args, **kwargs):
154
+ if kwargs:
155
+ assert not args
156
+ attributes = sorted(kwargs.items())
157
+ elif args:
158
+ assert len(args) == 1
159
+ attributes = args[0]
160
+ else:
161
+ return ""
162
+ data = ""
163
+ for attr, value in attributes:
164
+ if not isinstance(value, (bytes, str)):
165
+ value = str(value)
166
+ data = data + ' %s="%s"' % (attr, escapeattr(value))
167
+ return data
168
+
169
+
170
+ def escape(data):
171
+ data = tostr(data, "utf_8")
172
+ data = data.replace("&", "&amp;")
173
+ data = data.replace("<", "&lt;")
174
+ data = data.replace(">", "&gt;")
175
+ data = data.replace("\r", "&#13;")
176
+ return data
177
+
178
+
179
+ def escapeattr(data):
180
+ data = escape(data)
181
+ data = data.replace('"', "&quot;")
182
+ return data
183
+
184
+
185
+ def escape8bit(data):
186
+ """Input is Unicode string."""
187
+
188
+ def escapechar(c):
189
+ n = ord(c)
190
+ if 32 <= n <= 127 and c not in "<&>":
191
+ return c
192
+ else:
193
+ return "&#" + repr(n) + ";"
194
+
195
+ return strjoin(map(escapechar, data.decode("latin-1")))
196
+
197
+
198
+ def hexStr(s):
199
+ h = string.hexdigits
200
+ r = ""
201
+ for c in s:
202
+ i = byteord(c)
203
+ r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
204
+ return r