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,82 @@
1
+ from .interpolatableHelpers import *
2
+ import logging
3
+
4
+ log = logging.getLogger("fontTools.varLib.interpolatable")
5
+
6
+
7
+ def test_contour_order(glyph0, glyph1):
8
+ # We try matching both the StatisticsControlPen vector
9
+ # and the StatisticsPen vector.
10
+ #
11
+ # If either method found a identity matching, accept it.
12
+ # This is crucial for fonts like Kablammo[MORF].ttf and
13
+ # Nabla[EDPT,EHLT].ttf, since they really confuse the
14
+ # StatisticsPen vector because of their area=0 contours.
15
+
16
+ n = len(glyph0.controlVectors)
17
+ matching = None
18
+ matching_cost = 0
19
+ identity_cost = 0
20
+ done = n <= 1
21
+ if not done:
22
+ m0Control = glyph0.controlVectors
23
+ m1Control = glyph1.controlVectors
24
+ (
25
+ matching_control,
26
+ matching_cost_control,
27
+ identity_cost_control,
28
+ ) = matching_for_vectors(m0Control, m1Control)
29
+ done = matching_cost_control == identity_cost_control
30
+ if not done:
31
+ m0Green = glyph0.greenVectors
32
+ m1Green = glyph1.greenVectors
33
+ (
34
+ matching_green,
35
+ matching_cost_green,
36
+ identity_cost_green,
37
+ ) = matching_for_vectors(m0Green, m1Green)
38
+ done = matching_cost_green == identity_cost_green
39
+
40
+ if not done:
41
+ # See if reversing contours in one master helps.
42
+ # That's a common problem. Then the wrong_start_point
43
+ # test will fix them.
44
+ #
45
+ # Reverse the sign of the area (0); the rest stay the same.
46
+ if not done:
47
+ m1ControlReversed = [(-m[0],) + m[1:] for m in m1Control]
48
+ (
49
+ matching_control_reversed,
50
+ matching_cost_control_reversed,
51
+ identity_cost_control_reversed,
52
+ ) = matching_for_vectors(m0Control, m1ControlReversed)
53
+ done = matching_cost_control_reversed == identity_cost_control_reversed
54
+ if not done:
55
+ m1GreenReversed = [(-m[0],) + m[1:] for m in m1Green]
56
+ (
57
+ matching_control_reversed,
58
+ matching_cost_green_reversed,
59
+ identity_cost_green_reversed,
60
+ ) = matching_for_vectors(m0Green, m1GreenReversed)
61
+ done = matching_cost_green_reversed == identity_cost_green_reversed
62
+
63
+ if not done:
64
+ # Otherwise, use the worst of the two matchings.
65
+ if (
66
+ matching_cost_control / identity_cost_control
67
+ < matching_cost_green / identity_cost_green
68
+ ):
69
+ matching = matching_control
70
+ matching_cost = matching_cost_control
71
+ identity_cost = identity_cost_control
72
+ else:
73
+ matching = matching_green
74
+ matching_cost = matching_cost_green
75
+ identity_cost = identity_cost_green
76
+
77
+ this_tolerance = matching_cost / identity_cost if identity_cost else 1
78
+ log.debug(
79
+ "test-contour-order: tolerance %g",
80
+ this_tolerance,
81
+ )
82
+ return this_tolerance, matching
@@ -0,0 +1,107 @@
1
+ from .interpolatableHelpers import *
2
+
3
+
4
+ def test_starting_point(glyph0, glyph1, ix, tolerance, matching):
5
+ if matching is None:
6
+ matching = list(range(len(glyph0.isomorphisms)))
7
+ contour0 = glyph0.isomorphisms[ix]
8
+ contour1 = glyph1.isomorphisms[matching[ix]]
9
+ m0Vectors = glyph0.greenVectors
10
+ m1Vectors = [glyph1.greenVectors[i] for i in matching]
11
+
12
+ c0 = contour0[0]
13
+ # Next few lines duplicated below.
14
+ costs = [vdiff_hypot2_complex(c0[0], c1[0]) for c1 in contour1]
15
+ min_cost_idx, min_cost = min(enumerate(costs), key=lambda x: x[1])
16
+ first_cost = costs[0]
17
+ proposed_point = contour1[min_cost_idx][1]
18
+ reverse = contour1[min_cost_idx][2]
19
+
20
+ if min_cost < first_cost * tolerance:
21
+ # c0 is the first isomorphism of the m0 master
22
+ # contour1 is list of all isomorphisms of the m1 master
23
+ #
24
+ # If the two shapes are both circle-ish and slightly
25
+ # rotated, we detect wrong start point. This is for
26
+ # example the case hundreds of times in
27
+ # RobotoSerif-Italic[GRAD,opsz,wdth,wght].ttf
28
+ #
29
+ # If the proposed point is only one off from the first
30
+ # point (and not reversed), try harder:
31
+ #
32
+ # Find the major eigenvector of the covariance matrix,
33
+ # and rotate the contours by that angle. Then find the
34
+ # closest point again. If it matches this time, let it
35
+ # pass.
36
+
37
+ num_points = len(glyph1.points[ix])
38
+ leeway = 3
39
+ if not reverse and (
40
+ proposed_point <= leeway or proposed_point >= num_points - leeway
41
+ ):
42
+ # Try harder
43
+
44
+ # Recover the covariance matrix from the GreenVectors.
45
+ # This is a 2x2 matrix.
46
+ transforms = []
47
+ for vector in (m0Vectors[ix], m1Vectors[ix]):
48
+ meanX = vector[1]
49
+ meanY = vector[2]
50
+ stddevX = vector[3] * 0.5
51
+ stddevY = vector[4] * 0.5
52
+ correlation = vector[5]
53
+ if correlation:
54
+ correlation /= abs(vector[0])
55
+
56
+ # https://cookierobotics.com/007/
57
+ a = stddevX * stddevX # VarianceX
58
+ c = stddevY * stddevY # VarianceY
59
+ b = correlation * stddevX * stddevY # Covariance
60
+
61
+ delta = (((a - c) * 0.5) ** 2 + b * b) ** 0.5
62
+ lambda1 = (a + c) * 0.5 + delta # Major eigenvalue
63
+ lambda2 = (a + c) * 0.5 - delta # Minor eigenvalue
64
+ theta = atan2(lambda1 - a, b) if b != 0 else (pi * 0.5 if a < c else 0)
65
+ trans = Transform()
66
+ # Don't translate here. We are working on the complex-vector
67
+ # that includes more than just the points. It's horrible what
68
+ # we are doing anyway...
69
+ # trans = trans.translate(meanX, meanY)
70
+ trans = trans.rotate(theta)
71
+ trans = trans.scale(sqrt(lambda1), sqrt(lambda2))
72
+ transforms.append(trans)
73
+
74
+ trans = transforms[0]
75
+ new_c0 = (
76
+ [complex(*trans.transformPoint((pt.real, pt.imag))) for pt in c0[0]],
77
+ ) + c0[1:]
78
+ trans = transforms[1]
79
+ new_contour1 = []
80
+ for c1 in contour1:
81
+ new_c1 = (
82
+ [
83
+ complex(*trans.transformPoint((pt.real, pt.imag)))
84
+ for pt in c1[0]
85
+ ],
86
+ ) + c1[1:]
87
+ new_contour1.append(new_c1)
88
+
89
+ # Next few lines duplicate from above.
90
+ costs = [
91
+ vdiff_hypot2_complex(new_c0[0], new_c1[0]) for new_c1 in new_contour1
92
+ ]
93
+ min_cost_idx, min_cost = min(enumerate(costs), key=lambda x: x[1])
94
+ first_cost = costs[0]
95
+ if min_cost < first_cost * tolerance:
96
+ # Don't report this
97
+ # min_cost = first_cost
98
+ # reverse = False
99
+ # proposed_point = 0 # new_contour1[min_cost_idx][1]
100
+ pass
101
+
102
+ this_tolerance = min_cost / first_cost if first_cost else 1
103
+ log.debug(
104
+ "test-starting-point: tolerance %g",
105
+ this_tolerance,
106
+ )
107
+ return this_tolerance, proposed_point, reverse
@@ -0,0 +1,124 @@
1
+ """
2
+ Interpolate OpenType Layout tables (GDEF / GPOS / GSUB).
3
+ """
4
+
5
+ from fontTools.ttLib import TTFont
6
+ from fontTools.varLib import models, VarLibError, load_designspace, load_masters
7
+ from fontTools.varLib.merger import InstancerMerger
8
+ import os.path
9
+ import logging
10
+ from copy import deepcopy
11
+ from pprint import pformat
12
+
13
+ log = logging.getLogger("fontTools.varLib.interpolate_layout")
14
+
15
+
16
+ def interpolate_layout(designspace, loc, master_finder=lambda s: s, mapped=False):
17
+ """
18
+ Interpolate GPOS from a designspace file and location.
19
+
20
+ If master_finder is set, it should be a callable that takes master
21
+ filename as found in designspace file and map it to master font
22
+ binary as to be opened (eg. .ttf or .otf).
23
+
24
+ If mapped is False (default), then location is mapped using the
25
+ map element of the axes in designspace file. If mapped is True,
26
+ it is assumed that location is in designspace's internal space and
27
+ no mapping is performed.
28
+ """
29
+ if hasattr(designspace, "sources"): # Assume a DesignspaceDocument
30
+ pass
31
+ else: # Assume a file path
32
+ from fontTools.designspaceLib import DesignSpaceDocument
33
+
34
+ designspace = DesignSpaceDocument.fromfile(designspace)
35
+
36
+ ds = load_designspace(designspace)
37
+ log.info("Building interpolated font")
38
+
39
+ log.info("Loading master fonts")
40
+ master_fonts = load_masters(designspace, master_finder)
41
+ font = deepcopy(master_fonts[ds.base_idx])
42
+
43
+ log.info("Location: %s", pformat(loc))
44
+ if not mapped:
45
+ loc = {name: ds.axes[name].map_forward(v) for name, v in loc.items()}
46
+ log.info("Internal location: %s", pformat(loc))
47
+ loc = models.normalizeLocation(loc, ds.internal_axis_supports)
48
+ log.info("Normalized location: %s", pformat(loc))
49
+
50
+ # Assume single-model for now.
51
+ model = models.VariationModel(ds.normalized_master_locs)
52
+ assert 0 == model.mapping[ds.base_idx]
53
+
54
+ merger = InstancerMerger(font, model, loc)
55
+
56
+ log.info("Building interpolated tables")
57
+ # TODO GSUB/GDEF
58
+ merger.mergeTables(font, master_fonts, ["GPOS"])
59
+ return font
60
+
61
+
62
+ def main(args=None):
63
+ """Interpolate GDEF/GPOS/GSUB tables for a point on a designspace"""
64
+ from fontTools import configLogger
65
+ import argparse
66
+ import sys
67
+
68
+ parser = argparse.ArgumentParser(
69
+ "fonttools varLib.interpolate_layout",
70
+ description=main.__doc__,
71
+ )
72
+ parser.add_argument(
73
+ "designspace_filename", metavar="DESIGNSPACE", help="Input TTF files"
74
+ )
75
+ parser.add_argument(
76
+ "locations",
77
+ metavar="LOCATION",
78
+ type=str,
79
+ nargs="+",
80
+ help="Axis locations (e.g. wdth=120",
81
+ )
82
+ parser.add_argument(
83
+ "-o",
84
+ "--output",
85
+ metavar="OUTPUT",
86
+ help="Output font file (defaults to <designspacename>-instance.ttf)",
87
+ )
88
+ parser.add_argument(
89
+ "-l",
90
+ "--loglevel",
91
+ metavar="LEVEL",
92
+ default="INFO",
93
+ help="Logging level (defaults to INFO)",
94
+ )
95
+
96
+ args = parser.parse_args(args)
97
+
98
+ if not args.output:
99
+ args.output = os.path.splitext(args.designspace_filename)[0] + "-instance.ttf"
100
+
101
+ configLogger(level=args.loglevel)
102
+
103
+ finder = lambda s: s.replace("master_ufo", "master_ttf_interpolatable").replace(
104
+ ".ufo", ".ttf"
105
+ )
106
+
107
+ loc = {}
108
+ for arg in args.locations:
109
+ tag, val = arg.split("=")
110
+ loc[tag] = float(val)
111
+
112
+ font = interpolate_layout(args.designspace_filename, loc, finder)
113
+ log.info("Saving font %s", args.output)
114
+ font.save(args.output)
115
+
116
+
117
+ if __name__ == "__main__":
118
+ import sys
119
+
120
+ if len(sys.argv) > 1:
121
+ sys.exit(main())
122
+ import doctest
123
+
124
+ sys.exit(doctest.testmod().failed)