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,526 @@
1
+ # Copyright 2013 Google, Inc. All Rights Reserved.
2
+ #
3
+ # Google Author(s): Behdad Esfahbod, Roozbeh Pournader
4
+
5
+ from fontTools import ttLib
6
+ from fontTools.ttLib.tables.DefaultTable import DefaultTable
7
+ from fontTools.ttLib.tables import otTables
8
+ from fontTools.merge.base import add_method, mergeObjects
9
+ from fontTools.merge.util import *
10
+ import logging
11
+
12
+
13
+ log = logging.getLogger("fontTools.merge")
14
+
15
+
16
+ def mergeLookupLists(lst):
17
+ # TODO Do smarter merge.
18
+ return sumLists(lst)
19
+
20
+
21
+ def mergeFeatures(lst):
22
+ assert lst
23
+ self = otTables.Feature()
24
+ self.FeatureParams = None
25
+ self.LookupListIndex = mergeLookupLists(
26
+ [l.LookupListIndex for l in lst if l.LookupListIndex]
27
+ )
28
+ self.LookupCount = len(self.LookupListIndex)
29
+ return self
30
+
31
+
32
+ def mergeFeatureLists(lst):
33
+ d = {}
34
+ for l in lst:
35
+ for f in l:
36
+ tag = f.FeatureTag
37
+ if tag not in d:
38
+ d[tag] = []
39
+ d[tag].append(f.Feature)
40
+ ret = []
41
+ for tag in sorted(d.keys()):
42
+ rec = otTables.FeatureRecord()
43
+ rec.FeatureTag = tag
44
+ rec.Feature = mergeFeatures(d[tag])
45
+ ret.append(rec)
46
+ return ret
47
+
48
+
49
+ def mergeLangSyses(lst):
50
+ assert lst
51
+
52
+ # TODO Support merging ReqFeatureIndex
53
+ assert all(l.ReqFeatureIndex == 0xFFFF for l in lst)
54
+
55
+ self = otTables.LangSys()
56
+ self.LookupOrder = None
57
+ self.ReqFeatureIndex = 0xFFFF
58
+ self.FeatureIndex = mergeFeatureLists(
59
+ [l.FeatureIndex for l in lst if l.FeatureIndex]
60
+ )
61
+ self.FeatureCount = len(self.FeatureIndex)
62
+ return self
63
+
64
+
65
+ def mergeScripts(lst):
66
+ assert lst
67
+
68
+ if len(lst) == 1:
69
+ return lst[0]
70
+ langSyses = {}
71
+ for sr in lst:
72
+ for lsr in sr.LangSysRecord:
73
+ if lsr.LangSysTag not in langSyses:
74
+ langSyses[lsr.LangSysTag] = []
75
+ langSyses[lsr.LangSysTag].append(lsr.LangSys)
76
+ lsrecords = []
77
+ for tag, langSys_list in sorted(langSyses.items()):
78
+ lsr = otTables.LangSysRecord()
79
+ lsr.LangSys = mergeLangSyses(langSys_list)
80
+ lsr.LangSysTag = tag
81
+ lsrecords.append(lsr)
82
+
83
+ self = otTables.Script()
84
+ self.LangSysRecord = lsrecords
85
+ self.LangSysCount = len(lsrecords)
86
+ dfltLangSyses = [s.DefaultLangSys for s in lst if s.DefaultLangSys]
87
+ if dfltLangSyses:
88
+ self.DefaultLangSys = mergeLangSyses(dfltLangSyses)
89
+ else:
90
+ self.DefaultLangSys = None
91
+ return self
92
+
93
+
94
+ def mergeScriptRecords(lst):
95
+ d = {}
96
+ for l in lst:
97
+ for s in l:
98
+ tag = s.ScriptTag
99
+ if tag not in d:
100
+ d[tag] = []
101
+ d[tag].append(s.Script)
102
+ ret = []
103
+ for tag in sorted(d.keys()):
104
+ rec = otTables.ScriptRecord()
105
+ rec.ScriptTag = tag
106
+ rec.Script = mergeScripts(d[tag])
107
+ ret.append(rec)
108
+ return ret
109
+
110
+
111
+ otTables.ScriptList.mergeMap = {
112
+ "ScriptCount": lambda lst: None, # TODO
113
+ "ScriptRecord": mergeScriptRecords,
114
+ }
115
+ otTables.BaseScriptList.mergeMap = {
116
+ "BaseScriptCount": lambda lst: None, # TODO
117
+ # TODO: Merge duplicate entries
118
+ "BaseScriptRecord": lambda lst: sorted(
119
+ sumLists(lst), key=lambda s: s.BaseScriptTag
120
+ ),
121
+ }
122
+
123
+ otTables.FeatureList.mergeMap = {
124
+ "FeatureCount": sum,
125
+ "FeatureRecord": lambda lst: sorted(sumLists(lst), key=lambda s: s.FeatureTag),
126
+ }
127
+
128
+ otTables.LookupList.mergeMap = {
129
+ "LookupCount": sum,
130
+ "Lookup": sumLists,
131
+ }
132
+
133
+ otTables.Coverage.mergeMap = {
134
+ "Format": min,
135
+ "glyphs": sumLists,
136
+ }
137
+
138
+ otTables.ClassDef.mergeMap = {
139
+ "Format": min,
140
+ "classDefs": sumDicts,
141
+ }
142
+
143
+ otTables.LigCaretList.mergeMap = {
144
+ "Coverage": mergeObjects,
145
+ "LigGlyphCount": sum,
146
+ "LigGlyph": sumLists,
147
+ }
148
+
149
+ otTables.AttachList.mergeMap = {
150
+ "Coverage": mergeObjects,
151
+ "GlyphCount": sum,
152
+ "AttachPoint": sumLists,
153
+ }
154
+
155
+ # XXX Renumber MarkFilterSets of lookups
156
+ otTables.MarkGlyphSetsDef.mergeMap = {
157
+ "MarkSetTableFormat": equal,
158
+ "MarkSetCount": sum,
159
+ "Coverage": sumLists,
160
+ }
161
+
162
+ otTables.Axis.mergeMap = {
163
+ "*": mergeObjects,
164
+ }
165
+
166
+ # XXX Fix BASE table merging
167
+ otTables.BaseTagList.mergeMap = {
168
+ "BaseTagCount": sum,
169
+ "BaselineTag": sumLists,
170
+ }
171
+
172
+ otTables.GDEF.mergeMap = otTables.GSUB.mergeMap = otTables.GPOS.mergeMap = (
173
+ otTables.BASE.mergeMap
174
+ ) = otTables.JSTF.mergeMap = otTables.MATH.mergeMap = {
175
+ "*": mergeObjects,
176
+ "Version": max,
177
+ }
178
+
179
+ ttLib.getTableClass("GDEF").mergeMap = ttLib.getTableClass("GSUB").mergeMap = (
180
+ ttLib.getTableClass("GPOS").mergeMap
181
+ ) = ttLib.getTableClass("BASE").mergeMap = ttLib.getTableClass(
182
+ "JSTF"
183
+ ).mergeMap = ttLib.getTableClass(
184
+ "MATH"
185
+ ).mergeMap = {
186
+ "tableTag": onlyExisting(equal), # XXX clean me up
187
+ "table": mergeObjects,
188
+ }
189
+
190
+
191
+ @add_method(ttLib.getTableClass("GSUB"))
192
+ def merge(self, m, tables):
193
+ assert len(tables) == len(m.duplicateGlyphsPerFont)
194
+ for i, (table, dups) in enumerate(zip(tables, m.duplicateGlyphsPerFont)):
195
+ if not dups:
196
+ continue
197
+ if table is None or table is NotImplemented:
198
+ log.warning(
199
+ "Have non-identical duplicates to resolve for '%s' but no GSUB. Are duplicates intended?: %s",
200
+ m.fonts[i]._merger__name,
201
+ dups,
202
+ )
203
+ continue
204
+
205
+ synthFeature = None
206
+ synthLookup = None
207
+ for script in table.table.ScriptList.ScriptRecord:
208
+ if script.ScriptTag == "DFLT":
209
+ continue # XXX
210
+ for langsys in [script.Script.DefaultLangSys] + [
211
+ l.LangSys for l in script.Script.LangSysRecord
212
+ ]:
213
+ if langsys is None:
214
+ continue # XXX Create!
215
+ feature = [v for v in langsys.FeatureIndex if v.FeatureTag == "locl"]
216
+ assert len(feature) <= 1
217
+ if feature:
218
+ feature = feature[0]
219
+ else:
220
+ if not synthFeature:
221
+ synthFeature = otTables.FeatureRecord()
222
+ synthFeature.FeatureTag = "locl"
223
+ f = synthFeature.Feature = otTables.Feature()
224
+ f.FeatureParams = None
225
+ f.LookupCount = 0
226
+ f.LookupListIndex = []
227
+ table.table.FeatureList.FeatureRecord.append(synthFeature)
228
+ table.table.FeatureList.FeatureCount += 1
229
+ feature = synthFeature
230
+ langsys.FeatureIndex.append(feature)
231
+ langsys.FeatureIndex.sort(key=lambda v: v.FeatureTag)
232
+
233
+ if not synthLookup:
234
+ subtable = otTables.SingleSubst()
235
+ subtable.mapping = dups
236
+ synthLookup = otTables.Lookup()
237
+ synthLookup.LookupFlag = 0
238
+ synthLookup.LookupType = 1
239
+ synthLookup.SubTableCount = 1
240
+ synthLookup.SubTable = [subtable]
241
+ if table.table.LookupList is None:
242
+ # mtiLib uses None as default value for LookupList,
243
+ # while feaLib points to an empty array with count 0
244
+ # TODO: make them do the same
245
+ table.table.LookupList = otTables.LookupList()
246
+ table.table.LookupList.Lookup = []
247
+ table.table.LookupList.LookupCount = 0
248
+ table.table.LookupList.Lookup.append(synthLookup)
249
+ table.table.LookupList.LookupCount += 1
250
+
251
+ if feature.Feature.LookupListIndex[:1] != [synthLookup]:
252
+ feature.Feature.LookupListIndex[:0] = [synthLookup]
253
+ feature.Feature.LookupCount += 1
254
+
255
+ DefaultTable.merge(self, m, tables)
256
+ return self
257
+
258
+
259
+ @add_method(
260
+ otTables.SingleSubst,
261
+ otTables.MultipleSubst,
262
+ otTables.AlternateSubst,
263
+ otTables.LigatureSubst,
264
+ otTables.ReverseChainSingleSubst,
265
+ otTables.SinglePos,
266
+ otTables.PairPos,
267
+ otTables.CursivePos,
268
+ otTables.MarkBasePos,
269
+ otTables.MarkLigPos,
270
+ otTables.MarkMarkPos,
271
+ )
272
+ def mapLookups(self, lookupMap):
273
+ pass
274
+
275
+
276
+ # Copied and trimmed down from subset.py
277
+ @add_method(
278
+ otTables.ContextSubst,
279
+ otTables.ChainContextSubst,
280
+ otTables.ContextPos,
281
+ otTables.ChainContextPos,
282
+ )
283
+ def __merge_classify_context(self):
284
+ class ContextHelper(object):
285
+ def __init__(self, klass, Format):
286
+ if klass.__name__.endswith("Subst"):
287
+ Typ = "Sub"
288
+ Type = "Subst"
289
+ else:
290
+ Typ = "Pos"
291
+ Type = "Pos"
292
+ if klass.__name__.startswith("Chain"):
293
+ Chain = "Chain"
294
+ else:
295
+ Chain = ""
296
+ ChainTyp = Chain + Typ
297
+
298
+ self.Typ = Typ
299
+ self.Type = Type
300
+ self.Chain = Chain
301
+ self.ChainTyp = ChainTyp
302
+
303
+ self.LookupRecord = Type + "LookupRecord"
304
+
305
+ if Format == 1:
306
+ self.Rule = ChainTyp + "Rule"
307
+ self.RuleSet = ChainTyp + "RuleSet"
308
+ elif Format == 2:
309
+ self.Rule = ChainTyp + "ClassRule"
310
+ self.RuleSet = ChainTyp + "ClassSet"
311
+
312
+ if self.Format not in [1, 2, 3]:
313
+ return None # Don't shoot the messenger; let it go
314
+ if not hasattr(self.__class__, "_merge__ContextHelpers"):
315
+ self.__class__._merge__ContextHelpers = {}
316
+ if self.Format not in self.__class__._merge__ContextHelpers:
317
+ helper = ContextHelper(self.__class__, self.Format)
318
+ self.__class__._merge__ContextHelpers[self.Format] = helper
319
+ return self.__class__._merge__ContextHelpers[self.Format]
320
+
321
+
322
+ @add_method(
323
+ otTables.ContextSubst,
324
+ otTables.ChainContextSubst,
325
+ otTables.ContextPos,
326
+ otTables.ChainContextPos,
327
+ )
328
+ def mapLookups(self, lookupMap):
329
+ c = self.__merge_classify_context()
330
+
331
+ if self.Format in [1, 2]:
332
+ for rs in getattr(self, c.RuleSet):
333
+ if not rs:
334
+ continue
335
+ for r in getattr(rs, c.Rule):
336
+ if not r:
337
+ continue
338
+ for ll in getattr(r, c.LookupRecord):
339
+ if not ll:
340
+ continue
341
+ ll.LookupListIndex = lookupMap[ll.LookupListIndex]
342
+ elif self.Format == 3:
343
+ for ll in getattr(self, c.LookupRecord):
344
+ if not ll:
345
+ continue
346
+ ll.LookupListIndex = lookupMap[ll.LookupListIndex]
347
+ else:
348
+ assert 0, "unknown format: %s" % self.Format
349
+
350
+
351
+ @add_method(otTables.ExtensionSubst, otTables.ExtensionPos)
352
+ def mapLookups(self, lookupMap):
353
+ if self.Format == 1:
354
+ self.ExtSubTable.mapLookups(lookupMap)
355
+ else:
356
+ assert 0, "unknown format: %s" % self.Format
357
+
358
+
359
+ @add_method(otTables.Lookup)
360
+ def mapLookups(self, lookupMap):
361
+ for st in self.SubTable:
362
+ if not st:
363
+ continue
364
+ st.mapLookups(lookupMap)
365
+
366
+
367
+ @add_method(otTables.LookupList)
368
+ def mapLookups(self, lookupMap):
369
+ for l in self.Lookup:
370
+ if not l:
371
+ continue
372
+ l.mapLookups(lookupMap)
373
+
374
+
375
+ @add_method(otTables.Lookup)
376
+ def mapMarkFilteringSets(self, markFilteringSetMap):
377
+ if self.LookupFlag & 0x0010:
378
+ self.MarkFilteringSet = markFilteringSetMap[self.MarkFilteringSet]
379
+
380
+
381
+ @add_method(otTables.LookupList)
382
+ def mapMarkFilteringSets(self, markFilteringSetMap):
383
+ for l in self.Lookup:
384
+ if not l:
385
+ continue
386
+ l.mapMarkFilteringSets(markFilteringSetMap)
387
+
388
+
389
+ @add_method(otTables.Feature)
390
+ def mapLookups(self, lookupMap):
391
+ self.LookupListIndex = [lookupMap[i] for i in self.LookupListIndex]
392
+
393
+
394
+ @add_method(otTables.FeatureList)
395
+ def mapLookups(self, lookupMap):
396
+ for f in self.FeatureRecord:
397
+ if not f or not f.Feature:
398
+ continue
399
+ f.Feature.mapLookups(lookupMap)
400
+
401
+
402
+ @add_method(otTables.DefaultLangSys, otTables.LangSys)
403
+ def mapFeatures(self, featureMap):
404
+ self.FeatureIndex = [featureMap[i] for i in self.FeatureIndex]
405
+ if self.ReqFeatureIndex != 65535:
406
+ self.ReqFeatureIndex = featureMap[self.ReqFeatureIndex]
407
+
408
+
409
+ @add_method(otTables.Script)
410
+ def mapFeatures(self, featureMap):
411
+ if self.DefaultLangSys:
412
+ self.DefaultLangSys.mapFeatures(featureMap)
413
+ for l in self.LangSysRecord:
414
+ if not l or not l.LangSys:
415
+ continue
416
+ l.LangSys.mapFeatures(featureMap)
417
+
418
+
419
+ @add_method(otTables.ScriptList)
420
+ def mapFeatures(self, featureMap):
421
+ for s in self.ScriptRecord:
422
+ if not s or not s.Script:
423
+ continue
424
+ s.Script.mapFeatures(featureMap)
425
+
426
+
427
+ def layoutPreMerge(font):
428
+ # Map indices to references
429
+
430
+ GDEF = font.get("GDEF")
431
+ GSUB = font.get("GSUB")
432
+ GPOS = font.get("GPOS")
433
+
434
+ for t in [GSUB, GPOS]:
435
+ if not t:
436
+ continue
437
+
438
+ if t.table.LookupList:
439
+ lookupMap = {i: v for i, v in enumerate(t.table.LookupList.Lookup)}
440
+ t.table.LookupList.mapLookups(lookupMap)
441
+ t.table.FeatureList.mapLookups(lookupMap)
442
+
443
+ if (
444
+ GDEF
445
+ and GDEF.table.Version >= 0x00010002
446
+ and GDEF.table.MarkGlyphSetsDef
447
+ ):
448
+ markFilteringSetMap = {
449
+ i: v for i, v in enumerate(GDEF.table.MarkGlyphSetsDef.Coverage)
450
+ }
451
+ t.table.LookupList.mapMarkFilteringSets(markFilteringSetMap)
452
+
453
+ if t.table.FeatureList and t.table.ScriptList:
454
+ featureMap = {i: v for i, v in enumerate(t.table.FeatureList.FeatureRecord)}
455
+ t.table.ScriptList.mapFeatures(featureMap)
456
+
457
+ # TODO FeatureParams nameIDs
458
+
459
+
460
+ def layoutPostMerge(font):
461
+ # Map references back to indices
462
+
463
+ GDEF = font.get("GDEF")
464
+ GSUB = font.get("GSUB")
465
+ GPOS = font.get("GPOS")
466
+
467
+ for t in [GSUB, GPOS]:
468
+ if not t:
469
+ continue
470
+
471
+ if t.table.FeatureList and t.table.ScriptList:
472
+ # Collect unregistered (new) features.
473
+ featureMap = GregariousIdentityDict(t.table.FeatureList.FeatureRecord)
474
+ t.table.ScriptList.mapFeatures(featureMap)
475
+
476
+ # Record used features.
477
+ featureMap = AttendanceRecordingIdentityDict(
478
+ t.table.FeatureList.FeatureRecord
479
+ )
480
+ t.table.ScriptList.mapFeatures(featureMap)
481
+ usedIndices = featureMap.s
482
+
483
+ # Remove unused features
484
+ t.table.FeatureList.FeatureRecord = [
485
+ f
486
+ for i, f in enumerate(t.table.FeatureList.FeatureRecord)
487
+ if i in usedIndices
488
+ ]
489
+
490
+ # Map back to indices.
491
+ featureMap = NonhashableDict(t.table.FeatureList.FeatureRecord)
492
+ t.table.ScriptList.mapFeatures(featureMap)
493
+
494
+ t.table.FeatureList.FeatureCount = len(t.table.FeatureList.FeatureRecord)
495
+
496
+ if t.table.LookupList:
497
+ # Collect unregistered (new) lookups.
498
+ lookupMap = GregariousIdentityDict(t.table.LookupList.Lookup)
499
+ t.table.FeatureList.mapLookups(lookupMap)
500
+ t.table.LookupList.mapLookups(lookupMap)
501
+
502
+ # Record used lookups.
503
+ lookupMap = AttendanceRecordingIdentityDict(t.table.LookupList.Lookup)
504
+ t.table.FeatureList.mapLookups(lookupMap)
505
+ t.table.LookupList.mapLookups(lookupMap)
506
+ usedIndices = lookupMap.s
507
+
508
+ # Remove unused lookups
509
+ t.table.LookupList.Lookup = [
510
+ l for i, l in enumerate(t.table.LookupList.Lookup) if i in usedIndices
511
+ ]
512
+
513
+ # Map back to indices.
514
+ lookupMap = NonhashableDict(t.table.LookupList.Lookup)
515
+ t.table.FeatureList.mapLookups(lookupMap)
516
+ t.table.LookupList.mapLookups(lookupMap)
517
+
518
+ t.table.LookupList.LookupCount = len(t.table.LookupList.Lookup)
519
+
520
+ if GDEF and GDEF.table.Version >= 0x00010002:
521
+ markFilteringSetMap = NonhashableDict(
522
+ GDEF.table.MarkGlyphSetsDef.Coverage
523
+ )
524
+ t.table.LookupList.mapMarkFilteringSets(markFilteringSetMap)
525
+
526
+ # TODO FeatureParams nameIDs
@@ -0,0 +1,85 @@
1
+ # Copyright 2013 Google, Inc. All Rights Reserved.
2
+ #
3
+ # Google Author(s): Behdad Esfahbod, Roozbeh Pournader
4
+
5
+
6
+ class Options(object):
7
+ class UnknownOptionError(Exception):
8
+ pass
9
+
10
+ def __init__(self, **kwargs):
11
+ self.verbose = False
12
+ self.timing = False
13
+ self.drop_tables = []
14
+ self.input_file = None
15
+ self.output_file = "merged.ttf"
16
+ self.import_file = None
17
+
18
+ self.set(**kwargs)
19
+
20
+ def set(self, **kwargs):
21
+ for k, v in kwargs.items():
22
+ if not hasattr(self, k):
23
+ raise self.UnknownOptionError("Unknown option '%s'" % k)
24
+ setattr(self, k, v)
25
+
26
+ def parse_opts(self, argv, ignore_unknown=[]):
27
+ ret = []
28
+ opts = {}
29
+ for a in argv:
30
+ orig_a = a
31
+ if not a.startswith("--"):
32
+ ret.append(a)
33
+ continue
34
+ a = a[2:]
35
+ i = a.find("=")
36
+ op = "="
37
+ if i == -1:
38
+ if a.startswith("no-"):
39
+ k = a[3:]
40
+ v = False
41
+ else:
42
+ k = a
43
+ v = True
44
+ else:
45
+ k = a[:i]
46
+ if k[-1] in "-+":
47
+ op = k[-1] + "=" # Ops is '-=' or '+=' now.
48
+ k = k[:-1]
49
+ v = a[i + 1 :]
50
+ ok = k
51
+ k = k.replace("-", "_")
52
+ if not hasattr(self, k):
53
+ if ignore_unknown is True or ok in ignore_unknown:
54
+ ret.append(orig_a)
55
+ continue
56
+ else:
57
+ raise self.UnknownOptionError("Unknown option '%s'" % a)
58
+
59
+ ov = getattr(self, k)
60
+ if isinstance(ov, bool):
61
+ v = bool(v)
62
+ elif isinstance(ov, int):
63
+ v = int(v)
64
+ elif isinstance(ov, list):
65
+ vv = v.split(",")
66
+ if vv == [""]:
67
+ vv = []
68
+ vv = [int(x, 0) if len(x) and x[0] in "0123456789" else x for x in vv]
69
+ if op == "=":
70
+ v = vv
71
+ elif op == "+=":
72
+ v = ov
73
+ v.extend(vv)
74
+ elif op == "-=":
75
+ v = ov
76
+ for x in vv:
77
+ if x in v:
78
+ v.remove(x)
79
+ else:
80
+ assert 0
81
+
82
+ opts[k] = v
83
+ self.set(**opts)
84
+
85
+ return ret