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
Binary file
@@ -0,0 +1,287 @@
1
+ from fontTools.feaLib.error import FeatureLibError, IncludedFeaNotFound
2
+ from fontTools.feaLib.location import FeatureLibLocation
3
+ import re
4
+ import os
5
+
6
+ try:
7
+ import cython
8
+ except ImportError:
9
+ # if cython not installed, use mock module with no-op decorators and types
10
+ from fontTools.misc import cython
11
+
12
+
13
+ class Lexer(object):
14
+ NUMBER = "NUMBER"
15
+ HEXADECIMAL = "HEXADECIMAL"
16
+ OCTAL = "OCTAL"
17
+ NUMBERS = (NUMBER, HEXADECIMAL, OCTAL)
18
+ FLOAT = "FLOAT"
19
+ STRING = "STRING"
20
+ NAME = "NAME"
21
+ FILENAME = "FILENAME"
22
+ GLYPHCLASS = "GLYPHCLASS"
23
+ CID = "CID"
24
+ SYMBOL = "SYMBOL"
25
+ COMMENT = "COMMENT"
26
+ NEWLINE = "NEWLINE"
27
+ ANONYMOUS_BLOCK = "ANONYMOUS_BLOCK"
28
+
29
+ CHAR_WHITESPACE_ = " \t"
30
+ CHAR_NEWLINE_ = "\r\n"
31
+ CHAR_SYMBOL_ = ",;:-+'{}[]<>()="
32
+ CHAR_DIGIT_ = "0123456789"
33
+ CHAR_HEXDIGIT_ = "0123456789ABCDEFabcdef"
34
+ CHAR_LETTER_ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
35
+ CHAR_NAME_START_ = CHAR_LETTER_ + "_+*:.^~!\\"
36
+ CHAR_NAME_CONTINUATION_ = CHAR_LETTER_ + CHAR_DIGIT_ + "_.+*:^~!/-"
37
+
38
+ RE_GLYPHCLASS = re.compile(r"^[A-Za-z_0-9.\-]+$")
39
+
40
+ MODE_NORMAL_ = "NORMAL"
41
+ MODE_FILENAME_ = "FILENAME"
42
+
43
+ def __init__(self, text, filename):
44
+ self.filename_ = filename
45
+ self.line_ = 1
46
+ self.pos_ = 0
47
+ self.line_start_ = 0
48
+ self.text_ = text
49
+ self.text_length_ = len(text)
50
+ self.mode_ = Lexer.MODE_NORMAL_
51
+
52
+ def __iter__(self):
53
+ return self
54
+
55
+ def next(self): # Python 2
56
+ return self.__next__()
57
+
58
+ def __next__(self): # Python 3
59
+ while True:
60
+ token_type, token, location = self.next_()
61
+ if token_type != Lexer.NEWLINE:
62
+ return (token_type, token, location)
63
+
64
+ def location_(self):
65
+ column = self.pos_ - self.line_start_ + 1
66
+ return FeatureLibLocation(self.filename_ or "<features>", self.line_, column)
67
+
68
+ def next_(self):
69
+ self.scan_over_(Lexer.CHAR_WHITESPACE_)
70
+ location = self.location_()
71
+ start = self.pos_
72
+ text = self.text_
73
+ limit = len(text)
74
+ if start >= limit:
75
+ raise StopIteration()
76
+ cur_char = text[start]
77
+ next_char = text[start + 1] if start + 1 < limit else None
78
+
79
+ if cur_char == "\n":
80
+ self.pos_ += 1
81
+ self.line_ += 1
82
+ self.line_start_ = self.pos_
83
+ return (Lexer.NEWLINE, None, location)
84
+ if cur_char == "\r":
85
+ self.pos_ += 2 if next_char == "\n" else 1
86
+ self.line_ += 1
87
+ self.line_start_ = self.pos_
88
+ return (Lexer.NEWLINE, None, location)
89
+ if cur_char == "#":
90
+ self.scan_until_(Lexer.CHAR_NEWLINE_)
91
+ return (Lexer.COMMENT, text[start : self.pos_], location)
92
+
93
+ if self.mode_ is Lexer.MODE_FILENAME_:
94
+ if cur_char != "(":
95
+ raise FeatureLibError("Expected '(' before file name", location)
96
+ self.scan_until_(")")
97
+ cur_char = text[self.pos_] if self.pos_ < limit else None
98
+ if cur_char != ")":
99
+ raise FeatureLibError("Expected ')' after file name", location)
100
+ self.pos_ += 1
101
+ self.mode_ = Lexer.MODE_NORMAL_
102
+ return (Lexer.FILENAME, text[start + 1 : self.pos_ - 1], location)
103
+
104
+ if cur_char == "\\" and next_char in Lexer.CHAR_DIGIT_:
105
+ self.pos_ += 1
106
+ self.scan_over_(Lexer.CHAR_DIGIT_)
107
+ return (Lexer.CID, int(text[start + 1 : self.pos_], 10), location)
108
+ if cur_char == "@":
109
+ self.pos_ += 1
110
+ self.scan_over_(Lexer.CHAR_NAME_CONTINUATION_)
111
+ glyphclass = text[start + 1 : self.pos_]
112
+ if len(glyphclass) < 1:
113
+ raise FeatureLibError("Expected glyph class name", location)
114
+ if not Lexer.RE_GLYPHCLASS.match(glyphclass):
115
+ raise FeatureLibError(
116
+ "Glyph class names must consist of letters, digits, "
117
+ "underscore, period or hyphen",
118
+ location,
119
+ )
120
+ return (Lexer.GLYPHCLASS, glyphclass, location)
121
+ if cur_char in Lexer.CHAR_NAME_START_:
122
+ self.pos_ += 1
123
+ self.scan_over_(Lexer.CHAR_NAME_CONTINUATION_)
124
+ token = text[start : self.pos_]
125
+ if token == "include":
126
+ self.mode_ = Lexer.MODE_FILENAME_
127
+ return (Lexer.NAME, token, location)
128
+ if cur_char == "0" and next_char in "xX":
129
+ self.pos_ += 2
130
+ self.scan_over_(Lexer.CHAR_HEXDIGIT_)
131
+ return (Lexer.HEXADECIMAL, int(text[start : self.pos_], 16), location)
132
+ if cur_char == "0" and next_char in Lexer.CHAR_DIGIT_:
133
+ self.scan_over_(Lexer.CHAR_DIGIT_)
134
+ return (Lexer.OCTAL, int(text[start : self.pos_], 8), location)
135
+ if cur_char in Lexer.CHAR_DIGIT_:
136
+ self.scan_over_(Lexer.CHAR_DIGIT_)
137
+ if self.pos_ >= limit or text[self.pos_] != ".":
138
+ return (Lexer.NUMBER, int(text[start : self.pos_], 10), location)
139
+ self.scan_over_(".")
140
+ self.scan_over_(Lexer.CHAR_DIGIT_)
141
+ return (Lexer.FLOAT, float(text[start : self.pos_]), location)
142
+ if cur_char == "-" and next_char in Lexer.CHAR_DIGIT_:
143
+ self.pos_ += 1
144
+ self.scan_over_(Lexer.CHAR_DIGIT_)
145
+ if self.pos_ >= limit or text[self.pos_] != ".":
146
+ return (Lexer.NUMBER, int(text[start : self.pos_], 10), location)
147
+ self.scan_over_(".")
148
+ self.scan_over_(Lexer.CHAR_DIGIT_)
149
+ return (Lexer.FLOAT, float(text[start : self.pos_]), location)
150
+ if cur_char in Lexer.CHAR_SYMBOL_:
151
+ self.pos_ += 1
152
+ return (Lexer.SYMBOL, cur_char, location)
153
+ if cur_char == '"':
154
+ self.pos_ += 1
155
+ self.scan_until_('"')
156
+ if self.pos_ < self.text_length_ and self.text_[self.pos_] == '"':
157
+ self.pos_ += 1
158
+ # strip newlines embedded within a string
159
+ string = re.sub("[\r\n]", "", text[start + 1 : self.pos_ - 1])
160
+ return (Lexer.STRING, string, location)
161
+ else:
162
+ raise FeatureLibError("Expected '\"' to terminate string", location)
163
+ raise FeatureLibError("Unexpected character: %r" % cur_char, location)
164
+
165
+ def scan_over_(self, valid):
166
+ p = self.pos_
167
+ while p < self.text_length_ and self.text_[p] in valid:
168
+ p += 1
169
+ self.pos_ = p
170
+
171
+ def scan_until_(self, stop_at):
172
+ p = self.pos_
173
+ while p < self.text_length_ and self.text_[p] not in stop_at:
174
+ p += 1
175
+ self.pos_ = p
176
+
177
+ def scan_anonymous_block(self, tag):
178
+ location = self.location_()
179
+ tag = tag.strip()
180
+ self.scan_until_(Lexer.CHAR_NEWLINE_)
181
+ self.scan_over_(Lexer.CHAR_NEWLINE_)
182
+ regexp = r"}\s*" + tag + r"\s*;"
183
+ split = re.split(regexp, self.text_[self.pos_ :], maxsplit=1)
184
+ if len(split) != 2:
185
+ raise FeatureLibError(
186
+ "Expected '} %s;' to terminate anonymous block" % tag, location
187
+ )
188
+ self.pos_ += len(split[0])
189
+ return (Lexer.ANONYMOUS_BLOCK, split[0], location)
190
+
191
+
192
+ class IncludingLexer(object):
193
+ """A Lexer that follows include statements.
194
+
195
+ The OpenType feature file specification states that due to
196
+ historical reasons, relative imports should be resolved in this
197
+ order:
198
+
199
+ 1. If the source font is UFO format, then relative to the UFO's
200
+ font directory
201
+ 2. relative to the top-level include file
202
+ 3. relative to the parent include file
203
+
204
+ We only support 1 (via includeDir) and 2.
205
+ """
206
+
207
+ def __init__(self, featurefile, *, includeDir=None):
208
+ """Initializes an IncludingLexer.
209
+
210
+ Behavior:
211
+ If includeDir is passed, it will be used to determine the top-level
212
+ include directory to use for all encountered include statements. If it is
213
+ not passed, ``os.path.dirname(featurefile)`` will be considered the
214
+ include directory.
215
+ """
216
+
217
+ self.lexers_ = [self.make_lexer_(featurefile)]
218
+ self.featurefilepath = self.lexers_[0].filename_
219
+ self.includeDir = includeDir
220
+
221
+ def __iter__(self):
222
+ return self
223
+
224
+ def next(self): # Python 2
225
+ return self.__next__()
226
+
227
+ def __next__(self): # Python 3
228
+ while self.lexers_:
229
+ lexer = self.lexers_[-1]
230
+ try:
231
+ token_type, token, location = next(lexer)
232
+ except StopIteration:
233
+ self.lexers_.pop()
234
+ continue
235
+ if token_type is Lexer.NAME and token == "include":
236
+ fname_type, fname_token, fname_location = lexer.next()
237
+ if fname_type is not Lexer.FILENAME:
238
+ raise FeatureLibError("Expected file name", fname_location)
239
+ # semi_type, semi_token, semi_location = lexer.next()
240
+ # if semi_type is not Lexer.SYMBOL or semi_token != ";":
241
+ # raise FeatureLibError("Expected ';'", semi_location)
242
+ if os.path.isabs(fname_token):
243
+ path = fname_token
244
+ else:
245
+ if self.includeDir is not None:
246
+ curpath = self.includeDir
247
+ elif self.featurefilepath is not None:
248
+ curpath = os.path.dirname(self.featurefilepath)
249
+ else:
250
+ # if the IncludingLexer was initialized from an in-memory
251
+ # file-like stream, it doesn't have a 'name' pointing to
252
+ # its filesystem path, therefore we fall back to using the
253
+ # current working directory to resolve relative includes
254
+ curpath = os.getcwd()
255
+ path = os.path.join(curpath, fname_token)
256
+ if len(self.lexers_) >= 5:
257
+ raise FeatureLibError("Too many recursive includes", fname_location)
258
+ try:
259
+ self.lexers_.append(self.make_lexer_(path))
260
+ except FileNotFoundError as err:
261
+ raise IncludedFeaNotFound(fname_token, fname_location) from err
262
+ else:
263
+ return (token_type, token, location)
264
+ raise StopIteration()
265
+
266
+ @staticmethod
267
+ def make_lexer_(file_or_path):
268
+ if hasattr(file_or_path, "read"):
269
+ fileobj, closing = file_or_path, False
270
+ else:
271
+ filename, closing = file_or_path, True
272
+ fileobj = open(filename, "r", encoding="utf-8-sig")
273
+ data = fileobj.read()
274
+ filename = getattr(fileobj, "name", None)
275
+ if closing:
276
+ fileobj.close()
277
+ return Lexer(data, filename)
278
+
279
+ def scan_anonymous_block(self, tag):
280
+ return self.lexers_[-1].scan_anonymous_block(tag)
281
+
282
+
283
+ class NonIncludingLexer(IncludingLexer):
284
+ """Lexer that does not follow `include` statements, emits them as-is."""
285
+
286
+ def __next__(self): # Python 3
287
+ return next(self.lexers_[0])
@@ -0,0 +1,12 @@
1
+ from typing import NamedTuple
2
+
3
+
4
+ class FeatureLibLocation(NamedTuple):
5
+ """A location in a feature file"""
6
+
7
+ file: str
8
+ line: int
9
+ column: int
10
+
11
+ def __str__(self):
12
+ return f"{self.file}:{self.line}:{self.column}"
@@ -0,0 +1,12 @@
1
+ from typing import NamedTuple
2
+
3
+ LOOKUP_DEBUG_INFO_KEY = "com.github.fonttools.feaLib"
4
+ LOOKUP_DEBUG_ENV_VAR = "FONTTOOLS_LOOKUP_DEBUGGING"
5
+
6
+
7
+ class LookupDebugInfo(NamedTuple):
8
+ """Information about where a lookup came from, to be embedded in a font"""
9
+
10
+ location: str
11
+ name: str
12
+ feature: list