fonttools 4.55.6__cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.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.

Potentially problematic release.


This version of fonttools might be problematic. Click here for more details.

Files changed (329) 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/cffLib/CFF2ToCFF.py +203 -0
  6. fontTools/cffLib/CFFToCFF2.py +305 -0
  7. fontTools/cffLib/__init__.py +3659 -0
  8. fontTools/cffLib/specializer.py +924 -0
  9. fontTools/cffLib/transforms.py +490 -0
  10. fontTools/cffLib/width.py +210 -0
  11. fontTools/colorLib/__init__.py +0 -0
  12. fontTools/colorLib/builder.py +664 -0
  13. fontTools/colorLib/errors.py +2 -0
  14. fontTools/colorLib/geometry.py +143 -0
  15. fontTools/colorLib/table_builder.py +223 -0
  16. fontTools/colorLib/unbuilder.py +81 -0
  17. fontTools/config/__init__.py +75 -0
  18. fontTools/cu2qu/__init__.py +15 -0
  19. fontTools/cu2qu/__main__.py +6 -0
  20. fontTools/cu2qu/benchmark.py +54 -0
  21. fontTools/cu2qu/cli.py +198 -0
  22. fontTools/cu2qu/cu2qu.c +14829 -0
  23. fontTools/cu2qu/cu2qu.cpython-39-x86_64-linux-gnu.so +0 -0
  24. fontTools/cu2qu/cu2qu.py +531 -0
  25. fontTools/cu2qu/errors.py +77 -0
  26. fontTools/cu2qu/ufo.py +349 -0
  27. fontTools/designspaceLib/__init__.py +3338 -0
  28. fontTools/designspaceLib/__main__.py +6 -0
  29. fontTools/designspaceLib/split.py +475 -0
  30. fontTools/designspaceLib/statNames.py +253 -0
  31. fontTools/designspaceLib/types.py +147 -0
  32. fontTools/encodings/MacRoman.py +258 -0
  33. fontTools/encodings/StandardEncoding.py +258 -0
  34. fontTools/encodings/__init__.py +1 -0
  35. fontTools/encodings/codecs.py +135 -0
  36. fontTools/feaLib/__init__.py +4 -0
  37. fontTools/feaLib/__main__.py +78 -0
  38. fontTools/feaLib/ast.py +2134 -0
  39. fontTools/feaLib/builder.py +1747 -0
  40. fontTools/feaLib/error.py +22 -0
  41. fontTools/feaLib/lexer.c +17986 -0
  42. fontTools/feaLib/lexer.cpython-39-x86_64-linux-gnu.so +0 -0
  43. fontTools/feaLib/lexer.py +287 -0
  44. fontTools/feaLib/location.py +12 -0
  45. fontTools/feaLib/lookupDebugInfo.py +12 -0
  46. fontTools/feaLib/parser.py +2359 -0
  47. fontTools/feaLib/variableScalar.py +113 -0
  48. fontTools/fontBuilder.py +1008 -0
  49. fontTools/help.py +36 -0
  50. fontTools/merge/__init__.py +248 -0
  51. fontTools/merge/__main__.py +6 -0
  52. fontTools/merge/base.py +81 -0
  53. fontTools/merge/cmap.py +141 -0
  54. fontTools/merge/layout.py +526 -0
  55. fontTools/merge/options.py +85 -0
  56. fontTools/merge/tables.py +341 -0
  57. fontTools/merge/unicode.py +78 -0
  58. fontTools/merge/util.py +143 -0
  59. fontTools/misc/__init__.py +1 -0
  60. fontTools/misc/arrayTools.py +424 -0
  61. fontTools/misc/bezierTools.c +41831 -0
  62. fontTools/misc/bezierTools.cpython-39-x86_64-linux-gnu.so +0 -0
  63. fontTools/misc/bezierTools.py +1497 -0
  64. fontTools/misc/classifyTools.py +170 -0
  65. fontTools/misc/cliTools.py +53 -0
  66. fontTools/misc/configTools.py +349 -0
  67. fontTools/misc/cython.py +27 -0
  68. fontTools/misc/dictTools.py +83 -0
  69. fontTools/misc/eexec.py +119 -0
  70. fontTools/misc/encodingTools.py +72 -0
  71. fontTools/misc/etree.py +479 -0
  72. fontTools/misc/filenames.py +245 -0
  73. fontTools/misc/fixedTools.py +253 -0
  74. fontTools/misc/intTools.py +25 -0
  75. fontTools/misc/iterTools.py +12 -0
  76. fontTools/misc/lazyTools.py +42 -0
  77. fontTools/misc/loggingTools.py +543 -0
  78. fontTools/misc/macCreatorType.py +56 -0
  79. fontTools/misc/macRes.py +261 -0
  80. fontTools/misc/plistlib/__init__.py +681 -0
  81. fontTools/misc/plistlib/py.typed +0 -0
  82. fontTools/misc/psCharStrings.py +1496 -0
  83. fontTools/misc/psLib.py +398 -0
  84. fontTools/misc/psOperators.py +572 -0
  85. fontTools/misc/py23.py +96 -0
  86. fontTools/misc/roundTools.py +110 -0
  87. fontTools/misc/sstruct.py +231 -0
  88. fontTools/misc/symfont.py +244 -0
  89. fontTools/misc/testTools.py +229 -0
  90. fontTools/misc/textTools.py +154 -0
  91. fontTools/misc/timeTools.py +88 -0
  92. fontTools/misc/transform.py +516 -0
  93. fontTools/misc/treeTools.py +45 -0
  94. fontTools/misc/vector.py +147 -0
  95. fontTools/misc/visitor.py +142 -0
  96. fontTools/misc/xmlReader.py +188 -0
  97. fontTools/misc/xmlWriter.py +204 -0
  98. fontTools/mtiLib/__init__.py +1402 -0
  99. fontTools/mtiLib/__main__.py +5 -0
  100. fontTools/otlLib/__init__.py +1 -0
  101. fontTools/otlLib/builder.py +3221 -0
  102. fontTools/otlLib/error.py +11 -0
  103. fontTools/otlLib/maxContextCalc.py +96 -0
  104. fontTools/otlLib/optimize/__init__.py +53 -0
  105. fontTools/otlLib/optimize/__main__.py +6 -0
  106. fontTools/otlLib/optimize/gpos.py +453 -0
  107. fontTools/pens/__init__.py +1 -0
  108. fontTools/pens/areaPen.py +52 -0
  109. fontTools/pens/basePen.py +475 -0
  110. fontTools/pens/boundsPen.py +98 -0
  111. fontTools/pens/cairoPen.py +26 -0
  112. fontTools/pens/cocoaPen.py +26 -0
  113. fontTools/pens/cu2quPen.py +325 -0
  114. fontTools/pens/explicitClosingLinePen.py +101 -0
  115. fontTools/pens/filterPen.py +241 -0
  116. fontTools/pens/freetypePen.py +462 -0
  117. fontTools/pens/hashPointPen.py +89 -0
  118. fontTools/pens/momentsPen.c +13448 -0
  119. fontTools/pens/momentsPen.cpython-39-x86_64-linux-gnu.so +0 -0
  120. fontTools/pens/momentsPen.py +879 -0
  121. fontTools/pens/perimeterPen.py +69 -0
  122. fontTools/pens/pointInsidePen.py +192 -0
  123. fontTools/pens/pointPen.py +600 -0
  124. fontTools/pens/qtPen.py +29 -0
  125. fontTools/pens/qu2cuPen.py +105 -0
  126. fontTools/pens/quartzPen.py +43 -0
  127. fontTools/pens/recordingPen.py +335 -0
  128. fontTools/pens/reportLabPen.py +79 -0
  129. fontTools/pens/reverseContourPen.py +96 -0
  130. fontTools/pens/roundingPen.py +130 -0
  131. fontTools/pens/statisticsPen.py +312 -0
  132. fontTools/pens/svgPathPen.py +310 -0
  133. fontTools/pens/t2CharStringPen.py +68 -0
  134. fontTools/pens/teePen.py +55 -0
  135. fontTools/pens/transformPen.py +115 -0
  136. fontTools/pens/ttGlyphPen.py +335 -0
  137. fontTools/pens/wxPen.py +29 -0
  138. fontTools/qu2cu/__init__.py +15 -0
  139. fontTools/qu2cu/__main__.py +7 -0
  140. fontTools/qu2cu/benchmark.py +56 -0
  141. fontTools/qu2cu/cli.py +125 -0
  142. fontTools/qu2cu/qu2cu.c +16269 -0
  143. fontTools/qu2cu/qu2cu.cpython-39-x86_64-linux-gnu.so +0 -0
  144. fontTools/qu2cu/qu2cu.py +405 -0
  145. fontTools/subset/__init__.py +3838 -0
  146. fontTools/subset/__main__.py +6 -0
  147. fontTools/subset/cff.py +184 -0
  148. fontTools/subset/svg.py +253 -0
  149. fontTools/subset/util.py +25 -0
  150. fontTools/svgLib/__init__.py +3 -0
  151. fontTools/svgLib/path/__init__.py +65 -0
  152. fontTools/svgLib/path/arc.py +154 -0
  153. fontTools/svgLib/path/parser.py +322 -0
  154. fontTools/svgLib/path/shapes.py +183 -0
  155. fontTools/t1Lib/__init__.py +648 -0
  156. fontTools/tfmLib.py +460 -0
  157. fontTools/ttLib/__init__.py +26 -0
  158. fontTools/ttLib/__main__.py +109 -0
  159. fontTools/ttLib/macUtils.py +54 -0
  160. fontTools/ttLib/removeOverlaps.py +393 -0
  161. fontTools/ttLib/reorderGlyphs.py +284 -0
  162. fontTools/ttLib/scaleUpem.py +436 -0
  163. fontTools/ttLib/sfnt.py +662 -0
  164. fontTools/ttLib/standardGlyphOrder.py +271 -0
  165. fontTools/ttLib/tables/B_A_S_E_.py +14 -0
  166. fontTools/ttLib/tables/BitmapGlyphMetrics.py +64 -0
  167. fontTools/ttLib/tables/C_B_D_T_.py +113 -0
  168. fontTools/ttLib/tables/C_B_L_C_.py +19 -0
  169. fontTools/ttLib/tables/C_F_F_.py +61 -0
  170. fontTools/ttLib/tables/C_F_F__2.py +26 -0
  171. fontTools/ttLib/tables/C_O_L_R_.py +165 -0
  172. fontTools/ttLib/tables/C_P_A_L_.py +305 -0
  173. fontTools/ttLib/tables/D_S_I_G_.py +158 -0
  174. fontTools/ttLib/tables/D__e_b_g.py +17 -0
  175. fontTools/ttLib/tables/DefaultTable.py +49 -0
  176. fontTools/ttLib/tables/E_B_D_T_.py +835 -0
  177. fontTools/ttLib/tables/E_B_L_C_.py +718 -0
  178. fontTools/ttLib/tables/F_F_T_M_.py +52 -0
  179. fontTools/ttLib/tables/F__e_a_t.py +149 -0
  180. fontTools/ttLib/tables/G_D_E_F_.py +13 -0
  181. fontTools/ttLib/tables/G_M_A_P_.py +148 -0
  182. fontTools/ttLib/tables/G_P_K_G_.py +133 -0
  183. fontTools/ttLib/tables/G_P_O_S_.py +14 -0
  184. fontTools/ttLib/tables/G_S_U_B_.py +13 -0
  185. fontTools/ttLib/tables/G__l_a_t.py +235 -0
  186. fontTools/ttLib/tables/G__l_o_c.py +85 -0
  187. fontTools/ttLib/tables/H_V_A_R_.py +13 -0
  188. fontTools/ttLib/tables/J_S_T_F_.py +13 -0
  189. fontTools/ttLib/tables/L_T_S_H_.py +58 -0
  190. fontTools/ttLib/tables/M_A_T_H_.py +13 -0
  191. fontTools/ttLib/tables/M_E_T_A_.py +352 -0
  192. fontTools/ttLib/tables/M_V_A_R_.py +13 -0
  193. fontTools/ttLib/tables/O_S_2f_2.py +752 -0
  194. fontTools/ttLib/tables/S_I_N_G_.py +99 -0
  195. fontTools/ttLib/tables/S_T_A_T_.py +15 -0
  196. fontTools/ttLib/tables/S_V_G_.py +223 -0
  197. fontTools/ttLib/tables/S__i_l_f.py +1040 -0
  198. fontTools/ttLib/tables/S__i_l_l.py +92 -0
  199. fontTools/ttLib/tables/T_S_I_B_.py +13 -0
  200. fontTools/ttLib/tables/T_S_I_C_.py +14 -0
  201. fontTools/ttLib/tables/T_S_I_D_.py +13 -0
  202. fontTools/ttLib/tables/T_S_I_J_.py +13 -0
  203. fontTools/ttLib/tables/T_S_I_P_.py +13 -0
  204. fontTools/ttLib/tables/T_S_I_S_.py +13 -0
  205. fontTools/ttLib/tables/T_S_I_V_.py +26 -0
  206. fontTools/ttLib/tables/T_S_I__0.py +59 -0
  207. fontTools/ttLib/tables/T_S_I__1.py +166 -0
  208. fontTools/ttLib/tables/T_S_I__2.py +17 -0
  209. fontTools/ttLib/tables/T_S_I__3.py +22 -0
  210. fontTools/ttLib/tables/T_S_I__5.py +49 -0
  211. fontTools/ttLib/tables/T_T_F_A_.py +14 -0
  212. fontTools/ttLib/tables/TupleVariation.py +884 -0
  213. fontTools/ttLib/tables/V_A_R_C_.py +12 -0
  214. fontTools/ttLib/tables/V_D_M_X_.py +249 -0
  215. fontTools/ttLib/tables/V_O_R_G_.py +165 -0
  216. fontTools/ttLib/tables/V_V_A_R_.py +13 -0
  217. fontTools/ttLib/tables/__init__.py +97 -0
  218. fontTools/ttLib/tables/_a_n_k_r.py +15 -0
  219. fontTools/ttLib/tables/_a_v_a_r.py +191 -0
  220. fontTools/ttLib/tables/_b_s_l_n.py +15 -0
  221. fontTools/ttLib/tables/_c_i_d_g.py +24 -0
  222. fontTools/ttLib/tables/_c_m_a_p.py +1578 -0
  223. fontTools/ttLib/tables/_c_v_a_r.py +94 -0
  224. fontTools/ttLib/tables/_c_v_t.py +55 -0
  225. fontTools/ttLib/tables/_f_e_a_t.py +15 -0
  226. fontTools/ttLib/tables/_f_p_g_m.py +60 -0
  227. fontTools/ttLib/tables/_f_v_a_r.py +261 -0
  228. fontTools/ttLib/tables/_g_a_s_p.py +63 -0
  229. fontTools/ttLib/tables/_g_c_i_d.py +13 -0
  230. fontTools/ttLib/tables/_g_l_y_f.py +2311 -0
  231. fontTools/ttLib/tables/_g_v_a_r.py +292 -0
  232. fontTools/ttLib/tables/_h_d_m_x.py +127 -0
  233. fontTools/ttLib/tables/_h_e_a_d.py +130 -0
  234. fontTools/ttLib/tables/_h_h_e_a.py +147 -0
  235. fontTools/ttLib/tables/_h_m_t_x.py +160 -0
  236. fontTools/ttLib/tables/_k_e_r_n.py +289 -0
  237. fontTools/ttLib/tables/_l_c_a_r.py +13 -0
  238. fontTools/ttLib/tables/_l_o_c_a.py +70 -0
  239. fontTools/ttLib/tables/_l_t_a_g.py +72 -0
  240. fontTools/ttLib/tables/_m_a_x_p.py +147 -0
  241. fontTools/ttLib/tables/_m_e_t_a.py +112 -0
  242. fontTools/ttLib/tables/_m_o_r_t.py +14 -0
  243. fontTools/ttLib/tables/_m_o_r_x.py +15 -0
  244. fontTools/ttLib/tables/_n_a_m_e.py +1237 -0
  245. fontTools/ttLib/tables/_o_p_b_d.py +14 -0
  246. fontTools/ttLib/tables/_p_o_s_t.py +317 -0
  247. fontTools/ttLib/tables/_p_r_e_p.py +16 -0
  248. fontTools/ttLib/tables/_p_r_o_p.py +12 -0
  249. fontTools/ttLib/tables/_s_b_i_x.py +129 -0
  250. fontTools/ttLib/tables/_t_r_a_k.py +332 -0
  251. fontTools/ttLib/tables/_v_h_e_a.py +139 -0
  252. fontTools/ttLib/tables/_v_m_t_x.py +19 -0
  253. fontTools/ttLib/tables/asciiTable.py +20 -0
  254. fontTools/ttLib/tables/grUtils.py +92 -0
  255. fontTools/ttLib/tables/otBase.py +1465 -0
  256. fontTools/ttLib/tables/otConverters.py +2065 -0
  257. fontTools/ttLib/tables/otData.py +6400 -0
  258. fontTools/ttLib/tables/otTables.py +2700 -0
  259. fontTools/ttLib/tables/otTraverse.py +162 -0
  260. fontTools/ttLib/tables/sbixGlyph.py +149 -0
  261. fontTools/ttLib/tables/sbixStrike.py +177 -0
  262. fontTools/ttLib/tables/table_API_readme.txt +91 -0
  263. fontTools/ttLib/tables/ttProgram.py +594 -0
  264. fontTools/ttLib/ttCollection.py +125 -0
  265. fontTools/ttLib/ttFont.py +1155 -0
  266. fontTools/ttLib/ttGlyphSet.py +500 -0
  267. fontTools/ttLib/ttVisitor.py +32 -0
  268. fontTools/ttLib/woff2.py +1683 -0
  269. fontTools/ttx.py +467 -0
  270. fontTools/ufoLib/__init__.py +2477 -0
  271. fontTools/ufoLib/converters.py +334 -0
  272. fontTools/ufoLib/errors.py +22 -0
  273. fontTools/ufoLib/etree.py +6 -0
  274. fontTools/ufoLib/filenames.py +291 -0
  275. fontTools/ufoLib/glifLib.py +2022 -0
  276. fontTools/ufoLib/kerning.py +91 -0
  277. fontTools/ufoLib/plistlib.py +47 -0
  278. fontTools/ufoLib/pointPen.py +6 -0
  279. fontTools/ufoLib/utils.py +76 -0
  280. fontTools/ufoLib/validators.py +1186 -0
  281. fontTools/unicode.py +50 -0
  282. fontTools/unicodedata/Blocks.py +802 -0
  283. fontTools/unicodedata/OTTags.py +50 -0
  284. fontTools/unicodedata/ScriptExtensions.py +806 -0
  285. fontTools/unicodedata/Scripts.py +3618 -0
  286. fontTools/unicodedata/__init__.py +298 -0
  287. fontTools/varLib/__init__.py +1511 -0
  288. fontTools/varLib/__main__.py +6 -0
  289. fontTools/varLib/avar.py +260 -0
  290. fontTools/varLib/avarPlanner.py +1004 -0
  291. fontTools/varLib/builder.py +215 -0
  292. fontTools/varLib/cff.py +631 -0
  293. fontTools/varLib/errors.py +219 -0
  294. fontTools/varLib/featureVars.py +689 -0
  295. fontTools/varLib/instancer/__init__.py +1937 -0
  296. fontTools/varLib/instancer/__main__.py +5 -0
  297. fontTools/varLib/instancer/featureVars.py +190 -0
  298. fontTools/varLib/instancer/names.py +388 -0
  299. fontTools/varLib/instancer/solver.py +309 -0
  300. fontTools/varLib/interpolatable.py +1209 -0
  301. fontTools/varLib/interpolatableHelpers.py +396 -0
  302. fontTools/varLib/interpolatablePlot.py +1269 -0
  303. fontTools/varLib/interpolatableTestContourOrder.py +82 -0
  304. fontTools/varLib/interpolatableTestStartingPoint.py +107 -0
  305. fontTools/varLib/interpolate_layout.py +124 -0
  306. fontTools/varLib/iup.c +19154 -0
  307. fontTools/varLib/iup.cpython-39-x86_64-linux-gnu.so +0 -0
  308. fontTools/varLib/iup.py +490 -0
  309. fontTools/varLib/merger.py +1717 -0
  310. fontTools/varLib/models.py +642 -0
  311. fontTools/varLib/multiVarStore.py +253 -0
  312. fontTools/varLib/mutator.py +518 -0
  313. fontTools/varLib/mvar.py +40 -0
  314. fontTools/varLib/plot.py +238 -0
  315. fontTools/varLib/stat.py +149 -0
  316. fontTools/varLib/varStore.py +767 -0
  317. fontTools/voltLib/__init__.py +5 -0
  318. fontTools/voltLib/ast.py +448 -0
  319. fontTools/voltLib/error.py +12 -0
  320. fontTools/voltLib/lexer.py +99 -0
  321. fontTools/voltLib/parser.py +656 -0
  322. fontTools/voltLib/voltToFea.py +730 -0
  323. fonttools-4.55.6.data/data/share/man/man1/ttx.1 +225 -0
  324. fonttools-4.55.6.dist-info/LICENSE +21 -0
  325. fonttools-4.55.6.dist-info/METADATA +3413 -0
  326. fonttools-4.55.6.dist-info/RECORD +329 -0
  327. fonttools-4.55.6.dist-info/WHEEL +6 -0
  328. fonttools-4.55.6.dist-info/entry_points.txt +5 -0
  329. fonttools-4.55.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,500 @@
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 _TTGlyphSetGlyf(_TTGlyphSet):
108
+ def __init__(self, font, location, recalcBounds=True):
109
+ self.glyfTable = font["glyf"]
110
+ super().__init__(font, location, self.glyfTable, recalcBounds=recalcBounds)
111
+ self.gvarTable = font.get("gvar")
112
+
113
+ def __getitem__(self, glyphName):
114
+ return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
115
+
116
+
117
+ class _TTGlyphSetCFF(_TTGlyphSet):
118
+ def __init__(self, font, location):
119
+ tableTag = "CFF2" if "CFF2" in font else "CFF "
120
+ self.charStrings = list(font[tableTag].cff.values())[0].CharStrings
121
+ super().__init__(font, location, self.charStrings)
122
+ self.setLocation(location)
123
+
124
+ def __getitem__(self, glyphName):
125
+ return _TTGlyphCFF(self, glyphName)
126
+
127
+ def setLocation(self, location):
128
+ self.blender = None
129
+ if location:
130
+ # TODO Optimize by using instancer.setLocation()
131
+
132
+ from fontTools.varLib.varStore import VarStoreInstancer
133
+
134
+ varStore = getattr(self.charStrings, "varStore", None)
135
+ if varStore is not None:
136
+ instancer = VarStoreInstancer(
137
+ varStore.otVarStore, self.font["fvar"].axes, location
138
+ )
139
+ self.blender = instancer.interpolateFromDeltas
140
+ else:
141
+ self.blender = None
142
+
143
+ @contextmanager
144
+ def pushLocation(self, location, reset: bool):
145
+ self.setLocation(location)
146
+ with _TTGlyphSet.pushLocation(self, location, reset) as value:
147
+ try:
148
+ yield value
149
+ finally:
150
+ self.setLocation(self.location)
151
+
152
+
153
+ class _TTGlyphSetVARC(_TTGlyphSet):
154
+ def __init__(self, font, location, glyphSet):
155
+ self.glyphSet = glyphSet
156
+ super().__init__(font, location, glyphSet)
157
+ self.varcTable = font["VARC"].table
158
+
159
+ def __getitem__(self, glyphName):
160
+ varc = self.varcTable
161
+ if glyphName not in varc.Coverage.glyphs:
162
+ return self.glyphSet[glyphName]
163
+ return _TTGlyphVARC(self, glyphName)
164
+
165
+
166
+ class _TTGlyph(ABC):
167
+ """Glyph object that supports the Pen protocol, meaning that it has
168
+ .draw() and .drawPoints() methods that take a pen object as their only
169
+ argument. Additionally there are 'width' and 'lsb' attributes, read from
170
+ the 'hmtx' table.
171
+
172
+ If the font contains a 'vmtx' table, there will also be 'height' and 'tsb'
173
+ attributes.
174
+ """
175
+
176
+ def __init__(self, glyphSet, glyphName, *, recalcBounds=True):
177
+ self.glyphSet = glyphSet
178
+ self.name = glyphName
179
+ self.recalcBounds = recalcBounds
180
+ self.width, self.lsb = glyphSet.hMetrics[glyphName]
181
+ if glyphSet.vMetrics is not None:
182
+ self.height, self.tsb = glyphSet.vMetrics[glyphName]
183
+ else:
184
+ self.height, self.tsb = None, None
185
+ if glyphSet.location and glyphSet.hvarTable is not None:
186
+ varidx = (
187
+ glyphSet.font.getGlyphID(glyphName)
188
+ if glyphSet.hvarTable.AdvWidthMap is None
189
+ else glyphSet.hvarTable.AdvWidthMap.mapping[glyphName]
190
+ )
191
+ self.width += glyphSet.hvarInstancer[varidx]
192
+ # TODO: VVAR/VORG
193
+
194
+ @abstractmethod
195
+ def draw(self, pen):
196
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
197
+ how that works.
198
+ """
199
+ raise NotImplementedError
200
+
201
+ def drawPoints(self, pen):
202
+ """Draw the glyph onto ``pen``. See fontTools.pens.pointPen for details
203
+ how that works.
204
+ """
205
+ from fontTools.pens.pointPen import SegmentToPointPen
206
+
207
+ self.draw(SegmentToPointPen(pen))
208
+
209
+
210
+ class _TTGlyphGlyf(_TTGlyph):
211
+ def draw(self, pen):
212
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
213
+ how that works.
214
+ """
215
+ glyph, offset = self._getGlyphAndOffset()
216
+
217
+ with self.glyphSet.pushDepth() as depth:
218
+ if depth:
219
+ offset = 0 # Offset should only apply at top-level
220
+
221
+ glyph.draw(pen, self.glyphSet.glyfTable, offset)
222
+
223
+ def drawPoints(self, pen):
224
+ """Draw the glyph onto ``pen``. See fontTools.pens.pointPen for details
225
+ how that works.
226
+ """
227
+ glyph, offset = self._getGlyphAndOffset()
228
+
229
+ with self.glyphSet.pushDepth() as depth:
230
+ if depth:
231
+ offset = 0 # Offset should only apply at top-level
232
+
233
+ glyph.drawPoints(pen, self.glyphSet.glyfTable, offset)
234
+
235
+ def _getGlyphAndOffset(self):
236
+ if self.glyphSet.location and self.glyphSet.gvarTable is not None:
237
+ glyph = self._getGlyphInstance()
238
+ else:
239
+ glyph = self.glyphSet.glyfTable[self.name]
240
+
241
+ offset = self.lsb - glyph.xMin if hasattr(glyph, "xMin") else 0
242
+ return glyph, offset
243
+
244
+ def _getGlyphInstance(self):
245
+ from fontTools.varLib.iup import iup_delta
246
+ from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
247
+ from fontTools.varLib.models import supportScalar
248
+
249
+ glyphSet = self.glyphSet
250
+ glyfTable = glyphSet.glyfTable
251
+ variations = glyphSet.gvarTable.variations[self.name]
252
+ hMetrics = glyphSet.hMetrics
253
+ vMetrics = glyphSet.vMetrics
254
+ coordinates, _ = glyfTable._getCoordinatesAndControls(
255
+ self.name, hMetrics, vMetrics
256
+ )
257
+ origCoords, endPts = None, None
258
+ for var in variations:
259
+ scalar = supportScalar(glyphSet.location, var.axes)
260
+ if not scalar:
261
+ continue
262
+ delta = var.coordinates
263
+ if None in delta:
264
+ if origCoords is None:
265
+ origCoords, control = glyfTable._getCoordinatesAndControls(
266
+ self.name, hMetrics, vMetrics
267
+ )
268
+ endPts = (
269
+ control[1] if control[0] >= 1 else list(range(len(control[1])))
270
+ )
271
+ delta = iup_delta(delta, origCoords, endPts)
272
+ coordinates += GlyphCoordinates(delta) * scalar
273
+
274
+ glyph = copy(glyfTable[self.name]) # Shallow copy
275
+ width, lsb, height, tsb = _setCoordinates(
276
+ glyph, coordinates, glyfTable, recalcBounds=self.recalcBounds
277
+ )
278
+ self.lsb = lsb
279
+ self.tsb = tsb
280
+ if glyphSet.hvarTable is None:
281
+ # no HVAR: let's set metrics from the phantom points
282
+ self.width = width
283
+ self.height = height
284
+ return glyph
285
+
286
+
287
+ class _TTGlyphCFF(_TTGlyph):
288
+ def draw(self, pen):
289
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
290
+ how that works.
291
+ """
292
+ self.glyphSet.charStrings[self.name].draw(pen, self.glyphSet.blender)
293
+
294
+
295
+ def _evaluateCondition(condition, fvarAxes, location, instancer):
296
+ if condition.Format == 1:
297
+ # ConditionAxisRange
298
+ axisIndex = condition.AxisIndex
299
+ axisTag = fvarAxes[axisIndex].axisTag
300
+ axisValue = location.get(axisTag, 0)
301
+ minValue = condition.FilterRangeMinValue
302
+ maxValue = condition.FilterRangeMaxValue
303
+ return minValue <= axisValue <= maxValue
304
+ elif condition.Format == 2:
305
+ # ConditionValue
306
+ value = condition.DefaultValue
307
+ value += instancer[condition.VarIdx][0]
308
+ return value > 0
309
+ elif condition.Format == 3:
310
+ # ConditionAnd
311
+ for subcondition in condition.ConditionTable:
312
+ if not _evaluateCondition(subcondition, fvarAxes, location, instancer):
313
+ return False
314
+ return True
315
+ elif condition.Format == 4:
316
+ # ConditionOr
317
+ for subcondition in condition.ConditionTable:
318
+ if _evaluateCondition(subcondition, fvarAxes, location, instancer):
319
+ return True
320
+ return False
321
+ elif condition.Format == 5:
322
+ # ConditionNegate
323
+ return not _evaluateCondition(
324
+ condition.conditionTable, fvarAxes, location, instancer
325
+ )
326
+ else:
327
+ return False # Unkonwn condition format
328
+
329
+
330
+ class _TTGlyphVARC(_TTGlyph):
331
+ def _draw(self, pen, isPointPen):
332
+ """Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
333
+ how that works.
334
+ """
335
+ from fontTools.ttLib.tables.otTables import (
336
+ VarComponentFlags,
337
+ NO_VARIATION_INDEX,
338
+ )
339
+
340
+ glyphSet = self.glyphSet
341
+ varc = glyphSet.varcTable
342
+ idx = varc.Coverage.glyphs.index(self.name)
343
+ glyph = varc.VarCompositeGlyphs.VarCompositeGlyph[idx]
344
+
345
+ from fontTools.varLib.multiVarStore import MultiVarStoreInstancer
346
+ from fontTools.varLib.varStore import VarStoreInstancer
347
+
348
+ fvarAxes = glyphSet.font["fvar"].axes
349
+ instancer = MultiVarStoreInstancer(
350
+ varc.MultiVarStore, fvarAxes, self.glyphSet.location
351
+ )
352
+
353
+ for comp in glyph.components:
354
+ if comp.flags & VarComponentFlags.HAVE_CONDITION:
355
+ condition = varc.ConditionList.ConditionTable[comp.conditionIndex]
356
+ if not _evaluateCondition(
357
+ condition, fvarAxes, self.glyphSet.location, instancer
358
+ ):
359
+ continue
360
+
361
+ location = {}
362
+ if comp.axisIndicesIndex is not None:
363
+ axisIndices = varc.AxisIndicesList.Item[comp.axisIndicesIndex]
364
+ axisValues = Vector(comp.axisValues)
365
+ if comp.axisValuesVarIndex != NO_VARIATION_INDEX:
366
+ axisValues += fi2fl(instancer[comp.axisValuesVarIndex], 14)
367
+ assert len(axisIndices) == len(axisValues), (
368
+ len(axisIndices),
369
+ len(axisValues),
370
+ )
371
+ location = {
372
+ fvarAxes[i].axisTag: v for i, v in zip(axisIndices, axisValues)
373
+ }
374
+
375
+ if comp.transformVarIndex != NO_VARIATION_INDEX:
376
+ deltas = instancer[comp.transformVarIndex]
377
+ comp = deepcopy(comp)
378
+ comp.applyTransformDeltas(deltas)
379
+ transform = comp.transform
380
+
381
+ reset = comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES
382
+ with self.glyphSet.glyphSet.pushLocation(location, reset):
383
+ with self.glyphSet.pushLocation(location, reset):
384
+ shouldDecompose = self.name == comp.glyphName
385
+
386
+ if not shouldDecompose:
387
+ try:
388
+ pen.addVarComponent(
389
+ comp.glyphName, transform, self.glyphSet.rawLocation
390
+ )
391
+ except AttributeError:
392
+ shouldDecompose = True
393
+
394
+ if shouldDecompose:
395
+ t = transform.toTransform()
396
+ compGlyphSet = (
397
+ self.glyphSet
398
+ if comp.glyphName != self.name
399
+ else glyphSet.glyphSet
400
+ )
401
+ g = compGlyphSet[comp.glyphName]
402
+ if isPointPen:
403
+ tPen = TransformPointPen(pen, t)
404
+ g.drawPoints(tPen)
405
+ else:
406
+ tPen = TransformPen(pen, t)
407
+ g.draw(tPen)
408
+
409
+ def draw(self, pen):
410
+ self._draw(pen, False)
411
+
412
+ def drawPoints(self, pen):
413
+ self._draw(pen, True)
414
+
415
+
416
+ def _setCoordinates(glyph, coord, glyfTable, *, recalcBounds=True):
417
+ # Handle phantom points for (left, right, top, bottom) positions.
418
+ assert len(coord) >= 4
419
+ leftSideX = coord[-4][0]
420
+ rightSideX = coord[-3][0]
421
+ topSideY = coord[-2][1]
422
+ bottomSideY = coord[-1][1]
423
+
424
+ for _ in range(4):
425
+ del coord[-1]
426
+
427
+ if glyph.isComposite():
428
+ assert len(coord) == len(glyph.components)
429
+ glyph.components = [copy(comp) for comp in glyph.components] # Shallow copy
430
+ for p, comp in zip(coord, glyph.components):
431
+ if hasattr(comp, "x"):
432
+ comp.x, comp.y = p
433
+ elif glyph.numberOfContours == 0:
434
+ assert len(coord) == 0
435
+ else:
436
+ assert len(coord) == len(glyph.coordinates)
437
+ glyph.coordinates = coord
438
+
439
+ if recalcBounds:
440
+ glyph.recalcBounds(glyfTable)
441
+
442
+ horizontalAdvanceWidth = otRound(rightSideX - leftSideX)
443
+ verticalAdvanceWidth = otRound(topSideY - bottomSideY)
444
+ leftSideBearing = otRound(glyph.xMin - leftSideX)
445
+ topSideBearing = otRound(topSideY - glyph.yMax)
446
+ return (
447
+ horizontalAdvanceWidth,
448
+ leftSideBearing,
449
+ verticalAdvanceWidth,
450
+ topSideBearing,
451
+ )
452
+
453
+
454
+ class LerpGlyphSet(Mapping):
455
+ """A glyphset that interpolates between two other glyphsets.
456
+
457
+ Factor is typically between 0 and 1. 0 means the first glyphset,
458
+ 1 means the second glyphset, and 0.5 means the average of the
459
+ two glyphsets. Other values are possible, and can be useful to
460
+ extrapolate. Defaults to 0.5.
461
+ """
462
+
463
+ def __init__(self, glyphset1, glyphset2, factor=0.5):
464
+ self.glyphset1 = glyphset1
465
+ self.glyphset2 = glyphset2
466
+ self.factor = factor
467
+
468
+ def __getitem__(self, glyphname):
469
+ if glyphname in self.glyphset1 and glyphname in self.glyphset2:
470
+ return LerpGlyph(glyphname, self)
471
+ raise KeyError(glyphname)
472
+
473
+ def __contains__(self, glyphname):
474
+ return glyphname in self.glyphset1 and glyphname in self.glyphset2
475
+
476
+ def __iter__(self):
477
+ set1 = set(self.glyphset1)
478
+ set2 = set(self.glyphset2)
479
+ return iter(set1.intersection(set2))
480
+
481
+ def __len__(self):
482
+ set1 = set(self.glyphset1)
483
+ set2 = set(self.glyphset2)
484
+ return len(set1.intersection(set2))
485
+
486
+
487
+ class LerpGlyph:
488
+ def __init__(self, glyphname, glyphset):
489
+ self.glyphset = glyphset
490
+ self.glyphname = glyphname
491
+
492
+ def draw(self, pen):
493
+ recording1 = DecomposingRecordingPen(self.glyphset.glyphset1)
494
+ self.glyphset.glyphset1[self.glyphname].draw(recording1)
495
+ recording2 = DecomposingRecordingPen(self.glyphset.glyphset2)
496
+ self.glyphset.glyphset2[self.glyphname].draw(recording2)
497
+
498
+ factor = self.glyphset.factor
499
+
500
+ 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