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.
- fontTools/__init__.py +8 -0
- fontTools/__main__.py +35 -0
- fontTools/afmLib.py +439 -0
- fontTools/agl.py +5233 -0
- fontTools/annotations.py +30 -0
- fontTools/cffLib/CFF2ToCFF.py +258 -0
- fontTools/cffLib/CFFToCFF2.py +305 -0
- fontTools/cffLib/__init__.py +3694 -0
- fontTools/cffLib/specializer.py +927 -0
- fontTools/cffLib/transforms.py +495 -0
- fontTools/cffLib/width.py +210 -0
- fontTools/colorLib/__init__.py +0 -0
- fontTools/colorLib/builder.py +664 -0
- fontTools/colorLib/errors.py +2 -0
- fontTools/colorLib/geometry.py +143 -0
- fontTools/colorLib/table_builder.py +223 -0
- fontTools/colorLib/unbuilder.py +81 -0
- fontTools/config/__init__.py +90 -0
- fontTools/cu2qu/__init__.py +15 -0
- fontTools/cu2qu/__main__.py +6 -0
- fontTools/cu2qu/benchmark.py +54 -0
- fontTools/cu2qu/cli.py +198 -0
- fontTools/cu2qu/cu2qu.c +15817 -0
- fontTools/cu2qu/cu2qu.cp311-win32.pyd +0 -0
- fontTools/cu2qu/cu2qu.py +563 -0
- fontTools/cu2qu/errors.py +77 -0
- fontTools/cu2qu/ufo.py +363 -0
- fontTools/designspaceLib/__init__.py +3343 -0
- fontTools/designspaceLib/__main__.py +6 -0
- fontTools/designspaceLib/split.py +475 -0
- fontTools/designspaceLib/statNames.py +260 -0
- fontTools/designspaceLib/types.py +147 -0
- fontTools/encodings/MacRoman.py +258 -0
- fontTools/encodings/StandardEncoding.py +258 -0
- fontTools/encodings/__init__.py +1 -0
- fontTools/encodings/codecs.py +135 -0
- fontTools/feaLib/__init__.py +4 -0
- fontTools/feaLib/__main__.py +78 -0
- fontTools/feaLib/ast.py +2143 -0
- fontTools/feaLib/builder.py +1814 -0
- fontTools/feaLib/error.py +22 -0
- fontTools/feaLib/lexer.c +17029 -0
- fontTools/feaLib/lexer.cp311-win32.pyd +0 -0
- fontTools/feaLib/lexer.py +287 -0
- fontTools/feaLib/location.py +12 -0
- fontTools/feaLib/lookupDebugInfo.py +12 -0
- fontTools/feaLib/parser.py +2394 -0
- fontTools/feaLib/variableScalar.py +118 -0
- fontTools/fontBuilder.py +1014 -0
- fontTools/help.py +36 -0
- fontTools/merge/__init__.py +248 -0
- fontTools/merge/__main__.py +6 -0
- fontTools/merge/base.py +81 -0
- fontTools/merge/cmap.py +173 -0
- fontTools/merge/layout.py +526 -0
- fontTools/merge/options.py +85 -0
- fontTools/merge/tables.py +352 -0
- fontTools/merge/unicode.py +78 -0
- fontTools/merge/util.py +143 -0
- fontTools/misc/__init__.py +1 -0
- fontTools/misc/arrayTools.py +424 -0
- fontTools/misc/bezierTools.c +39731 -0
- fontTools/misc/bezierTools.cp311-win32.pyd +0 -0
- fontTools/misc/bezierTools.py +1500 -0
- fontTools/misc/classifyTools.py +170 -0
- fontTools/misc/cliTools.py +53 -0
- fontTools/misc/configTools.py +349 -0
- fontTools/misc/cython.py +27 -0
- fontTools/misc/dictTools.py +83 -0
- fontTools/misc/eexec.py +119 -0
- fontTools/misc/encodingTools.py +72 -0
- fontTools/misc/enumTools.py +23 -0
- fontTools/misc/etree.py +456 -0
- fontTools/misc/filenames.py +245 -0
- fontTools/misc/filesystem/__init__.py +68 -0
- fontTools/misc/filesystem/_base.py +134 -0
- fontTools/misc/filesystem/_copy.py +45 -0
- fontTools/misc/filesystem/_errors.py +54 -0
- fontTools/misc/filesystem/_info.py +75 -0
- fontTools/misc/filesystem/_osfs.py +164 -0
- fontTools/misc/filesystem/_path.py +67 -0
- fontTools/misc/filesystem/_subfs.py +92 -0
- fontTools/misc/filesystem/_tempfs.py +34 -0
- fontTools/misc/filesystem/_tools.py +34 -0
- fontTools/misc/filesystem/_walk.py +55 -0
- fontTools/misc/filesystem/_zipfs.py +204 -0
- fontTools/misc/fixedTools.py +253 -0
- fontTools/misc/intTools.py +25 -0
- fontTools/misc/iterTools.py +12 -0
- fontTools/misc/lazyTools.py +42 -0
- fontTools/misc/loggingTools.py +543 -0
- fontTools/misc/macCreatorType.py +56 -0
- fontTools/misc/macRes.py +261 -0
- fontTools/misc/plistlib/__init__.py +681 -0
- fontTools/misc/plistlib/py.typed +0 -0
- fontTools/misc/psCharStrings.py +1511 -0
- fontTools/misc/psLib.py +398 -0
- fontTools/misc/psOperators.py +572 -0
- fontTools/misc/py23.py +96 -0
- fontTools/misc/roundTools.py +110 -0
- fontTools/misc/sstruct.py +227 -0
- fontTools/misc/symfont.py +242 -0
- fontTools/misc/testTools.py +233 -0
- fontTools/misc/textTools.py +156 -0
- fontTools/misc/timeTools.py +88 -0
- fontTools/misc/transform.py +516 -0
- fontTools/misc/treeTools.py +45 -0
- fontTools/misc/vector.py +147 -0
- fontTools/misc/visitor.py +158 -0
- fontTools/misc/xmlReader.py +188 -0
- fontTools/misc/xmlWriter.py +231 -0
- fontTools/mtiLib/__init__.py +1400 -0
- fontTools/mtiLib/__main__.py +5 -0
- fontTools/otlLib/__init__.py +1 -0
- fontTools/otlLib/builder.py +3465 -0
- fontTools/otlLib/error.py +11 -0
- fontTools/otlLib/maxContextCalc.py +96 -0
- fontTools/otlLib/optimize/__init__.py +53 -0
- fontTools/otlLib/optimize/__main__.py +6 -0
- fontTools/otlLib/optimize/gpos.py +439 -0
- fontTools/pens/__init__.py +1 -0
- fontTools/pens/areaPen.py +52 -0
- fontTools/pens/basePen.py +475 -0
- fontTools/pens/boundsPen.py +98 -0
- fontTools/pens/cairoPen.py +26 -0
- fontTools/pens/cocoaPen.py +26 -0
- fontTools/pens/cu2quPen.py +325 -0
- fontTools/pens/explicitClosingLinePen.py +101 -0
- fontTools/pens/filterPen.py +433 -0
- fontTools/pens/freetypePen.py +462 -0
- fontTools/pens/hashPointPen.py +89 -0
- fontTools/pens/momentsPen.c +13378 -0
- fontTools/pens/momentsPen.cp311-win32.pyd +0 -0
- fontTools/pens/momentsPen.py +879 -0
- fontTools/pens/perimeterPen.py +69 -0
- fontTools/pens/pointInsidePen.py +192 -0
- fontTools/pens/pointPen.py +643 -0
- fontTools/pens/qtPen.py +29 -0
- fontTools/pens/qu2cuPen.py +105 -0
- fontTools/pens/quartzPen.py +43 -0
- fontTools/pens/recordingPen.py +335 -0
- fontTools/pens/reportLabPen.py +79 -0
- fontTools/pens/reverseContourPen.py +96 -0
- fontTools/pens/roundingPen.py +130 -0
- fontTools/pens/statisticsPen.py +312 -0
- fontTools/pens/svgPathPen.py +310 -0
- fontTools/pens/t2CharStringPen.py +88 -0
- fontTools/pens/teePen.py +55 -0
- fontTools/pens/transformPen.py +115 -0
- fontTools/pens/ttGlyphPen.py +335 -0
- fontTools/pens/wxPen.py +29 -0
- fontTools/qu2cu/__init__.py +15 -0
- fontTools/qu2cu/__main__.py +7 -0
- fontTools/qu2cu/benchmark.py +56 -0
- fontTools/qu2cu/cli.py +125 -0
- fontTools/qu2cu/qu2cu.c +16682 -0
- fontTools/qu2cu/qu2cu.cp311-win32.pyd +0 -0
- fontTools/qu2cu/qu2cu.py +405 -0
- fontTools/subset/__init__.py +4096 -0
- fontTools/subset/__main__.py +6 -0
- fontTools/subset/cff.py +184 -0
- fontTools/subset/svg.py +253 -0
- fontTools/subset/util.py +25 -0
- fontTools/svgLib/__init__.py +3 -0
- fontTools/svgLib/path/__init__.py +65 -0
- fontTools/svgLib/path/arc.py +154 -0
- fontTools/svgLib/path/parser.py +322 -0
- fontTools/svgLib/path/shapes.py +183 -0
- fontTools/t1Lib/__init__.py +648 -0
- fontTools/tfmLib.py +460 -0
- fontTools/ttLib/__init__.py +30 -0
- fontTools/ttLib/__main__.py +148 -0
- fontTools/ttLib/macUtils.py +54 -0
- fontTools/ttLib/removeOverlaps.py +395 -0
- fontTools/ttLib/reorderGlyphs.py +285 -0
- fontTools/ttLib/scaleUpem.py +436 -0
- fontTools/ttLib/sfnt.py +661 -0
- fontTools/ttLib/standardGlyphOrder.py +271 -0
- fontTools/ttLib/tables/B_A_S_E_.py +14 -0
- fontTools/ttLib/tables/BitmapGlyphMetrics.py +64 -0
- fontTools/ttLib/tables/C_B_D_T_.py +113 -0
- fontTools/ttLib/tables/C_B_L_C_.py +19 -0
- fontTools/ttLib/tables/C_F_F_.py +61 -0
- fontTools/ttLib/tables/C_F_F__2.py +26 -0
- fontTools/ttLib/tables/C_O_L_R_.py +165 -0
- fontTools/ttLib/tables/C_P_A_L_.py +305 -0
- fontTools/ttLib/tables/D_S_I_G_.py +158 -0
- fontTools/ttLib/tables/D__e_b_g.py +35 -0
- fontTools/ttLib/tables/DefaultTable.py +49 -0
- fontTools/ttLib/tables/E_B_D_T_.py +835 -0
- fontTools/ttLib/tables/E_B_L_C_.py +718 -0
- fontTools/ttLib/tables/F_F_T_M_.py +52 -0
- fontTools/ttLib/tables/F__e_a_t.py +149 -0
- fontTools/ttLib/tables/G_D_E_F_.py +13 -0
- fontTools/ttLib/tables/G_M_A_P_.py +148 -0
- fontTools/ttLib/tables/G_P_K_G_.py +133 -0
- fontTools/ttLib/tables/G_P_O_S_.py +14 -0
- fontTools/ttLib/tables/G_S_U_B_.py +13 -0
- fontTools/ttLib/tables/G_V_A_R_.py +5 -0
- fontTools/ttLib/tables/G__l_a_t.py +235 -0
- fontTools/ttLib/tables/G__l_o_c.py +85 -0
- fontTools/ttLib/tables/H_V_A_R_.py +13 -0
- fontTools/ttLib/tables/J_S_T_F_.py +13 -0
- fontTools/ttLib/tables/L_T_S_H_.py +58 -0
- fontTools/ttLib/tables/M_A_T_H_.py +13 -0
- fontTools/ttLib/tables/M_E_T_A_.py +352 -0
- fontTools/ttLib/tables/M_V_A_R_.py +13 -0
- fontTools/ttLib/tables/O_S_2f_2.py +752 -0
- fontTools/ttLib/tables/S_I_N_G_.py +99 -0
- fontTools/ttLib/tables/S_T_A_T_.py +15 -0
- fontTools/ttLib/tables/S_V_G_.py +223 -0
- fontTools/ttLib/tables/S__i_l_f.py +1040 -0
- fontTools/ttLib/tables/S__i_l_l.py +92 -0
- fontTools/ttLib/tables/T_S_I_B_.py +13 -0
- fontTools/ttLib/tables/T_S_I_C_.py +14 -0
- fontTools/ttLib/tables/T_S_I_D_.py +13 -0
- fontTools/ttLib/tables/T_S_I_J_.py +13 -0
- fontTools/ttLib/tables/T_S_I_P_.py +13 -0
- fontTools/ttLib/tables/T_S_I_S_.py +13 -0
- fontTools/ttLib/tables/T_S_I_V_.py +26 -0
- fontTools/ttLib/tables/T_S_I__0.py +70 -0
- fontTools/ttLib/tables/T_S_I__1.py +163 -0
- fontTools/ttLib/tables/T_S_I__2.py +17 -0
- fontTools/ttLib/tables/T_S_I__3.py +22 -0
- fontTools/ttLib/tables/T_S_I__5.py +60 -0
- fontTools/ttLib/tables/T_T_F_A_.py +14 -0
- fontTools/ttLib/tables/TupleVariation.py +884 -0
- fontTools/ttLib/tables/V_A_R_C_.py +12 -0
- fontTools/ttLib/tables/V_D_M_X_.py +249 -0
- fontTools/ttLib/tables/V_O_R_G_.py +165 -0
- fontTools/ttLib/tables/V_V_A_R_.py +13 -0
- fontTools/ttLib/tables/__init__.py +98 -0
- fontTools/ttLib/tables/_a_n_k_r.py +15 -0
- fontTools/ttLib/tables/_a_v_a_r.py +193 -0
- fontTools/ttLib/tables/_b_s_l_n.py +15 -0
- fontTools/ttLib/tables/_c_i_d_g.py +24 -0
- fontTools/ttLib/tables/_c_m_a_p.py +1591 -0
- fontTools/ttLib/tables/_c_v_a_r.py +94 -0
- fontTools/ttLib/tables/_c_v_t.py +56 -0
- fontTools/ttLib/tables/_f_e_a_t.py +15 -0
- fontTools/ttLib/tables/_f_p_g_m.py +62 -0
- fontTools/ttLib/tables/_f_v_a_r.py +261 -0
- fontTools/ttLib/tables/_g_a_s_p.py +63 -0
- fontTools/ttLib/tables/_g_c_i_d.py +13 -0
- fontTools/ttLib/tables/_g_l_y_f.py +2311 -0
- fontTools/ttLib/tables/_g_v_a_r.py +340 -0
- fontTools/ttLib/tables/_h_d_m_x.py +127 -0
- fontTools/ttLib/tables/_h_e_a_d.py +130 -0
- fontTools/ttLib/tables/_h_h_e_a.py +147 -0
- fontTools/ttLib/tables/_h_m_t_x.py +164 -0
- fontTools/ttLib/tables/_k_e_r_n.py +289 -0
- fontTools/ttLib/tables/_l_c_a_r.py +13 -0
- fontTools/ttLib/tables/_l_o_c_a.py +70 -0
- fontTools/ttLib/tables/_l_t_a_g.py +72 -0
- fontTools/ttLib/tables/_m_a_x_p.py +147 -0
- fontTools/ttLib/tables/_m_e_t_a.py +112 -0
- fontTools/ttLib/tables/_m_o_r_t.py +14 -0
- fontTools/ttLib/tables/_m_o_r_x.py +15 -0
- fontTools/ttLib/tables/_n_a_m_e.py +1242 -0
- fontTools/ttLib/tables/_o_p_b_d.py +14 -0
- fontTools/ttLib/tables/_p_o_s_t.py +319 -0
- fontTools/ttLib/tables/_p_r_e_p.py +16 -0
- fontTools/ttLib/tables/_p_r_o_p.py +12 -0
- fontTools/ttLib/tables/_s_b_i_x.py +129 -0
- fontTools/ttLib/tables/_t_r_a_k.py +332 -0
- fontTools/ttLib/tables/_v_h_e_a.py +139 -0
- fontTools/ttLib/tables/_v_m_t_x.py +19 -0
- fontTools/ttLib/tables/asciiTable.py +20 -0
- fontTools/ttLib/tables/grUtils.py +92 -0
- fontTools/ttLib/tables/otBase.py +1458 -0
- fontTools/ttLib/tables/otConverters.py +2068 -0
- fontTools/ttLib/tables/otData.py +6400 -0
- fontTools/ttLib/tables/otTables.py +2703 -0
- fontTools/ttLib/tables/otTraverse.py +163 -0
- fontTools/ttLib/tables/sbixGlyph.py +149 -0
- fontTools/ttLib/tables/sbixStrike.py +177 -0
- fontTools/ttLib/tables/table_API_readme.txt +91 -0
- fontTools/ttLib/tables/ttProgram.py +594 -0
- fontTools/ttLib/ttCollection.py +125 -0
- fontTools/ttLib/ttFont.py +1148 -0
- fontTools/ttLib/ttGlyphSet.py +490 -0
- fontTools/ttLib/ttVisitor.py +32 -0
- fontTools/ttLib/woff2.py +1680 -0
- fontTools/ttx.py +479 -0
- fontTools/ufoLib/__init__.py +2575 -0
- fontTools/ufoLib/converters.py +407 -0
- fontTools/ufoLib/errors.py +30 -0
- fontTools/ufoLib/etree.py +6 -0
- fontTools/ufoLib/filenames.py +356 -0
- fontTools/ufoLib/glifLib.py +2120 -0
- fontTools/ufoLib/kerning.py +141 -0
- fontTools/ufoLib/plistlib.py +47 -0
- fontTools/ufoLib/pointPen.py +6 -0
- fontTools/ufoLib/utils.py +107 -0
- fontTools/ufoLib/validators.py +1208 -0
- fontTools/unicode.py +50 -0
- fontTools/unicodedata/Blocks.py +817 -0
- fontTools/unicodedata/Mirrored.py +446 -0
- fontTools/unicodedata/OTTags.py +50 -0
- fontTools/unicodedata/ScriptExtensions.py +832 -0
- fontTools/unicodedata/Scripts.py +3639 -0
- fontTools/unicodedata/__init__.py +306 -0
- fontTools/varLib/__init__.py +1600 -0
- fontTools/varLib/__main__.py +6 -0
- fontTools/varLib/avar/__init__.py +0 -0
- fontTools/varLib/avar/__main__.py +72 -0
- fontTools/varLib/avar/build.py +79 -0
- fontTools/varLib/avar/map.py +108 -0
- fontTools/varLib/avar/plan.py +1004 -0
- fontTools/varLib/avar/unbuild.py +271 -0
- fontTools/varLib/avarPlanner.py +8 -0
- fontTools/varLib/builder.py +215 -0
- fontTools/varLib/cff.py +631 -0
- fontTools/varLib/errors.py +219 -0
- fontTools/varLib/featureVars.py +703 -0
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/instancer/__init__.py +2052 -0
- fontTools/varLib/instancer/__main__.py +5 -0
- fontTools/varLib/instancer/featureVars.py +190 -0
- fontTools/varLib/instancer/names.py +388 -0
- fontTools/varLib/instancer/solver.py +309 -0
- fontTools/varLib/interpolatable.py +1209 -0
- fontTools/varLib/interpolatableHelpers.py +399 -0
- fontTools/varLib/interpolatablePlot.py +1269 -0
- fontTools/varLib/interpolatableTestContourOrder.py +82 -0
- fontTools/varLib/interpolatableTestStartingPoint.py +107 -0
- fontTools/varLib/interpolate_layout.py +124 -0
- fontTools/varLib/iup.c +19815 -0
- fontTools/varLib/iup.cp311-win32.pyd +0 -0
- fontTools/varLib/iup.py +490 -0
- fontTools/varLib/merger.py +1717 -0
- fontTools/varLib/models.py +642 -0
- fontTools/varLib/multiVarStore.py +253 -0
- fontTools/varLib/mutator.py +529 -0
- fontTools/varLib/mvar.py +40 -0
- fontTools/varLib/plot.py +238 -0
- fontTools/varLib/stat.py +149 -0
- fontTools/varLib/varStore.py +739 -0
- fontTools/voltLib/__init__.py +5 -0
- fontTools/voltLib/__main__.py +206 -0
- fontTools/voltLib/ast.py +452 -0
- fontTools/voltLib/error.py +12 -0
- fontTools/voltLib/lexer.py +99 -0
- fontTools/voltLib/parser.py +664 -0
- fontTools/voltLib/voltToFea.py +911 -0
- fonttools-4.60.2.data/data/share/man/man1/ttx.1 +225 -0
- fonttools-4.60.2.dist-info/METADATA +2250 -0
- fonttools-4.60.2.dist-info/RECORD +353 -0
- fonttools-4.60.2.dist-info/WHEEL +5 -0
- fonttools-4.60.2.dist-info/entry_points.txt +5 -0
- fonttools-4.60.2.dist-info/licenses/LICENSE +21 -0
- fonttools-4.60.2.dist-info/licenses/LICENSE.external +388 -0
- fonttools-4.60.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from fontTools.misc import sstruct
|
|
2
|
+
from fontTools.misc.textTools import bytechr, byteord, tobytes, tostr, safeEval
|
|
3
|
+
from . import DefaultTable
|
|
4
|
+
|
|
5
|
+
SINGFormat = """
|
|
6
|
+
> # big endian
|
|
7
|
+
tableVersionMajor: H
|
|
8
|
+
tableVersionMinor: H
|
|
9
|
+
glyphletVersion: H
|
|
10
|
+
permissions: h
|
|
11
|
+
mainGID: H
|
|
12
|
+
unitsPerEm: H
|
|
13
|
+
vertAdvance: h
|
|
14
|
+
vertOrigin: h
|
|
15
|
+
uniqueName: 28s
|
|
16
|
+
METAMD5: 16s
|
|
17
|
+
nameLength: 1s
|
|
18
|
+
"""
|
|
19
|
+
# baseGlyphName is a byte string which follows the record above.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class table_S_I_N_G_(DefaultTable.DefaultTable):
|
|
23
|
+
"""Glyphlets SING table
|
|
24
|
+
|
|
25
|
+
The ``SING`` table is used by Adobe's SING Glyphlets.
|
|
26
|
+
|
|
27
|
+
See also https://web.archive.org/web/20080627183635/http://www.adobe.com/devnet/opentype/gdk/topic.html
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
dependencies = []
|
|
31
|
+
|
|
32
|
+
def decompile(self, data, ttFont):
|
|
33
|
+
dummy, rest = sstruct.unpack2(SINGFormat, data, self)
|
|
34
|
+
self.uniqueName = self.decompileUniqueName(self.uniqueName)
|
|
35
|
+
self.nameLength = byteord(self.nameLength)
|
|
36
|
+
assert len(rest) == self.nameLength
|
|
37
|
+
self.baseGlyphName = tostr(rest)
|
|
38
|
+
|
|
39
|
+
rawMETAMD5 = self.METAMD5
|
|
40
|
+
self.METAMD5 = "[" + hex(byteord(self.METAMD5[0]))
|
|
41
|
+
for char in rawMETAMD5[1:]:
|
|
42
|
+
self.METAMD5 = self.METAMD5 + ", " + hex(byteord(char))
|
|
43
|
+
self.METAMD5 = self.METAMD5 + "]"
|
|
44
|
+
|
|
45
|
+
def decompileUniqueName(self, data):
|
|
46
|
+
name = ""
|
|
47
|
+
for char in data:
|
|
48
|
+
val = byteord(char)
|
|
49
|
+
if val == 0:
|
|
50
|
+
break
|
|
51
|
+
if (val > 31) or (val < 128):
|
|
52
|
+
name += chr(val)
|
|
53
|
+
else:
|
|
54
|
+
octString = oct(val)
|
|
55
|
+
if len(octString) > 3:
|
|
56
|
+
octString = octString[1:] # chop off that leading zero.
|
|
57
|
+
elif len(octString) < 3:
|
|
58
|
+
octString.zfill(3)
|
|
59
|
+
name += "\\" + octString
|
|
60
|
+
return name
|
|
61
|
+
|
|
62
|
+
def compile(self, ttFont):
|
|
63
|
+
d = self.__dict__.copy()
|
|
64
|
+
d["nameLength"] = bytechr(len(self.baseGlyphName))
|
|
65
|
+
d["uniqueName"] = self.compilecompileUniqueName(self.uniqueName, 28)
|
|
66
|
+
METAMD5List = eval(self.METAMD5)
|
|
67
|
+
d["METAMD5"] = b""
|
|
68
|
+
for val in METAMD5List:
|
|
69
|
+
d["METAMD5"] += bytechr(val)
|
|
70
|
+
assert len(d["METAMD5"]) == 16, "Failed to pack 16 byte MD5 hash in SING table"
|
|
71
|
+
data = sstruct.pack(SINGFormat, d)
|
|
72
|
+
data = data + tobytes(self.baseGlyphName)
|
|
73
|
+
return data
|
|
74
|
+
|
|
75
|
+
def compilecompileUniqueName(self, name, length):
|
|
76
|
+
nameLen = len(name)
|
|
77
|
+
if length <= nameLen:
|
|
78
|
+
name = name[: length - 1] + "\000"
|
|
79
|
+
else:
|
|
80
|
+
name += (nameLen - length) * "\000"
|
|
81
|
+
return name
|
|
82
|
+
|
|
83
|
+
def toXML(self, writer, ttFont):
|
|
84
|
+
writer.comment("Most of this table will be recalculated by the compiler")
|
|
85
|
+
writer.newline()
|
|
86
|
+
formatstring, names, fixes = sstruct.getformat(SINGFormat)
|
|
87
|
+
for name in names:
|
|
88
|
+
value = getattr(self, name)
|
|
89
|
+
writer.simpletag(name, value=value)
|
|
90
|
+
writer.newline()
|
|
91
|
+
writer.simpletag("baseGlyphName", value=self.baseGlyphName)
|
|
92
|
+
writer.newline()
|
|
93
|
+
|
|
94
|
+
def fromXML(self, name, attrs, content, ttFont):
|
|
95
|
+
value = attrs["value"]
|
|
96
|
+
if name in ["uniqueName", "METAMD5", "baseGlyphName"]:
|
|
97
|
+
setattr(self, name, value)
|
|
98
|
+
else:
|
|
99
|
+
setattr(self, name, safeEval(value))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .otBase import BaseTTXConverter
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class table_S_T_A_T_(BaseTTXConverter):
|
|
5
|
+
"""Style Attributes table
|
|
6
|
+
|
|
7
|
+
The ``STAT`` table records stylistic or typeface-design attributes that
|
|
8
|
+
differentiate the individual fonts within a font family from one another.
|
|
9
|
+
Those attributes can be used to assist users when navigating the style
|
|
10
|
+
variations of a variable font or a family of static fonts.
|
|
11
|
+
|
|
12
|
+
See also https://learn.microsoft.com/en-us/typography/opentype/spec/stat
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
pass
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Compiles/decompiles SVG table.
|
|
2
|
+
|
|
3
|
+
https://docs.microsoft.com/en-us/typography/opentype/spec/svg
|
|
4
|
+
|
|
5
|
+
The XML format is:
|
|
6
|
+
|
|
7
|
+
.. code-block:: xml
|
|
8
|
+
|
|
9
|
+
<SVG>
|
|
10
|
+
<svgDoc endGlyphID="1" startGlyphID="1">
|
|
11
|
+
<![CDATA[ <complete SVG doc> ]]
|
|
12
|
+
</svgDoc>
|
|
13
|
+
...
|
|
14
|
+
<svgDoc endGlyphID="n" startGlyphID="m">
|
|
15
|
+
<![CDATA[ <complete SVG doc> ]]
|
|
16
|
+
</svgDoc>
|
|
17
|
+
</SVG>
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from fontTools.misc.textTools import bytesjoin, safeEval, strjoin, tobytes, tostr
|
|
21
|
+
from fontTools.misc import sstruct
|
|
22
|
+
from . import DefaultTable
|
|
23
|
+
from collections.abc import Sequence
|
|
24
|
+
from dataclasses import dataclass, astuple
|
|
25
|
+
from io import BytesIO
|
|
26
|
+
import struct
|
|
27
|
+
import logging
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
log = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
SVG_format_0 = """
|
|
34
|
+
> # big endian
|
|
35
|
+
version: H
|
|
36
|
+
offsetToSVGDocIndex: L
|
|
37
|
+
reserved: L
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
SVG_format_0Size = sstruct.calcsize(SVG_format_0)
|
|
41
|
+
|
|
42
|
+
doc_index_entry_format_0 = """
|
|
43
|
+
> # big endian
|
|
44
|
+
startGlyphID: H
|
|
45
|
+
endGlyphID: H
|
|
46
|
+
svgDocOffset: L
|
|
47
|
+
svgDocLength: L
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
doc_index_entry_format_0Size = sstruct.calcsize(doc_index_entry_format_0)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class table_S_V_G_(DefaultTable.DefaultTable):
|
|
54
|
+
"""Scalable Vector Graphics table
|
|
55
|
+
|
|
56
|
+
The ``SVG`` table contains representations for glyphs in the SVG
|
|
57
|
+
image format.
|
|
58
|
+
|
|
59
|
+
See also https://learn.microsoft.com/en-us/typography/opentype/spec/stat
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def decompile(self, data, ttFont):
|
|
63
|
+
self.docList = []
|
|
64
|
+
# Version 0 is the standardized version of the table; and current.
|
|
65
|
+
# https://www.microsoft.com/typography/otspec/svg.htm
|
|
66
|
+
sstruct.unpack(SVG_format_0, data[:SVG_format_0Size], self)
|
|
67
|
+
if self.version != 0:
|
|
68
|
+
log.warning(
|
|
69
|
+
"Unknown SVG table version '%s'. Decompiling as version 0.",
|
|
70
|
+
self.version,
|
|
71
|
+
)
|
|
72
|
+
# read in SVG Documents Index
|
|
73
|
+
# data starts with the first entry of the entry list.
|
|
74
|
+
pos = subTableStart = self.offsetToSVGDocIndex
|
|
75
|
+
self.numEntries = struct.unpack(">H", data[pos : pos + 2])[0]
|
|
76
|
+
pos += 2
|
|
77
|
+
if self.numEntries > 0:
|
|
78
|
+
data2 = data[pos:]
|
|
79
|
+
entries = []
|
|
80
|
+
for i in range(self.numEntries):
|
|
81
|
+
record_data = data2[
|
|
82
|
+
i
|
|
83
|
+
* doc_index_entry_format_0Size : (i + 1)
|
|
84
|
+
* doc_index_entry_format_0Size
|
|
85
|
+
]
|
|
86
|
+
docIndexEntry = sstruct.unpack(
|
|
87
|
+
doc_index_entry_format_0, record_data, DocumentIndexEntry()
|
|
88
|
+
)
|
|
89
|
+
entries.append(docIndexEntry)
|
|
90
|
+
|
|
91
|
+
for entry in entries:
|
|
92
|
+
start = entry.svgDocOffset + subTableStart
|
|
93
|
+
end = start + entry.svgDocLength
|
|
94
|
+
doc = data[start:end]
|
|
95
|
+
compressed = False
|
|
96
|
+
if doc.startswith(b"\x1f\x8b"):
|
|
97
|
+
import gzip
|
|
98
|
+
|
|
99
|
+
bytesIO = BytesIO(doc)
|
|
100
|
+
with gzip.GzipFile(None, "r", fileobj=bytesIO) as gunzipper:
|
|
101
|
+
doc = gunzipper.read()
|
|
102
|
+
del bytesIO
|
|
103
|
+
compressed = True
|
|
104
|
+
doc = tostr(doc, "utf_8")
|
|
105
|
+
self.docList.append(
|
|
106
|
+
SVGDocument(doc, entry.startGlyphID, entry.endGlyphID, compressed)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def compile(self, ttFont):
|
|
110
|
+
version = 0
|
|
111
|
+
offsetToSVGDocIndex = (
|
|
112
|
+
SVG_format_0Size # I start the SVGDocIndex right after the header.
|
|
113
|
+
)
|
|
114
|
+
# get SGVDoc info.
|
|
115
|
+
docList = []
|
|
116
|
+
entryList = []
|
|
117
|
+
numEntries = len(self.docList)
|
|
118
|
+
datum = struct.pack(">H", numEntries)
|
|
119
|
+
entryList.append(datum)
|
|
120
|
+
curOffset = len(datum) + doc_index_entry_format_0Size * numEntries
|
|
121
|
+
seenDocs = {}
|
|
122
|
+
allCompressed = getattr(self, "compressed", False)
|
|
123
|
+
for i, doc in enumerate(self.docList):
|
|
124
|
+
if isinstance(doc, (list, tuple)):
|
|
125
|
+
doc = SVGDocument(*doc)
|
|
126
|
+
self.docList[i] = doc
|
|
127
|
+
docBytes = tobytes(doc.data, encoding="utf_8")
|
|
128
|
+
if (allCompressed or doc.compressed) and not docBytes.startswith(
|
|
129
|
+
b"\x1f\x8b"
|
|
130
|
+
):
|
|
131
|
+
import gzip
|
|
132
|
+
|
|
133
|
+
bytesIO = BytesIO()
|
|
134
|
+
# mtime=0 strips the useless timestamp and makes gzip output reproducible;
|
|
135
|
+
# equivalent to `gzip -n`
|
|
136
|
+
with gzip.GzipFile(None, "w", fileobj=bytesIO, mtime=0) as gzipper:
|
|
137
|
+
gzipper.write(docBytes)
|
|
138
|
+
gzipped = bytesIO.getvalue()
|
|
139
|
+
if len(gzipped) < len(docBytes):
|
|
140
|
+
docBytes = gzipped
|
|
141
|
+
del gzipped, bytesIO
|
|
142
|
+
docLength = len(docBytes)
|
|
143
|
+
if docBytes in seenDocs:
|
|
144
|
+
docOffset = seenDocs[docBytes]
|
|
145
|
+
else:
|
|
146
|
+
docOffset = curOffset
|
|
147
|
+
curOffset += docLength
|
|
148
|
+
seenDocs[docBytes] = docOffset
|
|
149
|
+
docList.append(docBytes)
|
|
150
|
+
entry = struct.pack(
|
|
151
|
+
">HHLL", doc.startGlyphID, doc.endGlyphID, docOffset, docLength
|
|
152
|
+
)
|
|
153
|
+
entryList.append(entry)
|
|
154
|
+
entryList.extend(docList)
|
|
155
|
+
svgDocData = bytesjoin(entryList)
|
|
156
|
+
|
|
157
|
+
reserved = 0
|
|
158
|
+
header = struct.pack(">HLL", version, offsetToSVGDocIndex, reserved)
|
|
159
|
+
data = [header, svgDocData]
|
|
160
|
+
data = bytesjoin(data)
|
|
161
|
+
return data
|
|
162
|
+
|
|
163
|
+
def toXML(self, writer, ttFont):
|
|
164
|
+
for i, doc in enumerate(self.docList):
|
|
165
|
+
if isinstance(doc, (list, tuple)):
|
|
166
|
+
doc = SVGDocument(*doc)
|
|
167
|
+
self.docList[i] = doc
|
|
168
|
+
attrs = {"startGlyphID": doc.startGlyphID, "endGlyphID": doc.endGlyphID}
|
|
169
|
+
if doc.compressed:
|
|
170
|
+
attrs["compressed"] = 1
|
|
171
|
+
writer.begintag("svgDoc", **attrs)
|
|
172
|
+
writer.newline()
|
|
173
|
+
writer.writecdata(doc.data)
|
|
174
|
+
writer.newline()
|
|
175
|
+
writer.endtag("svgDoc")
|
|
176
|
+
writer.newline()
|
|
177
|
+
|
|
178
|
+
def fromXML(self, name, attrs, content, ttFont):
|
|
179
|
+
if name == "svgDoc":
|
|
180
|
+
if not hasattr(self, "docList"):
|
|
181
|
+
self.docList = []
|
|
182
|
+
doc = strjoin(content)
|
|
183
|
+
doc = doc.strip()
|
|
184
|
+
startGID = int(attrs["startGlyphID"])
|
|
185
|
+
endGID = int(attrs["endGlyphID"])
|
|
186
|
+
compressed = bool(safeEval(attrs.get("compressed", "0")))
|
|
187
|
+
self.docList.append(SVGDocument(doc, startGID, endGID, compressed))
|
|
188
|
+
else:
|
|
189
|
+
log.warning("Unknown %s %s", name, content)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class DocumentIndexEntry(object):
|
|
193
|
+
def __init__(self):
|
|
194
|
+
self.startGlyphID = None # USHORT
|
|
195
|
+
self.endGlyphID = None # USHORT
|
|
196
|
+
self.svgDocOffset = None # ULONG
|
|
197
|
+
self.svgDocLength = None # ULONG
|
|
198
|
+
|
|
199
|
+
def __repr__(self):
|
|
200
|
+
return (
|
|
201
|
+
"startGlyphID: %s, endGlyphID: %s, svgDocOffset: %s, svgDocLength: %s"
|
|
202
|
+
% (self.startGlyphID, self.endGlyphID, self.svgDocOffset, self.svgDocLength)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@dataclass
|
|
207
|
+
class SVGDocument(Sequence):
|
|
208
|
+
data: str
|
|
209
|
+
startGlyphID: int
|
|
210
|
+
endGlyphID: int
|
|
211
|
+
compressed: bool = False
|
|
212
|
+
|
|
213
|
+
# Previously, the SVG table's docList attribute contained a lists of 3 items:
|
|
214
|
+
# [doc, startGlyphID, endGlyphID]; later, we added a `compressed` attribute.
|
|
215
|
+
# For backward compatibility with code that depends of them being sequences of
|
|
216
|
+
# fixed length=3, we subclass the Sequence abstract base class and pretend only
|
|
217
|
+
# the first three items are present. 'compressed' is only accessible via named
|
|
218
|
+
# attribute lookup like regular dataclasses: i.e. `doc.compressed`, not `doc[3]`
|
|
219
|
+
def __getitem__(self, index):
|
|
220
|
+
return astuple(self)[:3][index]
|
|
221
|
+
|
|
222
|
+
def __len__(self):
|
|
223
|
+
return 3
|