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,1040 @@
1
+ from fontTools.misc import sstruct
2
+ from fontTools.misc.fixedTools import floatToFixedToStr
3
+ from fontTools.misc.textTools import byteord, safeEval
4
+
5
+ # from itertools import *
6
+ from . import DefaultTable
7
+ from . import grUtils
8
+ from array import array
9
+ from functools import reduce
10
+ import struct, re, sys
11
+
12
+ Silf_hdr_format = """
13
+ >
14
+ version: 16.16F
15
+ """
16
+
17
+ Silf_hdr_format_3 = """
18
+ >
19
+ version: 16.16F
20
+ compilerVersion: L
21
+ numSilf: H
22
+ x
23
+ x
24
+ """
25
+
26
+ Silf_part1_format_v3 = """
27
+ >
28
+ ruleVersion: 16.16F
29
+ passOffset: H
30
+ pseudosOffset: H
31
+ """
32
+
33
+ Silf_part1_format = """
34
+ >
35
+ maxGlyphID: H
36
+ extraAscent: h
37
+ extraDescent: h
38
+ numPasses: B
39
+ iSubst: B
40
+ iPos: B
41
+ iJust: B
42
+ iBidi: B
43
+ flags: B
44
+ maxPreContext: B
45
+ maxPostContext: B
46
+ attrPseudo: B
47
+ attrBreakWeight: B
48
+ attrDirectionality: B
49
+ attrMirroring: B
50
+ attrSkipPasses: B
51
+ numJLevels: B
52
+ """
53
+
54
+ Silf_justify_format = """
55
+ >
56
+ attrStretch: B
57
+ attrShrink: B
58
+ attrStep: B
59
+ attrWeight: B
60
+ runto: B
61
+ x
62
+ x
63
+ x
64
+ """
65
+
66
+ Silf_part2_format = """
67
+ >
68
+ numLigComp: H
69
+ numUserDefn: B
70
+ maxCompPerLig: B
71
+ direction: B
72
+ attCollisions: B
73
+ x
74
+ x
75
+ x
76
+ numCritFeatures: B
77
+ """
78
+
79
+ Silf_pseudomap_format = """
80
+ >
81
+ unicode: L
82
+ nPseudo: H
83
+ """
84
+
85
+ Silf_pseudomap_format_h = """
86
+ >
87
+ unicode: H
88
+ nPseudo: H
89
+ """
90
+
91
+ Silf_classmap_format = """
92
+ >
93
+ numClass: H
94
+ numLinear: H
95
+ """
96
+
97
+ Silf_lookupclass_format = """
98
+ >
99
+ numIDs: H
100
+ searchRange: H
101
+ entrySelector: H
102
+ rangeShift: H
103
+ """
104
+
105
+ Silf_lookuppair_format = """
106
+ >
107
+ glyphId: H
108
+ index: H
109
+ """
110
+
111
+ Silf_pass_format = """
112
+ >
113
+ flags: B
114
+ maxRuleLoop: B
115
+ maxRuleContext: B
116
+ maxBackup: B
117
+ numRules: H
118
+ fsmOffset: H
119
+ pcCode: L
120
+ rcCode: L
121
+ aCode: L
122
+ oDebug: L
123
+ numRows: H
124
+ numTransitional: H
125
+ numSuccess: H
126
+ numColumns: H
127
+ """
128
+
129
+ aCode_info = (
130
+ ("NOP", 0),
131
+ ("PUSH_BYTE", "b"),
132
+ ("PUSH_BYTE_U", "B"),
133
+ ("PUSH_SHORT", ">h"),
134
+ ("PUSH_SHORT_U", ">H"),
135
+ ("PUSH_LONG", ">L"),
136
+ ("ADD", 0),
137
+ ("SUB", 0),
138
+ ("MUL", 0),
139
+ ("DIV", 0),
140
+ ("MIN", 0),
141
+ ("MAX", 0),
142
+ ("NEG", 0),
143
+ ("TRUNC8", 0),
144
+ ("TRUNC16", 0),
145
+ ("COND", 0),
146
+ ("AND", 0), # x10
147
+ ("OR", 0),
148
+ ("NOT", 0),
149
+ ("EQUAL", 0),
150
+ ("NOT_EQ", 0),
151
+ ("LESS", 0),
152
+ ("GTR", 0),
153
+ ("LESS_EQ", 0),
154
+ ("GTR_EQ", 0),
155
+ ("NEXT", 0),
156
+ ("NEXT_N", "b"),
157
+ ("COPY_NEXT", 0),
158
+ ("PUT_GLYPH_8BIT_OBS", "B"),
159
+ ("PUT_SUBS_8BIT_OBS", "bBB"),
160
+ ("PUT_COPY", "b"),
161
+ ("INSERT", 0),
162
+ ("DELETE", 0), # x20
163
+ ("ASSOC", -1),
164
+ ("CNTXT_ITEM", "bB"),
165
+ ("ATTR_SET", "B"),
166
+ ("ATTR_ADD", "B"),
167
+ ("ATTR_SUB", "B"),
168
+ ("ATTR_SET_SLOT", "B"),
169
+ ("IATTR_SET_SLOT", "BB"),
170
+ ("PUSH_SLOT_ATTR", "Bb"),
171
+ ("PUSH_GLYPH_ATTR_OBS", "Bb"),
172
+ ("PUSH_GLYPH_METRIC", "Bbb"),
173
+ ("PUSH_FEAT", "Bb"),
174
+ ("PUSH_ATT_TO_GATTR_OBS", "Bb"),
175
+ ("PUSH_ATT_TO_GLYPH_METRIC", "Bbb"),
176
+ ("PUSH_ISLOT_ATTR", "Bbb"),
177
+ ("PUSH_IGLYPH_ATTR", "Bbb"),
178
+ ("POP_RET", 0), # x30
179
+ ("RET_ZERO", 0),
180
+ ("RET_TRUE", 0),
181
+ ("IATTR_SET", "BB"),
182
+ ("IATTR_ADD", "BB"),
183
+ ("IATTR_SUB", "BB"),
184
+ ("PUSH_PROC_STATE", "B"),
185
+ ("PUSH_VERSION", 0),
186
+ ("PUT_SUBS", ">bHH"),
187
+ ("PUT_SUBS2", 0),
188
+ ("PUT_SUBS3", 0),
189
+ ("PUT_GLYPH", ">H"),
190
+ ("PUSH_GLYPH_ATTR", ">Hb"),
191
+ ("PUSH_ATT_TO_GLYPH_ATTR", ">Hb"),
192
+ ("BITOR", 0),
193
+ ("BITAND", 0),
194
+ ("BITNOT", 0), # x40
195
+ ("BITSET", ">HH"),
196
+ ("SET_FEAT", "Bb"),
197
+ )
198
+ aCode_map = dict([(x[0], (i, x[1])) for i, x in enumerate(aCode_info)])
199
+
200
+
201
+ def disassemble(aCode):
202
+ codelen = len(aCode)
203
+ pc = 0
204
+ res = []
205
+ while pc < codelen:
206
+ opcode = byteord(aCode[pc : pc + 1])
207
+ if opcode > len(aCode_info):
208
+ instr = aCode_info[0]
209
+ else:
210
+ instr = aCode_info[opcode]
211
+ pc += 1
212
+ if instr[1] != 0 and pc >= codelen:
213
+ return res
214
+ if instr[1] == -1:
215
+ count = byteord(aCode[pc])
216
+ fmt = "%dB" % count
217
+ pc += 1
218
+ elif instr[1] == 0:
219
+ fmt = ""
220
+ else:
221
+ fmt = instr[1]
222
+ if fmt == "":
223
+ res.append(instr[0])
224
+ continue
225
+ parms = struct.unpack_from(fmt, aCode[pc:])
226
+ res.append(instr[0] + "(" + ", ".join(map(str, parms)) + ")")
227
+ pc += struct.calcsize(fmt)
228
+ return res
229
+
230
+
231
+ instre = re.compile(r"^\s*([^(]+)\s*(?:\(([^)]+)\))?")
232
+
233
+
234
+ def assemble(instrs):
235
+ res = b""
236
+ for inst in instrs:
237
+ m = instre.match(inst)
238
+ if not m or not m.group(1) in aCode_map:
239
+ continue
240
+ opcode, parmfmt = aCode_map[m.group(1)]
241
+ res += struct.pack("B", opcode)
242
+ if m.group(2):
243
+ if parmfmt == 0:
244
+ continue
245
+ parms = [int(x) for x in re.split(r",\s*", m.group(2))]
246
+ if parmfmt == -1:
247
+ l = len(parms)
248
+ res += struct.pack(("%dB" % (l + 1)), l, *parms)
249
+ else:
250
+ res += struct.pack(parmfmt, *parms)
251
+ return res
252
+
253
+
254
+ def writecode(tag, writer, instrs):
255
+ writer.begintag(tag)
256
+ writer.newline()
257
+ for l in disassemble(instrs):
258
+ writer.write(l)
259
+ writer.newline()
260
+ writer.endtag(tag)
261
+ writer.newline()
262
+
263
+
264
+ def readcode(content):
265
+ res = []
266
+ for e in content_string(content).split("\n"):
267
+ e = e.strip()
268
+ if not len(e):
269
+ continue
270
+ res.append(e)
271
+ return assemble(res)
272
+
273
+
274
+ attrs_info = (
275
+ "flags",
276
+ "extraAscent",
277
+ "extraDescent",
278
+ "maxGlyphID",
279
+ "numLigComp",
280
+ "numUserDefn",
281
+ "maxCompPerLig",
282
+ "direction",
283
+ "lbGID",
284
+ )
285
+ attrs_passindexes = ("iSubst", "iPos", "iJust", "iBidi")
286
+ attrs_contexts = ("maxPreContext", "maxPostContext")
287
+ attrs_attributes = (
288
+ "attrPseudo",
289
+ "attrBreakWeight",
290
+ "attrDirectionality",
291
+ "attrMirroring",
292
+ "attrSkipPasses",
293
+ "attCollisions",
294
+ )
295
+ pass_attrs_info = (
296
+ "flags",
297
+ "maxRuleLoop",
298
+ "maxRuleContext",
299
+ "maxBackup",
300
+ "minRulePreContext",
301
+ "maxRulePreContext",
302
+ "collisionThreshold",
303
+ )
304
+ pass_attrs_fsm = ("numRows", "numTransitional", "numSuccess", "numColumns")
305
+
306
+
307
+ def writesimple(tag, self, writer, *attrkeys):
308
+ attrs = dict([(k, getattr(self, k)) for k in attrkeys])
309
+ writer.simpletag(tag, **attrs)
310
+ writer.newline()
311
+
312
+
313
+ def getSimple(self, attrs, *attr_list):
314
+ for k in attr_list:
315
+ if k in attrs:
316
+ setattr(self, k, int(safeEval(attrs[k])))
317
+
318
+
319
+ def content_string(contents):
320
+ res = ""
321
+ for element in contents:
322
+ if isinstance(element, tuple):
323
+ continue
324
+ res += element
325
+ return res.strip()
326
+
327
+
328
+ def wrapline(writer, dat, length=80):
329
+ currline = ""
330
+ for d in dat:
331
+ if len(currline) > length:
332
+ writer.write(currline[:-1])
333
+ writer.newline()
334
+ currline = ""
335
+ currline += d + " "
336
+ if len(currline):
337
+ writer.write(currline[:-1])
338
+ writer.newline()
339
+
340
+
341
+ class _Object:
342
+ pass
343
+
344
+
345
+ class table_S__i_l_f(DefaultTable.DefaultTable):
346
+ """Graphite Rules table
347
+
348
+ See also https://graphite.sil.org/graphite_techAbout#graphite-font-tables
349
+ """
350
+
351
+ def __init__(self, tag=None):
352
+ DefaultTable.DefaultTable.__init__(self, tag)
353
+ self.silfs = []
354
+
355
+ def decompile(self, data, ttFont):
356
+ sstruct.unpack2(Silf_hdr_format, data, self)
357
+ self.version = float(floatToFixedToStr(self.version, precisionBits=16))
358
+ if self.version >= 5.0:
359
+ (data, self.scheme) = grUtils.decompress(data)
360
+ sstruct.unpack2(Silf_hdr_format_3, data, self)
361
+ base = sstruct.calcsize(Silf_hdr_format_3)
362
+ elif self.version < 3.0:
363
+ self.numSilf = struct.unpack(">H", data[4:6])
364
+ self.scheme = 0
365
+ self.compilerVersion = 0
366
+ base = 8
367
+ else:
368
+ self.scheme = 0
369
+ sstruct.unpack2(Silf_hdr_format_3, data, self)
370
+ base = sstruct.calcsize(Silf_hdr_format_3)
371
+
372
+ silfoffsets = struct.unpack_from((">%dL" % self.numSilf), data[base:])
373
+ for offset in silfoffsets:
374
+ s = Silf()
375
+ self.silfs.append(s)
376
+ s.decompile(data[offset:], ttFont, self.version)
377
+
378
+ def compile(self, ttFont):
379
+ self.numSilf = len(self.silfs)
380
+ if self.version < 3.0:
381
+ hdr = sstruct.pack(Silf_hdr_format, self)
382
+ hdr += struct.pack(">HH", self.numSilf, 0)
383
+ else:
384
+ hdr = sstruct.pack(Silf_hdr_format_3, self)
385
+ offset = len(hdr) + 4 * self.numSilf
386
+ data = b""
387
+ for s in self.silfs:
388
+ hdr += struct.pack(">L", offset)
389
+ subdata = s.compile(ttFont, self.version)
390
+ offset += len(subdata)
391
+ data += subdata
392
+ if self.version >= 5.0:
393
+ return grUtils.compress(self.scheme, hdr + data)
394
+ return hdr + data
395
+
396
+ def toXML(self, writer, ttFont):
397
+ writer.comment("Attributes starting with _ are informative only")
398
+ writer.newline()
399
+ writer.simpletag(
400
+ "version",
401
+ version=self.version,
402
+ compilerVersion=self.compilerVersion,
403
+ compressionScheme=self.scheme,
404
+ )
405
+ writer.newline()
406
+ for s in self.silfs:
407
+ writer.begintag("silf")
408
+ writer.newline()
409
+ s.toXML(writer, ttFont, self.version)
410
+ writer.endtag("silf")
411
+ writer.newline()
412
+
413
+ def fromXML(self, name, attrs, content, ttFont):
414
+ if name == "version":
415
+ self.scheme = int(safeEval(attrs["compressionScheme"]))
416
+ self.version = float(safeEval(attrs["version"]))
417
+ self.compilerVersion = int(safeEval(attrs["compilerVersion"]))
418
+ return
419
+ if name == "silf":
420
+ s = Silf()
421
+ self.silfs.append(s)
422
+ for element in content:
423
+ if not isinstance(element, tuple):
424
+ continue
425
+ tag, attrs, subcontent = element
426
+ s.fromXML(tag, attrs, subcontent, ttFont, self.version)
427
+
428
+
429
+ class Silf(object):
430
+ """A particular Silf subtable"""
431
+
432
+ def __init__(self):
433
+ self.passes = []
434
+ self.scriptTags = []
435
+ self.critFeatures = []
436
+ self.jLevels = []
437
+ self.pMap = {}
438
+
439
+ def decompile(self, data, ttFont, version=2.0):
440
+ if version >= 3.0:
441
+ _, data = sstruct.unpack2(Silf_part1_format_v3, data, self)
442
+ self.ruleVersion = float(
443
+ floatToFixedToStr(self.ruleVersion, precisionBits=16)
444
+ )
445
+ _, data = sstruct.unpack2(Silf_part1_format, data, self)
446
+ for jlevel in range(self.numJLevels):
447
+ j, data = sstruct.unpack2(Silf_justify_format, data, _Object())
448
+ self.jLevels.append(j)
449
+ _, data = sstruct.unpack2(Silf_part2_format, data, self)
450
+ if self.numCritFeatures:
451
+ self.critFeatures = struct.unpack_from(
452
+ (">%dH" % self.numCritFeatures), data
453
+ )
454
+ data = data[self.numCritFeatures * 2 + 1 :]
455
+ (numScriptTag,) = struct.unpack_from("B", data)
456
+ if numScriptTag:
457
+ self.scriptTags = [
458
+ struct.unpack("4s", data[x : x + 4])[0].decode("ascii")
459
+ for x in range(1, 1 + 4 * numScriptTag, 4)
460
+ ]
461
+ data = data[1 + 4 * numScriptTag :]
462
+ (self.lbGID,) = struct.unpack(">H", data[:2])
463
+ if self.numPasses:
464
+ self.oPasses = struct.unpack(
465
+ (">%dL" % (self.numPasses + 1)), data[2 : 6 + 4 * self.numPasses]
466
+ )
467
+ data = data[6 + 4 * self.numPasses :]
468
+ (numPseudo,) = struct.unpack(">H", data[:2])
469
+ for i in range(numPseudo):
470
+ if version >= 3.0:
471
+ pseudo = sstruct.unpack(
472
+ Silf_pseudomap_format, data[8 + 6 * i : 14 + 6 * i], _Object()
473
+ )
474
+ else:
475
+ pseudo = sstruct.unpack(
476
+ Silf_pseudomap_format_h, data[8 + 4 * i : 12 + 4 * i], _Object()
477
+ )
478
+ self.pMap[pseudo.unicode] = ttFont.getGlyphName(pseudo.nPseudo)
479
+ data = data[8 + 6 * numPseudo :]
480
+ currpos = (
481
+ sstruct.calcsize(Silf_part1_format)
482
+ + sstruct.calcsize(Silf_justify_format) * self.numJLevels
483
+ + sstruct.calcsize(Silf_part2_format)
484
+ + 2 * self.numCritFeatures
485
+ + 1
486
+ + 1
487
+ + 4 * numScriptTag
488
+ + 6
489
+ + 4 * self.numPasses
490
+ + 8
491
+ + 6 * numPseudo
492
+ )
493
+ if version >= 3.0:
494
+ currpos += sstruct.calcsize(Silf_part1_format_v3)
495
+ self.classes = Classes()
496
+ self.classes.decompile(data, ttFont, version)
497
+ for i in range(self.numPasses):
498
+ p = Pass()
499
+ self.passes.append(p)
500
+ p.decompile(
501
+ data[self.oPasses[i] - currpos : self.oPasses[i + 1] - currpos],
502
+ ttFont,
503
+ version,
504
+ )
505
+
506
+ def compile(self, ttFont, version=2.0):
507
+ self.numPasses = len(self.passes)
508
+ self.numJLevels = len(self.jLevels)
509
+ self.numCritFeatures = len(self.critFeatures)
510
+ numPseudo = len(self.pMap)
511
+ data = b""
512
+ if version >= 3.0:
513
+ hdroffset = sstruct.calcsize(Silf_part1_format_v3)
514
+ else:
515
+ hdroffset = 0
516
+ data += sstruct.pack(Silf_part1_format, self)
517
+ for j in self.jLevels:
518
+ data += sstruct.pack(Silf_justify_format, j)
519
+ data += sstruct.pack(Silf_part2_format, self)
520
+ if self.numCritFeatures:
521
+ data += struct.pack((">%dH" % self.numCritFeaturs), *self.critFeatures)
522
+ data += struct.pack("BB", 0, len(self.scriptTags))
523
+ if len(self.scriptTags):
524
+ tdata = [struct.pack("4s", x.encode("ascii")) for x in self.scriptTags]
525
+ data += b"".join(tdata)
526
+ data += struct.pack(">H", self.lbGID)
527
+ self.passOffset = len(data)
528
+
529
+ data1 = grUtils.bininfo(numPseudo, 6)
530
+ currpos = hdroffset + len(data) + 4 * (self.numPasses + 1)
531
+ self.pseudosOffset = currpos + len(data1)
532
+ for u, p in sorted(self.pMap.items()):
533
+ data1 += struct.pack(
534
+ (">LH" if version >= 3.0 else ">HH"), u, ttFont.getGlyphID(p)
535
+ )
536
+ data1 += self.classes.compile(ttFont, version)
537
+ currpos += len(data1)
538
+ data2 = b""
539
+ datao = b""
540
+ for i, p in enumerate(self.passes):
541
+ base = currpos + len(data2)
542
+ datao += struct.pack(">L", base)
543
+ data2 += p.compile(ttFont, base, version)
544
+ datao += struct.pack(">L", currpos + len(data2))
545
+
546
+ if version >= 3.0:
547
+ data3 = sstruct.pack(Silf_part1_format_v3, self)
548
+ else:
549
+ data3 = b""
550
+ return data3 + data + datao + data1 + data2
551
+
552
+ def toXML(self, writer, ttFont, version=2.0):
553
+ if version >= 3.0:
554
+ writer.simpletag("version", ruleVersion=self.ruleVersion)
555
+ writer.newline()
556
+ writesimple("info", self, writer, *attrs_info)
557
+ writesimple("passindexes", self, writer, *attrs_passindexes)
558
+ writesimple("contexts", self, writer, *attrs_contexts)
559
+ writesimple("attributes", self, writer, *attrs_attributes)
560
+ if len(self.jLevels):
561
+ writer.begintag("justifications")
562
+ writer.newline()
563
+ jformat, jnames, jfixes = sstruct.getformat(Silf_justify_format)
564
+ for i, j in enumerate(self.jLevels):
565
+ attrs = dict([(k, getattr(j, k)) for k in jnames])
566
+ writer.simpletag("justify", **attrs)
567
+ writer.newline()
568
+ writer.endtag("justifications")
569
+ writer.newline()
570
+ if len(self.critFeatures):
571
+ writer.begintag("critFeatures")
572
+ writer.newline()
573
+ writer.write(" ".join(map(str, self.critFeatures)))
574
+ writer.newline()
575
+ writer.endtag("critFeatures")
576
+ writer.newline()
577
+ if len(self.scriptTags):
578
+ writer.begintag("scriptTags")
579
+ writer.newline()
580
+ writer.write(" ".join(self.scriptTags))
581
+ writer.newline()
582
+ writer.endtag("scriptTags")
583
+ writer.newline()
584
+ if self.pMap:
585
+ writer.begintag("pseudoMap")
586
+ writer.newline()
587
+ for k, v in sorted(self.pMap.items()):
588
+ writer.simpletag("pseudo", unicode=hex(k), pseudo=v)
589
+ writer.newline()
590
+ writer.endtag("pseudoMap")
591
+ writer.newline()
592
+ self.classes.toXML(writer, ttFont, version)
593
+ if len(self.passes):
594
+ writer.begintag("passes")
595
+ writer.newline()
596
+ for i, p in enumerate(self.passes):
597
+ writer.begintag("pass", _index=i)
598
+ writer.newline()
599
+ p.toXML(writer, ttFont, version)
600
+ writer.endtag("pass")
601
+ writer.newline()
602
+ writer.endtag("passes")
603
+ writer.newline()
604
+
605
+ def fromXML(self, name, attrs, content, ttFont, version=2.0):
606
+ if name == "version":
607
+ self.ruleVersion = float(safeEval(attrs.get("ruleVersion", "0")))
608
+ if name == "info":
609
+ getSimple(self, attrs, *attrs_info)
610
+ elif name == "passindexes":
611
+ getSimple(self, attrs, *attrs_passindexes)
612
+ elif name == "contexts":
613
+ getSimple(self, attrs, *attrs_contexts)
614
+ elif name == "attributes":
615
+ getSimple(self, attrs, *attrs_attributes)
616
+ elif name == "justifications":
617
+ for element in content:
618
+ if not isinstance(element, tuple):
619
+ continue
620
+ (tag, attrs, subcontent) = element
621
+ if tag == "justify":
622
+ j = _Object()
623
+ for k, v in attrs.items():
624
+ setattr(j, k, int(v))
625
+ self.jLevels.append(j)
626
+ elif name == "critFeatures":
627
+ self.critFeatures = []
628
+ element = content_string(content)
629
+ self.critFeatures.extend(map(int, element.split()))
630
+ elif name == "scriptTags":
631
+ self.scriptTags = []
632
+ element = content_string(content)
633
+ for n in element.split():
634
+ self.scriptTags.append(n)
635
+ elif name == "pseudoMap":
636
+ self.pMap = {}
637
+ for element in content:
638
+ if not isinstance(element, tuple):
639
+ continue
640
+ (tag, attrs, subcontent) = element
641
+ if tag == "pseudo":
642
+ k = int(attrs["unicode"], 16)
643
+ v = attrs["pseudo"]
644
+ self.pMap[k] = v
645
+ elif name == "classes":
646
+ self.classes = Classes()
647
+ for element in content:
648
+ if not isinstance(element, tuple):
649
+ continue
650
+ tag, attrs, subcontent = element
651
+ self.classes.fromXML(tag, attrs, subcontent, ttFont, version)
652
+ elif name == "passes":
653
+ for element in content:
654
+ if not isinstance(element, tuple):
655
+ continue
656
+ tag, attrs, subcontent = element
657
+ if tag == "pass":
658
+ p = Pass()
659
+ for e in subcontent:
660
+ if not isinstance(e, tuple):
661
+ continue
662
+ p.fromXML(e[0], e[1], e[2], ttFont, version)
663
+ self.passes.append(p)
664
+
665
+
666
+ class Classes(object):
667
+ def __init__(self):
668
+ self.linear = []
669
+ self.nonLinear = []
670
+
671
+ def decompile(self, data, ttFont, version=2.0):
672
+ sstruct.unpack2(Silf_classmap_format, data, self)
673
+ if version >= 4.0:
674
+ oClasses = struct.unpack(
675
+ (">%dL" % (self.numClass + 1)), data[4 : 8 + 4 * self.numClass]
676
+ )
677
+ else:
678
+ oClasses = struct.unpack(
679
+ (">%dH" % (self.numClass + 1)), data[4 : 6 + 2 * self.numClass]
680
+ )
681
+ for s, e in zip(oClasses[: self.numLinear], oClasses[1 : self.numLinear + 1]):
682
+ self.linear.append(
683
+ ttFont.getGlyphName(x)
684
+ for x in struct.unpack((">%dH" % ((e - s) / 2)), data[s:e])
685
+ )
686
+ for s, e in zip(
687
+ oClasses[self.numLinear : self.numClass],
688
+ oClasses[self.numLinear + 1 : self.numClass + 1],
689
+ ):
690
+ nonLinids = [
691
+ struct.unpack(">HH", data[x : x + 4]) for x in range(s + 8, e, 4)
692
+ ]
693
+ nonLin = dict([(ttFont.getGlyphName(x[0]), x[1]) for x in nonLinids])
694
+ self.nonLinear.append(nonLin)
695
+
696
+ def compile(self, ttFont, version=2.0):
697
+ data = b""
698
+ oClasses = []
699
+ if version >= 4.0:
700
+ offset = 8 + 4 * (len(self.linear) + len(self.nonLinear))
701
+ else:
702
+ offset = 6 + 2 * (len(self.linear) + len(self.nonLinear))
703
+ for l in self.linear:
704
+ oClasses.append(len(data) + offset)
705
+ gs = [ttFont.getGlyphID(x) for x in l]
706
+ data += struct.pack((">%dH" % len(l)), *gs)
707
+ for l in self.nonLinear:
708
+ oClasses.append(len(data) + offset)
709
+ gs = [(ttFont.getGlyphID(x[0]), x[1]) for x in l.items()]
710
+ data += grUtils.bininfo(len(gs))
711
+ data += b"".join([struct.pack(">HH", *x) for x in sorted(gs)])
712
+ oClasses.append(len(data) + offset)
713
+ self.numClass = len(oClasses) - 1
714
+ self.numLinear = len(self.linear)
715
+ return (
716
+ sstruct.pack(Silf_classmap_format, self)
717
+ + struct.pack(
718
+ ((">%dL" if version >= 4.0 else ">%dH") % len(oClasses)), *oClasses
719
+ )
720
+ + data
721
+ )
722
+
723
+ def toXML(self, writer, ttFont, version=2.0):
724
+ writer.begintag("classes")
725
+ writer.newline()
726
+ writer.begintag("linearClasses")
727
+ writer.newline()
728
+ for i, l in enumerate(self.linear):
729
+ writer.begintag("linear", _index=i)
730
+ writer.newline()
731
+ wrapline(writer, l)
732
+ writer.endtag("linear")
733
+ writer.newline()
734
+ writer.endtag("linearClasses")
735
+ writer.newline()
736
+ writer.begintag("nonLinearClasses")
737
+ writer.newline()
738
+ for i, l in enumerate(self.nonLinear):
739
+ writer.begintag("nonLinear", _index=i + self.numLinear)
740
+ writer.newline()
741
+ for inp, ind in l.items():
742
+ writer.simpletag("map", glyph=inp, index=ind)
743
+ writer.newline()
744
+ writer.endtag("nonLinear")
745
+ writer.newline()
746
+ writer.endtag("nonLinearClasses")
747
+ writer.newline()
748
+ writer.endtag("classes")
749
+ writer.newline()
750
+
751
+ def fromXML(self, name, attrs, content, ttFont, version=2.0):
752
+ if name == "linearClasses":
753
+ for element in content:
754
+ if not isinstance(element, tuple):
755
+ continue
756
+ tag, attrs, subcontent = element
757
+ if tag == "linear":
758
+ l = content_string(subcontent).split()
759
+ self.linear.append(l)
760
+ elif name == "nonLinearClasses":
761
+ for element in content:
762
+ if not isinstance(element, tuple):
763
+ continue
764
+ tag, attrs, subcontent = element
765
+ if tag == "nonLinear":
766
+ l = {}
767
+ for e in subcontent:
768
+ if not isinstance(e, tuple):
769
+ continue
770
+ tag, attrs, subsubcontent = e
771
+ if tag == "map":
772
+ l[attrs["glyph"]] = int(safeEval(attrs["index"]))
773
+ self.nonLinear.append(l)
774
+
775
+
776
+ class Pass(object):
777
+ def __init__(self):
778
+ self.colMap = {}
779
+ self.rules = []
780
+ self.rulePreContexts = []
781
+ self.ruleSortKeys = []
782
+ self.ruleConstraints = []
783
+ self.passConstraints = b""
784
+ self.actions = []
785
+ self.stateTrans = []
786
+ self.startStates = []
787
+
788
+ def decompile(self, data, ttFont, version=2.0):
789
+ _, data = sstruct.unpack2(Silf_pass_format, data, self)
790
+ (numRange, _, _, _) = struct.unpack(">4H", data[:8])
791
+ data = data[8:]
792
+ for i in range(numRange):
793
+ (first, last, col) = struct.unpack(">3H", data[6 * i : 6 * i + 6])
794
+ for g in range(first, last + 1):
795
+ self.colMap[ttFont.getGlyphName(g)] = col
796
+ data = data[6 * numRange :]
797
+ oRuleMap = struct.unpack_from((">%dH" % (self.numSuccess + 1)), data)
798
+ data = data[2 + 2 * self.numSuccess :]
799
+ rules = struct.unpack_from((">%dH" % oRuleMap[-1]), data)
800
+ self.rules = [rules[s:e] for (s, e) in zip(oRuleMap, oRuleMap[1:])]
801
+ data = data[2 * oRuleMap[-1] :]
802
+ (self.minRulePreContext, self.maxRulePreContext) = struct.unpack("BB", data[:2])
803
+ numStartStates = self.maxRulePreContext - self.minRulePreContext + 1
804
+ self.startStates = struct.unpack(
805
+ (">%dH" % numStartStates), data[2 : 2 + numStartStates * 2]
806
+ )
807
+ data = data[2 + numStartStates * 2 :]
808
+ self.ruleSortKeys = struct.unpack(
809
+ (">%dH" % self.numRules), data[: 2 * self.numRules]
810
+ )
811
+ data = data[2 * self.numRules :]
812
+ self.rulePreContexts = struct.unpack(
813
+ ("%dB" % self.numRules), data[: self.numRules]
814
+ )
815
+ data = data[self.numRules :]
816
+ (self.collisionThreshold, pConstraint) = struct.unpack(">BH", data[:3])
817
+ oConstraints = list(
818
+ struct.unpack(
819
+ (">%dH" % (self.numRules + 1)), data[3 : 5 + self.numRules * 2]
820
+ )
821
+ )
822
+ data = data[5 + self.numRules * 2 :]
823
+ oActions = list(
824
+ struct.unpack((">%dH" % (self.numRules + 1)), data[: 2 + self.numRules * 2])
825
+ )
826
+ data = data[2 * self.numRules + 2 :]
827
+ for i in range(self.numTransitional):
828
+ a = array(
829
+ "H", data[i * self.numColumns * 2 : (i + 1) * self.numColumns * 2]
830
+ )
831
+ if sys.byteorder != "big":
832
+ a.byteswap()
833
+ self.stateTrans.append(a)
834
+ data = data[self.numTransitional * self.numColumns * 2 + 1 :]
835
+ self.passConstraints = data[:pConstraint]
836
+ data = data[pConstraint:]
837
+ for i in range(len(oConstraints) - 2, -1, -1):
838
+ if oConstraints[i] == 0:
839
+ oConstraints[i] = oConstraints[i + 1]
840
+ self.ruleConstraints = [
841
+ (data[s:e] if (e - s > 1) else b"")
842
+ for (s, e) in zip(oConstraints, oConstraints[1:])
843
+ ]
844
+ data = data[oConstraints[-1] :]
845
+ self.actions = [
846
+ (data[s:e] if (e - s > 1) else "") for (s, e) in zip(oActions, oActions[1:])
847
+ ]
848
+ data = data[oActions[-1] :]
849
+ # not using debug
850
+
851
+ def compile(self, ttFont, base, version=2.0):
852
+ # build it all up backwards
853
+ oActions = reduce(
854
+ lambda a, x: (a[0] + len(x), a[1] + [a[0]]), self.actions + [b""], (0, [])
855
+ )[1]
856
+ oConstraints = reduce(
857
+ lambda a, x: (a[0] + len(x), a[1] + [a[0]]),
858
+ self.ruleConstraints + [b""],
859
+ (1, []),
860
+ )[1]
861
+ constraintCode = b"\000" + b"".join(self.ruleConstraints)
862
+ transes = []
863
+ for t in self.stateTrans:
864
+ if sys.byteorder != "big":
865
+ t.byteswap()
866
+ transes.append(t.tobytes())
867
+ if sys.byteorder != "big":
868
+ t.byteswap()
869
+ if not len(transes):
870
+ self.startStates = [0]
871
+ oRuleMap = reduce(
872
+ lambda a, x: (a[0] + len(x), a[1] + [a[0]]), self.rules + [[]], (0, [])
873
+ )[1]
874
+ passRanges = []
875
+ gidcolmap = dict([(ttFont.getGlyphID(x[0]), x[1]) for x in self.colMap.items()])
876
+ for e in grUtils.entries(gidcolmap, sameval=True):
877
+ if e[1]:
878
+ passRanges.append((e[0], e[0] + e[1] - 1, e[2][0]))
879
+ self.numRules = len(self.actions)
880
+ self.fsmOffset = (
881
+ sstruct.calcsize(Silf_pass_format)
882
+ + 8
883
+ + len(passRanges) * 6
884
+ + len(oRuleMap) * 2
885
+ + 2 * oRuleMap[-1]
886
+ + 2
887
+ + 2 * len(self.startStates)
888
+ + 3 * self.numRules
889
+ + 3
890
+ + 4 * self.numRules
891
+ + 4
892
+ )
893
+ self.pcCode = (
894
+ self.fsmOffset + 2 * self.numTransitional * self.numColumns + 1 + base
895
+ )
896
+ self.rcCode = self.pcCode + len(self.passConstraints)
897
+ self.aCode = self.rcCode + len(constraintCode)
898
+ self.oDebug = 0
899
+ # now generate output
900
+ data = sstruct.pack(Silf_pass_format, self)
901
+ data += grUtils.bininfo(len(passRanges), 6)
902
+ data += b"".join(struct.pack(">3H", *p) for p in passRanges)
903
+ data += struct.pack((">%dH" % len(oRuleMap)), *oRuleMap)
904
+ flatrules = reduce(lambda a, x: a + x, self.rules, [])
905
+ data += struct.pack((">%dH" % oRuleMap[-1]), *flatrules)
906
+ data += struct.pack("BB", self.minRulePreContext, self.maxRulePreContext)
907
+ data += struct.pack((">%dH" % len(self.startStates)), *self.startStates)
908
+ data += struct.pack((">%dH" % self.numRules), *self.ruleSortKeys)
909
+ data += struct.pack(("%dB" % self.numRules), *self.rulePreContexts)
910
+ data += struct.pack(">BH", self.collisionThreshold, len(self.passConstraints))
911
+ data += struct.pack((">%dH" % (self.numRules + 1)), *oConstraints)
912
+ data += struct.pack((">%dH" % (self.numRules + 1)), *oActions)
913
+ return (
914
+ data
915
+ + b"".join(transes)
916
+ + struct.pack("B", 0)
917
+ + self.passConstraints
918
+ + constraintCode
919
+ + b"".join(self.actions)
920
+ )
921
+
922
+ def toXML(self, writer, ttFont, version=2.0):
923
+ writesimple("info", self, writer, *pass_attrs_info)
924
+ writesimple("fsminfo", self, writer, *pass_attrs_fsm)
925
+ writer.begintag("colmap")
926
+ writer.newline()
927
+ wrapline(
928
+ writer,
929
+ [
930
+ "{}={}".format(*x)
931
+ for x in sorted(
932
+ self.colMap.items(), key=lambda x: ttFont.getGlyphID(x[0])
933
+ )
934
+ ],
935
+ )
936
+ writer.endtag("colmap")
937
+ writer.newline()
938
+ writer.begintag("staterulemap")
939
+ writer.newline()
940
+ for i, r in enumerate(self.rules):
941
+ writer.simpletag(
942
+ "state",
943
+ number=self.numRows - self.numSuccess + i,
944
+ rules=" ".join(map(str, r)),
945
+ )
946
+ writer.newline()
947
+ writer.endtag("staterulemap")
948
+ writer.newline()
949
+ writer.begintag("rules")
950
+ writer.newline()
951
+ for i, action in enumerate(self.actions):
952
+ writer.begintag(
953
+ "rule",
954
+ index=i,
955
+ precontext=self.rulePreContexts[i],
956
+ sortkey=self.ruleSortKeys[i],
957
+ )
958
+ writer.newline()
959
+ if len(self.ruleConstraints[i]):
960
+ writecode("constraint", writer, self.ruleConstraints[i])
961
+ writecode("action", writer, action)
962
+ writer.endtag("rule")
963
+ writer.newline()
964
+ writer.endtag("rules")
965
+ writer.newline()
966
+ if len(self.passConstraints):
967
+ writecode("passConstraint", writer, self.passConstraints)
968
+ if len(self.stateTrans):
969
+ writer.begintag("fsm")
970
+ writer.newline()
971
+ writer.begintag("starts")
972
+ writer.write(" ".join(map(str, self.startStates)))
973
+ writer.endtag("starts")
974
+ writer.newline()
975
+ for i, s in enumerate(self.stateTrans):
976
+ writer.begintag("row", _i=i)
977
+ # no newlines here
978
+ writer.write(" ".join(map(str, s)))
979
+ writer.endtag("row")
980
+ writer.newline()
981
+ writer.endtag("fsm")
982
+ writer.newline()
983
+
984
+ def fromXML(self, name, attrs, content, ttFont, version=2.0):
985
+ if name == "info":
986
+ getSimple(self, attrs, *pass_attrs_info)
987
+ elif name == "fsminfo":
988
+ getSimple(self, attrs, *pass_attrs_fsm)
989
+ elif name == "colmap":
990
+ e = content_string(content)
991
+ for w in e.split():
992
+ x = w.split("=")
993
+ if len(x) != 2 or x[0] == "" or x[1] == "":
994
+ continue
995
+ self.colMap[x[0]] = int(x[1])
996
+ elif name == "staterulemap":
997
+ for e in content:
998
+ if not isinstance(e, tuple):
999
+ continue
1000
+ tag, a, c = e
1001
+ if tag == "state":
1002
+ self.rules.append([int(x) for x in a["rules"].split(" ")])
1003
+ elif name == "rules":
1004
+ for element in content:
1005
+ if not isinstance(element, tuple):
1006
+ continue
1007
+ tag, a, c = element
1008
+ if tag != "rule":
1009
+ continue
1010
+ self.rulePreContexts.append(int(a["precontext"]))
1011
+ self.ruleSortKeys.append(int(a["sortkey"]))
1012
+ con = b""
1013
+ act = b""
1014
+ for e in c:
1015
+ if not isinstance(e, tuple):
1016
+ continue
1017
+ tag, a, subc = e
1018
+ if tag == "constraint":
1019
+ con = readcode(subc)
1020
+ elif tag == "action":
1021
+ act = readcode(subc)
1022
+ self.actions.append(act)
1023
+ self.ruleConstraints.append(con)
1024
+ elif name == "passConstraint":
1025
+ self.passConstraints = readcode(content)
1026
+ elif name == "fsm":
1027
+ for element in content:
1028
+ if not isinstance(element, tuple):
1029
+ continue
1030
+ tag, a, c = element
1031
+ if tag == "row":
1032
+ s = array("H")
1033
+ e = content_string(c)
1034
+ s.extend(map(int, e.split()))
1035
+ self.stateTrans.append(s)
1036
+ elif tag == "starts":
1037
+ s = []
1038
+ e = content_string(c)
1039
+ s.extend(map(int, e.split()))
1040
+ self.startStates = s