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,490 @@
1
+ """GlyphSets returned by a TTFont."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from collections.abc import Mapping
5
+ from contextlib import contextmanager
6
+ from copy import copy, deepcopy
7
+ from types import SimpleNamespace
8
+ from fontTools.misc.vector import Vector
9
+ from fontTools.misc.fixedTools import otRound, fixedToFloat as fi2fl
10
+ from fontTools.misc.loggingTools import deprecateFunction
11
+ from fontTools.misc.transform import Transform, DecomposedTransform
12
+ from fontTools.pens.transformPen import TransformPen, TransformPointPen
13
+ from fontTools.pens.recordingPen import (
14
+ DecomposingRecordingPen,
15
+ lerpRecordings,
16
+ replayRecording,
17
+ )
18
+
19
+
20
+ class _TTGlyphSet(Mapping):
21
+ """Generic dict-like GlyphSet class that pulls metrics from hmtx and
22
+ glyph shape from TrueType or CFF.
23
+ """
24
+
25
+ def __init__(self, font, location, glyphsMapping, *, recalcBounds=True):
26
+ self.recalcBounds = recalcBounds
27
+ self.font = font
28
+ self.defaultLocationNormalized = (
29
+ {axis.axisTag: 0 for axis in self.font["fvar"].axes}
30
+ if "fvar" in self.font
31
+ else {}
32
+ )
33
+ self.location = location if location is not None else {}
34
+ self.rawLocation = {} # VarComponent-only location
35
+ self.originalLocation = location if location is not None else {}
36
+ self.depth = 0
37
+ self.locationStack = []
38
+ self.rawLocationStack = []
39
+ self.glyphsMapping = glyphsMapping
40
+ self.hMetrics = font["hmtx"].metrics
41
+ self.vMetrics = getattr(font.get("vmtx"), "metrics", None)
42
+ self.hvarTable = None
43
+ if location:
44
+ from fontTools.varLib.varStore import VarStoreInstancer
45
+
46
+ self.hvarTable = getattr(font.get("HVAR"), "table", None)
47
+ if self.hvarTable is not None:
48
+ self.hvarInstancer = VarStoreInstancer(
49
+ self.hvarTable.VarStore, font["fvar"].axes, location
50
+ )
51
+ # TODO VVAR, VORG
52
+
53
+ @contextmanager
54
+ def pushLocation(self, location, reset: bool):
55
+ self.locationStack.append(self.location)
56
+ self.rawLocationStack.append(self.rawLocation)
57
+ if reset:
58
+ self.location = self.originalLocation.copy()
59
+ self.rawLocation = self.defaultLocationNormalized.copy()
60
+ else:
61
+ self.location = self.location.copy()
62
+ self.rawLocation = {}
63
+ self.location.update(location)
64
+ self.rawLocation.update(location)
65
+
66
+ try:
67
+ yield None
68
+ finally:
69
+ self.location = self.locationStack.pop()
70
+ self.rawLocation = self.rawLocationStack.pop()
71
+
72
+ @contextmanager
73
+ def pushDepth(self):
74
+ try:
75
+ depth = self.depth
76
+ self.depth += 1
77
+ yield depth
78
+ finally:
79
+ self.depth -= 1
80
+
81
+ def __contains__(self, glyphName):
82
+ return glyphName in self.glyphsMapping
83
+
84
+ def __iter__(self):
85
+ return iter(self.glyphsMapping.keys())
86
+
87
+ def __len__(self):
88
+ return len(self.glyphsMapping)
89
+
90
+ @deprecateFunction(
91
+ "use 'glyphName in glyphSet' instead", category=DeprecationWarning
92
+ )
93
+ def has_key(self, glyphName):
94
+ return glyphName in self.glyphsMapping
95
+
96
+
97
+ class _TTGlyphSetGlyf(_TTGlyphSet):
98
+ def __init__(self, font, location, recalcBounds=True):
99
+ self.glyfTable = font["glyf"]
100
+ super().__init__(font, location, self.glyfTable, recalcBounds=recalcBounds)
101
+ self.gvarTable = font.get("gvar")
102
+
103
+ def __getitem__(self, glyphName):
104
+ return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
105
+
106
+
107
+ class _TTGlyphSetCFF(_TTGlyphSet):
108
+ def __init__(self, font, location):
109
+ tableTag = "CFF2" if "CFF2" in font else "CFF "
110
+ self.charStrings = list(font[tableTag].cff.values())[0].CharStrings
111
+ super().__init__(font, location, self.charStrings)
112
+ self.setLocation(location)
113
+
114
+ def __getitem__(self, glyphName):
115
+ return _TTGlyphCFF(self, glyphName)
116
+
117
+ def setLocation(self, location):
118
+ self.blender = None
119
+ if location:
120
+ # TODO Optimize by using instancer.setLocation()
121
+
122
+ from fontTools.varLib.varStore import VarStoreInstancer
123
+
124
+ varStore = getattr(self.charStrings, "varStore", None)
125
+ if varStore is not None:
126
+ instancer = VarStoreInstancer(
127
+ varStore.otVarStore, self.font["fvar"].axes, location
128
+ )
129
+ self.blender = instancer.interpolateFromDeltas
130
+ else:
131
+ self.blender = None
132
+
133
+ @contextmanager
134
+ def pushLocation(self, location, reset: bool):
135
+ self.setLocation(location)
136
+ with _TTGlyphSet.pushLocation(self, location, reset) as value:
137
+ try:
138
+ yield value
139
+ finally:
140
+ self.setLocation(self.location)
141
+
142
+
143
+ class _TTGlyphSetVARC(_TTGlyphSet):
144
+ def __init__(self, font, location, glyphSet):
145
+ self.glyphSet = glyphSet
146
+ super().__init__(font, location, glyphSet)
147
+ self.varcTable = font["VARC"].table
148
+
149
+ def __getitem__(self, glyphName):
150
+ varc = self.varcTable
151
+ if glyphName not in varc.Coverage.glyphs:
152
+ return self.glyphSet[glyphName]
153
+ return _TTGlyphVARC(self, glyphName)
154
+
155
+
156
+ class _TTGlyph(ABC):
157
+ """Glyph object that supports the Pen protocol, meaning that it has
158
+ .draw() and .drawPoints() methods that take a pen object as their only
159
+ argument. Additionally there are 'width' and 'lsb' attributes, read from
160
+ the 'hmtx' table.
161
+
162
+ If the font contains a 'vmtx' table, there will also be 'height' and 'tsb'
163
+ attributes.
164
+ """
165
+
166
+ def __init__(self, glyphSet, glyphName, *, recalcBounds=True):
167
+ self.glyphSet = glyphSet
168
+ self.name = glyphName
169
+ self.recalcBounds = recalcBounds
170
+ self.width, self.lsb = glyphSet.hMetrics[glyphName]
171
+ if glyphSet.vMetrics is not None:
172
+ self.height, self.tsb = glyphSet.vMetrics[glyphName]
173
+ else:
174
+ self.height, self.tsb = None, None
175
+ if glyphSet.location and glyphSet.hvarTable is not None:
176
+ varidx = (
177
+ glyphSet.font.getGlyphID(glyphName)
178
+ if glyphSet.hvarTable.AdvWidthMap is None
179
+ else glyphSet.hvarTable.AdvWidthMap.mapping[glyphName]
180
+ )
181
+ self.width += glyphSet.hvarInstancer[varidx]
182
+ # TODO: VVAR/VORG
183
+
184
+ @abstractmethod
185
+ def draw(self, pen):
186
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
187
+ how that works.
188
+ """
189
+ raise NotImplementedError
190
+
191
+ def drawPoints(self, pen):
192
+ """Draw the glyph onto ``pen``. See fontTools.pens.pointPen for details
193
+ how that works.
194
+ """
195
+ from fontTools.pens.pointPen import SegmentToPointPen
196
+
197
+ self.draw(SegmentToPointPen(pen))
198
+
199
+
200
+ class _TTGlyphGlyf(_TTGlyph):
201
+ def draw(self, pen):
202
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
203
+ how that works.
204
+ """
205
+ glyph, offset = self._getGlyphAndOffset()
206
+
207
+ with self.glyphSet.pushDepth() as depth:
208
+ if depth:
209
+ offset = 0 # Offset should only apply at top-level
210
+
211
+ glyph.draw(pen, self.glyphSet.glyfTable, offset)
212
+
213
+ def drawPoints(self, pen):
214
+ """Draw the glyph onto ``pen``. See fontTools.pens.pointPen for details
215
+ how that works.
216
+ """
217
+ glyph, offset = self._getGlyphAndOffset()
218
+
219
+ with self.glyphSet.pushDepth() as depth:
220
+ if depth:
221
+ offset = 0 # Offset should only apply at top-level
222
+
223
+ glyph.drawPoints(pen, self.glyphSet.glyfTable, offset)
224
+
225
+ def _getGlyphAndOffset(self):
226
+ if self.glyphSet.location and self.glyphSet.gvarTable is not None:
227
+ glyph = self._getGlyphInstance()
228
+ else:
229
+ glyph = self.glyphSet.glyfTable[self.name]
230
+
231
+ offset = self.lsb - glyph.xMin if hasattr(glyph, "xMin") else 0
232
+ return glyph, offset
233
+
234
+ def _getGlyphInstance(self):
235
+ from fontTools.varLib.iup import iup_delta
236
+ from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
237
+ from fontTools.varLib.models import supportScalar
238
+
239
+ glyphSet = self.glyphSet
240
+ glyfTable = glyphSet.glyfTable
241
+ variations = glyphSet.gvarTable.variations[self.name]
242
+ hMetrics = glyphSet.hMetrics
243
+ vMetrics = glyphSet.vMetrics
244
+ coordinates, _ = glyfTable._getCoordinatesAndControls(
245
+ self.name, hMetrics, vMetrics
246
+ )
247
+ origCoords, endPts = None, None
248
+ for var in variations:
249
+ scalar = supportScalar(glyphSet.location, var.axes)
250
+ if not scalar:
251
+ continue
252
+ delta = var.coordinates
253
+ if None in delta:
254
+ if origCoords is None:
255
+ origCoords, control = glyfTable._getCoordinatesAndControls(
256
+ self.name, hMetrics, vMetrics
257
+ )
258
+ endPts = (
259
+ control[1] if control[0] >= 1 else list(range(len(control[1])))
260
+ )
261
+ delta = iup_delta(delta, origCoords, endPts)
262
+ coordinates += GlyphCoordinates(delta) * scalar
263
+
264
+ glyph = copy(glyfTable[self.name]) # Shallow copy
265
+ width, lsb, height, tsb = _setCoordinates(
266
+ glyph, coordinates, glyfTable, recalcBounds=self.recalcBounds
267
+ )
268
+ self.lsb = lsb
269
+ self.tsb = tsb
270
+ if glyphSet.hvarTable is None:
271
+ # no HVAR: let's set metrics from the phantom points
272
+ self.width = width
273
+ self.height = height
274
+ return glyph
275
+
276
+
277
+ class _TTGlyphCFF(_TTGlyph):
278
+ def draw(self, pen):
279
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
280
+ how that works.
281
+ """
282
+ self.glyphSet.charStrings[self.name].draw(pen, self.glyphSet.blender)
283
+
284
+
285
+ def _evaluateCondition(condition, fvarAxes, location, instancer):
286
+ if condition.Format == 1:
287
+ # ConditionAxisRange
288
+ axisIndex = condition.AxisIndex
289
+ axisTag = fvarAxes[axisIndex].axisTag
290
+ axisValue = location.get(axisTag, 0)
291
+ minValue = condition.FilterRangeMinValue
292
+ maxValue = condition.FilterRangeMaxValue
293
+ return minValue <= axisValue <= maxValue
294
+ elif condition.Format == 2:
295
+ # ConditionValue
296
+ value = condition.DefaultValue
297
+ value += instancer[condition.VarIdx][0]
298
+ return value > 0
299
+ elif condition.Format == 3:
300
+ # ConditionAnd
301
+ for subcondition in condition.ConditionTable:
302
+ if not _evaluateCondition(subcondition, fvarAxes, location, instancer):
303
+ return False
304
+ return True
305
+ elif condition.Format == 4:
306
+ # ConditionOr
307
+ for subcondition in condition.ConditionTable:
308
+ if _evaluateCondition(subcondition, fvarAxes, location, instancer):
309
+ return True
310
+ return False
311
+ elif condition.Format == 5:
312
+ # ConditionNegate
313
+ return not _evaluateCondition(
314
+ condition.conditionTable, fvarAxes, location, instancer
315
+ )
316
+ else:
317
+ return False # Unkonwn condition format
318
+
319
+
320
+ class _TTGlyphVARC(_TTGlyph):
321
+ def _draw(self, pen, isPointPen):
322
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
323
+ how that works.
324
+ """
325
+ from fontTools.ttLib.tables.otTables import (
326
+ VarComponentFlags,
327
+ NO_VARIATION_INDEX,
328
+ )
329
+
330
+ glyphSet = self.glyphSet
331
+ varc = glyphSet.varcTable
332
+ idx = varc.Coverage.glyphs.index(self.name)
333
+ glyph = varc.VarCompositeGlyphs.VarCompositeGlyph[idx]
334
+
335
+ from fontTools.varLib.multiVarStore import MultiVarStoreInstancer
336
+ from fontTools.varLib.varStore import VarStoreInstancer
337
+
338
+ fvarAxes = glyphSet.font["fvar"].axes
339
+ instancer = MultiVarStoreInstancer(
340
+ varc.MultiVarStore, fvarAxes, self.glyphSet.location
341
+ )
342
+
343
+ for comp in glyph.components:
344
+ if comp.flags & VarComponentFlags.HAVE_CONDITION:
345
+ condition = varc.ConditionList.ConditionTable[comp.conditionIndex]
346
+ if not _evaluateCondition(
347
+ condition, fvarAxes, self.glyphSet.location, instancer
348
+ ):
349
+ continue
350
+
351
+ location = {}
352
+ if comp.axisIndicesIndex is not None:
353
+ axisIndices = varc.AxisIndicesList.Item[comp.axisIndicesIndex]
354
+ axisValues = Vector(comp.axisValues)
355
+ if comp.axisValuesVarIndex != NO_VARIATION_INDEX:
356
+ axisValues += fi2fl(instancer[comp.axisValuesVarIndex], 14)
357
+ assert len(axisIndices) == len(axisValues), (
358
+ len(axisIndices),
359
+ len(axisValues),
360
+ )
361
+ location = {
362
+ fvarAxes[i].axisTag: v for i, v in zip(axisIndices, axisValues)
363
+ }
364
+
365
+ if comp.transformVarIndex != NO_VARIATION_INDEX:
366
+ deltas = instancer[comp.transformVarIndex]
367
+ comp = deepcopy(comp)
368
+ comp.applyTransformDeltas(deltas)
369
+ transform = comp.transform
370
+
371
+ reset = comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES
372
+ with self.glyphSet.glyphSet.pushLocation(location, reset):
373
+ with self.glyphSet.pushLocation(location, reset):
374
+ shouldDecompose = self.name == comp.glyphName
375
+
376
+ if not shouldDecompose:
377
+ try:
378
+ pen.addVarComponent(
379
+ comp.glyphName, transform, self.glyphSet.rawLocation
380
+ )
381
+ except AttributeError:
382
+ shouldDecompose = True
383
+
384
+ if shouldDecompose:
385
+ t = transform.toTransform()
386
+ compGlyphSet = (
387
+ self.glyphSet
388
+ if comp.glyphName != self.name
389
+ else glyphSet.glyphSet
390
+ )
391
+ g = compGlyphSet[comp.glyphName]
392
+ if isPointPen:
393
+ tPen = TransformPointPen(pen, t)
394
+ g.drawPoints(tPen)
395
+ else:
396
+ tPen = TransformPen(pen, t)
397
+ g.draw(tPen)
398
+
399
+ def draw(self, pen):
400
+ self._draw(pen, False)
401
+
402
+ def drawPoints(self, pen):
403
+ self._draw(pen, True)
404
+
405
+
406
+ def _setCoordinates(glyph, coord, glyfTable, *, recalcBounds=True):
407
+ # Handle phantom points for (left, right, top, bottom) positions.
408
+ assert len(coord) >= 4
409
+ leftSideX = coord[-4][0]
410
+ rightSideX = coord[-3][0]
411
+ topSideY = coord[-2][1]
412
+ bottomSideY = coord[-1][1]
413
+
414
+ for _ in range(4):
415
+ del coord[-1]
416
+
417
+ if glyph.isComposite():
418
+ assert len(coord) == len(glyph.components)
419
+ glyph.components = [copy(comp) for comp in glyph.components] # Shallow copy
420
+ for p, comp in zip(coord, glyph.components):
421
+ if hasattr(comp, "x"):
422
+ comp.x, comp.y = p
423
+ elif glyph.numberOfContours == 0:
424
+ assert len(coord) == 0
425
+ else:
426
+ assert len(coord) == len(glyph.coordinates)
427
+ glyph.coordinates = coord
428
+
429
+ if recalcBounds:
430
+ glyph.recalcBounds(glyfTable)
431
+
432
+ horizontalAdvanceWidth = otRound(rightSideX - leftSideX)
433
+ verticalAdvanceWidth = otRound(topSideY - bottomSideY)
434
+ leftSideBearing = otRound(glyph.xMin - leftSideX)
435
+ topSideBearing = otRound(topSideY - glyph.yMax)
436
+ return (
437
+ horizontalAdvanceWidth,
438
+ leftSideBearing,
439
+ verticalAdvanceWidth,
440
+ topSideBearing,
441
+ )
442
+
443
+
444
+ class LerpGlyphSet(Mapping):
445
+ """A glyphset that interpolates between two other glyphsets.
446
+
447
+ Factor is typically between 0 and 1. 0 means the first glyphset,
448
+ 1 means the second glyphset, and 0.5 means the average of the
449
+ two glyphsets. Other values are possible, and can be useful to
450
+ extrapolate. Defaults to 0.5.
451
+ """
452
+
453
+ def __init__(self, glyphset1, glyphset2, factor=0.5):
454
+ self.glyphset1 = glyphset1
455
+ self.glyphset2 = glyphset2
456
+ self.factor = factor
457
+
458
+ def __getitem__(self, glyphname):
459
+ if glyphname in self.glyphset1 and glyphname in self.glyphset2:
460
+ return LerpGlyph(glyphname, self)
461
+ raise KeyError(glyphname)
462
+
463
+ def __contains__(self, glyphname):
464
+ return glyphname in self.glyphset1 and glyphname in self.glyphset2
465
+
466
+ def __iter__(self):
467
+ set1 = set(self.glyphset1)
468
+ set2 = set(self.glyphset2)
469
+ return iter(set1.intersection(set2))
470
+
471
+ def __len__(self):
472
+ set1 = set(self.glyphset1)
473
+ set2 = set(self.glyphset2)
474
+ return len(set1.intersection(set2))
475
+
476
+
477
+ class LerpGlyph:
478
+ def __init__(self, glyphname, glyphset):
479
+ self.glyphset = glyphset
480
+ self.glyphname = glyphname
481
+
482
+ def draw(self, pen):
483
+ recording1 = DecomposingRecordingPen(self.glyphset.glyphset1)
484
+ self.glyphset.glyphset1[self.glyphname].draw(recording1)
485
+ recording2 = DecomposingRecordingPen(self.glyphset.glyphset2)
486
+ self.glyphset.glyphset2[self.glyphname].draw(recording2)
487
+
488
+ factor = self.glyphset.factor
489
+
490
+ replayRecording(lerpRecordings(recording1.value, recording2.value, factor), pen)
@@ -0,0 +1,32 @@
1
+ """Specialization of fontTools.misc.visitor to work with TTFont."""
2
+
3
+ from fontTools.misc.visitor import Visitor
4
+ from fontTools.ttLib import TTFont
5
+
6
+
7
+ class TTVisitor(Visitor):
8
+ def visitAttr(self, obj, attr, value, *args, **kwargs):
9
+ if isinstance(value, TTFont):
10
+ return False
11
+ super().visitAttr(obj, attr, value, *args, **kwargs)
12
+
13
+ def visit(self, obj, *args, **kwargs):
14
+ if hasattr(obj, "ensureDecompiled"):
15
+ obj.ensureDecompiled(recurse=False)
16
+ super().visit(obj, *args, **kwargs)
17
+
18
+
19
+ @TTVisitor.register(TTFont)
20
+ def visit(visitor, font, *args, **kwargs):
21
+ # Some objects have links back to TTFont; even though we
22
+ # have a check in visitAttr to stop them from recursing
23
+ # onto TTFont, sometimes they still do, for example when
24
+ # someone overrides visitAttr.
25
+ if hasattr(visitor, "font"):
26
+ return False
27
+
28
+ visitor.font = font
29
+ for tag in font.keys():
30
+ visitor.visit(font[tag], *args, **kwargs)
31
+ del visitor.font
32
+ return False