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,163 @@
1
+ """Methods for traversing trees of otData-driven OpenType tables."""
2
+
3
+ from collections import deque
4
+ from typing import Callable, Deque, Iterable, List, Optional, Tuple
5
+ from .otBase import BaseTable
6
+
7
+
8
+ __all__ = [
9
+ "bfs_base_table",
10
+ "dfs_base_table",
11
+ "SubTablePath",
12
+ ]
13
+
14
+
15
+ class SubTablePath(Tuple[BaseTable.SubTableEntry, ...]):
16
+ def __str__(self) -> str:
17
+ path_parts = []
18
+ for entry in self:
19
+ path_part = entry.name
20
+ if entry.index is not None:
21
+ path_part += f"[{entry.index}]"
22
+ path_parts.append(path_part)
23
+ return ".".join(path_parts)
24
+
25
+
26
+ # Given f(current frontier, new entries) add new entries to frontier
27
+ AddToFrontierFn = Callable[[Deque[SubTablePath], List[SubTablePath]], None]
28
+
29
+
30
+ def dfs_base_table(
31
+ root: BaseTable,
32
+ root_accessor: Optional[str] = None,
33
+ skip_root: bool = False,
34
+ predicate: Optional[Callable[[SubTablePath], bool]] = None,
35
+ iter_subtables_fn: Optional[
36
+ Callable[[BaseTable], Iterable[BaseTable.SubTableEntry]]
37
+ ] = None,
38
+ ) -> Iterable[SubTablePath]:
39
+ """Depth-first search tree of BaseTables.
40
+
41
+ Args:
42
+ root (BaseTable): the root of the tree.
43
+ root_accessor (Optional[str]): attribute name for the root table, if any (mostly
44
+ useful for debugging).
45
+ skip_root (Optional[bool]): if True, the root itself is not visited, only its
46
+ children.
47
+ predicate (Optional[Callable[[SubTablePath], bool]]): function to filter out
48
+ paths. If True, the path is yielded and its subtables are added to the
49
+ queue. If False, the path is skipped and its subtables are not traversed.
50
+ iter_subtables_fn (Optional[Callable[[BaseTable], Iterable[BaseTable.SubTableEntry]]]):
51
+ function to iterate over subtables of a table. If None, the default
52
+ BaseTable.iterSubTables() is used.
53
+
54
+ Yields:
55
+ SubTablePath: tuples of BaseTable.SubTableEntry(name, table, index) namedtuples
56
+ for each of the nodes in the tree. The last entry in a path is the current
57
+ subtable, whereas preceding ones refer to its parent tables all the way up to
58
+ the root.
59
+ """
60
+ yield from _traverse_ot_data(
61
+ root,
62
+ root_accessor,
63
+ skip_root,
64
+ predicate,
65
+ lambda frontier, new: frontier.extendleft(reversed(new)),
66
+ iter_subtables_fn,
67
+ )
68
+
69
+
70
+ def bfs_base_table(
71
+ root: BaseTable,
72
+ root_accessor: Optional[str] = None,
73
+ skip_root: bool = False,
74
+ predicate: Optional[Callable[[SubTablePath], bool]] = None,
75
+ iter_subtables_fn: Optional[
76
+ Callable[[BaseTable], Iterable[BaseTable.SubTableEntry]]
77
+ ] = None,
78
+ ) -> Iterable[SubTablePath]:
79
+ """Breadth-first search tree of BaseTables.
80
+
81
+ Args:
82
+ root
83
+ the root of the tree.
84
+ root_accessor (Optional[str]): attribute name for the root table, if any (mostly
85
+ useful for debugging).
86
+ skip_root (Optional[bool]): if True, the root itself is not visited, only its
87
+ children.
88
+ predicate (Optional[Callable[[SubTablePath], bool]]): function to filter out
89
+ paths. If True, the path is yielded and its subtables are added to the
90
+ queue. If False, the path is skipped and its subtables are not traversed.
91
+ iter_subtables_fn (Optional[Callable[[BaseTable], Iterable[BaseTable.SubTableEntry]]]):
92
+ function to iterate over subtables of a table. If None, the default
93
+ BaseTable.iterSubTables() is used.
94
+
95
+ Yields:
96
+ SubTablePath: tuples of BaseTable.SubTableEntry(name, table, index) namedtuples
97
+ for each of the nodes in the tree. The last entry in a path is the current
98
+ subtable, whereas preceding ones refer to its parent tables all the way up to
99
+ the root.
100
+ """
101
+ yield from _traverse_ot_data(
102
+ root,
103
+ root_accessor,
104
+ skip_root,
105
+ predicate,
106
+ lambda frontier, new: frontier.extend(new),
107
+ iter_subtables_fn,
108
+ )
109
+
110
+
111
+ def _traverse_ot_data(
112
+ root: BaseTable,
113
+ root_accessor: Optional[str],
114
+ skip_root: bool,
115
+ predicate: Optional[Callable[[SubTablePath], bool]],
116
+ add_to_frontier_fn: AddToFrontierFn,
117
+ iter_subtables_fn: Optional[
118
+ Callable[[BaseTable], Iterable[BaseTable.SubTableEntry]]
119
+ ] = None,
120
+ ) -> Iterable[SubTablePath]:
121
+ # no visited because general otData cannot cycle (forward-offset only)
122
+ if root_accessor is None:
123
+ root_accessor = type(root).__name__
124
+
125
+ if predicate is None:
126
+
127
+ def predicate(path):
128
+ return True
129
+
130
+ if iter_subtables_fn is None:
131
+
132
+ def iter_subtables_fn(table):
133
+ return table.iterSubTables()
134
+
135
+ frontier: Deque[SubTablePath] = deque()
136
+
137
+ root_entry = BaseTable.SubTableEntry(root_accessor, root)
138
+ if not skip_root:
139
+ frontier.append((root_entry,))
140
+ else:
141
+ add_to_frontier_fn(
142
+ frontier,
143
+ [
144
+ (root_entry, subtable_entry)
145
+ for subtable_entry in iter_subtables_fn(root)
146
+ ],
147
+ )
148
+
149
+ while frontier:
150
+ # path is (value, attr_name) tuples. attr_name is attr of parent to get value
151
+ path = frontier.popleft()
152
+ current = path[-1].value
153
+
154
+ if not predicate(path):
155
+ continue
156
+
157
+ yield SubTablePath(path)
158
+
159
+ new_entries = [
160
+ path + (subtable_entry,) for subtable_entry in iter_subtables_fn(current)
161
+ ]
162
+
163
+ add_to_frontier_fn(frontier, new_entries)
@@ -0,0 +1,149 @@
1
+ from fontTools.misc import sstruct
2
+ from fontTools.misc.textTools import readHex, safeEval
3
+ import struct
4
+
5
+
6
+ sbixGlyphHeaderFormat = """
7
+ >
8
+ originOffsetX: h # The x-value of the point in the glyph relative to its
9
+ # lower-left corner which corresponds to the origin of
10
+ # the glyph on the screen, that is the point on the
11
+ # baseline at the left edge of the glyph.
12
+ originOffsetY: h # The y-value of the point in the glyph relative to its
13
+ # lower-left corner which corresponds to the origin of
14
+ # the glyph on the screen, that is the point on the
15
+ # baseline at the left edge of the glyph.
16
+ graphicType: 4s # e.g. "png "
17
+ """
18
+
19
+ sbixGlyphHeaderFormatSize = sstruct.calcsize(sbixGlyphHeaderFormat)
20
+
21
+
22
+ class Glyph(object):
23
+ def __init__(
24
+ self,
25
+ glyphName=None,
26
+ referenceGlyphName=None,
27
+ originOffsetX=0,
28
+ originOffsetY=0,
29
+ graphicType=None,
30
+ imageData=None,
31
+ rawdata=None,
32
+ gid=0,
33
+ ):
34
+ self.gid = gid
35
+ self.glyphName = glyphName
36
+ self.referenceGlyphName = referenceGlyphName
37
+ self.originOffsetX = originOffsetX
38
+ self.originOffsetY = originOffsetY
39
+ self.rawdata = rawdata
40
+ self.graphicType = graphicType
41
+ self.imageData = imageData
42
+
43
+ # fix self.graphicType if it is null terminated or too short
44
+ if self.graphicType is not None:
45
+ if self.graphicType[-1] == "\0":
46
+ self.graphicType = self.graphicType[:-1]
47
+ if len(self.graphicType) > 4:
48
+ from fontTools import ttLib
49
+
50
+ raise ttLib.TTLibError(
51
+ "Glyph.graphicType must not be longer than 4 characters."
52
+ )
53
+ elif len(self.graphicType) < 4:
54
+ # pad with spaces
55
+ self.graphicType += " "[: (4 - len(self.graphicType))]
56
+
57
+ def is_reference_type(self):
58
+ """Returns True if this glyph is a reference to another glyph's image data."""
59
+ return self.graphicType == "dupe" or self.graphicType == "flip"
60
+
61
+ def decompile(self, ttFont):
62
+ self.glyphName = ttFont.getGlyphName(self.gid)
63
+ if self.rawdata is None:
64
+ from fontTools import ttLib
65
+
66
+ raise ttLib.TTLibError("No table data to decompile")
67
+ if len(self.rawdata) > 0:
68
+ if len(self.rawdata) < sbixGlyphHeaderFormatSize:
69
+ from fontTools import ttLib
70
+
71
+ # print "Glyph %i header too short: Expected %x, got %x." % (self.gid, sbixGlyphHeaderFormatSize, len(self.rawdata))
72
+ raise ttLib.TTLibError("Glyph header too short.")
73
+
74
+ sstruct.unpack(
75
+ sbixGlyphHeaderFormat, self.rawdata[:sbixGlyphHeaderFormatSize], self
76
+ )
77
+
78
+ if self.is_reference_type():
79
+ # this glyph is a reference to another glyph's image data
80
+ (gid,) = struct.unpack(">H", self.rawdata[sbixGlyphHeaderFormatSize:])
81
+ self.referenceGlyphName = ttFont.getGlyphName(gid)
82
+ else:
83
+ self.imageData = self.rawdata[sbixGlyphHeaderFormatSize:]
84
+ self.referenceGlyphName = None
85
+ # clean up
86
+ del self.rawdata
87
+ del self.gid
88
+
89
+ def compile(self, ttFont):
90
+ if self.glyphName is None:
91
+ from fontTools import ttLib
92
+
93
+ raise ttLib.TTLibError("Can't compile Glyph without glyph name")
94
+ # TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index?
95
+ # (needed if you just want to compile the sbix table on its own)
96
+ self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName))
97
+ if self.graphicType is None:
98
+ rawdata = b""
99
+ else:
100
+ rawdata = sstruct.pack(sbixGlyphHeaderFormat, self)
101
+ if self.is_reference_type():
102
+ rawdata += struct.pack(">H", ttFont.getGlyphID(self.referenceGlyphName))
103
+ else:
104
+ assert self.imageData is not None
105
+ rawdata += self.imageData
106
+ self.rawdata = rawdata
107
+
108
+ def toXML(self, xmlWriter, ttFont):
109
+ if self.graphicType is None:
110
+ # TODO: ignore empty glyphs?
111
+ # a glyph data entry is required for each glyph,
112
+ # but empty ones can be calculated at compile time
113
+ xmlWriter.simpletag("glyph", name=self.glyphName)
114
+ xmlWriter.newline()
115
+ return
116
+ xmlWriter.begintag(
117
+ "glyph",
118
+ graphicType=self.graphicType,
119
+ name=self.glyphName,
120
+ originOffsetX=self.originOffsetX,
121
+ originOffsetY=self.originOffsetY,
122
+ )
123
+ xmlWriter.newline()
124
+ if self.is_reference_type():
125
+ # this glyph is a reference to another glyph id.
126
+ xmlWriter.simpletag("ref", glyphname=self.referenceGlyphName)
127
+ else:
128
+ xmlWriter.begintag("hexdata")
129
+ xmlWriter.newline()
130
+ xmlWriter.dumphex(self.imageData)
131
+ xmlWriter.endtag("hexdata")
132
+ xmlWriter.newline()
133
+ xmlWriter.endtag("glyph")
134
+ xmlWriter.newline()
135
+
136
+ def fromXML(self, name, attrs, content, ttFont):
137
+ if name == "ref":
138
+ # this glyph i.e. a reference to another glyph's image data.
139
+ # in this case imageData contains the glyph id of the reference glyph
140
+ # get glyph id from glyphname
141
+ glyphname = safeEval("'''" + attrs["glyphname"] + "'''")
142
+ self.imageData = struct.pack(">H", ttFont.getGlyphID(glyphname))
143
+ self.referenceGlyphName = glyphname
144
+ elif name == "hexdata":
145
+ self.imageData = readHex(content)
146
+ else:
147
+ from fontTools import ttLib
148
+
149
+ raise ttLib.TTLibError("can't handle '%s' element" % name)
@@ -0,0 +1,177 @@
1
+ from fontTools.misc import sstruct
2
+ from fontTools.misc.textTools import safeEval
3
+ from .sbixGlyph import Glyph
4
+ import struct
5
+
6
+ sbixStrikeHeaderFormat = """
7
+ >
8
+ ppem: H # The PPEM for which this strike was designed (e.g., 9,
9
+ # 12, 24)
10
+ resolution: H # The screen resolution (in dpi) for which this strike
11
+ # was designed (e.g., 72)
12
+ """
13
+
14
+ sbixGlyphDataOffsetFormat = """
15
+ >
16
+ glyphDataOffset: L # Offset from the beginning of the strike data record
17
+ # to data for the individual glyph
18
+ """
19
+
20
+ sbixStrikeHeaderFormatSize = sstruct.calcsize(sbixStrikeHeaderFormat)
21
+ sbixGlyphDataOffsetFormatSize = sstruct.calcsize(sbixGlyphDataOffsetFormat)
22
+
23
+
24
+ class Strike(object):
25
+ def __init__(self, rawdata=None, ppem=0, resolution=72):
26
+ self.data = rawdata
27
+ self.ppem = ppem
28
+ self.resolution = resolution
29
+ self.glyphs = {}
30
+
31
+ def decompile(self, ttFont):
32
+ if self.data is None:
33
+ from fontTools import ttLib
34
+
35
+ raise ttLib.TTLibError
36
+ if len(self.data) < sbixStrikeHeaderFormatSize:
37
+ from fontTools import ttLib
38
+
39
+ raise (
40
+ ttLib.TTLibError,
41
+ "Strike header too short: Expected %x, got %x.",
42
+ ) % (sbixStrikeHeaderFormatSize, len(self.data))
43
+
44
+ # read Strike header from raw data
45
+ sstruct.unpack(
46
+ sbixStrikeHeaderFormat, self.data[:sbixStrikeHeaderFormatSize], self
47
+ )
48
+
49
+ # calculate number of glyphs
50
+ (firstGlyphDataOffset,) = struct.unpack(
51
+ ">L",
52
+ self.data[
53
+ sbixStrikeHeaderFormatSize : sbixStrikeHeaderFormatSize
54
+ + sbixGlyphDataOffsetFormatSize
55
+ ],
56
+ )
57
+ self.numGlyphs = (
58
+ firstGlyphDataOffset - sbixStrikeHeaderFormatSize
59
+ ) // sbixGlyphDataOffsetFormatSize - 1
60
+ # ^ -1 because there's one more offset than glyphs
61
+
62
+ # build offset list for single glyph data offsets
63
+ self.glyphDataOffsets = []
64
+ for i in range(
65
+ self.numGlyphs + 1
66
+ ): # + 1 because there's one more offset than glyphs
67
+ start = i * sbixGlyphDataOffsetFormatSize + sbixStrikeHeaderFormatSize
68
+ (current_offset,) = struct.unpack(
69
+ ">L", self.data[start : start + sbixGlyphDataOffsetFormatSize]
70
+ )
71
+ self.glyphDataOffsets.append(current_offset)
72
+
73
+ # iterate through offset list and slice raw data into glyph data records
74
+ for i in range(self.numGlyphs):
75
+ current_glyph = Glyph(
76
+ rawdata=self.data[
77
+ self.glyphDataOffsets[i] : self.glyphDataOffsets[i + 1]
78
+ ],
79
+ gid=i,
80
+ )
81
+ current_glyph.decompile(ttFont)
82
+ self.glyphs[current_glyph.glyphName] = current_glyph
83
+ del self.glyphDataOffsets
84
+ del self.numGlyphs
85
+ del self.data
86
+
87
+ def compile(self, ttFont):
88
+ self.glyphDataOffsets = b""
89
+ self.bitmapData = b""
90
+
91
+ glyphOrder = ttFont.getGlyphOrder()
92
+
93
+ # first glyph starts right after the header
94
+ currentGlyphDataOffset = (
95
+ sbixStrikeHeaderFormatSize
96
+ + sbixGlyphDataOffsetFormatSize * (len(glyphOrder) + 1)
97
+ )
98
+ for glyphName in glyphOrder:
99
+ if glyphName in self.glyphs:
100
+ # we have glyph data for this glyph
101
+ current_glyph = self.glyphs[glyphName]
102
+ else:
103
+ # must add empty glyph data record for this glyph
104
+ current_glyph = Glyph(glyphName=glyphName)
105
+ current_glyph.compile(ttFont)
106
+ current_glyph.glyphDataOffset = currentGlyphDataOffset
107
+ self.bitmapData += current_glyph.rawdata
108
+ currentGlyphDataOffset += len(current_glyph.rawdata)
109
+ self.glyphDataOffsets += sstruct.pack(
110
+ sbixGlyphDataOffsetFormat, current_glyph
111
+ )
112
+
113
+ # add last "offset", really the end address of the last glyph data record
114
+ dummy = Glyph()
115
+ dummy.glyphDataOffset = currentGlyphDataOffset
116
+ self.glyphDataOffsets += sstruct.pack(sbixGlyphDataOffsetFormat, dummy)
117
+
118
+ # pack header
119
+ self.data = sstruct.pack(sbixStrikeHeaderFormat, self)
120
+ # add offsets and image data after header
121
+ self.data += self.glyphDataOffsets + self.bitmapData
122
+
123
+ def toXML(self, xmlWriter, ttFont):
124
+ xmlWriter.begintag("strike")
125
+ xmlWriter.newline()
126
+ xmlWriter.simpletag("ppem", value=self.ppem)
127
+ xmlWriter.newline()
128
+ xmlWriter.simpletag("resolution", value=self.resolution)
129
+ xmlWriter.newline()
130
+ glyphOrder = ttFont.getGlyphOrder()
131
+ for glyphName in glyphOrder:
132
+ if glyphName in self.glyphs:
133
+ self.glyphs[glyphName].toXML(xmlWriter, ttFont)
134
+ # TODO: what if there are more glyph data records than (glyf table) glyphs?
135
+ xmlWriter.endtag("strike")
136
+ xmlWriter.newline()
137
+
138
+ def fromXML(self, name, attrs, content, ttFont):
139
+ if name in ["ppem", "resolution"]:
140
+ setattr(self, name, safeEval(attrs["value"]))
141
+ elif name == "glyph":
142
+ if "graphicType" in attrs:
143
+ myFormat = safeEval("'''" + attrs["graphicType"] + "'''")
144
+ else:
145
+ myFormat = None
146
+ if "glyphname" in attrs:
147
+ myGlyphName = safeEval("'''" + attrs["glyphname"] + "'''")
148
+ elif "name" in attrs:
149
+ myGlyphName = safeEval("'''" + attrs["name"] + "'''")
150
+ else:
151
+ from fontTools import ttLib
152
+
153
+ raise ttLib.TTLibError("Glyph must have a glyph name.")
154
+ if "originOffsetX" in attrs:
155
+ myOffsetX = safeEval(attrs["originOffsetX"])
156
+ else:
157
+ myOffsetX = 0
158
+ if "originOffsetY" in attrs:
159
+ myOffsetY = safeEval(attrs["originOffsetY"])
160
+ else:
161
+ myOffsetY = 0
162
+ current_glyph = Glyph(
163
+ glyphName=myGlyphName,
164
+ graphicType=myFormat,
165
+ originOffsetX=myOffsetX,
166
+ originOffsetY=myOffsetY,
167
+ )
168
+ for element in content:
169
+ if isinstance(element, tuple):
170
+ name, attrs, content = element
171
+ current_glyph.fromXML(name, attrs, content, ttFont)
172
+ current_glyph.compile(ttFont)
173
+ self.glyphs[current_glyph.glyphName] = current_glyph
174
+ else:
175
+ from fontTools import ttLib
176
+
177
+ raise ttLib.TTLibError("can't handle '%s' element" % name)
@@ -0,0 +1,91 @@
1
+ This folder is a subpackage of ttLib. Each module here is a
2
+ specialized TT/OT table converter: they can convert raw data
3
+ to Python objects and vice versa. Usually you don't need to
4
+ use the modules directly: they are imported and used
5
+ automatically when needed by ttLib.
6
+
7
+ If you are writing you own table converter the following is
8
+ important.
9
+
10
+ The modules here have pretty strange names: this is due to the
11
+ fact that we need to map TT table tags (which are case sensitive)
12
+ to filenames (which on Mac and Win aren't case sensitive) as well
13
+ as to Python identifiers. The latter means it can only contain
14
+ [A-Za-z0-9_] and cannot start with a number.
15
+
16
+ ttLib provides functions to expand a tag into the format used here:
17
+
18
+ >>> from fontTools import ttLib
19
+ >>> ttLib.tagToIdentifier("FOO ")
20
+ 'F_O_O_'
21
+ >>> ttLib.tagToIdentifier("cvt ")
22
+ '_c_v_t'
23
+ >>> ttLib.tagToIdentifier("OS/2")
24
+ 'O_S_2f_2'
25
+ >>> ttLib.tagToIdentifier("glyf")
26
+ '_g_l_y_f'
27
+ >>>
28
+
29
+ And vice versa:
30
+
31
+ >>> ttLib.identifierToTag("F_O_O_")
32
+ 'FOO '
33
+ >>> ttLib.identifierToTag("_c_v_t")
34
+ 'cvt '
35
+ >>> ttLib.identifierToTag("O_S_2f_2")
36
+ 'OS/2'
37
+ >>> ttLib.identifierToTag("_g_l_y_f")
38
+ 'glyf'
39
+ >>>
40
+
41
+ Eg. the 'glyf' table converter lives in a Python file called:
42
+
43
+ _g_l_y_f.py
44
+
45
+ The converter itself is a class, named "table_" + expandedtag. Eg:
46
+
47
+ class table__g_l_y_f:
48
+ etc.
49
+
50
+ Note that if you _do_ need to use such modules or classes manually,
51
+ there are two convenient API functions that let you find them by tag:
52
+
53
+ >>> ttLib.getTableModule('glyf')
54
+ <module 'ttLib.tables._g_l_y_f'>
55
+ >>> ttLib.getTableClass('glyf')
56
+ <class ttLib.tables._g_l_y_f.table__g_l_y_f at 645f400>
57
+ >>>
58
+
59
+ You must subclass from DefaultTable.DefaultTable. It provides some default
60
+ behavior, as well as a constructor method (__init__) that you don't need to
61
+ override.
62
+
63
+ Your converter should minimally provide two methods:
64
+
65
+ class table_F_O_O_(DefaultTable.DefaultTable): # converter for table 'FOO '
66
+
67
+ def decompile(self, data, ttFont):
68
+ # 'data' is the raw table data. Unpack it into a
69
+ # Python data structure.
70
+ # 'ttFont' is a ttLib.TTfile instance, enabling you to
71
+ # refer to other tables. Do ***not*** keep a reference to
72
+ # it: it will cause a circular reference (ttFont saves
73
+ # a reference to us), and that means we'll be leaking
74
+ # memory. If you need to use it in other methods, just
75
+ # pass it around as a method argument.
76
+
77
+ def compile(self, ttFont):
78
+ # Return the raw data, as converted from the Python
79
+ # data structure.
80
+ # Again, 'ttFont' is there so you can access other tables.
81
+ # Same warning applies.
82
+
83
+ If you want to support TTX import/export as well, you need to provide two
84
+ additional methods:
85
+
86
+ def toXML(self, writer, ttFont):
87
+ # XXX
88
+
89
+ def fromXML(self, (name, attrs, content), ttFont):
90
+ # XXX
91
+