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,332 @@
1
+ from fontTools.misc import sstruct
2
+ from fontTools.misc.fixedTools import (
3
+ fixedToFloat as fi2fl,
4
+ floatToFixed as fl2fi,
5
+ floatToFixedToStr as fl2str,
6
+ strToFixedToFloat as str2fl,
7
+ )
8
+ from fontTools.misc.textTools import bytesjoin, safeEval
9
+ from fontTools.ttLib import TTLibError
10
+ from . import DefaultTable
11
+ import struct
12
+ from collections.abc import MutableMapping
13
+
14
+
15
+ # Apple's documentation of 'trak':
16
+ # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html
17
+
18
+ TRAK_HEADER_FORMAT = """
19
+ > # big endian
20
+ version: 16.16F
21
+ format: H
22
+ horizOffset: H
23
+ vertOffset: H
24
+ reserved: H
25
+ """
26
+
27
+ TRAK_HEADER_FORMAT_SIZE = sstruct.calcsize(TRAK_HEADER_FORMAT)
28
+
29
+
30
+ TRACK_DATA_FORMAT = """
31
+ > # big endian
32
+ nTracks: H
33
+ nSizes: H
34
+ sizeTableOffset: L
35
+ """
36
+
37
+ TRACK_DATA_FORMAT_SIZE = sstruct.calcsize(TRACK_DATA_FORMAT)
38
+
39
+
40
+ TRACK_TABLE_ENTRY_FORMAT = """
41
+ > # big endian
42
+ track: 16.16F
43
+ nameIndex: H
44
+ offset: H
45
+ """
46
+
47
+ TRACK_TABLE_ENTRY_FORMAT_SIZE = sstruct.calcsize(TRACK_TABLE_ENTRY_FORMAT)
48
+
49
+
50
+ # size values are actually '16.16F' fixed-point values, but here I do the
51
+ # fixedToFloat conversion manually instead of relying on sstruct
52
+ SIZE_VALUE_FORMAT = ">l"
53
+ SIZE_VALUE_FORMAT_SIZE = struct.calcsize(SIZE_VALUE_FORMAT)
54
+
55
+ # per-Size values are in 'FUnits', i.e. 16-bit signed integers
56
+ PER_SIZE_VALUE_FORMAT = ">h"
57
+ PER_SIZE_VALUE_FORMAT_SIZE = struct.calcsize(PER_SIZE_VALUE_FORMAT)
58
+
59
+
60
+ class table__t_r_a_k(DefaultTable.DefaultTable):
61
+ """The AAT ``trak`` table can store per-size adjustments to each glyph's
62
+ sidebearings to make when tracking is enabled, which applications can
63
+ use to provide more visually balanced line spacing.
64
+
65
+ See also https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html
66
+ """
67
+
68
+ dependencies = ["name"]
69
+
70
+ def compile(self, ttFont):
71
+ dataList = []
72
+ offset = TRAK_HEADER_FORMAT_SIZE
73
+ for direction in ("horiz", "vert"):
74
+ trackData = getattr(self, direction + "Data", TrackData())
75
+ offsetName = direction + "Offset"
76
+ # set offset to 0 if None or empty
77
+ if not trackData:
78
+ setattr(self, offsetName, 0)
79
+ continue
80
+ # TrackData table format must be longword aligned
81
+ alignedOffset = (offset + 3) & ~3
82
+ padding, offset = b"\x00" * (alignedOffset - offset), alignedOffset
83
+ setattr(self, offsetName, offset)
84
+
85
+ data = trackData.compile(offset)
86
+ offset += len(data)
87
+ dataList.append(padding + data)
88
+
89
+ self.reserved = 0
90
+ tableData = bytesjoin([sstruct.pack(TRAK_HEADER_FORMAT, self)] + dataList)
91
+ return tableData
92
+
93
+ def decompile(self, data, ttFont):
94
+ sstruct.unpack(TRAK_HEADER_FORMAT, data[:TRAK_HEADER_FORMAT_SIZE], self)
95
+ for direction in ("horiz", "vert"):
96
+ trackData = TrackData()
97
+ offset = getattr(self, direction + "Offset")
98
+ if offset != 0:
99
+ trackData.decompile(data, offset)
100
+ setattr(self, direction + "Data", trackData)
101
+
102
+ def toXML(self, writer, ttFont):
103
+ writer.simpletag("version", value=self.version)
104
+ writer.newline()
105
+ writer.simpletag("format", value=self.format)
106
+ writer.newline()
107
+ for direction in ("horiz", "vert"):
108
+ dataName = direction + "Data"
109
+ writer.begintag(dataName)
110
+ writer.newline()
111
+ trackData = getattr(self, dataName, TrackData())
112
+ trackData.toXML(writer, ttFont)
113
+ writer.endtag(dataName)
114
+ writer.newline()
115
+
116
+ def fromXML(self, name, attrs, content, ttFont):
117
+ if name == "version":
118
+ self.version = safeEval(attrs["value"])
119
+ elif name == "format":
120
+ self.format = safeEval(attrs["value"])
121
+ elif name in ("horizData", "vertData"):
122
+ trackData = TrackData()
123
+ setattr(self, name, trackData)
124
+ for element in content:
125
+ if not isinstance(element, tuple):
126
+ continue
127
+ name, attrs, content_ = element
128
+ trackData.fromXML(name, attrs, content_, ttFont)
129
+
130
+
131
+ class TrackData(MutableMapping):
132
+ def __init__(self, initialdata={}):
133
+ self._map = dict(initialdata)
134
+
135
+ def compile(self, offset):
136
+ nTracks = len(self)
137
+ sizes = self.sizes()
138
+ nSizes = len(sizes)
139
+
140
+ # offset to the start of the size subtable
141
+ offset += TRACK_DATA_FORMAT_SIZE + TRACK_TABLE_ENTRY_FORMAT_SIZE * nTracks
142
+ trackDataHeader = sstruct.pack(
143
+ TRACK_DATA_FORMAT,
144
+ {"nTracks": nTracks, "nSizes": nSizes, "sizeTableOffset": offset},
145
+ )
146
+
147
+ entryDataList = []
148
+ perSizeDataList = []
149
+ # offset to per-size tracking values
150
+ offset += SIZE_VALUE_FORMAT_SIZE * nSizes
151
+ # sort track table entries by track value
152
+ for track, entry in sorted(self.items()):
153
+ assert entry.nameIndex is not None
154
+ entry.track = track
155
+ entry.offset = offset
156
+ entryDataList += [sstruct.pack(TRACK_TABLE_ENTRY_FORMAT, entry)]
157
+ # sort per-size values by size
158
+ for size, value in sorted(entry.items()):
159
+ perSizeDataList += [struct.pack(PER_SIZE_VALUE_FORMAT, value)]
160
+ offset += PER_SIZE_VALUE_FORMAT_SIZE * nSizes
161
+ # sort size values
162
+ sizeDataList = [
163
+ struct.pack(SIZE_VALUE_FORMAT, fl2fi(sv, 16)) for sv in sorted(sizes)
164
+ ]
165
+
166
+ data = bytesjoin(
167
+ [trackDataHeader] + entryDataList + sizeDataList + perSizeDataList
168
+ )
169
+ return data
170
+
171
+ def decompile(self, data, offset):
172
+ # initial offset is from the start of trak table to the current TrackData
173
+ trackDataHeader = data[offset : offset + TRACK_DATA_FORMAT_SIZE]
174
+ if len(trackDataHeader) != TRACK_DATA_FORMAT_SIZE:
175
+ raise TTLibError("not enough data to decompile TrackData header")
176
+ sstruct.unpack(TRACK_DATA_FORMAT, trackDataHeader, self)
177
+ offset += TRACK_DATA_FORMAT_SIZE
178
+
179
+ nSizes = self.nSizes
180
+ sizeTableOffset = self.sizeTableOffset
181
+ sizeTable = []
182
+ for i in range(nSizes):
183
+ sizeValueData = data[
184
+ sizeTableOffset : sizeTableOffset + SIZE_VALUE_FORMAT_SIZE
185
+ ]
186
+ if len(sizeValueData) < SIZE_VALUE_FORMAT_SIZE:
187
+ raise TTLibError("not enough data to decompile TrackData size subtable")
188
+ (sizeValue,) = struct.unpack(SIZE_VALUE_FORMAT, sizeValueData)
189
+ sizeTable.append(fi2fl(sizeValue, 16))
190
+ sizeTableOffset += SIZE_VALUE_FORMAT_SIZE
191
+
192
+ for i in range(self.nTracks):
193
+ entry = TrackTableEntry()
194
+ entryData = data[offset : offset + TRACK_TABLE_ENTRY_FORMAT_SIZE]
195
+ if len(entryData) < TRACK_TABLE_ENTRY_FORMAT_SIZE:
196
+ raise TTLibError("not enough data to decompile TrackTableEntry record")
197
+ sstruct.unpack(TRACK_TABLE_ENTRY_FORMAT, entryData, entry)
198
+ perSizeOffset = entry.offset
199
+ for j in range(nSizes):
200
+ size = sizeTable[j]
201
+ perSizeValueData = data[
202
+ perSizeOffset : perSizeOffset + PER_SIZE_VALUE_FORMAT_SIZE
203
+ ]
204
+ if len(perSizeValueData) < PER_SIZE_VALUE_FORMAT_SIZE:
205
+ raise TTLibError(
206
+ "not enough data to decompile per-size track values"
207
+ )
208
+ (perSizeValue,) = struct.unpack(PER_SIZE_VALUE_FORMAT, perSizeValueData)
209
+ entry[size] = perSizeValue
210
+ perSizeOffset += PER_SIZE_VALUE_FORMAT_SIZE
211
+ self[entry.track] = entry
212
+ offset += TRACK_TABLE_ENTRY_FORMAT_SIZE
213
+
214
+ def toXML(self, writer, ttFont):
215
+ nTracks = len(self)
216
+ nSizes = len(self.sizes())
217
+ writer.comment("nTracks=%d, nSizes=%d" % (nTracks, nSizes))
218
+ writer.newline()
219
+ for track, entry in sorted(self.items()):
220
+ assert entry.nameIndex is not None
221
+ entry.track = track
222
+ entry.toXML(writer, ttFont)
223
+
224
+ def fromXML(self, name, attrs, content, ttFont):
225
+ if name != "trackEntry":
226
+ return
227
+ entry = TrackTableEntry()
228
+ entry.fromXML(name, attrs, content, ttFont)
229
+ self[entry.track] = entry
230
+
231
+ def sizes(self):
232
+ if not self:
233
+ return frozenset()
234
+ tracks = list(self.tracks())
235
+ sizes = self[tracks.pop(0)].sizes()
236
+ for track in tracks:
237
+ entrySizes = self[track].sizes()
238
+ if sizes != entrySizes:
239
+ raise TTLibError(
240
+ "'trak' table entries must specify the same sizes: "
241
+ "%s != %s" % (sorted(sizes), sorted(entrySizes))
242
+ )
243
+ return frozenset(sizes)
244
+
245
+ def __getitem__(self, track):
246
+ return self._map[track]
247
+
248
+ def __delitem__(self, track):
249
+ del self._map[track]
250
+
251
+ def __setitem__(self, track, entry):
252
+ self._map[track] = entry
253
+
254
+ def __len__(self):
255
+ return len(self._map)
256
+
257
+ def __iter__(self):
258
+ return iter(self._map)
259
+
260
+ def keys(self):
261
+ return self._map.keys()
262
+
263
+ tracks = keys
264
+
265
+ def __repr__(self):
266
+ return "TrackData({})".format(self._map if self else "")
267
+
268
+
269
+ class TrackTableEntry(MutableMapping):
270
+ def __init__(self, values={}, nameIndex=None):
271
+ self.nameIndex = nameIndex
272
+ self._map = dict(values)
273
+
274
+ def toXML(self, writer, ttFont):
275
+ name = ttFont["name"].getDebugName(self.nameIndex)
276
+ writer.begintag(
277
+ "trackEntry",
278
+ (("value", fl2str(self.track, 16)), ("nameIndex", self.nameIndex)),
279
+ )
280
+ writer.newline()
281
+ if name:
282
+ writer.comment(name)
283
+ writer.newline()
284
+ for size, perSizeValue in sorted(self.items()):
285
+ writer.simpletag("track", size=fl2str(size, 16), value=perSizeValue)
286
+ writer.newline()
287
+ writer.endtag("trackEntry")
288
+ writer.newline()
289
+
290
+ def fromXML(self, name, attrs, content, ttFont):
291
+ self.track = str2fl(attrs["value"], 16)
292
+ self.nameIndex = safeEval(attrs["nameIndex"])
293
+ for element in content:
294
+ if not isinstance(element, tuple):
295
+ continue
296
+ name, attrs, _ = element
297
+ if name != "track":
298
+ continue
299
+ size = str2fl(attrs["size"], 16)
300
+ self[size] = safeEval(attrs["value"])
301
+
302
+ def __getitem__(self, size):
303
+ return self._map[size]
304
+
305
+ def __delitem__(self, size):
306
+ del self._map[size]
307
+
308
+ def __setitem__(self, size, value):
309
+ self._map[size] = value
310
+
311
+ def __len__(self):
312
+ return len(self._map)
313
+
314
+ def __iter__(self):
315
+ return iter(self._map)
316
+
317
+ def keys(self):
318
+ return self._map.keys()
319
+
320
+ sizes = keys
321
+
322
+ def __repr__(self):
323
+ return "TrackTableEntry({}, nameIndex={})".format(self._map, self.nameIndex)
324
+
325
+ def __eq__(self, other):
326
+ if not isinstance(other, self.__class__):
327
+ return NotImplemented
328
+ return self.nameIndex == other.nameIndex and dict(self) == dict(other)
329
+
330
+ def __ne__(self, other):
331
+ result = self.__eq__(other)
332
+ return result if result is NotImplemented else not result
@@ -0,0 +1,139 @@
1
+ from fontTools.misc import sstruct
2
+ from fontTools.misc.textTools import safeEval
3
+ from fontTools.misc.fixedTools import (
4
+ ensureVersionIsLong as fi2ve,
5
+ versionToFixed as ve2fi,
6
+ )
7
+ from . import DefaultTable
8
+ import math
9
+
10
+
11
+ vheaFormat = """
12
+ > # big endian
13
+ tableVersion: L
14
+ ascent: h
15
+ descent: h
16
+ lineGap: h
17
+ advanceHeightMax: H
18
+ minTopSideBearing: h
19
+ minBottomSideBearing: h
20
+ yMaxExtent: h
21
+ caretSlopeRise: h
22
+ caretSlopeRun: h
23
+ caretOffset: h
24
+ reserved1: h
25
+ reserved2: h
26
+ reserved3: h
27
+ reserved4: h
28
+ metricDataFormat: h
29
+ numberOfVMetrics: H
30
+ """
31
+
32
+
33
+ class table__v_h_e_a(DefaultTable.DefaultTable):
34
+ """Vertical Header table
35
+
36
+ The ``vhea`` table contains information needed during vertical
37
+ text layout.
38
+
39
+ .. note::
40
+ This converter class is kept in sync with the :class:`._h_h_e_a.table__h_h_e_a`
41
+ table constructor.
42
+
43
+ See also https://learn.microsoft.com/en-us/typography/opentype/spec/vhea
44
+ """
45
+
46
+ # Note: Keep in sync with table__h_h_e_a
47
+
48
+ dependencies = ["vmtx", "glyf", "CFF ", "CFF2"]
49
+
50
+ def decompile(self, data, ttFont):
51
+ sstruct.unpack(vheaFormat, data, self)
52
+
53
+ def compile(self, ttFont):
54
+ if ttFont.recalcBBoxes and (
55
+ ttFont.isLoaded("glyf")
56
+ or ttFont.isLoaded("CFF ")
57
+ or ttFont.isLoaded("CFF2")
58
+ ):
59
+ self.recalc(ttFont)
60
+ self.tableVersion = fi2ve(self.tableVersion)
61
+ return sstruct.pack(vheaFormat, self)
62
+
63
+ def recalc(self, ttFont):
64
+ if "vmtx" not in ttFont:
65
+ return
66
+
67
+ vmtxTable = ttFont["vmtx"]
68
+ self.advanceHeightMax = max(adv for adv, _ in vmtxTable.metrics.values())
69
+
70
+ boundsHeightDict = {}
71
+ if "glyf" in ttFont:
72
+ glyfTable = ttFont["glyf"]
73
+ for name in ttFont.getGlyphOrder():
74
+ g = glyfTable[name]
75
+ if g.numberOfContours == 0:
76
+ continue
77
+ if g.numberOfContours < 0 and not hasattr(g, "yMax"):
78
+ # Composite glyph without extents set.
79
+ # Calculate those.
80
+ g.recalcBounds(glyfTable)
81
+ boundsHeightDict[name] = g.yMax - g.yMin
82
+ elif "CFF " in ttFont or "CFF2" in ttFont:
83
+ if "CFF " in ttFont:
84
+ topDict = ttFont["CFF "].cff.topDictIndex[0]
85
+ else:
86
+ topDict = ttFont["CFF2"].cff.topDictIndex[0]
87
+ charStrings = topDict.CharStrings
88
+ for name in ttFont.getGlyphOrder():
89
+ cs = charStrings[name]
90
+ bounds = cs.calcBounds(charStrings)
91
+ if bounds is not None:
92
+ boundsHeightDict[name] = int(
93
+ math.ceil(bounds[3]) - math.floor(bounds[1])
94
+ )
95
+
96
+ if boundsHeightDict:
97
+ minTopSideBearing = float("inf")
98
+ minBottomSideBearing = float("inf")
99
+ yMaxExtent = -float("inf")
100
+ for name, boundsHeight in boundsHeightDict.items():
101
+ advanceHeight, tsb = vmtxTable[name]
102
+ bsb = advanceHeight - tsb - boundsHeight
103
+ extent = tsb + boundsHeight
104
+ minTopSideBearing = min(minTopSideBearing, tsb)
105
+ minBottomSideBearing = min(minBottomSideBearing, bsb)
106
+ yMaxExtent = max(yMaxExtent, extent)
107
+ self.minTopSideBearing = minTopSideBearing
108
+ self.minBottomSideBearing = minBottomSideBearing
109
+ self.yMaxExtent = yMaxExtent
110
+
111
+ else: # No glyph has outlines.
112
+ self.minTopSideBearing = 0
113
+ self.minBottomSideBearing = 0
114
+ self.yMaxExtent = 0
115
+
116
+ def toXML(self, writer, ttFont):
117
+ formatstring, names, fixes = sstruct.getformat(vheaFormat)
118
+ for name in names:
119
+ value = getattr(self, name)
120
+ if name == "tableVersion":
121
+ value = fi2ve(value)
122
+ value = "0x%08x" % value
123
+ writer.simpletag(name, value=value)
124
+ writer.newline()
125
+
126
+ def fromXML(self, name, attrs, content, ttFont):
127
+ if name == "tableVersion":
128
+ setattr(self, name, ve2fi(attrs["value"]))
129
+ return
130
+ setattr(self, name, safeEval(attrs["value"]))
131
+
132
+ # reserved0 is caretOffset for legacy reasons
133
+ @property
134
+ def reserved0(self):
135
+ return self.caretOffset
136
+
137
+ @reserved0.setter
138
+ def reserved0(self, value):
139
+ self.caretOffset = value
@@ -0,0 +1,19 @@
1
+ from fontTools import ttLib
2
+
3
+ superclass = ttLib.getTableClass("hmtx")
4
+
5
+
6
+ class table__v_m_t_x(superclass):
7
+ """Vertical Metrics table
8
+
9
+ The ``vmtx`` table contains per-glyph metrics for the glyphs in a
10
+ ``glyf``, ``CFF ``, or ``CFF2`` table, as needed for vertical text
11
+ layout.
12
+
13
+ See also https://learn.microsoft.com/en-us/typography/opentype/spec/vmtx
14
+ """
15
+
16
+ headerTag = "vhea"
17
+ advanceName = "height"
18
+ sideBearingName = "tsb"
19
+ numberOfMetricsName = "numberOfVMetrics"
@@ -0,0 +1,20 @@
1
+ from fontTools.misc.textTools import strjoin, tobytes, tostr
2
+ from . import DefaultTable
3
+
4
+
5
+ class asciiTable(DefaultTable.DefaultTable):
6
+ def toXML(self, writer, ttFont):
7
+ data = tostr(self.data)
8
+ # removing null bytes. XXX needed??
9
+ data = data.split("\0")
10
+ data = strjoin(data)
11
+ writer.begintag("source")
12
+ writer.newline()
13
+ writer.write_noindent(data)
14
+ writer.newline()
15
+ writer.endtag("source")
16
+ writer.newline()
17
+
18
+ def fromXML(self, name, attrs, content, ttFont):
19
+ lines = strjoin(content).split("\n")
20
+ self.data = tobytes("\n".join(lines[1:-1]))
@@ -0,0 +1,92 @@
1
+ import struct, warnings
2
+
3
+ try:
4
+ import lz4
5
+ except ImportError:
6
+ lz4 = None
7
+ else:
8
+ import lz4.block
9
+
10
+ # old scheme for VERSION < 0.9 otherwise use lz4.block
11
+
12
+
13
+ def decompress(data):
14
+ (compression,) = struct.unpack(">L", data[4:8])
15
+ scheme = compression >> 27
16
+ size = compression & 0x07FFFFFF
17
+ if scheme == 0:
18
+ pass
19
+ elif scheme == 1 and lz4:
20
+ res = lz4.block.decompress(struct.pack("<L", size) + data[8:])
21
+ if len(res) != size:
22
+ warnings.warn("Table decompression failed.")
23
+ else:
24
+ data = res
25
+ else:
26
+ warnings.warn("Table is compressed with an unsupported compression scheme")
27
+ return (data, scheme)
28
+
29
+
30
+ def compress(scheme, data):
31
+ hdr = data[:4] + struct.pack(">L", (scheme << 27) + (len(data) & 0x07FFFFFF))
32
+ if scheme == 0:
33
+ return data
34
+ elif scheme == 1 and lz4:
35
+ res = lz4.block.compress(
36
+ data, mode="high_compression", compression=16, store_size=False
37
+ )
38
+ return hdr + res
39
+ else:
40
+ warnings.warn("Table failed to compress by unsupported compression scheme")
41
+ return data
42
+
43
+
44
+ def _entries(attrs, sameval):
45
+ ak = 0
46
+ vals = []
47
+ lastv = 0
48
+ for k, v in attrs:
49
+ if len(vals) and (k != ak + 1 or (sameval and v != lastv)):
50
+ yield (ak - len(vals) + 1, len(vals), vals)
51
+ vals = []
52
+ ak = k
53
+ vals.append(v)
54
+ lastv = v
55
+ yield (ak - len(vals) + 1, len(vals), vals)
56
+
57
+
58
+ def entries(attributes, sameval=False):
59
+ g = _entries(sorted(attributes.items(), key=lambda x: int(x[0])), sameval)
60
+ return g
61
+
62
+
63
+ def bininfo(num, size=1):
64
+ if num == 0:
65
+ return struct.pack(">4H", 0, 0, 0, 0)
66
+ srange = 1
67
+ select = 0
68
+ while srange <= num:
69
+ srange *= 2
70
+ select += 1
71
+ select -= 1
72
+ srange //= 2
73
+ srange *= size
74
+ shift = num * size - srange
75
+ return struct.pack(">4H", num, srange, select, shift)
76
+
77
+
78
+ def num2tag(n):
79
+ if n < 0x200000:
80
+ return str(n)
81
+ else:
82
+ return (
83
+ struct.unpack("4s", struct.pack(">L", n))[0].replace(b"\000", b"").decode()
84
+ )
85
+
86
+
87
+ def tag2num(n):
88
+ try:
89
+ return int(n)
90
+ except ValueError:
91
+ n = (n + " ")[:4]
92
+ return struct.unpack(">L", n.encode("ascii"))[0]