fonttools 4.60.2__cp311-cp311-win32.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.
Files changed (353) 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/annotations.py +30 -0
  6. fontTools/cffLib/CFF2ToCFF.py +258 -0
  7. fontTools/cffLib/CFFToCFF2.py +305 -0
  8. fontTools/cffLib/__init__.py +3694 -0
  9. fontTools/cffLib/specializer.py +927 -0
  10. fontTools/cffLib/transforms.py +495 -0
  11. fontTools/cffLib/width.py +210 -0
  12. fontTools/colorLib/__init__.py +0 -0
  13. fontTools/colorLib/builder.py +664 -0
  14. fontTools/colorLib/errors.py +2 -0
  15. fontTools/colorLib/geometry.py +143 -0
  16. fontTools/colorLib/table_builder.py +223 -0
  17. fontTools/colorLib/unbuilder.py +81 -0
  18. fontTools/config/__init__.py +90 -0
  19. fontTools/cu2qu/__init__.py +15 -0
  20. fontTools/cu2qu/__main__.py +6 -0
  21. fontTools/cu2qu/benchmark.py +54 -0
  22. fontTools/cu2qu/cli.py +198 -0
  23. fontTools/cu2qu/cu2qu.c +15817 -0
  24. fontTools/cu2qu/cu2qu.cp311-win32.pyd +0 -0
  25. fontTools/cu2qu/cu2qu.py +563 -0
  26. fontTools/cu2qu/errors.py +77 -0
  27. fontTools/cu2qu/ufo.py +363 -0
  28. fontTools/designspaceLib/__init__.py +3343 -0
  29. fontTools/designspaceLib/__main__.py +6 -0
  30. fontTools/designspaceLib/split.py +475 -0
  31. fontTools/designspaceLib/statNames.py +260 -0
  32. fontTools/designspaceLib/types.py +147 -0
  33. fontTools/encodings/MacRoman.py +258 -0
  34. fontTools/encodings/StandardEncoding.py +258 -0
  35. fontTools/encodings/__init__.py +1 -0
  36. fontTools/encodings/codecs.py +135 -0
  37. fontTools/feaLib/__init__.py +4 -0
  38. fontTools/feaLib/__main__.py +78 -0
  39. fontTools/feaLib/ast.py +2143 -0
  40. fontTools/feaLib/builder.py +1814 -0
  41. fontTools/feaLib/error.py +22 -0
  42. fontTools/feaLib/lexer.c +17029 -0
  43. fontTools/feaLib/lexer.cp311-win32.pyd +0 -0
  44. fontTools/feaLib/lexer.py +287 -0
  45. fontTools/feaLib/location.py +12 -0
  46. fontTools/feaLib/lookupDebugInfo.py +12 -0
  47. fontTools/feaLib/parser.py +2394 -0
  48. fontTools/feaLib/variableScalar.py +118 -0
  49. fontTools/fontBuilder.py +1014 -0
  50. fontTools/help.py +36 -0
  51. fontTools/merge/__init__.py +248 -0
  52. fontTools/merge/__main__.py +6 -0
  53. fontTools/merge/base.py +81 -0
  54. fontTools/merge/cmap.py +173 -0
  55. fontTools/merge/layout.py +526 -0
  56. fontTools/merge/options.py +85 -0
  57. fontTools/merge/tables.py +352 -0
  58. fontTools/merge/unicode.py +78 -0
  59. fontTools/merge/util.py +143 -0
  60. fontTools/misc/__init__.py +1 -0
  61. fontTools/misc/arrayTools.py +424 -0
  62. fontTools/misc/bezierTools.c +39731 -0
  63. fontTools/misc/bezierTools.cp311-win32.pyd +0 -0
  64. fontTools/misc/bezierTools.py +1500 -0
  65. fontTools/misc/classifyTools.py +170 -0
  66. fontTools/misc/cliTools.py +53 -0
  67. fontTools/misc/configTools.py +349 -0
  68. fontTools/misc/cython.py +27 -0
  69. fontTools/misc/dictTools.py +83 -0
  70. fontTools/misc/eexec.py +119 -0
  71. fontTools/misc/encodingTools.py +72 -0
  72. fontTools/misc/enumTools.py +23 -0
  73. fontTools/misc/etree.py +456 -0
  74. fontTools/misc/filenames.py +245 -0
  75. fontTools/misc/filesystem/__init__.py +68 -0
  76. fontTools/misc/filesystem/_base.py +134 -0
  77. fontTools/misc/filesystem/_copy.py +45 -0
  78. fontTools/misc/filesystem/_errors.py +54 -0
  79. fontTools/misc/filesystem/_info.py +75 -0
  80. fontTools/misc/filesystem/_osfs.py +164 -0
  81. fontTools/misc/filesystem/_path.py +67 -0
  82. fontTools/misc/filesystem/_subfs.py +92 -0
  83. fontTools/misc/filesystem/_tempfs.py +34 -0
  84. fontTools/misc/filesystem/_tools.py +34 -0
  85. fontTools/misc/filesystem/_walk.py +55 -0
  86. fontTools/misc/filesystem/_zipfs.py +204 -0
  87. fontTools/misc/fixedTools.py +253 -0
  88. fontTools/misc/intTools.py +25 -0
  89. fontTools/misc/iterTools.py +12 -0
  90. fontTools/misc/lazyTools.py +42 -0
  91. fontTools/misc/loggingTools.py +543 -0
  92. fontTools/misc/macCreatorType.py +56 -0
  93. fontTools/misc/macRes.py +261 -0
  94. fontTools/misc/plistlib/__init__.py +681 -0
  95. fontTools/misc/plistlib/py.typed +0 -0
  96. fontTools/misc/psCharStrings.py +1511 -0
  97. fontTools/misc/psLib.py +398 -0
  98. fontTools/misc/psOperators.py +572 -0
  99. fontTools/misc/py23.py +96 -0
  100. fontTools/misc/roundTools.py +110 -0
  101. fontTools/misc/sstruct.py +227 -0
  102. fontTools/misc/symfont.py +242 -0
  103. fontTools/misc/testTools.py +233 -0
  104. fontTools/misc/textTools.py +156 -0
  105. fontTools/misc/timeTools.py +88 -0
  106. fontTools/misc/transform.py +516 -0
  107. fontTools/misc/treeTools.py +45 -0
  108. fontTools/misc/vector.py +147 -0
  109. fontTools/misc/visitor.py +158 -0
  110. fontTools/misc/xmlReader.py +188 -0
  111. fontTools/misc/xmlWriter.py +231 -0
  112. fontTools/mtiLib/__init__.py +1400 -0
  113. fontTools/mtiLib/__main__.py +5 -0
  114. fontTools/otlLib/__init__.py +1 -0
  115. fontTools/otlLib/builder.py +3465 -0
  116. fontTools/otlLib/error.py +11 -0
  117. fontTools/otlLib/maxContextCalc.py +96 -0
  118. fontTools/otlLib/optimize/__init__.py +53 -0
  119. fontTools/otlLib/optimize/__main__.py +6 -0
  120. fontTools/otlLib/optimize/gpos.py +439 -0
  121. fontTools/pens/__init__.py +1 -0
  122. fontTools/pens/areaPen.py +52 -0
  123. fontTools/pens/basePen.py +475 -0
  124. fontTools/pens/boundsPen.py +98 -0
  125. fontTools/pens/cairoPen.py +26 -0
  126. fontTools/pens/cocoaPen.py +26 -0
  127. fontTools/pens/cu2quPen.py +325 -0
  128. fontTools/pens/explicitClosingLinePen.py +101 -0
  129. fontTools/pens/filterPen.py +433 -0
  130. fontTools/pens/freetypePen.py +462 -0
  131. fontTools/pens/hashPointPen.py +89 -0
  132. fontTools/pens/momentsPen.c +13378 -0
  133. fontTools/pens/momentsPen.cp311-win32.pyd +0 -0
  134. fontTools/pens/momentsPen.py +879 -0
  135. fontTools/pens/perimeterPen.py +69 -0
  136. fontTools/pens/pointInsidePen.py +192 -0
  137. fontTools/pens/pointPen.py +643 -0
  138. fontTools/pens/qtPen.py +29 -0
  139. fontTools/pens/qu2cuPen.py +105 -0
  140. fontTools/pens/quartzPen.py +43 -0
  141. fontTools/pens/recordingPen.py +335 -0
  142. fontTools/pens/reportLabPen.py +79 -0
  143. fontTools/pens/reverseContourPen.py +96 -0
  144. fontTools/pens/roundingPen.py +130 -0
  145. fontTools/pens/statisticsPen.py +312 -0
  146. fontTools/pens/svgPathPen.py +310 -0
  147. fontTools/pens/t2CharStringPen.py +88 -0
  148. fontTools/pens/teePen.py +55 -0
  149. fontTools/pens/transformPen.py +115 -0
  150. fontTools/pens/ttGlyphPen.py +335 -0
  151. fontTools/pens/wxPen.py +29 -0
  152. fontTools/qu2cu/__init__.py +15 -0
  153. fontTools/qu2cu/__main__.py +7 -0
  154. fontTools/qu2cu/benchmark.py +56 -0
  155. fontTools/qu2cu/cli.py +125 -0
  156. fontTools/qu2cu/qu2cu.c +16682 -0
  157. fontTools/qu2cu/qu2cu.cp311-win32.pyd +0 -0
  158. fontTools/qu2cu/qu2cu.py +405 -0
  159. fontTools/subset/__init__.py +4096 -0
  160. fontTools/subset/__main__.py +6 -0
  161. fontTools/subset/cff.py +184 -0
  162. fontTools/subset/svg.py +253 -0
  163. fontTools/subset/util.py +25 -0
  164. fontTools/svgLib/__init__.py +3 -0
  165. fontTools/svgLib/path/__init__.py +65 -0
  166. fontTools/svgLib/path/arc.py +154 -0
  167. fontTools/svgLib/path/parser.py +322 -0
  168. fontTools/svgLib/path/shapes.py +183 -0
  169. fontTools/t1Lib/__init__.py +648 -0
  170. fontTools/tfmLib.py +460 -0
  171. fontTools/ttLib/__init__.py +30 -0
  172. fontTools/ttLib/__main__.py +148 -0
  173. fontTools/ttLib/macUtils.py +54 -0
  174. fontTools/ttLib/removeOverlaps.py +395 -0
  175. fontTools/ttLib/reorderGlyphs.py +285 -0
  176. fontTools/ttLib/scaleUpem.py +436 -0
  177. fontTools/ttLib/sfnt.py +661 -0
  178. fontTools/ttLib/standardGlyphOrder.py +271 -0
  179. fontTools/ttLib/tables/B_A_S_E_.py +14 -0
  180. fontTools/ttLib/tables/BitmapGlyphMetrics.py +64 -0
  181. fontTools/ttLib/tables/C_B_D_T_.py +113 -0
  182. fontTools/ttLib/tables/C_B_L_C_.py +19 -0
  183. fontTools/ttLib/tables/C_F_F_.py +61 -0
  184. fontTools/ttLib/tables/C_F_F__2.py +26 -0
  185. fontTools/ttLib/tables/C_O_L_R_.py +165 -0
  186. fontTools/ttLib/tables/C_P_A_L_.py +305 -0
  187. fontTools/ttLib/tables/D_S_I_G_.py +158 -0
  188. fontTools/ttLib/tables/D__e_b_g.py +35 -0
  189. fontTools/ttLib/tables/DefaultTable.py +49 -0
  190. fontTools/ttLib/tables/E_B_D_T_.py +835 -0
  191. fontTools/ttLib/tables/E_B_L_C_.py +718 -0
  192. fontTools/ttLib/tables/F_F_T_M_.py +52 -0
  193. fontTools/ttLib/tables/F__e_a_t.py +149 -0
  194. fontTools/ttLib/tables/G_D_E_F_.py +13 -0
  195. fontTools/ttLib/tables/G_M_A_P_.py +148 -0
  196. fontTools/ttLib/tables/G_P_K_G_.py +133 -0
  197. fontTools/ttLib/tables/G_P_O_S_.py +14 -0
  198. fontTools/ttLib/tables/G_S_U_B_.py +13 -0
  199. fontTools/ttLib/tables/G_V_A_R_.py +5 -0
  200. fontTools/ttLib/tables/G__l_a_t.py +235 -0
  201. fontTools/ttLib/tables/G__l_o_c.py +85 -0
  202. fontTools/ttLib/tables/H_V_A_R_.py +13 -0
  203. fontTools/ttLib/tables/J_S_T_F_.py +13 -0
  204. fontTools/ttLib/tables/L_T_S_H_.py +58 -0
  205. fontTools/ttLib/tables/M_A_T_H_.py +13 -0
  206. fontTools/ttLib/tables/M_E_T_A_.py +352 -0
  207. fontTools/ttLib/tables/M_V_A_R_.py +13 -0
  208. fontTools/ttLib/tables/O_S_2f_2.py +752 -0
  209. fontTools/ttLib/tables/S_I_N_G_.py +99 -0
  210. fontTools/ttLib/tables/S_T_A_T_.py +15 -0
  211. fontTools/ttLib/tables/S_V_G_.py +223 -0
  212. fontTools/ttLib/tables/S__i_l_f.py +1040 -0
  213. fontTools/ttLib/tables/S__i_l_l.py +92 -0
  214. fontTools/ttLib/tables/T_S_I_B_.py +13 -0
  215. fontTools/ttLib/tables/T_S_I_C_.py +14 -0
  216. fontTools/ttLib/tables/T_S_I_D_.py +13 -0
  217. fontTools/ttLib/tables/T_S_I_J_.py +13 -0
  218. fontTools/ttLib/tables/T_S_I_P_.py +13 -0
  219. fontTools/ttLib/tables/T_S_I_S_.py +13 -0
  220. fontTools/ttLib/tables/T_S_I_V_.py +26 -0
  221. fontTools/ttLib/tables/T_S_I__0.py +70 -0
  222. fontTools/ttLib/tables/T_S_I__1.py +163 -0
  223. fontTools/ttLib/tables/T_S_I__2.py +17 -0
  224. fontTools/ttLib/tables/T_S_I__3.py +22 -0
  225. fontTools/ttLib/tables/T_S_I__5.py +60 -0
  226. fontTools/ttLib/tables/T_T_F_A_.py +14 -0
  227. fontTools/ttLib/tables/TupleVariation.py +884 -0
  228. fontTools/ttLib/tables/V_A_R_C_.py +12 -0
  229. fontTools/ttLib/tables/V_D_M_X_.py +249 -0
  230. fontTools/ttLib/tables/V_O_R_G_.py +165 -0
  231. fontTools/ttLib/tables/V_V_A_R_.py +13 -0
  232. fontTools/ttLib/tables/__init__.py +98 -0
  233. fontTools/ttLib/tables/_a_n_k_r.py +15 -0
  234. fontTools/ttLib/tables/_a_v_a_r.py +193 -0
  235. fontTools/ttLib/tables/_b_s_l_n.py +15 -0
  236. fontTools/ttLib/tables/_c_i_d_g.py +24 -0
  237. fontTools/ttLib/tables/_c_m_a_p.py +1591 -0
  238. fontTools/ttLib/tables/_c_v_a_r.py +94 -0
  239. fontTools/ttLib/tables/_c_v_t.py +56 -0
  240. fontTools/ttLib/tables/_f_e_a_t.py +15 -0
  241. fontTools/ttLib/tables/_f_p_g_m.py +62 -0
  242. fontTools/ttLib/tables/_f_v_a_r.py +261 -0
  243. fontTools/ttLib/tables/_g_a_s_p.py +63 -0
  244. fontTools/ttLib/tables/_g_c_i_d.py +13 -0
  245. fontTools/ttLib/tables/_g_l_y_f.py +2311 -0
  246. fontTools/ttLib/tables/_g_v_a_r.py +340 -0
  247. fontTools/ttLib/tables/_h_d_m_x.py +127 -0
  248. fontTools/ttLib/tables/_h_e_a_d.py +130 -0
  249. fontTools/ttLib/tables/_h_h_e_a.py +147 -0
  250. fontTools/ttLib/tables/_h_m_t_x.py +164 -0
  251. fontTools/ttLib/tables/_k_e_r_n.py +289 -0
  252. fontTools/ttLib/tables/_l_c_a_r.py +13 -0
  253. fontTools/ttLib/tables/_l_o_c_a.py +70 -0
  254. fontTools/ttLib/tables/_l_t_a_g.py +72 -0
  255. fontTools/ttLib/tables/_m_a_x_p.py +147 -0
  256. fontTools/ttLib/tables/_m_e_t_a.py +112 -0
  257. fontTools/ttLib/tables/_m_o_r_t.py +14 -0
  258. fontTools/ttLib/tables/_m_o_r_x.py +15 -0
  259. fontTools/ttLib/tables/_n_a_m_e.py +1242 -0
  260. fontTools/ttLib/tables/_o_p_b_d.py +14 -0
  261. fontTools/ttLib/tables/_p_o_s_t.py +319 -0
  262. fontTools/ttLib/tables/_p_r_e_p.py +16 -0
  263. fontTools/ttLib/tables/_p_r_o_p.py +12 -0
  264. fontTools/ttLib/tables/_s_b_i_x.py +129 -0
  265. fontTools/ttLib/tables/_t_r_a_k.py +332 -0
  266. fontTools/ttLib/tables/_v_h_e_a.py +139 -0
  267. fontTools/ttLib/tables/_v_m_t_x.py +19 -0
  268. fontTools/ttLib/tables/asciiTable.py +20 -0
  269. fontTools/ttLib/tables/grUtils.py +92 -0
  270. fontTools/ttLib/tables/otBase.py +1458 -0
  271. fontTools/ttLib/tables/otConverters.py +2068 -0
  272. fontTools/ttLib/tables/otData.py +6400 -0
  273. fontTools/ttLib/tables/otTables.py +2703 -0
  274. fontTools/ttLib/tables/otTraverse.py +163 -0
  275. fontTools/ttLib/tables/sbixGlyph.py +149 -0
  276. fontTools/ttLib/tables/sbixStrike.py +177 -0
  277. fontTools/ttLib/tables/table_API_readme.txt +91 -0
  278. fontTools/ttLib/tables/ttProgram.py +594 -0
  279. fontTools/ttLib/ttCollection.py +125 -0
  280. fontTools/ttLib/ttFont.py +1148 -0
  281. fontTools/ttLib/ttGlyphSet.py +490 -0
  282. fontTools/ttLib/ttVisitor.py +32 -0
  283. fontTools/ttLib/woff2.py +1680 -0
  284. fontTools/ttx.py +479 -0
  285. fontTools/ufoLib/__init__.py +2575 -0
  286. fontTools/ufoLib/converters.py +407 -0
  287. fontTools/ufoLib/errors.py +30 -0
  288. fontTools/ufoLib/etree.py +6 -0
  289. fontTools/ufoLib/filenames.py +356 -0
  290. fontTools/ufoLib/glifLib.py +2120 -0
  291. fontTools/ufoLib/kerning.py +141 -0
  292. fontTools/ufoLib/plistlib.py +47 -0
  293. fontTools/ufoLib/pointPen.py +6 -0
  294. fontTools/ufoLib/utils.py +107 -0
  295. fontTools/ufoLib/validators.py +1208 -0
  296. fontTools/unicode.py +50 -0
  297. fontTools/unicodedata/Blocks.py +817 -0
  298. fontTools/unicodedata/Mirrored.py +446 -0
  299. fontTools/unicodedata/OTTags.py +50 -0
  300. fontTools/unicodedata/ScriptExtensions.py +832 -0
  301. fontTools/unicodedata/Scripts.py +3639 -0
  302. fontTools/unicodedata/__init__.py +306 -0
  303. fontTools/varLib/__init__.py +1600 -0
  304. fontTools/varLib/__main__.py +6 -0
  305. fontTools/varLib/avar/__init__.py +0 -0
  306. fontTools/varLib/avar/__main__.py +72 -0
  307. fontTools/varLib/avar/build.py +79 -0
  308. fontTools/varLib/avar/map.py +108 -0
  309. fontTools/varLib/avar/plan.py +1004 -0
  310. fontTools/varLib/avar/unbuild.py +271 -0
  311. fontTools/varLib/avarPlanner.py +8 -0
  312. fontTools/varLib/builder.py +215 -0
  313. fontTools/varLib/cff.py +631 -0
  314. fontTools/varLib/errors.py +219 -0
  315. fontTools/varLib/featureVars.py +703 -0
  316. fontTools/varLib/hvar.py +113 -0
  317. fontTools/varLib/instancer/__init__.py +2052 -0
  318. fontTools/varLib/instancer/__main__.py +5 -0
  319. fontTools/varLib/instancer/featureVars.py +190 -0
  320. fontTools/varLib/instancer/names.py +388 -0
  321. fontTools/varLib/instancer/solver.py +309 -0
  322. fontTools/varLib/interpolatable.py +1209 -0
  323. fontTools/varLib/interpolatableHelpers.py +399 -0
  324. fontTools/varLib/interpolatablePlot.py +1269 -0
  325. fontTools/varLib/interpolatableTestContourOrder.py +82 -0
  326. fontTools/varLib/interpolatableTestStartingPoint.py +107 -0
  327. fontTools/varLib/interpolate_layout.py +124 -0
  328. fontTools/varLib/iup.c +19815 -0
  329. fontTools/varLib/iup.cp311-win32.pyd +0 -0
  330. fontTools/varLib/iup.py +490 -0
  331. fontTools/varLib/merger.py +1717 -0
  332. fontTools/varLib/models.py +642 -0
  333. fontTools/varLib/multiVarStore.py +253 -0
  334. fontTools/varLib/mutator.py +529 -0
  335. fontTools/varLib/mvar.py +40 -0
  336. fontTools/varLib/plot.py +238 -0
  337. fontTools/varLib/stat.py +149 -0
  338. fontTools/varLib/varStore.py +739 -0
  339. fontTools/voltLib/__init__.py +5 -0
  340. fontTools/voltLib/__main__.py +206 -0
  341. fontTools/voltLib/ast.py +452 -0
  342. fontTools/voltLib/error.py +12 -0
  343. fontTools/voltLib/lexer.py +99 -0
  344. fontTools/voltLib/parser.py +664 -0
  345. fontTools/voltLib/voltToFea.py +911 -0
  346. fonttools-4.60.2.data/data/share/man/man1/ttx.1 +225 -0
  347. fonttools-4.60.2.dist-info/METADATA +2250 -0
  348. fonttools-4.60.2.dist-info/RECORD +353 -0
  349. fonttools-4.60.2.dist-info/WHEEL +5 -0
  350. fonttools-4.60.2.dist-info/entry_points.txt +5 -0
  351. fonttools-4.60.2.dist-info/licenses/LICENSE +21 -0
  352. fonttools-4.60.2.dist-info/licenses/LICENSE.external +388 -0
  353. fonttools-4.60.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,233 @@
1
+ """Helpers for writing unit tests."""
2
+
3
+ from collections.abc import Iterable
4
+ from io import BytesIO
5
+ import os
6
+ import re
7
+ import shutil
8
+ import sys
9
+ import tempfile
10
+ from unittest import TestCase as _TestCase
11
+ from fontTools.config import Config
12
+ from fontTools.misc.textTools import tobytes
13
+ from fontTools.misc.xmlWriter import XMLWriter
14
+
15
+
16
+ def parseXML(xmlSnippet):
17
+ """Parses a snippet of XML.
18
+
19
+ Input can be either a single string (unicode or UTF-8 bytes), or a
20
+ a sequence of strings.
21
+
22
+ The result is in the same format that would be returned by
23
+ XMLReader, but the parser imposes no constraints on the root
24
+ element so it can be called on small snippets of TTX files.
25
+ """
26
+ # To support snippets with multiple elements, we add a fake root.
27
+ reader = TestXMLReader_()
28
+ xml = b"<root>"
29
+ if isinstance(xmlSnippet, bytes):
30
+ xml += xmlSnippet
31
+ elif isinstance(xmlSnippet, str):
32
+ xml += tobytes(xmlSnippet, "utf-8")
33
+ elif isinstance(xmlSnippet, Iterable):
34
+ xml += b"".join(tobytes(s, "utf-8") for s in xmlSnippet)
35
+ else:
36
+ raise TypeError(
37
+ "expected string or sequence of strings; found %r"
38
+ % type(xmlSnippet).__name__
39
+ )
40
+ xml += b"</root>"
41
+ reader.parser.Parse(xml, 1)
42
+ return reader.root[2]
43
+
44
+
45
+ def parseXmlInto(font, parseInto, xmlSnippet):
46
+ parsed_xml = [e for e in parseXML(xmlSnippet.strip()) if not isinstance(e, str)]
47
+ for name, attrs, content in parsed_xml:
48
+ parseInto.fromXML(name, attrs, content, font)
49
+ if hasattr(parseInto, "populateDefaults"):
50
+ parseInto.populateDefaults()
51
+ return parseInto
52
+
53
+
54
+ class FakeFont:
55
+ def __init__(self, glyphs):
56
+ self.glyphOrder_ = glyphs
57
+ self.reverseGlyphOrderDict_ = {g: i for i, g in enumerate(glyphs)}
58
+ self.lazy = False
59
+ self.tables = {}
60
+ self.cfg = Config()
61
+
62
+ def __contains__(self, tag):
63
+ return tag in self.tables
64
+
65
+ def __getitem__(self, tag):
66
+ return self.tables[tag]
67
+
68
+ def __setitem__(self, tag, table):
69
+ self.tables[tag] = table
70
+
71
+ def get(self, tag, default=None):
72
+ return self.tables.get(tag, default)
73
+
74
+ def getGlyphID(self, name):
75
+ return self.reverseGlyphOrderDict_[name]
76
+
77
+ def getGlyphIDMany(self, lst):
78
+ return [self.getGlyphID(gid) for gid in lst]
79
+
80
+ def getGlyphName(self, glyphID):
81
+ if glyphID < len(self.glyphOrder_):
82
+ return self.glyphOrder_[glyphID]
83
+ else:
84
+ return "glyph%.5d" % glyphID
85
+
86
+ def getGlyphNameMany(self, lst):
87
+ return [self.getGlyphName(gid) for gid in lst]
88
+
89
+ def getGlyphOrder(self):
90
+ return self.glyphOrder_
91
+
92
+ def getReverseGlyphMap(self):
93
+ return self.reverseGlyphOrderDict_
94
+
95
+ def getGlyphNames(self):
96
+ return sorted(self.getGlyphOrder())
97
+
98
+
99
+ class TestXMLReader_(object):
100
+ def __init__(self):
101
+ from xml.parsers.expat import ParserCreate
102
+
103
+ self.parser = ParserCreate()
104
+ self.parser.StartElementHandler = self.startElement_
105
+ self.parser.EndElementHandler = self.endElement_
106
+ self.parser.CharacterDataHandler = self.addCharacterData_
107
+ self.root = None
108
+ self.stack = []
109
+
110
+ def startElement_(self, name, attrs):
111
+ element = (name, attrs, [])
112
+ if self.stack:
113
+ self.stack[-1][2].append(element)
114
+ else:
115
+ self.root = element
116
+ self.stack.append(element)
117
+
118
+ def endElement_(self, name):
119
+ self.stack.pop()
120
+
121
+ def addCharacterData_(self, data):
122
+ self.stack[-1][2].append(data)
123
+
124
+
125
+ def makeXMLWriter(newlinestr="\n"):
126
+ # don't write OS-specific new lines
127
+ writer = XMLWriter(BytesIO(), newlinestr=newlinestr)
128
+ # erase XML declaration
129
+ writer.file.seek(0)
130
+ writer.file.truncate()
131
+ return writer
132
+
133
+
134
+ def getXML(func, ttFont=None):
135
+ """Call the passed toXML function and return the written content as a
136
+ list of lines (unicode strings).
137
+ Result is stripped of XML declaration and OS-specific newline characters.
138
+ """
139
+ writer = makeXMLWriter()
140
+ func(writer, ttFont)
141
+ xml = writer.file.getvalue().decode("utf-8")
142
+ # toXML methods must always end with a writer.newline()
143
+ assert xml.endswith("\n")
144
+ return xml.splitlines()
145
+
146
+
147
+ def stripVariableItemsFromTTX(
148
+ string: str,
149
+ ttLibVersion: bool = True,
150
+ checkSumAdjustment: bool = True,
151
+ modified: bool = True,
152
+ created: bool = True,
153
+ sfntVersion: bool = False, # opt-in only
154
+ ) -> str:
155
+ """Strip stuff like ttLibVersion, checksums, timestamps, etc. from TTX dumps."""
156
+ # ttlib changes with the fontTools version
157
+ if ttLibVersion:
158
+ string = re.sub(' ttLibVersion="[^"]+"', "", string)
159
+ # sometimes (e.g. some subsetter tests) we don't care whether it's OTF or TTF
160
+ if sfntVersion:
161
+ string = re.sub(' sfntVersion="[^"]+"', "", string)
162
+ # head table checksum and creation and mod date changes with each save.
163
+ if checkSumAdjustment:
164
+ string = re.sub('<checkSumAdjustment value="[^"]+"/>', "", string)
165
+ if modified:
166
+ string = re.sub('<modified value="[^"]+"/>', "", string)
167
+ if created:
168
+ string = re.sub('<created value="[^"]+"/>', "", string)
169
+ return string
170
+
171
+
172
+ class MockFont(object):
173
+ """A font-like object that automatically adds any looked up glyphname
174
+ to its glyphOrder."""
175
+
176
+ def __init__(self):
177
+ self._glyphOrder = [".notdef"]
178
+
179
+ class AllocatingDict(dict):
180
+ def __missing__(reverseDict, key):
181
+ self._glyphOrder.append(key)
182
+ gid = len(reverseDict)
183
+ reverseDict[key] = gid
184
+ return gid
185
+
186
+ self._reverseGlyphOrder = AllocatingDict({".notdef": 0})
187
+ self.lazy = False
188
+
189
+ def getGlyphID(self, glyph):
190
+ gid = self._reverseGlyphOrder[glyph]
191
+ return gid
192
+
193
+ def getReverseGlyphMap(self):
194
+ return self._reverseGlyphOrder
195
+
196
+ def getGlyphName(self, gid):
197
+ return self._glyphOrder[gid]
198
+
199
+ def getGlyphOrder(self):
200
+ return self._glyphOrder
201
+
202
+
203
+ class TestCase(_TestCase):
204
+ def __init__(self, methodName):
205
+ _TestCase.__init__(self, methodName)
206
+ # Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
207
+ # and fires deprecation warnings if a program uses the old name.
208
+ if not hasattr(self, "assertRaisesRegex"):
209
+ self.assertRaisesRegex = self.assertRaisesRegexp
210
+
211
+
212
+ class DataFilesHandler(TestCase):
213
+ def setUp(self):
214
+ self.tempdir = None
215
+ self.num_tempfiles = 0
216
+
217
+ def tearDown(self):
218
+ if self.tempdir:
219
+ shutil.rmtree(self.tempdir)
220
+
221
+ def getpath(self, testfile):
222
+ folder = os.path.dirname(sys.modules[self.__module__].__file__)
223
+ return os.path.join(folder, "data", testfile)
224
+
225
+ def temp_dir(self):
226
+ if not self.tempdir:
227
+ self.tempdir = tempfile.mkdtemp()
228
+
229
+ def temp_font(self, font_path, file_name):
230
+ self.temp_dir()
231
+ temppath = os.path.join(self.tempdir, file_name)
232
+ shutil.copy2(font_path, temppath)
233
+ return temppath
@@ -0,0 +1,156 @@
1
+ """fontTools.misc.textTools.py -- miscellaneous routines."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast
6
+ import string
7
+
8
+
9
+ # alias kept for backward compatibility
10
+ safeEval = ast.literal_eval
11
+
12
+
13
+ class Tag(str):
14
+ @staticmethod
15
+ def transcode(blob):
16
+ if isinstance(blob, bytes):
17
+ blob = blob.decode("latin-1")
18
+ return blob
19
+
20
+ def __new__(self, content):
21
+ return str.__new__(self, self.transcode(content))
22
+
23
+ def __ne__(self, other):
24
+ return not self.__eq__(other)
25
+
26
+ def __eq__(self, other):
27
+ return str.__eq__(self, self.transcode(other))
28
+
29
+ def __hash__(self):
30
+ return str.__hash__(self)
31
+
32
+ def tobytes(self):
33
+ return self.encode("latin-1")
34
+
35
+
36
+ def readHex(content):
37
+ """Convert a list of hex strings to binary data."""
38
+ return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, str)))
39
+
40
+
41
+ def deHexStr(hexdata):
42
+ """Convert a hex string to binary data."""
43
+ hexdata = strjoin(hexdata.split())
44
+ if len(hexdata) % 2:
45
+ hexdata = hexdata + "0"
46
+ data = []
47
+ for i in range(0, len(hexdata), 2):
48
+ data.append(bytechr(int(hexdata[i : i + 2], 16)))
49
+ return bytesjoin(data)
50
+
51
+
52
+ def hexStr(data):
53
+ """Convert binary data to a hex string."""
54
+ h = string.hexdigits
55
+ r = ""
56
+ for c in data:
57
+ i = byteord(c)
58
+ r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
59
+ return r
60
+
61
+
62
+ def num2binary(l, bits=32):
63
+ items = []
64
+ binary = ""
65
+ for i in range(bits):
66
+ if l & 0x1:
67
+ binary = "1" + binary
68
+ else:
69
+ binary = "0" + binary
70
+ l = l >> 1
71
+ if not ((i + 1) % 8):
72
+ items.append(binary)
73
+ binary = ""
74
+ if binary:
75
+ items.append(binary)
76
+ items.reverse()
77
+ assert l in (0, -1), "number doesn't fit in number of bits"
78
+ return " ".join(items)
79
+
80
+
81
+ def binary2num(bin):
82
+ bin = strjoin(bin.split())
83
+ l = 0
84
+ for digit in bin:
85
+ l = l << 1
86
+ if digit != "0":
87
+ l = l | 0x1
88
+ return l
89
+
90
+
91
+ def caselessSort(alist):
92
+ """Return a sorted copy of a list. If there are only strings
93
+ in the list, it will not consider case.
94
+ """
95
+
96
+ try:
97
+ return sorted(alist, key=lambda a: (a.lower(), a))
98
+ except TypeError:
99
+ return sorted(alist)
100
+
101
+
102
+ def pad(data, size):
103
+ r"""Pad byte string 'data' with null bytes until its length is a
104
+ multiple of 'size'.
105
+
106
+ >>> len(pad(b'abcd', 4))
107
+ 4
108
+ >>> len(pad(b'abcde', 2))
109
+ 6
110
+ >>> len(pad(b'abcde', 4))
111
+ 8
112
+ >>> pad(b'abcdef', 4) == b'abcdef\x00\x00'
113
+ True
114
+ """
115
+ data = tobytes(data)
116
+ if size > 1:
117
+ remainder = len(data) % size
118
+ if remainder:
119
+ data += b"\0" * (size - remainder)
120
+ return data
121
+
122
+
123
+ def tostr(s: str | bytes, encoding: str = "ascii", errors: str = "strict") -> str:
124
+ if not isinstance(s, str):
125
+ return s.decode(encoding, errors)
126
+ else:
127
+ return s
128
+
129
+
130
+ def tobytes(s: str | bytes, encoding: str = "ascii", errors: str = "strict") -> bytes:
131
+ if isinstance(s, str):
132
+ return s.encode(encoding, errors)
133
+ else:
134
+ return bytes(s)
135
+
136
+
137
+ def bytechr(n):
138
+ return bytes([n])
139
+
140
+
141
+ def byteord(c):
142
+ return c if isinstance(c, int) else ord(c)
143
+
144
+
145
+ def strjoin(iterable, joiner=""):
146
+ return tostr(joiner).join(iterable)
147
+
148
+
149
+ def bytesjoin(iterable, joiner=b""):
150
+ return tobytes(joiner).join(tobytes(item) for item in iterable)
151
+
152
+
153
+ if __name__ == "__main__":
154
+ import doctest, sys
155
+
156
+ sys.exit(doctest.testmod().failed)
@@ -0,0 +1,88 @@
1
+ """fontTools.misc.timeTools.py -- tools for working with OpenType timestamps.
2
+ """
3
+
4
+ import os
5
+ import time
6
+ from datetime import datetime, timezone
7
+ import calendar
8
+
9
+
10
+ epoch_diff = calendar.timegm((1904, 1, 1, 0, 0, 0, 0, 0, 0))
11
+
12
+ DAYNAMES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
13
+ MONTHNAMES = [
14
+ None,
15
+ "Jan",
16
+ "Feb",
17
+ "Mar",
18
+ "Apr",
19
+ "May",
20
+ "Jun",
21
+ "Jul",
22
+ "Aug",
23
+ "Sep",
24
+ "Oct",
25
+ "Nov",
26
+ "Dec",
27
+ ]
28
+
29
+
30
+ def asctime(t=None):
31
+ """
32
+ Convert a tuple or struct_time representing a time as returned by gmtime()
33
+ or localtime() to a 24-character string of the following form:
34
+
35
+ >>> asctime(time.gmtime(0))
36
+ 'Thu Jan 1 00:00:00 1970'
37
+
38
+ If t is not provided, the current time as returned by localtime() is used.
39
+ Locale information is not used by asctime().
40
+
41
+ This is meant to normalise the output of the built-in time.asctime() across
42
+ different platforms and Python versions.
43
+ In Python 3.x, the day of the month is right-justified, whereas on Windows
44
+ Python 2.7 it is padded with zeros.
45
+
46
+ See https://github.com/fonttools/fonttools/issues/455
47
+ """
48
+ if t is None:
49
+ t = time.localtime()
50
+ s = "%s %s %2s %s" % (
51
+ DAYNAMES[t.tm_wday],
52
+ MONTHNAMES[t.tm_mon],
53
+ t.tm_mday,
54
+ time.strftime("%H:%M:%S %Y", t),
55
+ )
56
+ return s
57
+
58
+
59
+ def timestampToString(value):
60
+ return asctime(time.gmtime(max(0, value + epoch_diff)))
61
+
62
+
63
+ def timestampFromString(value):
64
+ wkday, mnth = value[:7].split()
65
+ t = datetime.strptime(value[7:], " %d %H:%M:%S %Y")
66
+ t = t.replace(month=MONTHNAMES.index(mnth), tzinfo=timezone.utc)
67
+ wkday_idx = DAYNAMES.index(wkday)
68
+ assert t.weekday() == wkday_idx, '"' + value + '" has inconsistent weekday'
69
+ return int(t.timestamp()) - epoch_diff
70
+
71
+
72
+ def timestampNow():
73
+ # https://reproducible-builds.org/specs/source-date-epoch/
74
+ source_date_epoch = os.environ.get("SOURCE_DATE_EPOCH")
75
+ if source_date_epoch is not None:
76
+ return int(source_date_epoch) - epoch_diff
77
+ return int(time.time() - epoch_diff)
78
+
79
+
80
+ def timestampSinceEpoch(value):
81
+ return int(value - epoch_diff)
82
+
83
+
84
+ if __name__ == "__main__":
85
+ import sys
86
+ import doctest
87
+
88
+ sys.exit(doctest.testmod().failed)