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,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Calculate the perimeter of a glyph."""
3
+
4
+ from fontTools.pens.basePen import BasePen
5
+ from fontTools.misc.bezierTools import (
6
+ approximateQuadraticArcLengthC,
7
+ calcQuadraticArcLengthC,
8
+ approximateCubicArcLengthC,
9
+ calcCubicArcLengthC,
10
+ )
11
+ import math
12
+
13
+
14
+ __all__ = ["PerimeterPen"]
15
+
16
+
17
+ def _distance(p0, p1):
18
+ return math.hypot(p0[0] - p1[0], p0[1] - p1[1])
19
+
20
+
21
+ class PerimeterPen(BasePen):
22
+ def __init__(self, glyphset=None, tolerance=0.005):
23
+ BasePen.__init__(self, glyphset)
24
+ self.value = 0
25
+ self.tolerance = tolerance
26
+
27
+ # Choose which algorithm to use for quadratic and for cubic.
28
+ # Quadrature is faster but has fixed error characteristic with no strong
29
+ # error bound. The cutoff points are derived empirically.
30
+ self._addCubic = (
31
+ self._addCubicQuadrature if tolerance >= 0.0015 else self._addCubicRecursive
32
+ )
33
+ self._addQuadratic = (
34
+ self._addQuadraticQuadrature
35
+ if tolerance >= 0.00075
36
+ else self._addQuadraticExact
37
+ )
38
+
39
+ def _moveTo(self, p0):
40
+ self.__startPoint = p0
41
+
42
+ def _closePath(self):
43
+ p0 = self._getCurrentPoint()
44
+ if p0 != self.__startPoint:
45
+ self._lineTo(self.__startPoint)
46
+
47
+ def _lineTo(self, p1):
48
+ p0 = self._getCurrentPoint()
49
+ self.value += _distance(p0, p1)
50
+
51
+ def _addQuadraticExact(self, c0, c1, c2):
52
+ self.value += calcQuadraticArcLengthC(c0, c1, c2)
53
+
54
+ def _addQuadraticQuadrature(self, c0, c1, c2):
55
+ self.value += approximateQuadraticArcLengthC(c0, c1, c2)
56
+
57
+ def _qCurveToOne(self, p1, p2):
58
+ p0 = self._getCurrentPoint()
59
+ self._addQuadratic(complex(*p0), complex(*p1), complex(*p2))
60
+
61
+ def _addCubicRecursive(self, c0, c1, c2, c3):
62
+ self.value += calcCubicArcLengthC(c0, c1, c2, c3, self.tolerance)
63
+
64
+ def _addCubicQuadrature(self, c0, c1, c2, c3):
65
+ self.value += approximateCubicArcLengthC(c0, c1, c2, c3)
66
+
67
+ def _curveToOne(self, p1, p2, p3):
68
+ p0 = self._getCurrentPoint()
69
+ self._addCubic(complex(*p0), complex(*p1), complex(*p2), complex(*p3))
@@ -0,0 +1,192 @@
1
+ """fontTools.pens.pointInsidePen -- Pen implementing "point inside" testing
2
+ for shapes.
3
+ """
4
+
5
+ from fontTools.pens.basePen import BasePen
6
+ from fontTools.misc.bezierTools import solveQuadratic, solveCubic
7
+
8
+
9
+ __all__ = ["PointInsidePen"]
10
+
11
+
12
+ class PointInsidePen(BasePen):
13
+ """This pen implements "point inside" testing: to test whether
14
+ a given point lies inside the shape (black) or outside (white).
15
+ Instances of this class can be recycled, as long as the
16
+ setTestPoint() method is used to set the new point to test.
17
+
18
+ :Example:
19
+ .. code-block::
20
+
21
+ pen = PointInsidePen(glyphSet, (100, 200))
22
+ outline.draw(pen)
23
+ isInside = pen.getResult()
24
+
25
+ Both the even-odd algorithm and the non-zero-winding-rule
26
+ algorithm are implemented. The latter is the default, specify
27
+ True for the evenOdd argument of __init__ or setTestPoint
28
+ to use the even-odd algorithm.
29
+ """
30
+
31
+ # This class implements the classical "shoot a ray from the test point
32
+ # to infinity and count how many times it intersects the outline" (as well
33
+ # as the non-zero variant, where the counter is incremented if the outline
34
+ # intersects the ray in one direction and decremented if it intersects in
35
+ # the other direction).
36
+ # I found an amazingly clear explanation of the subtleties involved in
37
+ # implementing this correctly for polygons here:
38
+ # http://graphics.cs.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html
39
+ # I extended the principles outlined on that page to curves.
40
+
41
+ def __init__(self, glyphSet, testPoint, evenOdd=False):
42
+ BasePen.__init__(self, glyphSet)
43
+ self.setTestPoint(testPoint, evenOdd)
44
+
45
+ def setTestPoint(self, testPoint, evenOdd=False):
46
+ """Set the point to test. Call this _before_ the outline gets drawn."""
47
+ self.testPoint = testPoint
48
+ self.evenOdd = evenOdd
49
+ self.firstPoint = None
50
+ self.intersectionCount = 0
51
+
52
+ def getWinding(self):
53
+ if self.firstPoint is not None:
54
+ # always make sure the sub paths are closed; the algorithm only works
55
+ # for closed paths.
56
+ self.closePath()
57
+ return self.intersectionCount
58
+
59
+ def getResult(self):
60
+ """After the shape has been drawn, getResult() returns True if the test
61
+ point lies within the (black) shape, and False if it doesn't.
62
+ """
63
+ winding = self.getWinding()
64
+ if self.evenOdd:
65
+ result = winding % 2
66
+ else: # non-zero
67
+ result = self.intersectionCount != 0
68
+ return not not result
69
+
70
+ def _addIntersection(self, goingUp):
71
+ if self.evenOdd or goingUp:
72
+ self.intersectionCount += 1
73
+ else:
74
+ self.intersectionCount -= 1
75
+
76
+ def _moveTo(self, point):
77
+ if self.firstPoint is not None:
78
+ # always make sure the sub paths are closed; the algorithm only works
79
+ # for closed paths.
80
+ self.closePath()
81
+ self.firstPoint = point
82
+
83
+ def _lineTo(self, point):
84
+ x, y = self.testPoint
85
+ x1, y1 = self._getCurrentPoint()
86
+ x2, y2 = point
87
+
88
+ if x1 < x and x2 < x:
89
+ return
90
+ if y1 < y and y2 < y:
91
+ return
92
+ if y1 >= y and y2 >= y:
93
+ return
94
+
95
+ dx = x2 - x1
96
+ dy = y2 - y1
97
+ t = (y - y1) / dy
98
+ ix = dx * t + x1
99
+ if ix < x:
100
+ return
101
+ self._addIntersection(y2 > y1)
102
+
103
+ def _curveToOne(self, bcp1, bcp2, point):
104
+ x, y = self.testPoint
105
+ x1, y1 = self._getCurrentPoint()
106
+ x2, y2 = bcp1
107
+ x3, y3 = bcp2
108
+ x4, y4 = point
109
+
110
+ if x1 < x and x2 < x and x3 < x and x4 < x:
111
+ return
112
+ if y1 < y and y2 < y and y3 < y and y4 < y:
113
+ return
114
+ if y1 >= y and y2 >= y and y3 >= y and y4 >= y:
115
+ return
116
+
117
+ dy = y1
118
+ cy = (y2 - dy) * 3.0
119
+ by = (y3 - y2) * 3.0 - cy
120
+ ay = y4 - dy - cy - by
121
+ solutions = sorted(solveCubic(ay, by, cy, dy - y))
122
+ solutions = [t for t in solutions if -0.0 <= t <= 1.0]
123
+ if not solutions:
124
+ return
125
+
126
+ dx = x1
127
+ cx = (x2 - dx) * 3.0
128
+ bx = (x3 - x2) * 3.0 - cx
129
+ ax = x4 - dx - cx - bx
130
+
131
+ above = y1 >= y
132
+ lastT = None
133
+ for t in solutions:
134
+ if t == lastT:
135
+ continue
136
+ lastT = t
137
+ t2 = t * t
138
+ t3 = t2 * t
139
+
140
+ direction = 3 * ay * t2 + 2 * by * t + cy
141
+ incomingGoingUp = outgoingGoingUp = direction > 0.0
142
+ if direction == 0.0:
143
+ direction = 6 * ay * t + 2 * by
144
+ outgoingGoingUp = direction > 0.0
145
+ incomingGoingUp = not outgoingGoingUp
146
+ if direction == 0.0:
147
+ direction = ay
148
+ incomingGoingUp = outgoingGoingUp = direction > 0.0
149
+
150
+ xt = ax * t3 + bx * t2 + cx * t + dx
151
+ if xt < x:
152
+ continue
153
+
154
+ if t in (0.0, -0.0):
155
+ if not outgoingGoingUp:
156
+ self._addIntersection(outgoingGoingUp)
157
+ elif t == 1.0:
158
+ if incomingGoingUp:
159
+ self._addIntersection(incomingGoingUp)
160
+ else:
161
+ if incomingGoingUp == outgoingGoingUp:
162
+ self._addIntersection(outgoingGoingUp)
163
+ # else:
164
+ # we're not really intersecting, merely touching
165
+
166
+ def _qCurveToOne_unfinished(self, bcp, point):
167
+ # XXX need to finish this, for now doing it through a cubic
168
+ # (BasePen implements _qCurveTo in terms of a cubic) will
169
+ # have to do.
170
+ x, y = self.testPoint
171
+ x1, y1 = self._getCurrentPoint()
172
+ x2, y2 = bcp
173
+ x3, y3 = point
174
+ c = y1
175
+ b = (y2 - c) * 2.0
176
+ a = y3 - c - b
177
+ solutions = sorted(solveQuadratic(a, b, c - y))
178
+ solutions = [
179
+ t for t in solutions if ZERO_MINUS_EPSILON <= t <= ONE_PLUS_EPSILON
180
+ ]
181
+ if not solutions:
182
+ return
183
+ # XXX
184
+
185
+ def _closePath(self):
186
+ if self._getCurrentPoint() != self.firstPoint:
187
+ self.lineTo(self.firstPoint)
188
+ self.firstPoint = None
189
+
190
+ def _endPath(self):
191
+ """Insideness is not defined for open contours."""
192
+ raise NotImplementedError