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,352 @@
|
|
|
1
|
+
# Copyright 2013 Google, Inc. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Google Author(s): Behdad Esfahbod, Roozbeh Pournader
|
|
4
|
+
|
|
5
|
+
from fontTools import ttLib, cffLib
|
|
6
|
+
from fontTools.misc.psCharStrings import T2WidthExtractor
|
|
7
|
+
from fontTools.ttLib.tables.DefaultTable import DefaultTable
|
|
8
|
+
from fontTools.merge.base import add_method, mergeObjects
|
|
9
|
+
from fontTools.merge.cmap import computeMegaCmap
|
|
10
|
+
from fontTools.merge.util import *
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
log = logging.getLogger("fontTools.merge")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
ttLib.getTableClass("maxp").mergeMap = {
|
|
18
|
+
"*": max,
|
|
19
|
+
"tableTag": equal,
|
|
20
|
+
"tableVersion": equal,
|
|
21
|
+
"numGlyphs": sum,
|
|
22
|
+
"maxStorage": first,
|
|
23
|
+
"maxFunctionDefs": first,
|
|
24
|
+
"maxInstructionDefs": first,
|
|
25
|
+
# TODO When we correctly merge hinting data, update these values:
|
|
26
|
+
# maxFunctionDefs, maxInstructionDefs, maxSizeOfInstructions
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
headFlagsMergeBitMap = {
|
|
30
|
+
"size": 16,
|
|
31
|
+
"*": bitwise_or,
|
|
32
|
+
1: bitwise_and, # Baseline at y = 0
|
|
33
|
+
2: bitwise_and, # lsb at x = 0
|
|
34
|
+
3: bitwise_and, # Force ppem to integer values. FIXME?
|
|
35
|
+
5: bitwise_and, # Font is vertical
|
|
36
|
+
6: lambda bit: 0, # Always set to zero
|
|
37
|
+
11: bitwise_and, # Font data is 'lossless'
|
|
38
|
+
13: bitwise_and, # Optimized for ClearType
|
|
39
|
+
14: bitwise_and, # Last resort font. FIXME? equal or first may be better
|
|
40
|
+
15: lambda bit: 0, # Always set to zero
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
ttLib.getTableClass("head").mergeMap = {
|
|
44
|
+
"tableTag": equal,
|
|
45
|
+
"tableVersion": max,
|
|
46
|
+
"fontRevision": max,
|
|
47
|
+
"checkSumAdjustment": lambda lst: 0, # We need *something* here
|
|
48
|
+
"magicNumber": equal,
|
|
49
|
+
"flags": mergeBits(headFlagsMergeBitMap),
|
|
50
|
+
"unitsPerEm": equal,
|
|
51
|
+
"created": current_time,
|
|
52
|
+
"modified": current_time,
|
|
53
|
+
"xMin": min,
|
|
54
|
+
"yMin": min,
|
|
55
|
+
"xMax": max,
|
|
56
|
+
"yMax": max,
|
|
57
|
+
"macStyle": first,
|
|
58
|
+
"lowestRecPPEM": max,
|
|
59
|
+
"fontDirectionHint": lambda lst: 2,
|
|
60
|
+
"indexToLocFormat": first,
|
|
61
|
+
"glyphDataFormat": equal,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
ttLib.getTableClass("hhea").mergeMap = {
|
|
65
|
+
"*": equal,
|
|
66
|
+
"tableTag": equal,
|
|
67
|
+
"tableVersion": max,
|
|
68
|
+
"ascent": max,
|
|
69
|
+
"descent": min,
|
|
70
|
+
"lineGap": max,
|
|
71
|
+
"advanceWidthMax": max,
|
|
72
|
+
"minLeftSideBearing": min,
|
|
73
|
+
"minRightSideBearing": min,
|
|
74
|
+
"xMaxExtent": max,
|
|
75
|
+
"caretSlopeRise": first,
|
|
76
|
+
"caretSlopeRun": first,
|
|
77
|
+
"caretOffset": first,
|
|
78
|
+
"numberOfHMetrics": recalculate,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ttLib.getTableClass("vhea").mergeMap = {
|
|
82
|
+
"*": equal,
|
|
83
|
+
"tableTag": equal,
|
|
84
|
+
"tableVersion": max,
|
|
85
|
+
"ascent": max,
|
|
86
|
+
"descent": min,
|
|
87
|
+
"lineGap": max,
|
|
88
|
+
"advanceHeightMax": max,
|
|
89
|
+
"minTopSideBearing": min,
|
|
90
|
+
"minBottomSideBearing": min,
|
|
91
|
+
"yMaxExtent": max,
|
|
92
|
+
"caretSlopeRise": first,
|
|
93
|
+
"caretSlopeRun": first,
|
|
94
|
+
"caretOffset": first,
|
|
95
|
+
"numberOfVMetrics": recalculate,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
os2FsTypeMergeBitMap = {
|
|
99
|
+
"size": 16,
|
|
100
|
+
"*": lambda bit: 0,
|
|
101
|
+
1: bitwise_or, # no embedding permitted
|
|
102
|
+
2: bitwise_and, # allow previewing and printing documents
|
|
103
|
+
3: bitwise_and, # allow editing documents
|
|
104
|
+
8: bitwise_or, # no subsetting permitted
|
|
105
|
+
9: bitwise_or, # no embedding of outlines permitted
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def mergeOs2FsType(lst):
|
|
110
|
+
lst = list(lst)
|
|
111
|
+
if all(item == 0 for item in lst):
|
|
112
|
+
return 0
|
|
113
|
+
|
|
114
|
+
# Compute least restrictive logic for each fsType value
|
|
115
|
+
for i in range(len(lst)):
|
|
116
|
+
# unset bit 1 (no embedding permitted) if either bit 2 or 3 is set
|
|
117
|
+
if lst[i] & 0x000C:
|
|
118
|
+
lst[i] &= ~0x0002
|
|
119
|
+
# set bit 2 (allow previewing) if bit 3 is set (allow editing)
|
|
120
|
+
elif lst[i] & 0x0008:
|
|
121
|
+
lst[i] |= 0x0004
|
|
122
|
+
# set bits 2 and 3 if everything is allowed
|
|
123
|
+
elif lst[i] == 0:
|
|
124
|
+
lst[i] = 0x000C
|
|
125
|
+
|
|
126
|
+
fsType = mergeBits(os2FsTypeMergeBitMap)(lst)
|
|
127
|
+
# unset bits 2 and 3 if bit 1 is set (some font is "no embedding")
|
|
128
|
+
if fsType & 0x0002:
|
|
129
|
+
fsType &= ~0x000C
|
|
130
|
+
return fsType
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
ttLib.getTableClass("OS/2").mergeMap = {
|
|
134
|
+
"*": first,
|
|
135
|
+
"tableTag": equal,
|
|
136
|
+
"version": max,
|
|
137
|
+
"xAvgCharWidth": first, # Will be recalculated at the end on the merged font
|
|
138
|
+
"fsType": mergeOs2FsType, # Will be overwritten
|
|
139
|
+
"panose": first, # FIXME: should really be the first Latin font
|
|
140
|
+
"ulUnicodeRange1": bitwise_or,
|
|
141
|
+
"ulUnicodeRange2": bitwise_or,
|
|
142
|
+
"ulUnicodeRange3": bitwise_or,
|
|
143
|
+
"ulUnicodeRange4": bitwise_or,
|
|
144
|
+
"fsFirstCharIndex": min,
|
|
145
|
+
"fsLastCharIndex": max,
|
|
146
|
+
"sTypoAscender": max,
|
|
147
|
+
"sTypoDescender": min,
|
|
148
|
+
"sTypoLineGap": max,
|
|
149
|
+
"usWinAscent": max,
|
|
150
|
+
"usWinDescent": max,
|
|
151
|
+
# Version 1
|
|
152
|
+
"ulCodePageRange1": onlyExisting(bitwise_or),
|
|
153
|
+
"ulCodePageRange2": onlyExisting(bitwise_or),
|
|
154
|
+
# Version 2, 3, 4
|
|
155
|
+
"sxHeight": onlyExisting(max),
|
|
156
|
+
"sCapHeight": onlyExisting(max),
|
|
157
|
+
"usDefaultChar": onlyExisting(first),
|
|
158
|
+
"usBreakChar": onlyExisting(first),
|
|
159
|
+
"usMaxContext": onlyExisting(max),
|
|
160
|
+
# version 5
|
|
161
|
+
"usLowerOpticalPointSize": onlyExisting(min),
|
|
162
|
+
"usUpperOpticalPointSize": onlyExisting(max),
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@add_method(ttLib.getTableClass("OS/2"))
|
|
167
|
+
def merge(self, m, tables):
|
|
168
|
+
DefaultTable.merge(self, m, tables)
|
|
169
|
+
if self.version < 2:
|
|
170
|
+
# bits 8 and 9 are reserved and should be set to zero
|
|
171
|
+
self.fsType &= ~0x0300
|
|
172
|
+
if self.version >= 3:
|
|
173
|
+
# Only one of bits 1, 2, and 3 may be set. We already take
|
|
174
|
+
# care of bit 1 implications in mergeOs2FsType. So unset
|
|
175
|
+
# bit 2 if bit 3 is already set.
|
|
176
|
+
if self.fsType & 0x0008:
|
|
177
|
+
self.fsType &= ~0x0004
|
|
178
|
+
return self
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
ttLib.getTableClass("post").mergeMap = {
|
|
182
|
+
"*": first,
|
|
183
|
+
"tableTag": equal,
|
|
184
|
+
"formatType": max,
|
|
185
|
+
"isFixedPitch": min,
|
|
186
|
+
"minMemType42": max,
|
|
187
|
+
"maxMemType42": lambda lst: 0,
|
|
188
|
+
"minMemType1": max,
|
|
189
|
+
"maxMemType1": lambda lst: 0,
|
|
190
|
+
"mapping": onlyExisting(sumDicts),
|
|
191
|
+
"extraNames": lambda lst: [],
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
ttLib.getTableClass("vmtx").mergeMap = ttLib.getTableClass("hmtx").mergeMap = {
|
|
195
|
+
"tableTag": equal,
|
|
196
|
+
"metrics": sumDicts,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
ttLib.getTableClass("name").mergeMap = {
|
|
200
|
+
"tableTag": equal,
|
|
201
|
+
"names": first, # FIXME? Does mixing name records make sense?
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
ttLib.getTableClass("loca").mergeMap = {
|
|
205
|
+
"*": recalculate,
|
|
206
|
+
"tableTag": equal,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
ttLib.getTableClass("glyf").mergeMap = {
|
|
210
|
+
"tableTag": equal,
|
|
211
|
+
"glyphs": sumDicts,
|
|
212
|
+
"glyphOrder": sumLists,
|
|
213
|
+
"_reverseGlyphOrder": recalculate,
|
|
214
|
+
"axisTags": equal,
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@add_method(ttLib.getTableClass("glyf"))
|
|
219
|
+
def merge(self, m, tables):
|
|
220
|
+
for i, table in enumerate(tables):
|
|
221
|
+
for g in table.glyphs.values():
|
|
222
|
+
if i:
|
|
223
|
+
# Drop hints for all but first font, since
|
|
224
|
+
# we don't map functions / CVT values.
|
|
225
|
+
g.removeHinting()
|
|
226
|
+
# Expand composite glyphs to load their
|
|
227
|
+
# composite glyph names.
|
|
228
|
+
if g.isComposite():
|
|
229
|
+
g.expand(table)
|
|
230
|
+
return DefaultTable.merge(self, m, tables)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
ttLib.getTableClass("prep").mergeMap = lambda self, lst: first(lst)
|
|
234
|
+
ttLib.getTableClass("fpgm").mergeMap = lambda self, lst: first(lst)
|
|
235
|
+
ttLib.getTableClass("cvt ").mergeMap = lambda self, lst: first(lst)
|
|
236
|
+
ttLib.getTableClass("gasp").mergeMap = lambda self, lst: first(
|
|
237
|
+
lst
|
|
238
|
+
) # FIXME? Appears irreconcilable
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@add_method(ttLib.getTableClass("CFF "))
|
|
242
|
+
def merge(self, m, tables):
|
|
243
|
+
if any(hasattr(table.cff[0], "FDSelect") for table in tables):
|
|
244
|
+
raise NotImplementedError("Merging CID-keyed CFF tables is not supported yet")
|
|
245
|
+
|
|
246
|
+
for table in tables:
|
|
247
|
+
table.cff.desubroutinize()
|
|
248
|
+
|
|
249
|
+
newcff = tables[0]
|
|
250
|
+
newfont = newcff.cff[0]
|
|
251
|
+
private = newfont.Private
|
|
252
|
+
newDefaultWidthX, newNominalWidthX = private.defaultWidthX, private.nominalWidthX
|
|
253
|
+
storedNamesStrings = []
|
|
254
|
+
glyphOrderStrings = []
|
|
255
|
+
glyphOrder = set(newfont.getGlyphOrder())
|
|
256
|
+
|
|
257
|
+
for name in newfont.strings.strings:
|
|
258
|
+
if name not in glyphOrder:
|
|
259
|
+
storedNamesStrings.append(name)
|
|
260
|
+
else:
|
|
261
|
+
glyphOrderStrings.append(name)
|
|
262
|
+
|
|
263
|
+
chrset = list(newfont.charset)
|
|
264
|
+
newcs = newfont.CharStrings
|
|
265
|
+
log.debug("FONT 0 CharStrings: %d.", len(newcs))
|
|
266
|
+
|
|
267
|
+
for i, table in enumerate(tables[1:], start=1):
|
|
268
|
+
font = table.cff[0]
|
|
269
|
+
defaultWidthX, nominalWidthX = (
|
|
270
|
+
font.Private.defaultWidthX,
|
|
271
|
+
font.Private.nominalWidthX,
|
|
272
|
+
)
|
|
273
|
+
widthsDiffer = (
|
|
274
|
+
defaultWidthX != newDefaultWidthX or nominalWidthX != newNominalWidthX
|
|
275
|
+
)
|
|
276
|
+
font.Private = private
|
|
277
|
+
fontGlyphOrder = set(font.getGlyphOrder())
|
|
278
|
+
for name in font.strings.strings:
|
|
279
|
+
if name in fontGlyphOrder:
|
|
280
|
+
glyphOrderStrings.append(name)
|
|
281
|
+
cs = font.CharStrings
|
|
282
|
+
gs = table.cff.GlobalSubrs
|
|
283
|
+
log.debug("Font %d CharStrings: %d.", i, len(cs))
|
|
284
|
+
chrset.extend(font.charset)
|
|
285
|
+
if newcs.charStringsAreIndexed:
|
|
286
|
+
for i, name in enumerate(cs.charStrings, start=len(newcs)):
|
|
287
|
+
newcs.charStrings[name] = i
|
|
288
|
+
newcs.charStringsIndex.items.append(None)
|
|
289
|
+
for name in cs.charStrings:
|
|
290
|
+
if widthsDiffer:
|
|
291
|
+
c = cs[name]
|
|
292
|
+
defaultWidthXToken = object()
|
|
293
|
+
extractor = T2WidthExtractor([], [], nominalWidthX, defaultWidthXToken)
|
|
294
|
+
extractor.execute(c)
|
|
295
|
+
width = extractor.width
|
|
296
|
+
if width is not defaultWidthXToken:
|
|
297
|
+
# The following will be wrong if the width is added
|
|
298
|
+
# by a subroutine. Ouch!
|
|
299
|
+
c.program.pop(0)
|
|
300
|
+
else:
|
|
301
|
+
width = defaultWidthX
|
|
302
|
+
if width != newDefaultWidthX:
|
|
303
|
+
c.program.insert(0, width - newNominalWidthX)
|
|
304
|
+
newcs[name] = cs[name]
|
|
305
|
+
|
|
306
|
+
newfont.charset = chrset
|
|
307
|
+
newfont.numGlyphs = len(chrset)
|
|
308
|
+
newfont.strings.strings = glyphOrderStrings + storedNamesStrings
|
|
309
|
+
|
|
310
|
+
return newcff
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@add_method(ttLib.getTableClass("cmap"))
|
|
314
|
+
def merge(self, m, tables):
|
|
315
|
+
if not hasattr(m, "cmap"):
|
|
316
|
+
computeMegaCmap(m, tables)
|
|
317
|
+
cmap = m.cmap
|
|
318
|
+
|
|
319
|
+
cmapBmpOnly = {uni: gid for uni, gid in cmap.items() if uni <= 0xFFFF}
|
|
320
|
+
self.tables = []
|
|
321
|
+
module = ttLib.getTableModule("cmap")
|
|
322
|
+
if len(cmapBmpOnly) != len(cmap):
|
|
323
|
+
# format-12 required.
|
|
324
|
+
cmapTable = module.cmap_classes[12](12)
|
|
325
|
+
cmapTable.platformID = 3
|
|
326
|
+
cmapTable.platEncID = 10
|
|
327
|
+
cmapTable.language = 0
|
|
328
|
+
cmapTable.cmap = cmap
|
|
329
|
+
self.tables.append(cmapTable)
|
|
330
|
+
# always create format-4
|
|
331
|
+
cmapTable = module.cmap_classes[4](4)
|
|
332
|
+
cmapTable.platformID = 3
|
|
333
|
+
cmapTable.platEncID = 1
|
|
334
|
+
cmapTable.language = 0
|
|
335
|
+
cmapTable.cmap = cmapBmpOnly
|
|
336
|
+
# ordered by platform then encoding
|
|
337
|
+
self.tables.insert(0, cmapTable)
|
|
338
|
+
|
|
339
|
+
uvsDict = m.uvsDict
|
|
340
|
+
if uvsDict:
|
|
341
|
+
# format-14
|
|
342
|
+
uvsTable = module.cmap_classes[14](14)
|
|
343
|
+
uvsTable.platformID = 0
|
|
344
|
+
uvsTable.platEncID = 5
|
|
345
|
+
uvsTable.language = 0
|
|
346
|
+
uvsTable.cmap = {}
|
|
347
|
+
uvsTable.uvsDict = uvsDict
|
|
348
|
+
# ordered by platform then encoding
|
|
349
|
+
self.tables.insert(0, uvsTable)
|
|
350
|
+
self.tableVersion = 0
|
|
351
|
+
self.numSubTables = len(self.tables)
|
|
352
|
+
return self
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Copyright 2021 Behdad Esfahbod. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def is_Default_Ignorable(u):
|
|
5
|
+
# http://www.unicode.org/reports/tr44/#Default_Ignorable_Code_Point
|
|
6
|
+
#
|
|
7
|
+
# TODO Move me to unicodedata module and autogenerate.
|
|
8
|
+
#
|
|
9
|
+
# Unicode 14.0:
|
|
10
|
+
# $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
|
|
11
|
+
# 00AD # Cf SOFT HYPHEN
|
|
12
|
+
# 034F # Mn COMBINING GRAPHEME JOINER
|
|
13
|
+
# 061C # Cf ARABIC LETTER MARK
|
|
14
|
+
# 115F..1160 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
|
|
15
|
+
# 17B4..17B5 # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
|
|
16
|
+
# 180B..180D # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
|
|
17
|
+
# 180E # Cf MONGOLIAN VOWEL SEPARATOR
|
|
18
|
+
# 180F # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
|
|
19
|
+
# 200B..200F # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
|
|
20
|
+
# 202A..202E # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
|
|
21
|
+
# 2060..2064 # Cf [5] WORD JOINER..INVISIBLE PLUS
|
|
22
|
+
# 2065 # Cn <reserved-2065>
|
|
23
|
+
# 2066..206F # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
|
|
24
|
+
# 3164 # Lo HANGUL FILLER
|
|
25
|
+
# FE00..FE0F # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
|
|
26
|
+
# FEFF # Cf ZERO WIDTH NO-BREAK SPACE
|
|
27
|
+
# FFA0 # Lo HALFWIDTH HANGUL FILLER
|
|
28
|
+
# FFF0..FFF8 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
|
|
29
|
+
# 1BCA0..1BCA3 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
|
|
30
|
+
# 1D173..1D17A # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
|
|
31
|
+
# E0000 # Cn <reserved-E0000>
|
|
32
|
+
# E0001 # Cf LANGUAGE TAG
|
|
33
|
+
# E0002..E001F # Cn [30] <reserved-E0002>..<reserved-E001F>
|
|
34
|
+
# E0020..E007F # Cf [96] TAG SPACE..CANCEL TAG
|
|
35
|
+
# E0080..E00FF # Cn [128] <reserved-E0080>..<reserved-E00FF>
|
|
36
|
+
# E0100..E01EF # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
|
|
37
|
+
# E01F0..E0FFF # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
|
|
38
|
+
return (
|
|
39
|
+
u == 0x00AD
|
|
40
|
+
or u == 0x034F # Cf SOFT HYPHEN
|
|
41
|
+
or u == 0x061C # Mn COMBINING GRAPHEME JOINER
|
|
42
|
+
or 0x115F <= u <= 0x1160 # Cf ARABIC LETTER MARK
|
|
43
|
+
or 0x17B4 # Lo [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
|
|
44
|
+
<= u
|
|
45
|
+
<= 0x17B5
|
|
46
|
+
or 0x180B # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
|
|
47
|
+
<= u
|
|
48
|
+
<= 0x180D
|
|
49
|
+
or u # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
|
|
50
|
+
== 0x180E
|
|
51
|
+
or u == 0x180F # Cf MONGOLIAN VOWEL SEPARATOR
|
|
52
|
+
or 0x200B <= u <= 0x200F # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
|
|
53
|
+
or 0x202A <= u <= 0x202E # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
|
|
54
|
+
or 0x2060 # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
|
|
55
|
+
<= u
|
|
56
|
+
<= 0x2064
|
|
57
|
+
or u == 0x2065 # Cf [5] WORD JOINER..INVISIBLE PLUS
|
|
58
|
+
or 0x2066 <= u <= 0x206F # Cn <reserved-2065>
|
|
59
|
+
or u == 0x3164 # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
|
|
60
|
+
or 0xFE00 <= u <= 0xFE0F # Lo HANGUL FILLER
|
|
61
|
+
or u == 0xFEFF # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
|
|
62
|
+
or u == 0xFFA0 # Cf ZERO WIDTH NO-BREAK SPACE
|
|
63
|
+
or 0xFFF0 <= u <= 0xFFF8 # Lo HALFWIDTH HANGUL FILLER
|
|
64
|
+
or 0x1BCA0 <= u <= 0x1BCA3 # Cn [9] <reserved-FFF0>..<reserved-FFF8>
|
|
65
|
+
or 0x1D173 # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
|
|
66
|
+
<= u
|
|
67
|
+
<= 0x1D17A
|
|
68
|
+
or u == 0xE0000 # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
|
|
69
|
+
or u == 0xE0001 # Cn <reserved-E0000>
|
|
70
|
+
or 0xE0002 <= u <= 0xE001F # Cf LANGUAGE TAG
|
|
71
|
+
or 0xE0020 <= u <= 0xE007F # Cn [30] <reserved-E0002>..<reserved-E001F>
|
|
72
|
+
or 0xE0080 <= u <= 0xE00FF # Cf [96] TAG SPACE..CANCEL TAG
|
|
73
|
+
or 0xE0100 <= u <= 0xE01EF # Cn [128] <reserved-E0080>..<reserved-E00FF>
|
|
74
|
+
or 0xE01F0 # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
|
|
75
|
+
<= u
|
|
76
|
+
<= 0xE0FFF
|
|
77
|
+
or False # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
|
|
78
|
+
)
|
fontTools/merge/util.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Copyright 2013 Google, Inc. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Google Author(s): Behdad Esfahbod, Roozbeh Pournader
|
|
4
|
+
|
|
5
|
+
from fontTools.misc.timeTools import timestampNow
|
|
6
|
+
from fontTools.ttLib.tables.DefaultTable import DefaultTable
|
|
7
|
+
from functools import reduce
|
|
8
|
+
import operator
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
log = logging.getLogger("fontTools.merge")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# General utility functions for merging values from different fonts
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def equal(lst):
|
|
19
|
+
lst = list(lst)
|
|
20
|
+
t = iter(lst)
|
|
21
|
+
first = next(t)
|
|
22
|
+
assert all(item == first for item in t), "Expected all items to be equal: %s" % lst
|
|
23
|
+
return first
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def first(lst):
|
|
27
|
+
return next(iter(lst))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def recalculate(lst):
|
|
31
|
+
return NotImplemented
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def current_time(lst):
|
|
35
|
+
return timestampNow()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def bitwise_and(lst):
|
|
39
|
+
return reduce(operator.and_, lst)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def bitwise_or(lst):
|
|
43
|
+
return reduce(operator.or_, lst)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def avg_int(lst):
|
|
47
|
+
lst = list(lst)
|
|
48
|
+
return sum(lst) // len(lst)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def onlyExisting(func):
|
|
52
|
+
"""Returns a filter func that when called with a list,
|
|
53
|
+
only calls func on the non-NotImplemented items of the list,
|
|
54
|
+
and only so if there's at least one item remaining.
|
|
55
|
+
Otherwise returns NotImplemented."""
|
|
56
|
+
|
|
57
|
+
def wrapper(lst):
|
|
58
|
+
items = [item for item in lst if item is not NotImplemented]
|
|
59
|
+
return func(items) if items else NotImplemented
|
|
60
|
+
|
|
61
|
+
return wrapper
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def sumLists(lst):
|
|
65
|
+
l = []
|
|
66
|
+
for item in lst:
|
|
67
|
+
l.extend(item)
|
|
68
|
+
return l
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def sumDicts(lst):
|
|
72
|
+
d = {}
|
|
73
|
+
for item in lst:
|
|
74
|
+
d.update(item)
|
|
75
|
+
return d
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def mergeBits(bitmap):
|
|
79
|
+
def wrapper(lst):
|
|
80
|
+
lst = list(lst)
|
|
81
|
+
returnValue = 0
|
|
82
|
+
for bitNumber in range(bitmap["size"]):
|
|
83
|
+
try:
|
|
84
|
+
mergeLogic = bitmap[bitNumber]
|
|
85
|
+
except KeyError:
|
|
86
|
+
try:
|
|
87
|
+
mergeLogic = bitmap["*"]
|
|
88
|
+
except KeyError:
|
|
89
|
+
raise Exception("Don't know how to merge bit %s" % bitNumber)
|
|
90
|
+
shiftedBit = 1 << bitNumber
|
|
91
|
+
mergedValue = mergeLogic(bool(item & shiftedBit) for item in lst)
|
|
92
|
+
returnValue |= mergedValue << bitNumber
|
|
93
|
+
return returnValue
|
|
94
|
+
|
|
95
|
+
return wrapper
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class AttendanceRecordingIdentityDict(object):
|
|
99
|
+
"""A dictionary-like object that records indices of items actually accessed
|
|
100
|
+
from a list."""
|
|
101
|
+
|
|
102
|
+
def __init__(self, lst):
|
|
103
|
+
self.l = lst
|
|
104
|
+
self.d = {id(v): i for i, v in enumerate(lst)}
|
|
105
|
+
self.s = set()
|
|
106
|
+
|
|
107
|
+
def __getitem__(self, v):
|
|
108
|
+
self.s.add(self.d[id(v)])
|
|
109
|
+
return v
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class GregariousIdentityDict(object):
|
|
113
|
+
"""A dictionary-like object that welcomes guests without reservations and
|
|
114
|
+
adds them to the end of the guest list."""
|
|
115
|
+
|
|
116
|
+
def __init__(self, lst):
|
|
117
|
+
self.l = lst
|
|
118
|
+
self.s = set(id(v) for v in lst)
|
|
119
|
+
|
|
120
|
+
def __getitem__(self, v):
|
|
121
|
+
if id(v) not in self.s:
|
|
122
|
+
self.s.add(id(v))
|
|
123
|
+
self.l.append(v)
|
|
124
|
+
return v
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class NonhashableDict(object):
|
|
128
|
+
"""A dictionary-like object mapping objects to values."""
|
|
129
|
+
|
|
130
|
+
def __init__(self, keys, values=None):
|
|
131
|
+
if values is None:
|
|
132
|
+
self.d = {id(v): i for i, v in enumerate(keys)}
|
|
133
|
+
else:
|
|
134
|
+
self.d = {id(k): v for k, v in zip(keys, values)}
|
|
135
|
+
|
|
136
|
+
def __getitem__(self, k):
|
|
137
|
+
return self.d[id(k)]
|
|
138
|
+
|
|
139
|
+
def __setitem__(self, k, v):
|
|
140
|
+
self.d[id(k)] = v
|
|
141
|
+
|
|
142
|
+
def __delitem__(self, k):
|
|
143
|
+
del self.d[id(k)]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Empty __init__.py file to signal Python this directory is a package."""
|