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,352 @@
1
+ # Copyright 2013 Google, Inc. All Rights Reserved.
2
+ #
3
+ # Google Author(s): Behdad Esfahbod, Roozbeh Pournader
4
+
5
+ from fontTools import ttLib, cffLib
6
+ from fontTools.misc.psCharStrings import T2WidthExtractor
7
+ from fontTools.ttLib.tables.DefaultTable import DefaultTable
8
+ from fontTools.merge.base import add_method, mergeObjects
9
+ from fontTools.merge.cmap import computeMegaCmap
10
+ from fontTools.merge.util import *
11
+ import logging
12
+
13
+
14
+ log = logging.getLogger("fontTools.merge")
15
+
16
+
17
+ ttLib.getTableClass("maxp").mergeMap = {
18
+ "*": max,
19
+ "tableTag": equal,
20
+ "tableVersion": equal,
21
+ "numGlyphs": sum,
22
+ "maxStorage": first,
23
+ "maxFunctionDefs": first,
24
+ "maxInstructionDefs": first,
25
+ # TODO When we correctly merge hinting data, update these values:
26
+ # maxFunctionDefs, maxInstructionDefs, maxSizeOfInstructions
27
+ }
28
+
29
+ headFlagsMergeBitMap = {
30
+ "size": 16,
31
+ "*": bitwise_or,
32
+ 1: bitwise_and, # Baseline at y = 0
33
+ 2: bitwise_and, # lsb at x = 0
34
+ 3: bitwise_and, # Force ppem to integer values. FIXME?
35
+ 5: bitwise_and, # Font is vertical
36
+ 6: lambda bit: 0, # Always set to zero
37
+ 11: bitwise_and, # Font data is 'lossless'
38
+ 13: bitwise_and, # Optimized for ClearType
39
+ 14: bitwise_and, # Last resort font. FIXME? equal or first may be better
40
+ 15: lambda bit: 0, # Always set to zero
41
+ }
42
+
43
+ ttLib.getTableClass("head").mergeMap = {
44
+ "tableTag": equal,
45
+ "tableVersion": max,
46
+ "fontRevision": max,
47
+ "checkSumAdjustment": lambda lst: 0, # We need *something* here
48
+ "magicNumber": equal,
49
+ "flags": mergeBits(headFlagsMergeBitMap),
50
+ "unitsPerEm": equal,
51
+ "created": current_time,
52
+ "modified": current_time,
53
+ "xMin": min,
54
+ "yMin": min,
55
+ "xMax": max,
56
+ "yMax": max,
57
+ "macStyle": first,
58
+ "lowestRecPPEM": max,
59
+ "fontDirectionHint": lambda lst: 2,
60
+ "indexToLocFormat": first,
61
+ "glyphDataFormat": equal,
62
+ }
63
+
64
+ ttLib.getTableClass("hhea").mergeMap = {
65
+ "*": equal,
66
+ "tableTag": equal,
67
+ "tableVersion": max,
68
+ "ascent": max,
69
+ "descent": min,
70
+ "lineGap": max,
71
+ "advanceWidthMax": max,
72
+ "minLeftSideBearing": min,
73
+ "minRightSideBearing": min,
74
+ "xMaxExtent": max,
75
+ "caretSlopeRise": first,
76
+ "caretSlopeRun": first,
77
+ "caretOffset": first,
78
+ "numberOfHMetrics": recalculate,
79
+ }
80
+
81
+ ttLib.getTableClass("vhea").mergeMap = {
82
+ "*": equal,
83
+ "tableTag": equal,
84
+ "tableVersion": max,
85
+ "ascent": max,
86
+ "descent": min,
87
+ "lineGap": max,
88
+ "advanceHeightMax": max,
89
+ "minTopSideBearing": min,
90
+ "minBottomSideBearing": min,
91
+ "yMaxExtent": max,
92
+ "caretSlopeRise": first,
93
+ "caretSlopeRun": first,
94
+ "caretOffset": first,
95
+ "numberOfVMetrics": recalculate,
96
+ }
97
+
98
+ os2FsTypeMergeBitMap = {
99
+ "size": 16,
100
+ "*": lambda bit: 0,
101
+ 1: bitwise_or, # no embedding permitted
102
+ 2: bitwise_and, # allow previewing and printing documents
103
+ 3: bitwise_and, # allow editing documents
104
+ 8: bitwise_or, # no subsetting permitted
105
+ 9: bitwise_or, # no embedding of outlines permitted
106
+ }
107
+
108
+
109
+ def mergeOs2FsType(lst):
110
+ lst = list(lst)
111
+ if all(item == 0 for item in lst):
112
+ return 0
113
+
114
+ # Compute least restrictive logic for each fsType value
115
+ for i in range(len(lst)):
116
+ # unset bit 1 (no embedding permitted) if either bit 2 or 3 is set
117
+ if lst[i] & 0x000C:
118
+ lst[i] &= ~0x0002
119
+ # set bit 2 (allow previewing) if bit 3 is set (allow editing)
120
+ elif lst[i] & 0x0008:
121
+ lst[i] |= 0x0004
122
+ # set bits 2 and 3 if everything is allowed
123
+ elif lst[i] == 0:
124
+ lst[i] = 0x000C
125
+
126
+ fsType = mergeBits(os2FsTypeMergeBitMap)(lst)
127
+ # unset bits 2 and 3 if bit 1 is set (some font is "no embedding")
128
+ if fsType & 0x0002:
129
+ fsType &= ~0x000C
130
+ return fsType
131
+
132
+
133
+ ttLib.getTableClass("OS/2").mergeMap = {
134
+ "*": first,
135
+ "tableTag": equal,
136
+ "version": max,
137
+ "xAvgCharWidth": first, # Will be recalculated at the end on the merged font
138
+ "fsType": mergeOs2FsType, # Will be overwritten
139
+ "panose": first, # FIXME: should really be the first Latin font
140
+ "ulUnicodeRange1": bitwise_or,
141
+ "ulUnicodeRange2": bitwise_or,
142
+ "ulUnicodeRange3": bitwise_or,
143
+ "ulUnicodeRange4": bitwise_or,
144
+ "fsFirstCharIndex": min,
145
+ "fsLastCharIndex": max,
146
+ "sTypoAscender": max,
147
+ "sTypoDescender": min,
148
+ "sTypoLineGap": max,
149
+ "usWinAscent": max,
150
+ "usWinDescent": max,
151
+ # Version 1
152
+ "ulCodePageRange1": onlyExisting(bitwise_or),
153
+ "ulCodePageRange2": onlyExisting(bitwise_or),
154
+ # Version 2, 3, 4
155
+ "sxHeight": onlyExisting(max),
156
+ "sCapHeight": onlyExisting(max),
157
+ "usDefaultChar": onlyExisting(first),
158
+ "usBreakChar": onlyExisting(first),
159
+ "usMaxContext": onlyExisting(max),
160
+ # version 5
161
+ "usLowerOpticalPointSize": onlyExisting(min),
162
+ "usUpperOpticalPointSize": onlyExisting(max),
163
+ }
164
+
165
+
166
+ @add_method(ttLib.getTableClass("OS/2"))
167
+ def merge(self, m, tables):
168
+ DefaultTable.merge(self, m, tables)
169
+ if self.version < 2:
170
+ # bits 8 and 9 are reserved and should be set to zero
171
+ self.fsType &= ~0x0300
172
+ if self.version >= 3:
173
+ # Only one of bits 1, 2, and 3 may be set. We already take
174
+ # care of bit 1 implications in mergeOs2FsType. So unset
175
+ # bit 2 if bit 3 is already set.
176
+ if self.fsType & 0x0008:
177
+ self.fsType &= ~0x0004
178
+ return self
179
+
180
+
181
+ ttLib.getTableClass("post").mergeMap = {
182
+ "*": first,
183
+ "tableTag": equal,
184
+ "formatType": max,
185
+ "isFixedPitch": min,
186
+ "minMemType42": max,
187
+ "maxMemType42": lambda lst: 0,
188
+ "minMemType1": max,
189
+ "maxMemType1": lambda lst: 0,
190
+ "mapping": onlyExisting(sumDicts),
191
+ "extraNames": lambda lst: [],
192
+ }
193
+
194
+ ttLib.getTableClass("vmtx").mergeMap = ttLib.getTableClass("hmtx").mergeMap = {
195
+ "tableTag": equal,
196
+ "metrics": sumDicts,
197
+ }
198
+
199
+ ttLib.getTableClass("name").mergeMap = {
200
+ "tableTag": equal,
201
+ "names": first, # FIXME? Does mixing name records make sense?
202
+ }
203
+
204
+ ttLib.getTableClass("loca").mergeMap = {
205
+ "*": recalculate,
206
+ "tableTag": equal,
207
+ }
208
+
209
+ ttLib.getTableClass("glyf").mergeMap = {
210
+ "tableTag": equal,
211
+ "glyphs": sumDicts,
212
+ "glyphOrder": sumLists,
213
+ "_reverseGlyphOrder": recalculate,
214
+ "axisTags": equal,
215
+ }
216
+
217
+
218
+ @add_method(ttLib.getTableClass("glyf"))
219
+ def merge(self, m, tables):
220
+ for i, table in enumerate(tables):
221
+ for g in table.glyphs.values():
222
+ if i:
223
+ # Drop hints for all but first font, since
224
+ # we don't map functions / CVT values.
225
+ g.removeHinting()
226
+ # Expand composite glyphs to load their
227
+ # composite glyph names.
228
+ if g.isComposite():
229
+ g.expand(table)
230
+ return DefaultTable.merge(self, m, tables)
231
+
232
+
233
+ ttLib.getTableClass("prep").mergeMap = lambda self, lst: first(lst)
234
+ ttLib.getTableClass("fpgm").mergeMap = lambda self, lst: first(lst)
235
+ ttLib.getTableClass("cvt ").mergeMap = lambda self, lst: first(lst)
236
+ ttLib.getTableClass("gasp").mergeMap = lambda self, lst: first(
237
+ lst
238
+ ) # FIXME? Appears irreconcilable
239
+
240
+
241
+ @add_method(ttLib.getTableClass("CFF "))
242
+ def merge(self, m, tables):
243
+ if any(hasattr(table.cff[0], "FDSelect") for table in tables):
244
+ raise NotImplementedError("Merging CID-keyed CFF tables is not supported yet")
245
+
246
+ for table in tables:
247
+ table.cff.desubroutinize()
248
+
249
+ newcff = tables[0]
250
+ newfont = newcff.cff[0]
251
+ private = newfont.Private
252
+ newDefaultWidthX, newNominalWidthX = private.defaultWidthX, private.nominalWidthX
253
+ storedNamesStrings = []
254
+ glyphOrderStrings = []
255
+ glyphOrder = set(newfont.getGlyphOrder())
256
+
257
+ for name in newfont.strings.strings:
258
+ if name not in glyphOrder:
259
+ storedNamesStrings.append(name)
260
+ else:
261
+ glyphOrderStrings.append(name)
262
+
263
+ chrset = list(newfont.charset)
264
+ newcs = newfont.CharStrings
265
+ log.debug("FONT 0 CharStrings: %d.", len(newcs))
266
+
267
+ for i, table in enumerate(tables[1:], start=1):
268
+ font = table.cff[0]
269
+ defaultWidthX, nominalWidthX = (
270
+ font.Private.defaultWidthX,
271
+ font.Private.nominalWidthX,
272
+ )
273
+ widthsDiffer = (
274
+ defaultWidthX != newDefaultWidthX or nominalWidthX != newNominalWidthX
275
+ )
276
+ font.Private = private
277
+ fontGlyphOrder = set(font.getGlyphOrder())
278
+ for name in font.strings.strings:
279
+ if name in fontGlyphOrder:
280
+ glyphOrderStrings.append(name)
281
+ cs = font.CharStrings
282
+ gs = table.cff.GlobalSubrs
283
+ log.debug("Font %d CharStrings: %d.", i, len(cs))
284
+ chrset.extend(font.charset)
285
+ if newcs.charStringsAreIndexed:
286
+ for i, name in enumerate(cs.charStrings, start=len(newcs)):
287
+ newcs.charStrings[name] = i
288
+ newcs.charStringsIndex.items.append(None)
289
+ for name in cs.charStrings:
290
+ if widthsDiffer:
291
+ c = cs[name]
292
+ defaultWidthXToken = object()
293
+ extractor = T2WidthExtractor([], [], nominalWidthX, defaultWidthXToken)
294
+ extractor.execute(c)
295
+ width = extractor.width
296
+ if width is not defaultWidthXToken:
297
+ # The following will be wrong if the width is added
298
+ # by a subroutine. Ouch!
299
+ c.program.pop(0)
300
+ else:
301
+ width = defaultWidthX
302
+ if width != newDefaultWidthX:
303
+ c.program.insert(0, width - newNominalWidthX)
304
+ newcs[name] = cs[name]
305
+
306
+ newfont.charset = chrset
307
+ newfont.numGlyphs = len(chrset)
308
+ newfont.strings.strings = glyphOrderStrings + storedNamesStrings
309
+
310
+ return newcff
311
+
312
+
313
+ @add_method(ttLib.getTableClass("cmap"))
314
+ def merge(self, m, tables):
315
+ if not hasattr(m, "cmap"):
316
+ computeMegaCmap(m, tables)
317
+ cmap = m.cmap
318
+
319
+ cmapBmpOnly = {uni: gid for uni, gid in cmap.items() if uni <= 0xFFFF}
320
+ self.tables = []
321
+ module = ttLib.getTableModule("cmap")
322
+ if len(cmapBmpOnly) != len(cmap):
323
+ # format-12 required.
324
+ cmapTable = module.cmap_classes[12](12)
325
+ cmapTable.platformID = 3
326
+ cmapTable.platEncID = 10
327
+ cmapTable.language = 0
328
+ cmapTable.cmap = cmap
329
+ self.tables.append(cmapTable)
330
+ # always create format-4
331
+ cmapTable = module.cmap_classes[4](4)
332
+ cmapTable.platformID = 3
333
+ cmapTable.platEncID = 1
334
+ cmapTable.language = 0
335
+ cmapTable.cmap = cmapBmpOnly
336
+ # ordered by platform then encoding
337
+ self.tables.insert(0, cmapTable)
338
+
339
+ uvsDict = m.uvsDict
340
+ if uvsDict:
341
+ # format-14
342
+ uvsTable = module.cmap_classes[14](14)
343
+ uvsTable.platformID = 0
344
+ uvsTable.platEncID = 5
345
+ uvsTable.language = 0
346
+ uvsTable.cmap = {}
347
+ uvsTable.uvsDict = uvsDict
348
+ # ordered by platform then encoding
349
+ self.tables.insert(0, uvsTable)
350
+ self.tableVersion = 0
351
+ self.numSubTables = len(self.tables)
352
+ return self
@@ -0,0 +1,78 @@
1
+ # Copyright 2021 Behdad Esfahbod. All Rights Reserved.
2
+
3
+
4
+ def is_Default_Ignorable(u):
5
+ # http://www.unicode.org/reports/tr44/#Default_Ignorable_Code_Point
6
+ #
7
+ # TODO Move me to unicodedata module and autogenerate.
8
+ #
9
+ # Unicode 14.0:
10
+ # $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
11
+ # 00AD # Cf SOFT HYPHEN
12
+ # 034F # Mn COMBINING GRAPHEME JOINER
13
+ # 061C # Cf ARABIC LETTER MARK
14
+ # 115F..1160 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
15
+ # 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
16
+ # 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
17
+ # 180E # Cf MONGOLIAN VOWEL SEPARATOR
18
+ # 180F # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
19
+ # 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
20
+ # 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
21
+ # 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS
22
+ # 2065 # Cn <reserved-2065>
23
+ # 2066..206F # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
24
+ # 3164 # Lo HANGUL FILLER
25
+ # FE00..FE0F # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
26
+ # FEFF # Cf ZERO WIDTH NO-BREAK SPACE
27
+ # FFA0 # Lo HALFWIDTH HANGUL FILLER
28
+ # FFF0..FFF8 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
29
+ # 1BCA0..1BCA3 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
30
+ # 1D173..1D17A # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
31
+ # E0000 # Cn <reserved-E0000>
32
+ # E0001 # Cf LANGUAGE TAG
33
+ # E0002..E001F # Cn [30] <reserved-E0002>..<reserved-E001F>
34
+ # E0020..E007F # Cf [96] TAG SPACE..CANCEL TAG
35
+ # E0080..E00FF # Cn [128] <reserved-E0080>..<reserved-E00FF>
36
+ # E0100..E01EF # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
37
+ # E01F0..E0FFF # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
38
+ return (
39
+ u == 0x00AD
40
+ or u == 0x034F # Cf SOFT HYPHEN
41
+ or u == 0x061C # Mn COMBINING GRAPHEME JOINER
42
+ or 0x115F <= u <= 0x1160 # Cf ARABIC LETTER MARK
43
+ or 0x17B4 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
44
+ <= u
45
+ <= 0x17B5
46
+ or 0x180B # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
47
+ <= u
48
+ <= 0x180D
49
+ or u # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
50
+ == 0x180E
51
+ or u == 0x180F # Cf MONGOLIAN VOWEL SEPARATOR
52
+ or 0x200B <= u <= 0x200F # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
53
+ or 0x202A <= u <= 0x202E # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
54
+ or 0x2060 # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
55
+ <= u
56
+ <= 0x2064
57
+ or u == 0x2065 # Cf [5] WORD JOINER..INVISIBLE PLUS
58
+ or 0x2066 <= u <= 0x206F # Cn <reserved-2065>
59
+ or u == 0x3164 # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
60
+ or 0xFE00 <= u <= 0xFE0F # Lo HANGUL FILLER
61
+ or u == 0xFEFF # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
62
+ or u == 0xFFA0 # Cf ZERO WIDTH NO-BREAK SPACE
63
+ or 0xFFF0 <= u <= 0xFFF8 # Lo HALFWIDTH HANGUL FILLER
64
+ or 0x1BCA0 <= u <= 0x1BCA3 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
65
+ or 0x1D173 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
66
+ <= u
67
+ <= 0x1D17A
68
+ or u == 0xE0000 # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
69
+ or u == 0xE0001 # Cn <reserved-E0000>
70
+ or 0xE0002 <= u <= 0xE001F # Cf LANGUAGE TAG
71
+ or 0xE0020 <= u <= 0xE007F # Cn [30] <reserved-E0002>..<reserved-E001F>
72
+ or 0xE0080 <= u <= 0xE00FF # Cf [96] TAG SPACE..CANCEL TAG
73
+ or 0xE0100 <= u <= 0xE01EF # Cn [128] <reserved-E0080>..<reserved-E00FF>
74
+ or 0xE01F0 # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
75
+ <= u
76
+ <= 0xE0FFF
77
+ or False # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
78
+ )
@@ -0,0 +1,143 @@
1
+ # Copyright 2013 Google, Inc. All Rights Reserved.
2
+ #
3
+ # Google Author(s): Behdad Esfahbod, Roozbeh Pournader
4
+
5
+ from fontTools.misc.timeTools import timestampNow
6
+ from fontTools.ttLib.tables.DefaultTable import DefaultTable
7
+ from functools import reduce
8
+ import operator
9
+ import logging
10
+
11
+
12
+ log = logging.getLogger("fontTools.merge")
13
+
14
+
15
+ # General utility functions for merging values from different fonts
16
+
17
+
18
+ def equal(lst):
19
+ lst = list(lst)
20
+ t = iter(lst)
21
+ first = next(t)
22
+ assert all(item == first for item in t), "Expected all items to be equal: %s" % lst
23
+ return first
24
+
25
+
26
+ def first(lst):
27
+ return next(iter(lst))
28
+
29
+
30
+ def recalculate(lst):
31
+ return NotImplemented
32
+
33
+
34
+ def current_time(lst):
35
+ return timestampNow()
36
+
37
+
38
+ def bitwise_and(lst):
39
+ return reduce(operator.and_, lst)
40
+
41
+
42
+ def bitwise_or(lst):
43
+ return reduce(operator.or_, lst)
44
+
45
+
46
+ def avg_int(lst):
47
+ lst = list(lst)
48
+ return sum(lst) // len(lst)
49
+
50
+
51
+ def onlyExisting(func):
52
+ """Returns a filter func that when called with a list,
53
+ only calls func on the non-NotImplemented items of the list,
54
+ and only so if there's at least one item remaining.
55
+ Otherwise returns NotImplemented."""
56
+
57
+ def wrapper(lst):
58
+ items = [item for item in lst if item is not NotImplemented]
59
+ return func(items) if items else NotImplemented
60
+
61
+ return wrapper
62
+
63
+
64
+ def sumLists(lst):
65
+ l = []
66
+ for item in lst:
67
+ l.extend(item)
68
+ return l
69
+
70
+
71
+ def sumDicts(lst):
72
+ d = {}
73
+ for item in lst:
74
+ d.update(item)
75
+ return d
76
+
77
+
78
+ def mergeBits(bitmap):
79
+ def wrapper(lst):
80
+ lst = list(lst)
81
+ returnValue = 0
82
+ for bitNumber in range(bitmap["size"]):
83
+ try:
84
+ mergeLogic = bitmap[bitNumber]
85
+ except KeyError:
86
+ try:
87
+ mergeLogic = bitmap["*"]
88
+ except KeyError:
89
+ raise Exception("Don't know how to merge bit %s" % bitNumber)
90
+ shiftedBit = 1 << bitNumber
91
+ mergedValue = mergeLogic(bool(item & shiftedBit) for item in lst)
92
+ returnValue |= mergedValue << bitNumber
93
+ return returnValue
94
+
95
+ return wrapper
96
+
97
+
98
+ class AttendanceRecordingIdentityDict(object):
99
+ """A dictionary-like object that records indices of items actually accessed
100
+ from a list."""
101
+
102
+ def __init__(self, lst):
103
+ self.l = lst
104
+ self.d = {id(v): i for i, v in enumerate(lst)}
105
+ self.s = set()
106
+
107
+ def __getitem__(self, v):
108
+ self.s.add(self.d[id(v)])
109
+ return v
110
+
111
+
112
+ class GregariousIdentityDict(object):
113
+ """A dictionary-like object that welcomes guests without reservations and
114
+ adds them to the end of the guest list."""
115
+
116
+ def __init__(self, lst):
117
+ self.l = lst
118
+ self.s = set(id(v) for v in lst)
119
+
120
+ def __getitem__(self, v):
121
+ if id(v) not in self.s:
122
+ self.s.add(id(v))
123
+ self.l.append(v)
124
+ return v
125
+
126
+
127
+ class NonhashableDict(object):
128
+ """A dictionary-like object mapping objects to values."""
129
+
130
+ def __init__(self, keys, values=None):
131
+ if values is None:
132
+ self.d = {id(v): i for i, v in enumerate(keys)}
133
+ else:
134
+ self.d = {id(k): v for k, v in zip(keys, values)}
135
+
136
+ def __getitem__(self, k):
137
+ return self.d[id(k)]
138
+
139
+ def __setitem__(self, k, v):
140
+ self.d[id(k)] = v
141
+
142
+ def __delitem__(self, k):
143
+ del self.d[id(k)]
@@ -0,0 +1 @@
1
+ """Empty __init__.py file to signal Python this directory is a package."""