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
fontTools/tfmLib.py ADDED
@@ -0,0 +1,460 @@
1
+ """Module for reading TFM (TeX Font Metrics) files.
2
+
3
+ The TFM format is described in the TFtoPL WEB source code, whose typeset form
4
+ can be found on `CTAN <http://mirrors.ctan.org/info/knuth-pdf/texware/tftopl.pdf>`_.
5
+
6
+ >>> from fontTools.tfmLib import TFM
7
+ >>> tfm = TFM("Tests/tfmLib/data/cmr10.tfm")
8
+ >>>
9
+ >>> # Accessing an attribute gets you metadata.
10
+ >>> tfm.checksum
11
+ 1274110073
12
+ >>> tfm.designsize
13
+ 10.0
14
+ >>> tfm.codingscheme
15
+ 'TeX text'
16
+ >>> tfm.family
17
+ 'CMR'
18
+ >>> tfm.seven_bit_safe_flag
19
+ False
20
+ >>> tfm.face
21
+ 234
22
+ >>> tfm.extraheader
23
+ {}
24
+ >>> tfm.fontdimens
25
+ {'SLANT': 0.0, 'SPACE': 0.33333396911621094, 'STRETCH': 0.16666698455810547, 'SHRINK': 0.11111164093017578, 'XHEIGHT': 0.4305553436279297, 'QUAD': 1.0000028610229492, 'EXTRASPACE': 0.11111164093017578}
26
+ >>> # Accessing a character gets you its metrics.
27
+ >>> # “width” is always available, other metrics are available only when
28
+ >>> # applicable. All values are relative to “designsize”.
29
+ >>> tfm.chars[ord("g")]
30
+ {'width': 0.5000019073486328, 'height': 0.4305553436279297, 'depth': 0.1944446563720703, 'italic': 0.013888359069824219}
31
+ >>> # Kerning and ligature can be accessed as well.
32
+ >>> tfm.kerning[ord("c")]
33
+ {104: -0.02777862548828125, 107: -0.02777862548828125}
34
+ >>> tfm.ligatures[ord("f")]
35
+ {105: ('LIG', 12), 102: ('LIG', 11), 108: ('LIG', 13)}
36
+ """
37
+
38
+ from types import SimpleNamespace
39
+
40
+ from fontTools.misc.sstruct import calcsize, unpack, unpack2
41
+
42
+ SIZES_FORMAT = """
43
+ >
44
+ lf: h # length of the entire file, in words
45
+ lh: h # length of the header data, in words
46
+ bc: h # smallest character code in the font
47
+ ec: h # largest character code in the font
48
+ nw: h # number of words in the width table
49
+ nh: h # number of words in the height table
50
+ nd: h # number of words in the depth table
51
+ ni: h # number of words in the italic correction table
52
+ nl: h # number of words in the ligature/kern table
53
+ nk: h # number of words in the kern table
54
+ ne: h # number of words in the extensible character table
55
+ np: h # number of font parameter words
56
+ """
57
+
58
+ SIZES_SIZE = calcsize(SIZES_FORMAT)
59
+
60
+ FIXED_FORMAT = "12.20F"
61
+
62
+ HEADER_FORMAT1 = f"""
63
+ >
64
+ checksum: L
65
+ designsize: {FIXED_FORMAT}
66
+ """
67
+
68
+ HEADER_FORMAT2 = f"""
69
+ {HEADER_FORMAT1}
70
+ codingscheme: 40p
71
+ """
72
+
73
+ HEADER_FORMAT3 = f"""
74
+ {HEADER_FORMAT2}
75
+ family: 20p
76
+ """
77
+
78
+ HEADER_FORMAT4 = f"""
79
+ {HEADER_FORMAT3}
80
+ seven_bit_safe_flag: ?
81
+ ignored: x
82
+ ignored: x
83
+ face: B
84
+ """
85
+
86
+ HEADER_SIZE1 = calcsize(HEADER_FORMAT1)
87
+ HEADER_SIZE2 = calcsize(HEADER_FORMAT2)
88
+ HEADER_SIZE3 = calcsize(HEADER_FORMAT3)
89
+ HEADER_SIZE4 = calcsize(HEADER_FORMAT4)
90
+
91
+ LIG_KERN_COMMAND = """
92
+ >
93
+ skip_byte: B
94
+ next_char: B
95
+ op_byte: B
96
+ remainder: B
97
+ """
98
+
99
+ BASE_PARAMS = [
100
+ "SLANT",
101
+ "SPACE",
102
+ "STRETCH",
103
+ "SHRINK",
104
+ "XHEIGHT",
105
+ "QUAD",
106
+ "EXTRASPACE",
107
+ ]
108
+
109
+ MATHSY_PARAMS = [
110
+ "NUM1",
111
+ "NUM2",
112
+ "NUM3",
113
+ "DENOM1",
114
+ "DENOM2",
115
+ "SUP1",
116
+ "SUP2",
117
+ "SUP3",
118
+ "SUB1",
119
+ "SUB2",
120
+ "SUPDROP",
121
+ "SUBDROP",
122
+ "DELIM1",
123
+ "DELIM2",
124
+ "AXISHEIGHT",
125
+ ]
126
+
127
+ MATHEX_PARAMS = [
128
+ "DEFAULTRULETHICKNESS",
129
+ "BIGOPSPACING1",
130
+ "BIGOPSPACING2",
131
+ "BIGOPSPACING3",
132
+ "BIGOPSPACING4",
133
+ "BIGOPSPACING5",
134
+ ]
135
+
136
+ VANILLA = 0
137
+ MATHSY = 1
138
+ MATHEX = 2
139
+
140
+ UNREACHABLE = 0
141
+ PASSTHROUGH = 1
142
+ ACCESSABLE = 2
143
+
144
+ NO_TAG = 0
145
+ LIG_TAG = 1
146
+ LIST_TAG = 2
147
+ EXT_TAG = 3
148
+
149
+ STOP_FLAG = 128
150
+ KERN_FLAG = 128
151
+
152
+
153
+ class TFMException(Exception):
154
+ def __init__(self, message):
155
+ super().__init__(message)
156
+
157
+
158
+ class TFM:
159
+ def __init__(self, file):
160
+ self._read(file)
161
+
162
+ def __repr__(self):
163
+ return (
164
+ f"<TFM"
165
+ f" for {self.family}"
166
+ f" in {self.codingscheme}"
167
+ f" at {self.designsize:g}pt>"
168
+ )
169
+
170
+ def _read(self, file):
171
+ if hasattr(file, "read"):
172
+ data = file.read()
173
+ else:
174
+ with open(file, "rb") as fp:
175
+ data = fp.read()
176
+
177
+ self._data = data
178
+
179
+ if len(data) < SIZES_SIZE:
180
+ raise TFMException("Too short input file")
181
+
182
+ sizes = SimpleNamespace()
183
+ unpack2(SIZES_FORMAT, data, sizes)
184
+
185
+ # Do some file structure sanity checks.
186
+ # TeX and TFtoPL do additional functional checks and might even correct
187
+ # “errors” in the input file, but we instead try to output the file as
188
+ # it is as long as it is parsable, even if the data make no sense.
189
+
190
+ if sizes.lf < 0:
191
+ raise TFMException("The file claims to have negative or zero length!")
192
+
193
+ if len(data) < sizes.lf * 4:
194
+ raise TFMException("The file has fewer bytes than it claims!")
195
+
196
+ for name, length in vars(sizes).items():
197
+ if length < 0:
198
+ raise TFMException("The subfile size: '{name}' is negative!")
199
+
200
+ if sizes.lh < 2:
201
+ raise TFMException(f"The header length is only {sizes.lh}!")
202
+
203
+ if sizes.bc > sizes.ec + 1 or sizes.ec > 255:
204
+ raise TFMException(
205
+ f"The character code range {sizes.bc}..{sizes.ec} is illegal!"
206
+ )
207
+
208
+ if sizes.nw == 0 or sizes.nh == 0 or sizes.nd == 0 or sizes.ni == 0:
209
+ raise TFMException("Incomplete subfiles for character dimensions!")
210
+
211
+ if sizes.ne > 256:
212
+ raise TFMException(f"There are {ne} extensible recipes!")
213
+
214
+ if sizes.lf != (
215
+ 6
216
+ + sizes.lh
217
+ + (sizes.ec - sizes.bc + 1)
218
+ + sizes.nw
219
+ + sizes.nh
220
+ + sizes.nd
221
+ + sizes.ni
222
+ + sizes.nl
223
+ + sizes.nk
224
+ + sizes.ne
225
+ + sizes.np
226
+ ):
227
+ raise TFMException("Subfile sizes don’t add up to the stated total")
228
+
229
+ # Subfile offsets, used in the helper function below. These all are
230
+ # 32-bit word offsets not 8-bit byte offsets.
231
+ char_base = 6 + sizes.lh - sizes.bc
232
+ width_base = char_base + sizes.ec + 1
233
+ height_base = width_base + sizes.nw
234
+ depth_base = height_base + sizes.nh
235
+ italic_base = depth_base + sizes.nd
236
+ lig_kern_base = italic_base + sizes.ni
237
+ kern_base = lig_kern_base + sizes.nl
238
+ exten_base = kern_base + sizes.nk
239
+ param_base = exten_base + sizes.ne
240
+
241
+ # Helper functions for accessing individual data. If this looks
242
+ # nonidiomatic Python, I blame the effect of reading the literate WEB
243
+ # documentation of TFtoPL.
244
+ def char_info(c):
245
+ return 4 * (char_base + c)
246
+
247
+ def width_index(c):
248
+ return data[char_info(c)]
249
+
250
+ def noneexistent(c):
251
+ return c < sizes.bc or c > sizes.ec or width_index(c) == 0
252
+
253
+ def height_index(c):
254
+ return data[char_info(c) + 1] // 16
255
+
256
+ def depth_index(c):
257
+ return data[char_info(c) + 1] % 16
258
+
259
+ def italic_index(c):
260
+ return data[char_info(c) + 2] // 4
261
+
262
+ def tag(c):
263
+ return data[char_info(c) + 2] % 4
264
+
265
+ def remainder(c):
266
+ return data[char_info(c) + 3]
267
+
268
+ def width(c):
269
+ r = 4 * (width_base + width_index(c))
270
+ return read_fixed(r, "v")["v"]
271
+
272
+ def height(c):
273
+ r = 4 * (height_base + height_index(c))
274
+ return read_fixed(r, "v")["v"]
275
+
276
+ def depth(c):
277
+ r = 4 * (depth_base + depth_index(c))
278
+ return read_fixed(r, "v")["v"]
279
+
280
+ def italic(c):
281
+ r = 4 * (italic_base + italic_index(c))
282
+ return read_fixed(r, "v")["v"]
283
+
284
+ def exten(c):
285
+ return 4 * (exten_base + remainder(c))
286
+
287
+ def lig_step(i):
288
+ return 4 * (lig_kern_base + i)
289
+
290
+ def lig_kern_command(i):
291
+ command = SimpleNamespace()
292
+ unpack2(LIG_KERN_COMMAND, data[i:], command)
293
+ return command
294
+
295
+ def kern(i):
296
+ r = 4 * (kern_base + i)
297
+ return read_fixed(r, "v")["v"]
298
+
299
+ def param(i):
300
+ return 4 * (param_base + i)
301
+
302
+ def read_fixed(index, key, obj=None):
303
+ ret = unpack2(f">;{key}:{FIXED_FORMAT}", data[index:], obj)
304
+ return ret[0]
305
+
306
+ # Set all attributes to empty values regardless of the header size.
307
+ unpack(HEADER_FORMAT4, [0] * HEADER_SIZE4, self)
308
+
309
+ offset = 24
310
+ length = sizes.lh * 4
311
+ self.extraheader = {}
312
+ if length >= HEADER_SIZE4:
313
+ rest = unpack2(HEADER_FORMAT4, data[offset:], self)[1]
314
+ if self.face < 18:
315
+ s = self.face % 2
316
+ b = self.face // 2
317
+ self.face = "MBL"[b % 3] + "RI"[s] + "RCE"[b // 3]
318
+ for i in range(sizes.lh - HEADER_SIZE4 // 4):
319
+ rest = unpack2(f">;HEADER{i + 18}:l", rest, self.extraheader)[1]
320
+ elif length >= HEADER_SIZE3:
321
+ unpack2(HEADER_FORMAT3, data[offset:], self)
322
+ elif length >= HEADER_SIZE2:
323
+ unpack2(HEADER_FORMAT2, data[offset:], self)
324
+ elif length >= HEADER_SIZE1:
325
+ unpack2(HEADER_FORMAT1, data[offset:], self)
326
+
327
+ self.fonttype = VANILLA
328
+ scheme = self.codingscheme.upper()
329
+ if scheme.startswith("TEX MATH SY"):
330
+ self.fonttype = MATHSY
331
+ elif scheme.startswith("TEX MATH EX"):
332
+ self.fonttype = MATHEX
333
+
334
+ self.fontdimens = {}
335
+ for i in range(sizes.np):
336
+ name = f"PARAMETER{i+1}"
337
+ if i <= 6:
338
+ name = BASE_PARAMS[i]
339
+ elif self.fonttype == MATHSY and i <= 21:
340
+ name = MATHSY_PARAMS[i - 7]
341
+ elif self.fonttype == MATHEX and i <= 12:
342
+ name = MATHEX_PARAMS[i - 7]
343
+ read_fixed(param(i), name, self.fontdimens)
344
+
345
+ lig_kern_map = {}
346
+ self.right_boundary_char = None
347
+ self.left_boundary_char = None
348
+ if sizes.nl > 0:
349
+ cmd = lig_kern_command(lig_step(0))
350
+ if cmd.skip_byte == 255:
351
+ self.right_boundary_char = cmd.next_char
352
+
353
+ cmd = lig_kern_command(lig_step((sizes.nl - 1)))
354
+ if cmd.skip_byte == 255:
355
+ self.left_boundary_char = 256
356
+ r = 256 * cmd.op_byte + cmd.remainder
357
+ lig_kern_map[self.left_boundary_char] = r
358
+
359
+ self.chars = {}
360
+ for c in range(sizes.bc, sizes.ec + 1):
361
+ if width_index(c) > 0:
362
+ self.chars[c] = info = {}
363
+ info["width"] = width(c)
364
+ if height_index(c) > 0:
365
+ info["height"] = height(c)
366
+ if depth_index(c) > 0:
367
+ info["depth"] = depth(c)
368
+ if italic_index(c) > 0:
369
+ info["italic"] = italic(c)
370
+ char_tag = tag(c)
371
+ if char_tag == NO_TAG:
372
+ pass
373
+ elif char_tag == LIG_TAG:
374
+ lig_kern_map[c] = remainder(c)
375
+ elif char_tag == LIST_TAG:
376
+ info["nextlarger"] = remainder(c)
377
+ elif char_tag == EXT_TAG:
378
+ info["varchar"] = varchar = {}
379
+ for i in range(4):
380
+ part = data[exten(c) + i]
381
+ if i == 3 or part > 0:
382
+ name = "rep"
383
+ if i == 0:
384
+ name = "top"
385
+ elif i == 1:
386
+ name = "mid"
387
+ elif i == 2:
388
+ name = "bot"
389
+ if noneexistent(part):
390
+ varchar[name] = c
391
+ else:
392
+ varchar[name] = part
393
+
394
+ self.ligatures = {}
395
+ self.kerning = {}
396
+ for c, i in sorted(lig_kern_map.items()):
397
+ cmd = lig_kern_command(lig_step(i))
398
+ if cmd.skip_byte > STOP_FLAG:
399
+ i = 256 * cmd.op_byte + cmd.remainder
400
+
401
+ while i < sizes.nl:
402
+ cmd = lig_kern_command(lig_step(i))
403
+ if cmd.skip_byte > STOP_FLAG:
404
+ pass
405
+ else:
406
+ if cmd.op_byte >= KERN_FLAG:
407
+ r = 256 * (cmd.op_byte - KERN_FLAG) + cmd.remainder
408
+ self.kerning.setdefault(c, {})[cmd.next_char] = kern(r)
409
+ else:
410
+ r = cmd.op_byte
411
+ if r == 4 or (r > 7 and r != 11):
412
+ # Ligature step with nonstandard code, we output
413
+ # the code verbatim.
414
+ lig = r
415
+ else:
416
+ lig = ""
417
+ if r % 4 > 1:
418
+ lig += "/"
419
+ lig += "LIG"
420
+ if r % 2 != 0:
421
+ lig += "/"
422
+ while r > 3:
423
+ lig += ">"
424
+ r -= 4
425
+ self.ligatures.setdefault(c, {})[cmd.next_char] = (
426
+ lig,
427
+ cmd.remainder,
428
+ )
429
+
430
+ if cmd.skip_byte >= STOP_FLAG:
431
+ break
432
+ i += cmd.skip_byte + 1
433
+
434
+
435
+ if __name__ == "__main__":
436
+ import sys
437
+
438
+ tfm = TFM(sys.argv[1])
439
+ print(
440
+ "\n".join(
441
+ x
442
+ for x in [
443
+ f"tfm.checksum={tfm.checksum}",
444
+ f"tfm.designsize={tfm.designsize}",
445
+ f"tfm.codingscheme={tfm.codingscheme}",
446
+ f"tfm.fonttype={tfm.fonttype}",
447
+ f"tfm.family={tfm.family}",
448
+ f"tfm.seven_bit_safe_flag={tfm.seven_bit_safe_flag}",
449
+ f"tfm.face={tfm.face}",
450
+ f"tfm.extraheader={tfm.extraheader}",
451
+ f"tfm.fontdimens={tfm.fontdimens}",
452
+ f"tfm.right_boundary_char={tfm.right_boundary_char}",
453
+ f"tfm.left_boundary_char={tfm.left_boundary_char}",
454
+ f"tfm.kerning={tfm.kerning}",
455
+ f"tfm.ligatures={tfm.ligatures}",
456
+ f"tfm.chars={tfm.chars}",
457
+ ]
458
+ )
459
+ )
460
+ print(tfm)
@@ -0,0 +1,30 @@
1
+ """fontTools.ttLib -- a package for dealing with TrueType fonts."""
2
+
3
+ from fontTools.config import OPTIONS
4
+ from fontTools.misc.loggingTools import deprecateFunction
5
+ import logging
6
+
7
+
8
+ log = logging.getLogger(__name__)
9
+
10
+
11
+ OPTIMIZE_FONT_SPEED = OPTIONS["fontTools.ttLib:OPTIMIZE_FONT_SPEED"]
12
+
13
+
14
+ class TTLibError(Exception):
15
+ pass
16
+
17
+
18
+ class TTLibFileIsCollectionError(TTLibError):
19
+ pass
20
+
21
+
22
+ @deprecateFunction("use logging instead", category=DeprecationWarning)
23
+ def debugmsg(msg):
24
+ import time
25
+
26
+ print(msg + time.strftime(" (%H:%M:%S)", time.localtime(time.time())))
27
+
28
+
29
+ from fontTools.ttLib.ttFont import *
30
+ from fontTools.ttLib.ttCollection import TTCollection
@@ -0,0 +1,148 @@
1
+ import sys
2
+ from fontTools.ttLib import OPTIMIZE_FONT_SPEED, TTLibError, TTLibFileIsCollectionError
3
+ from fontTools.ttLib.ttFont import *
4
+ from fontTools.ttLib.ttCollection import TTCollection
5
+
6
+
7
+ def main(args=None):
8
+ """Open/save fonts with TTFont() or TTCollection()
9
+
10
+ ./fonttools ttLib [-oFILE] [-yNUMBER] files...
11
+
12
+ If multiple files are given on the command-line,
13
+ they are each opened (as a font or collection),
14
+ and added to the font list.
15
+
16
+ If -o (output-file) argument is given, the font
17
+ list is then saved to the output file, either as
18
+ a single font, if there is only one font, or as
19
+ a collection otherwise.
20
+
21
+ If -y (font-number) argument is given, only the
22
+ specified font from collections is opened.
23
+
24
+ The above allow extracting a single font from a
25
+ collection, or combining multiple fonts into a
26
+ collection.
27
+
28
+ If --lazy or --no-lazy are give, those are passed
29
+ to the TTFont() or TTCollection() constructors.
30
+ """
31
+ from fontTools import configLogger
32
+
33
+ if args is None:
34
+ args = sys.argv[1:]
35
+
36
+ import argparse
37
+
38
+ parser = argparse.ArgumentParser(
39
+ "fonttools ttLib",
40
+ description="Open/save fonts with TTFont() or TTCollection()",
41
+ epilog="""
42
+ If multiple files are given on the command-line,
43
+ they are each opened (as a font or collection),
44
+ and added to the font list.
45
+
46
+ The above, when combined with -o / --output,
47
+ allows for extracting a single font from a
48
+ collection, or combining multiple fonts into a
49
+ collection.
50
+ """,
51
+ )
52
+ parser.add_argument("font", metavar="font", nargs="*", help="Font file.")
53
+ parser.add_argument(
54
+ "-t", "--table", metavar="table", action="append", help="Tables to decompile."
55
+ )
56
+ parser.add_argument(
57
+ "-o", "--output", metavar="FILE", default=None, help="Output file."
58
+ )
59
+ parser.add_argument(
60
+ "-y", metavar="NUMBER", default=-1, help="Font number to load from collections."
61
+ )
62
+ parser.add_argument(
63
+ "--lazy", action="store_true", default=None, help="Load fonts lazily."
64
+ )
65
+ parser.add_argument(
66
+ "--no-lazy", dest="lazy", action="store_false", help="Load fonts immediately."
67
+ )
68
+ parser.add_argument(
69
+ "--flavor",
70
+ dest="flavor",
71
+ default=None,
72
+ help="Flavor of output font. 'woff' or 'woff2'.",
73
+ )
74
+ parser.add_argument(
75
+ "--no-recalc-timestamp",
76
+ dest="recalcTimestamp",
77
+ action="store_false",
78
+ help="Keep the original font 'modified' timestamp.",
79
+ )
80
+ parser.add_argument(
81
+ "-b",
82
+ dest="recalcBBoxes",
83
+ action="store_false",
84
+ help="Don't recalc glyph bounding boxes: use the values in the original font.",
85
+ )
86
+ parser.add_argument(
87
+ "--optimize-font-speed",
88
+ action="store_true",
89
+ help=(
90
+ "Enable optimizations that prioritize speed over file size. This "
91
+ "mainly affects how glyf table and gvar / VARC tables are compiled."
92
+ ),
93
+ )
94
+ options = parser.parse_args(args)
95
+
96
+ fontNumber = int(options.y) if options.y is not None else None
97
+ outFile = options.output
98
+ lazy = options.lazy
99
+ flavor = options.flavor
100
+ tables = options.table
101
+ recalcBBoxes = options.recalcBBoxes
102
+ recalcTimestamp = options.recalcTimestamp
103
+ optimizeFontSpeed = options.optimize_font_speed
104
+
105
+ fonts = []
106
+ for f in options.font:
107
+ try:
108
+ font = TTFont(
109
+ f,
110
+ recalcBBoxes=recalcBBoxes,
111
+ recalcTimestamp=recalcTimestamp,
112
+ fontNumber=fontNumber,
113
+ lazy=lazy,
114
+ )
115
+ if optimizeFontSpeed:
116
+ font.cfg[OPTIMIZE_FONT_SPEED] = optimizeFontSpeed
117
+ fonts.append(font)
118
+ except TTLibFileIsCollectionError:
119
+ collection = TTCollection(f, lazy=lazy)
120
+ fonts.extend(collection.fonts)
121
+
122
+ if tables is None:
123
+ if lazy is False:
124
+ tables = ["*"]
125
+ elif optimizeFontSpeed:
126
+ tables = {"glyf", "gvar", "VARC"}.intersection(font.keys())
127
+ else:
128
+ tables = []
129
+ for font in fonts:
130
+ if "GlyphOrder" in tables:
131
+ font.getGlyphOrder()
132
+ for table in tables if "*" not in tables else font.keys():
133
+ font[table] # Decompiles
134
+
135
+ if outFile is not None:
136
+ if len(fonts) == 1:
137
+ fonts[0].flavor = flavor
138
+ fonts[0].save(outFile)
139
+ else:
140
+ if flavor is not None:
141
+ raise TTLibError("Cannot set flavor for collections.")
142
+ collection = TTCollection()
143
+ collection.fonts = fonts
144
+ collection.save(outFile)
145
+
146
+
147
+ if __name__ == "__main__":
148
+ sys.exit(main())
@@ -0,0 +1,54 @@
1
+ """ttLib.macUtils.py -- Various Mac-specific stuff."""
2
+
3
+ from io import BytesIO
4
+ from fontTools.misc.macRes import ResourceReader, ResourceError
5
+
6
+
7
+ def getSFNTResIndices(path):
8
+ """Determine whether a file has a 'sfnt' resource fork or not."""
9
+ try:
10
+ reader = ResourceReader(path)
11
+ indices = reader.getIndices("sfnt")
12
+ reader.close()
13
+ return indices
14
+ except ResourceError:
15
+ return []
16
+
17
+
18
+ def openTTFonts(path):
19
+ """Given a pathname, return a list of TTFont objects. In the case
20
+ of a flat TTF/OTF file, the list will contain just one font object;
21
+ but in the case of a Mac font suitcase it will contain as many
22
+ font objects as there are sfnt resources in the file.
23
+ """
24
+ from fontTools import ttLib
25
+
26
+ fonts = []
27
+ sfnts = getSFNTResIndices(path)
28
+ if not sfnts:
29
+ fonts.append(ttLib.TTFont(path))
30
+ else:
31
+ for index in sfnts:
32
+ fonts.append(ttLib.TTFont(path, index))
33
+ if not fonts:
34
+ raise ttLib.TTLibError("no fonts found in file '%s'" % path)
35
+ return fonts
36
+
37
+
38
+ class SFNTResourceReader(BytesIO):
39
+ """Simple read-only file wrapper for 'sfnt' resources."""
40
+
41
+ def __init__(self, path, res_name_or_index):
42
+ from fontTools import ttLib
43
+
44
+ reader = ResourceReader(path)
45
+ if isinstance(res_name_or_index, str):
46
+ rsrc = reader.getNamedResource("sfnt", res_name_or_index)
47
+ else:
48
+ rsrc = reader.getIndResource("sfnt", res_name_or_index)
49
+ if rsrc is None:
50
+ raise ttLib.TTLibError("sfnt resource not found: %s" % res_name_or_index)
51
+ reader.close()
52
+ self.rsrc = rsrc
53
+ super(SFNTResourceReader, self).__init__(rsrc.data)
54
+ self.name = path