Merge pull request #2068 from fonttools/remove-overlaps-snippet

add module to remove overlaps from TTF with skia-pathops
This commit is contained in:
Cosimo Lupo 2020-09-30 16:01:26 +01:00 committed by GitHub
commit bec25751c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1755 additions and 20 deletions

View File

@ -27,4 +27,4 @@ if [ "$TRAVIS_OS_NAME" == "osx" ]; then
source .venv/bin/activate
fi
python -m pip install $ci_requirements
python -m pip install --upgrade $ci_requirements

View File

@ -0,0 +1,192 @@
""" Simplify TrueType glyphs by merging overlapping contours/components.
Requires https://github.com/fonttools/skia-pathops
"""
import itertools
import logging
from typing import Iterable, Optional, Mapping
from fontTools.ttLib import ttFont
from fontTools.ttLib.tables import _g_l_y_f
from fontTools.ttLib.tables import _h_m_t_x
from fontTools.pens.ttGlyphPen import TTGlyphPen
import pathops
__all__ = ["removeOverlaps"]
log = logging.getLogger("fontTools.ttLib.removeOverlaps")
_TTGlyphMapping = Mapping[str, ttFont._TTGlyph]
def skPathFromGlyph(glyphName: str, glyphSet: _TTGlyphMapping) -> pathops.Path:
path = pathops.Path()
pathPen = path.getPen(glyphSet=glyphSet)
glyphSet[glyphName].draw(pathPen)
return path
def skPathFromGlyphComponent(
component: _g_l_y_f.GlyphComponent, glyphSet: _TTGlyphMapping
):
baseGlyphName, transformation = component.getComponentInfo()
path = skPathFromGlyph(baseGlyphName, glyphSet)
return path.transform(*transformation)
def componentsOverlap(glyph: _g_l_y_f.Glyph, glyphSet: _TTGlyphMapping) -> bool:
if not glyph.isComposite():
raise ValueError("This method only works with TrueType composite glyphs")
if len(glyph.components) < 2:
return False # single component, no overlaps
component_paths = {}
def _get_nth_component_path(index: int) -> pathops.Path:
if index not in component_paths:
component_paths[index] = skPathFromGlyphComponent(
glyph.components[index], glyphSet
)
return component_paths[index]
return any(
pathops.op(
_get_nth_component_path(i),
_get_nth_component_path(j),
pathops.PathOp.INTERSECTION,
fix_winding=False,
keep_starting_points=False,
)
for i, j in itertools.combinations(range(len(glyph.components)), 2)
)
def ttfGlyphFromSkPath(path: pathops.Path) -> _g_l_y_f.Glyph:
# Skia paths have no 'components', no need for glyphSet
ttPen = TTGlyphPen(glyphSet=None)
path.draw(ttPen)
glyph = ttPen.glyph()
assert not glyph.isComposite()
# compute glyph.xMin (glyfTable parameter unused for non composites)
glyph.recalcBounds(glyfTable=None)
return glyph
def removeTTGlyphOverlaps(
glyphName: str,
glyphSet: _TTGlyphMapping,
glyfTable: _g_l_y_f.table__g_l_y_f,
hmtxTable: _h_m_t_x.table__h_m_t_x,
removeHinting: bool = True,
) -> bool:
glyph = glyfTable[glyphName]
# decompose composite glyphs only if components overlap each other
if (
glyph.numberOfContours > 0
or glyph.isComposite()
and componentsOverlap(glyph, glyphSet)
):
path = skPathFromGlyph(glyphName, glyphSet)
# remove overlaps
path2 = pathops.simplify(path, clockwise=path.clockwise)
# replace TTGlyph if simplified path is different (ignoring contour order)
if {tuple(c) for c in path.contours} != {tuple(c) for c in path2.contours}:
glyfTable[glyphName] = glyph = ttfGlyphFromSkPath(path2)
# simplified glyph is always unhinted
assert not glyph.program
# also ensure hmtx LSB == glyph.xMin so glyph origin is at x=0
width, lsb = hmtxTable[glyphName]
if lsb != glyph.xMin:
hmtxTable[glyphName] = (width, glyph.xMin)
return True
if removeHinting:
glyph.removeHinting()
return False
def removeOverlaps(
font: ttFont.TTFont,
glyphNames: Optional[Iterable[str]] = None,
removeHinting: bool = True,
) -> None:
"""Simplify glyphs in TTFont by merging overlapping contours.
Overlapping components are first decomposed to simple contours, then merged.
Currently this only works with TrueType fonts with 'glyf' table.
Raises NotImplementedError if 'glyf' table is absent.
Note that removing overlaps invalidates the hinting. By default we drop hinting
from all glyphs whether or not overlaps are removed from a given one, as it would
look weird if only some glyphs are left (un)hinted.
Args:
font: input TTFont object, modified in place.
glyphNames: optional iterable of glyph names (str) to remove overlaps from.
By default, all glyphs in the font are processed.
removeHinting (bool): set to False to keep hinting for unmodified glyphs.
"""
try:
glyfTable = font["glyf"]
except KeyError:
raise NotImplementedError("removeOverlaps currently only works with TTFs")
hmtxTable = font["hmtx"]
# wraps the underlying glyf Glyphs, takes care of interfacing with drawing pens
glyphSet = font.getGlyphSet()
if glyphNames is None:
glyphNames = font.getGlyphOrder()
# process all simple glyphs first, then composites with increasing component depth,
# so that by the time we test for component intersections the respective base glyphs
# have already been simplified
glyphNames = sorted(
glyphNames,
key=lambda name: (
glyfTable[name].getCompositeMaxpValues(glyfTable).maxComponentDepth
if glyfTable[name].isComposite()
else 0,
name,
),
)
modified = set()
for glyphName in glyphNames:
if removeTTGlyphOverlaps(
glyphName, glyphSet, glyfTable, hmtxTable, removeHinting
):
modified.add(glyphName)
log.debug("Removed overlaps for %s glyphs:\n%s", len(modified), " ".join(modified))
def main(args=None):
import sys
if args is None:
args = sys.argv[1:]
if len(args) < 2:
print(
f"usage: fonttools ttLib.removeOverlaps INPUT.ttf OUTPUT.ttf [GLYPHS ...]"
)
sys.exit(1)
src = args[0]
dst = args[1]
glyphNames = args[2:] or None
with ttFont.TTFont(src) as f:
removeOverlaps(f, glyphNames)
f.save(dst)
if __name__ == "__main__":
main()

View File

@ -87,6 +87,7 @@ from fontTools.varLib.merger import MutatorMerger
from contextlib import contextmanager
import collections
from copy import deepcopy
from enum import IntEnum
import logging
from itertools import islice
import os
@ -121,6 +122,12 @@ class NormalizedAxisRange(AxisRange):
return self
class OverlapMode(IntEnum):
KEEP_AND_DONT_SET_FLAGS = 0
KEEP_AND_SET_FLAGS = 1
REMOVE = 2
def instantiateTupleVariationStore(
variations, axisLimits, origCoords=None, endPts=None
):
@ -578,7 +585,7 @@ class _TupleVarStoreAdapter(object):
def instantiateItemVariationStore(itemVarStore, fvarAxes, axisLimits):
""" Compute deltas at partial location, and update varStore in-place.
"""Compute deltas at partial location, and update varStore in-place.
Remove regions in which all axes were instanced, or fall outside the new axis
limits. Scale the deltas of the remaining regions where only some of the axes
@ -1175,9 +1182,13 @@ def populateAxisDefaults(varfont, axisLimits):
def instantiateVariableFont(
varfont, axisLimits, inplace=False, optimize=True, overlap=True
varfont,
axisLimits,
inplace=False,
optimize=True,
overlap=OverlapMode.KEEP_AND_SET_FLAGS,
):
""" Instantiate variable font, either fully or partially.
"""Instantiate variable font, either fully or partially.
Depending on whether the `axisLimits` dictionary references all or some of the
input varfont's axes, the output font will either be a full instance (static
@ -1198,13 +1209,20 @@ def instantiateVariableFont(
remaining 'gvar' table's deltas. Possibly faster, and might work around
rendering issues in some buggy environments, at the cost of a slightly
larger file size.
overlap (bool): variable fonts usually contain overlapping contours, and some
font rendering engines on Apple platforms require that the `OVERLAP_SIMPLE`
and `OVERLAP_COMPOUND` flags in the 'glyf' table be set to force rendering
using a non-zero fill rule. Thus we always set these flags on all glyphs
to maximise cross-compatibility of the generated instance. You can disable
this by setting `overalap` to False.
overlap (OverlapMode): variable fonts usually contain overlapping contours, and
some font rendering engines on Apple platforms require that the
`OVERLAP_SIMPLE` and `OVERLAP_COMPOUND` flags in the 'glyf' table be set to
force rendering using a non-zero fill rule. Thus we always set these flags
on all glyphs to maximise cross-compatibility of the generated instance.
You can disable this by passing OverlapMode.KEEP_AND_DONT_SET_FLAGS.
If you want to remove the overlaps altogether and merge overlapping
contours and components, you can pass OverlapMode.REMOVE. Note that this
requires the skia-pathops package (available to pip install).
The overlap parameter only has effect when generating full static instances.
"""
# 'overlap' used to be bool and is now enum; for backward compat keep accepting bool
overlap = OverlapMode(int(overlap))
sanityCheckVariableTables(varfont)
axisLimits = populateAxisDefaults(varfont, axisLimits)
@ -1245,8 +1263,14 @@ def instantiateVariableFont(
instantiateFvar(varfont, axisLimits)
if "fvar" not in varfont:
if "glyf" in varfont and overlap:
setMacOverlapFlags(varfont["glyf"])
if "glyf" in varfont:
if overlap == OverlapMode.KEEP_AND_SET_FLAGS:
setMacOverlapFlags(varfont["glyf"])
elif overlap == OverlapMode.REMOVE:
from fontTools.ttLib.removeOverlaps import removeOverlaps
log.info("Removing overlaps from glyf table")
removeOverlaps(varfont)
varLib.set_default_weight_width_slant(
varfont,
@ -1346,6 +1370,13 @@ def parseArgs(args):
help="Don't set OVERLAP_SIMPLE/OVERLAP_COMPOUND glyf flags (only applicable "
"when generating a full instance)",
)
parser.add_argument(
"--remove-overlaps",
dest="remove_overlaps",
action="store_true",
help="Merge overlapping contours and components (only applicable "
"when generating a full instance). Requires skia-pathops",
)
loggingGroup = parser.add_mutually_exclusive_group(required=False)
loggingGroup.add_argument(
"-v", "--verbose", action="store_true", help="Run more verbosely."
@ -1355,6 +1386,11 @@ def parseArgs(args):
)
options = parser.parse_args(args)
if options.remove_overlaps:
options.overlap = OverlapMode.REMOVE
else:
options.overlap = OverlapMode(int(options.overlap))
infile = options.input
if not os.path.isfile(infile):
parser.error("No such file '{}'".format(infile))

View File

@ -174,6 +174,16 @@ are required to unlock the extra features named "ufo", etc.
*Extra:* ``type1``
- ``Lib/fontTools/ttLib/removeOverlaps.py``
Simplify TrueType glyphs by merging overlapping contours and components.
* `skia-pathops <https://pypi.python.org/pypy/skia-pathops>`__: Python
bindings for the Skia library's PathOps module, performing boolean
operations on paths (union, intersection, etc.).
*Extra:* ``pathops``
- ``Lib/fontTools/pens/cocoaPen.py``
Pen for drawing glyphs with Cocoa ``NSBezierPath``, requires:

View File

@ -0,0 +1,439 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.15">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="A"/>
<GlyphID id="2" name="B"/>
<GlyphID id="3" name="C"/>
<GlyphID id="4" name="D"/>
<GlyphID id="5" name="E"/>
<GlyphID id="6" name="F"/>
<GlyphID id="7" name="space"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0xc3d4abe6"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Wed Sep 23 12:54:22 2020"/>
<modified value="Tue Sep 29 18:06:03 2020"/>
<xMin value="-152"/>
<yMin value="-200"/>
<xMax value="1059"/>
<yMax value="800"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1000"/>
<descent value="-200"/>
<lineGap value="0"/>
<advanceWidthMax value="600"/>
<minLeftSideBearing value="-152"/>
<minRightSideBearing value="-559"/>
<xMaxExtent value="1059"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="8"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="8"/>
<maxPoints value="8"/>
<maxContours value="2"/>
<maxCompositePoints value="12"/>
<maxCompositeContours value="3"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="3"/>
<maxComponentDepth value="1"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="513"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00001000"/>
<ySubscriptXSize value="650"/>
<ySubscriptYSize value="600"/>
<ySubscriptXOffset value="0"/>
<ySubscriptYOffset value="75"/>
<ySuperscriptXSize value="650"/>
<ySuperscriptYSize value="600"/>
<ySuperscriptXOffset value="0"/>
<ySuperscriptYOffset value="350"/>
<yStrikeoutSize value="50"/>
<yStrikeoutPosition value="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="0"/>
<bProportion value="0"/>
<bContrast value="0"/>
<bStrokeVariation value="0"/>
<bArmStyle value="0"/>
<bLetterForm value="0"/>
<bMidline value="0"/>
<bXHeight value="0"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="NONE"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="70"/>
<sTypoAscender value="800"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="200"/>
<usWinAscent value="1000"/>
<usWinDescent value="200"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="700"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="500" lsb="50"/>
<mtx name="A" width="500" lsb="153"/>
<mtx name="B" width="500" lsb="-152"/>
<mtx name="C" width="500" lsb="-133"/>
<mtx name="D" width="500" lsb="-97"/>
<mtx name="E" width="500" lsb="-87"/>
<mtx name="F" width="500" lsb="-107"/>
<mtx name="space" width="600" lsb="0"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
</cmap>
<loca>
<!-- The 'loca' table will be calculated by the compiler -->
</loca>
<glyf>
<!-- The xMin, yMin, xMax and yMax values
will be recalculated by the compiler. -->
<TTGlyph name=".notdef" xMin="50" yMin="-200" xMax="450" yMax="800">
<contour>
<pt x="50" y="-200" on="1"/>
<pt x="50" y="800" on="1"/>
<pt x="450" y="800" on="1"/>
<pt x="450" y="-200" on="1"/>
</contour>
<contour>
<pt x="100" y="-150" on="1"/>
<pt x="400" y="-150" on="1"/>
<pt x="400" y="750" on="1"/>
<pt x="100" y="750" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="A" xMin="153" yMin="-66" xMax="350" yMax="646">
<contour>
<pt x="153" y="646" on="1"/>
<pt x="350" y="646" on="1"/>
<pt x="350" y="-66" on="1"/>
<pt x="153" y="-66" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="B" xMin="-152" yMin="39" xMax="752" yMax="592">
<contour>
<pt x="-152" y="448" on="1"/>
<pt x="752" y="448" on="1"/>
<pt x="752" y="215" on="1"/>
<pt x="-152" y="215" on="1"/>
</contour>
<contour>
<pt x="129" y="592" on="1"/>
<pt x="401" y="592" on="1"/>
<pt x="401" y="39" on="1"/>
<pt x="129" y="39" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="C" xMin="-133" yMin="-66" xMax="771" yMax="646">
<component glyphName="A" x="-250" y="0" flags="0x4"/>
<component glyphName="B" x="19" y="-28" flags="0x4"/>
</TTGlyph>
<TTGlyph name="D" xMin="-97" yMin="-66" xMax="1059" yMax="646">
<component glyphName="A" x="-250" y="0" flags="0x4"/>
<component glyphName="B" x="307" y="-28" flags="0x4"/>
</TTGlyph>
<TTGlyph name="E" xMin="-87" yMin="-87" xMax="801" yMax="650">
<component glyphName="A" x="450" y="-77" scalex="0.9397" scale01="0.34204" scale10="-0.34204" scaley="0.9397" flags="0x4"/>
<component glyphName="A" x="8" y="4" flags="0x4"/>
<component glyphName="A" x="-240" y="0" flags="0x4"/>
</TTGlyph>
<TTGlyph name="F" xMin="-107" yMin="-95" xMax="837" yMax="650">
<component glyphName="A" x="501" y="-114" scalex="0.866" scale01="0.5" scale10="-0.5" scaley="0.866" flags="0x4"/>
<component glyphName="A" x="-12" y="4" flags="0x4"/>
<component glyphName="A" x="-260" y="0" flags="0x4"/>
</TTGlyph>
<TTGlyph name="space"/><!-- contains no outline data -->
</glyf>
<name>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="257" platformID="1" platEncID="0" langID="0x0" unicode="True">
Regular
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.000;NONE;RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
</name>
<post>
<formatType value="2.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-100"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
<psNames>
<!-- This file uses unique glyph names based on the information
found in the 'post' table. Since these names might not be unique,
we have to invent artificial names in case of clashes. In order to
be able to retain the original information, we need a name to
ps name mapping for those cases where they differ. That's what
you see below.
-->
</psNames>
<extraNames>
<!-- following are the name that are not taken from the standard Mac glyph order -->
</extraNames>
</post>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=8 -->
<NumShorts value="0"/>
<!-- VarRegionCount=0 -->
<Item index="0" value="[]"/>
<Item index="1" value="[]"/>
<Item index="2" value="[]"/>
<Item index="3" value="[]"/>
<Item index="4" value="[]"/>
<Item index="5" value="[]"/>
<Item index="6" value="[]"/>
<Item index="7" value="[]"/>
</VarData>
</VarStore>
</HVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="256"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<Flags>0x0</Flags>
<MinValue>400.0</MinValue>
<DefaultValue>400.0</DefaultValue>
<MaxValue>700.0</MaxValue>
<AxisNameID>256</AxisNameID>
</Axis>
<!-- Regular -->
<NamedInstance flags="0x0" subfamilyNameID="257">
<coord axis="wght" value="400.0"/>
</NamedInstance>
<!-- Regular -->
<NamedInstance flags="0x0" subfamilyNameID="257">
<coord axis="wght" value="700.0"/>
</NamedInstance>
</fvar>
<gvar>
<version value="1"/>
<reserved value="0"/>
<glyphVariations glyph="A">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="-40" y="0"/>
<delta pt="1" x="40" y="0"/>
<delta pt="2" x="40" y="0"/>
<delta pt="3" x="-40" y="0"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="0" y="0"/>
<delta pt="6" x="0" y="0"/>
<delta pt="7" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="B">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="-40" y="0"/>
<delta pt="2" x="40" y="0"/>
<delta pt="5" x="40" y="20"/>
<delta pt="7" x="-40" y="-20"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="C">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="0" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="D">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="0" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="E">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="0" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="0" y="0"/>
<delta pt="6" x="0" y="0"/>
</tuple>
</glyphVariations>
<glyphVariations glyph="F">
<tuple>
<coord axis="wght" value="1.0"/>
<delta pt="0" x="0" y="0"/>
<delta pt="1" x="0" y="0"/>
<delta pt="2" x="0" y="0"/>
<delta pt="3" x="0" y="0"/>
<delta pt="4" x="0" y="0"/>
<delta pt="5" x="0" y="0"/>
<delta pt="6" x="0" y="0"/>
</tuple>
</glyphVariations>
</gvar>
</ttFont>

View File

@ -0,0 +1,305 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.15">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="A"/>
<GlyphID id="2" name="B"/>
<GlyphID id="3" name="C"/>
<GlyphID id="4" name="D"/>
<GlyphID id="5" name="E"/>
<GlyphID id="6" name="F"/>
<GlyphID id="7" name="space"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0x98c89e17"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Wed Sep 23 12:54:22 2020"/>
<modified value="Tue Sep 29 18:06:03 2020"/>
<xMin value="-152"/>
<yMin value="-200"/>
<xMax value="1059"/>
<yMax value="800"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1000"/>
<descent value="-200"/>
<lineGap value="0"/>
<advanceWidthMax value="600"/>
<minLeftSideBearing value="-152"/>
<minRightSideBearing value="-559"/>
<xMaxExtent value="1059"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="8"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="8"/>
<maxPoints value="8"/>
<maxContours value="2"/>
<maxCompositePoints value="12"/>
<maxCompositeContours value="3"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="3"/>
<maxComponentDepth value="1"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="513"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00001000"/>
<ySubscriptXSize value="650"/>
<ySubscriptYSize value="600"/>
<ySubscriptXOffset value="0"/>
<ySubscriptYOffset value="75"/>
<ySuperscriptXSize value="650"/>
<ySuperscriptYSize value="600"/>
<ySuperscriptXOffset value="0"/>
<ySuperscriptYOffset value="350"/>
<yStrikeoutSize value="50"/>
<yStrikeoutPosition value="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="0"/>
<bProportion value="0"/>
<bContrast value="0"/>
<bStrokeVariation value="0"/>
<bArmStyle value="0"/>
<bLetterForm value="0"/>
<bMidline value="0"/>
<bXHeight value="0"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="NONE"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="70"/>
<sTypoAscender value="800"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="200"/>
<usWinAscent value="1000"/>
<usWinDescent value="200"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="700"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="500" lsb="50"/>
<mtx name="A" width="500" lsb="153"/>
<mtx name="B" width="500" lsb="-152"/>
<mtx name="C" width="500" lsb="-133"/>
<mtx name="D" width="500" lsb="-97"/>
<mtx name="E" width="500" lsb="-87"/>
<mtx name="F" width="500" lsb="-107"/>
<mtx name="space" width="600" lsb="0"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
</cmap>
<loca>
<!-- The 'loca' table will be calculated by the compiler -->
</loca>
<glyf>
<!-- The xMin, yMin, xMax and yMax values
will be recalculated by the compiler. -->
<TTGlyph name=".notdef" xMin="50" yMin="-200" xMax="450" yMax="800">
<contour>
<pt x="50" y="-200" on="1"/>
<pt x="50" y="800" on="1"/>
<pt x="450" y="800" on="1"/>
<pt x="450" y="-200" on="1"/>
</contour>
<contour>
<pt x="100" y="-150" on="1"/>
<pt x="400" y="-150" on="1"/>
<pt x="400" y="750" on="1"/>
<pt x="100" y="750" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="A" xMin="153" yMin="-66" xMax="350" yMax="646">
<contour>
<pt x="153" y="646" on="1"/>
<pt x="350" y="646" on="1"/>
<pt x="350" y="-66" on="1"/>
<pt x="153" y="-66" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="B" xMin="-152" yMin="39" xMax="752" yMax="592">
<contour>
<pt x="-152" y="448" on="1"/>
<pt x="752" y="448" on="1"/>
<pt x="752" y="215" on="1"/>
<pt x="-152" y="215" on="1"/>
</contour>
<contour>
<pt x="129" y="592" on="1"/>
<pt x="401" y="592" on="1"/>
<pt x="401" y="39" on="1"/>
<pt x="129" y="39" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="C" xMin="-133" yMin="-66" xMax="771" yMax="646">
<component glyphName="A" x="-250" y="0" flags="0x4"/>
<component glyphName="B" x="19" y="-28" flags="0x4"/>
</TTGlyph>
<TTGlyph name="D" xMin="-97" yMin="-66" xMax="1059" yMax="646">
<component glyphName="A" x="-250" y="0" flags="0x4"/>
<component glyphName="B" x="307" y="-28" flags="0x4"/>
</TTGlyph>
<TTGlyph name="E" xMin="-87" yMin="-87" xMax="801" yMax="650">
<component glyphName="A" x="450" y="-77" scalex="0.9397" scale01="0.34204" scale10="-0.34204" scaley="0.9397" flags="0x4"/>
<component glyphName="A" x="8" y="4" flags="0x4"/>
<component glyphName="A" x="-240" y="0" flags="0x4"/>
</TTGlyph>
<TTGlyph name="F" xMin="-107" yMin="-95" xMax="837" yMax="650">
<component glyphName="A" x="501" y="-114" scalex="0.866" scale01="0.5" scale10="-0.5" scaley="0.866" flags="0x4"/>
<component glyphName="A" x="-12" y="4" flags="0x4"/>
<component glyphName="A" x="-260" y="0" flags="0x4"/>
</TTGlyph>
<TTGlyph name="space"/><!-- contains no outline data -->
</glyf>
<name>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.000;NONE;RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
</name>
<post>
<formatType value="2.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-100"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
<psNames>
<!-- This file uses unique glyph names based on the information
found in the 'post' table. Since these names might not be unique,
we have to invent artificial names in case of clashes. In order to
be able to retain the original information, we need a name to
ps name mapping for those cases where they differ. That's what
you see below.
-->
</psNames>
<extraNames>
<!-- following are the name that are not taken from the standard Mac glyph order -->
</extraNames>
</post>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="256"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
</ttFont>

View File

@ -0,0 +1,343 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.15">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="A"/>
<GlyphID id="2" name="B"/>
<GlyphID id="3" name="C"/>
<GlyphID id="4" name="D"/>
<GlyphID id="5" name="E"/>
<GlyphID id="6" name="F"/>
<GlyphID id="7" name="space"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0x1cd9cd87"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Wed Sep 23 12:54:22 2020"/>
<modified value="Tue Sep 29 18:06:03 2020"/>
<xMin value="-152"/>
<yMin value="-200"/>
<xMax value="1059"/>
<yMax value="800"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1000"/>
<descent value="-200"/>
<lineGap value="0"/>
<advanceWidthMax value="600"/>
<minLeftSideBearing value="-152"/>
<minRightSideBearing value="-559"/>
<xMaxExtent value="1059"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="8"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="8"/>
<maxPoints value="20"/>
<maxContours value="2"/>
<maxCompositePoints value="16"/>
<maxCompositeContours value="3"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="3"/>
<maxComponentDepth value="1"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="513"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00001000"/>
<ySubscriptXSize value="650"/>
<ySubscriptYSize value="600"/>
<ySubscriptXOffset value="0"/>
<ySubscriptYOffset value="75"/>
<ySuperscriptXSize value="650"/>
<ySuperscriptYSize value="600"/>
<ySuperscriptXOffset value="0"/>
<ySuperscriptYOffset value="350"/>
<yStrikeoutSize value="50"/>
<yStrikeoutPosition value="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="0"/>
<bProportion value="0"/>
<bContrast value="0"/>
<bStrokeVariation value="0"/>
<bArmStyle value="0"/>
<bLetterForm value="0"/>
<bMidline value="0"/>
<bXHeight value="0"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="NONE"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="70"/>
<sTypoAscender value="800"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="200"/>
<usWinAscent value="1000"/>
<usWinDescent value="200"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="700"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="500" lsb="50"/>
<mtx name="A" width="500" lsb="153"/>
<mtx name="B" width="500" lsb="-152"/>
<mtx name="C" width="500" lsb="-133"/>
<mtx name="D" width="500" lsb="-97"/>
<mtx name="E" width="500" lsb="-87"/>
<mtx name="F" width="500" lsb="-107"/>
<mtx name="space" width="600" lsb="0"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
</cmap>
<loca>
<!-- The 'loca' table will be calculated by the compiler -->
</loca>
<glyf>
<!-- The xMin, yMin, xMax and yMax values
will be recalculated by the compiler. -->
<TTGlyph name=".notdef" xMin="50" yMin="-200" xMax="450" yMax="800">
<contour>
<pt x="50" y="-200" on="1"/>
<pt x="50" y="800" on="1"/>
<pt x="450" y="800" on="1"/>
<pt x="450" y="-200" on="1"/>
</contour>
<contour>
<pt x="100" y="-150" on="1"/>
<pt x="400" y="-150" on="1"/>
<pt x="400" y="750" on="1"/>
<pt x="100" y="750" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="A" xMin="153" yMin="-66" xMax="350" yMax="646">
<contour>
<pt x="153" y="646" on="1"/>
<pt x="350" y="646" on="1"/>
<pt x="350" y="-66" on="1"/>
<pt x="153" y="-66" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="B" xMin="-152" yMin="39" xMax="752" yMax="592">
<contour>
<pt x="-152" y="448" on="1"/>
<pt x="129" y="448" on="1"/>
<pt x="129" y="592" on="1"/>
<pt x="401" y="592" on="1"/>
<pt x="401" y="448" on="1"/>
<pt x="752" y="448" on="1"/>
<pt x="752" y="215" on="1"/>
<pt x="401" y="215" on="1"/>
<pt x="401" y="39" on="1"/>
<pt x="129" y="39" on="1"/>
<pt x="129" y="215" on="1"/>
<pt x="-152" y="215" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="C" xMin="-133" yMin="-66" xMax="771" yMax="646">
<contour>
<pt x="-97" y="646" on="1"/>
<pt x="100" y="646" on="1"/>
<pt x="100" y="420" on="1"/>
<pt x="148" y="420" on="1"/>
<pt x="148" y="564" on="1"/>
<pt x="420" y="564" on="1"/>
<pt x="420" y="420" on="1"/>
<pt x="771" y="420" on="1"/>
<pt x="771" y="187" on="1"/>
<pt x="420" y="187" on="1"/>
<pt x="420" y="11" on="1"/>
<pt x="148" y="11" on="1"/>
<pt x="148" y="187" on="1"/>
<pt x="100" y="187" on="1"/>
<pt x="100" y="-66" on="1"/>
<pt x="-97" y="-66" on="1"/>
<pt x="-97" y="187" on="1"/>
<pt x="-133" y="187" on="1"/>
<pt x="-133" y="420" on="1"/>
<pt x="-97" y="420" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="D" xMin="-97" yMin="-66" xMax="1059" yMax="646">
<component glyphName="A" x="-250" y="0" flags="0x4"/>
<component glyphName="B" x="307" y="-28" flags="0x4"/>
</TTGlyph>
<TTGlyph name="E" xMin="-87" yMin="-87" xMax="801" yMax="650">
<component glyphName="A" x="450" y="-77" scalex="0.9397" scale01="0.34204" scale10="-0.34204" scaley="0.9397" flags="0x4"/>
<component glyphName="A" x="8" y="4" flags="0x4"/>
<component glyphName="A" x="-240" y="0" flags="0x4"/>
</TTGlyph>
<TTGlyph name="F" xMin="-107" yMin="-95" xMax="837" yMax="650">
<contour>
<pt x="141" y="650" on="1"/>
<pt x="338" y="650" on="1"/>
<pt x="338" y="538" on="1"/>
<pt x="481" y="620" on="1"/>
<pt x="837" y="4" on="1"/>
<pt x="667" y="-95" on="1"/>
<pt x="338" y="474" on="1"/>
<pt x="338" y="-62" on="1"/>
<pt x="141" y="-62" on="1"/>
</contour>
<contour>
<pt x="-107" y="646" on="1"/>
<pt x="90" y="646" on="1"/>
<pt x="90" y="-66" on="1"/>
<pt x="-107" y="-66" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="space"/><!-- contains no outline data -->
</glyf>
<name>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.000;NONE;RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
</name>
<post>
<formatType value="2.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-100"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
<psNames>
<!-- This file uses unique glyph names based on the information
found in the 'post' table. Since these names might not be unique,
we have to invent artificial names in case of clashes. In order to
be able to retain the original information, we need a name to
ps name mapping for those cases where they differ. That's what
you see below.
-->
</psNames>
<extraNames>
<!-- following are the name that are not taken from the standard Mac glyph order -->
</extraNames>
</post>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="256"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
</ttFont>

View File

@ -0,0 +1,367 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.15">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="A"/>
<GlyphID id="2" name="B"/>
<GlyphID id="3" name="C"/>
<GlyphID id="4" name="D"/>
<GlyphID id="5" name="E"/>
<GlyphID id="6" name="F"/>
<GlyphID id="7" name="space"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.0"/>
<checkSumAdjustment value="0xc12af6d1"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Wed Sep 23 12:54:22 2020"/>
<modified value="Tue Sep 29 18:06:03 2020"/>
<xMin value="-192"/>
<yMin value="-200"/>
<xMax value="1099"/>
<yMax value="800"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="6"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1000"/>
<descent value="-200"/>
<lineGap value="0"/>
<advanceWidthMax value="600"/>
<minLeftSideBearing value="-192"/>
<minRightSideBearing value="-599"/>
<xMaxExtent value="1099"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="8"/>
</hhea>
<maxp>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="0x10000"/>
<numGlyphs value="8"/>
<maxPoints value="16"/>
<maxContours value="2"/>
<maxCompositePoints value="0"/>
<maxCompositeContours value="0"/>
<maxZones value="1"/>
<maxTwilightPoints value="0"/>
<maxStorage value="0"/>
<maxFunctionDefs value="0"/>
<maxInstructionDefs value="0"/>
<maxStackElements value="0"/>
<maxSizeOfInstructions value="0"/>
<maxComponentElements value="0"/>
<maxComponentDepth value="0"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="513"/>
<usWeightClass value="700"/>
<usWidthClass value="5"/>
<fsType value="00000000 00001000"/>
<ySubscriptXSize value="650"/>
<ySubscriptYSize value="600"/>
<ySubscriptXOffset value="0"/>
<ySubscriptYOffset value="75"/>
<ySuperscriptXSize value="650"/>
<ySuperscriptYSize value="600"/>
<ySuperscriptXOffset value="0"/>
<ySuperscriptYOffset value="350"/>
<yStrikeoutSize value="50"/>
<yStrikeoutPosition value="300"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="0"/>
<bSerifStyle value="0"/>
<bWeight value="0"/>
<bProportion value="0"/>
<bContrast value="0"/>
<bStrokeVariation value="0"/>
<bArmStyle value="0"/>
<bLetterForm value="0"/>
<bMidline value="0"/>
<bXHeight value="0"/>
</panose>
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="NONE"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="32"/>
<usLastCharIndex value="70"/>
<sTypoAscender value="800"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="200"/>
<usWinAscent value="1000"/>
<usWinDescent value="200"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="700"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="0"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="500" lsb="50"/>
<mtx name="A" width="500" lsb="113"/>
<mtx name="B" width="500" lsb="-192"/>
<mtx name="C" width="500" lsb="-173"/>
<mtx name="D" width="500" lsb="-137"/>
<mtx name="E" width="500" lsb="-127"/>
<mtx name="F" width="500" lsb="-147"/>
<mtx name="space" width="600" lsb="0"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x20" name="space"/><!-- SPACE -->
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
<map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
<map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
<map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
<map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
<map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
</cmap_format_4>
</cmap>
<loca>
<!-- The 'loca' table will be calculated by the compiler -->
</loca>
<glyf>
<!-- The xMin, yMin, xMax and yMax values
will be recalculated by the compiler. -->
<TTGlyph name=".notdef" xMin="50" yMin="-200" xMax="450" yMax="800">
<contour>
<pt x="50" y="-200" on="1"/>
<pt x="50" y="800" on="1"/>
<pt x="450" y="800" on="1"/>
<pt x="450" y="-200" on="1"/>
</contour>
<contour>
<pt x="100" y="-150" on="1"/>
<pt x="400" y="-150" on="1"/>
<pt x="400" y="750" on="1"/>
<pt x="100" y="750" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="A" xMin="113" yMin="-66" xMax="390" yMax="646">
<contour>
<pt x="113" y="646" on="1"/>
<pt x="390" y="646" on="1"/>
<pt x="390" y="-66" on="1"/>
<pt x="113" y="-66" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="B" xMin="-192" yMin="19" xMax="792" yMax="612">
<contour>
<pt x="-192" y="448" on="1"/>
<pt x="89" y="448" on="1"/>
<pt x="89" y="612" on="1"/>
<pt x="441" y="612" on="1"/>
<pt x="441" y="448" on="1"/>
<pt x="792" y="448" on="1"/>
<pt x="792" y="215" on="1"/>
<pt x="441" y="215" on="1"/>
<pt x="441" y="19" on="1"/>
<pt x="89" y="19" on="1"/>
<pt x="89" y="215" on="1"/>
<pt x="-192" y="215" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="C" xMin="-173" yMin="-66" xMax="811" yMax="646">
<contour>
<pt x="-137" y="646" on="1"/>
<pt x="140" y="646" on="1"/>
<pt x="140" y="584" on="1"/>
<pt x="460" y="584" on="1"/>
<pt x="460" y="420" on="1"/>
<pt x="811" y="420" on="1"/>
<pt x="811" y="187" on="1"/>
<pt x="460" y="187" on="1"/>
<pt x="460" y="-9" on="1"/>
<pt x="140" y="-9" on="1"/>
<pt x="140" y="-66" on="1"/>
<pt x="-137" y="-66" on="1"/>
<pt x="-137" y="187" on="1"/>
<pt x="-173" y="187" on="1"/>
<pt x="-173" y="420" on="1"/>
<pt x="-137" y="420" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="D" xMin="-137" yMin="-66" xMax="1099" yMax="646">
<contour>
<pt x="-137" y="646" on="1"/>
<pt x="140" y="646" on="1"/>
<pt x="140" y="420" on="1"/>
<pt x="396" y="420" on="1"/>
<pt x="396" y="584" on="1"/>
<pt x="748" y="584" on="1"/>
<pt x="748" y="420" on="1"/>
<pt x="1099" y="420" on="1"/>
<pt x="1099" y="187" on="1"/>
<pt x="748" y="187" on="1"/>
<pt x="748" y="-9" on="1"/>
<pt x="396" y="-9" on="1"/>
<pt x="396" y="187" on="1"/>
<pt x="140" y="187" on="1"/>
<pt x="140" y="-66" on="1"/>
<pt x="-137" y="-66" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="E" xMin="-127" yMin="-100" xMax="839" yMax="663">
<contour>
<pt x="121" y="650" on="1"/>
<pt x="398" y="650" on="1"/>
<pt x="398" y="592" on="1"/>
<pt x="596" y="663" on="1"/>
<pt x="839" y="-6" on="1"/>
<pt x="579" y="-100" on="1"/>
<pt x="398" y="396" on="1"/>
<pt x="398" y="-62" on="1"/>
<pt x="150" y="-62" on="1"/>
<pt x="150" y="-66" on="1"/>
<pt x="-127" y="-66" on="1"/>
<pt x="-127" y="646" on="1"/>
<pt x="121" y="646" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="F" xMin="-147" yMin="-115" xMax="872" yMax="650">
<contour>
<pt x="101" y="650" on="1"/>
<pt x="378" y="650" on="1"/>
<pt x="378" y="561" on="1"/>
<pt x="516" y="640" on="1"/>
<pt x="872" y="24" on="1"/>
<pt x="632" y="-115" on="1"/>
<pt x="378" y="325" on="1"/>
<pt x="378" y="-62" on="1"/>
<pt x="130" y="-62" on="1"/>
<pt x="130" y="-66" on="1"/>
<pt x="-147" y="-66" on="1"/>
<pt x="-147" y="646" on="1"/>
<pt x="101" y="646" on="1"/>
</contour>
<instructions/>
</TTGlyph>
<TTGlyph name="space"/><!-- contains no outline data -->
</glyf>
<name>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.000;NONE;RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Remove Overlaps Test Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.000
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
RemoveOverlapsTest-Regular
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
</name>
<post>
<formatType value="2.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-100"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
<psNames>
<!-- This file uses unique glyph names based on the information
found in the 'post' table. Since these names might not be unique,
we have to invent artificial names in case of clashes. In order to
be able to retain the original information, we need a name to
ps name mapping for those cases where they differ. That's what
you see below.
-->
</psNames>
<extraNames>
<!-- following are the name that are not taken from the standard Mac glyph order -->
</extraNames>
</post>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="256"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
</ttFont>

View File

@ -1400,6 +1400,13 @@ def varfont2():
return f
@pytest.fixture
def varfont3():
f = ttLib.TTFont(recalcTimestamp=False)
f.importXML(os.path.join(TESTDATA, "PartialInstancerTest3-VF.ttx"))
return f
def _dump_ttx(ttFont):
# compile to temporary bytes stream, reload and dump to XML
tmp = BytesIO()
@ -1411,13 +1418,16 @@ def _dump_ttx(ttFont):
return _strip_ttLibVersion(s.getvalue())
def _get_expected_instance_ttx(wght, wdth):
def _get_expected_instance_ttx(
name, *locations, overlap=instancer.OverlapMode.KEEP_AND_SET_FLAGS
):
filename = f"{name}-VF-instance-{','.join(str(loc) for loc in locations)}"
if overlap == instancer.OverlapMode.KEEP_AND_DONT_SET_FLAGS:
filename += "-no-overlap-flags"
elif overlap == instancer.OverlapMode.REMOVE:
filename += "-no-overlaps"
with open(
os.path.join(
TESTDATA,
"test_results",
"PartialInstancerTest2-VF-instance-{0},{1}.ttx".format(wght, wdth),
),
os.path.join(TESTDATA, "test_results", f"{filename}.ttx"),
"r",
encoding="utf-8",
) as fp:
@ -1433,7 +1443,7 @@ class InstantiateVariableFontTest(object):
partial = instancer.instantiateVariableFont(varfont2, {"wght": wght})
instance = instancer.instantiateVariableFont(partial, {"wdth": wdth})
expected = _get_expected_instance_ttx(wght, wdth)
expected = _get_expected_instance_ttx("PartialInstancerTest2", wght, wdth)
assert _dump_ttx(instance) == expected
@ -1442,7 +1452,30 @@ class InstantiateVariableFontTest(object):
varfont2, {"wght": None, "wdth": None}
)
expected = _get_expected_instance_ttx(400, 100)
expected = _get_expected_instance_ttx("PartialInstancerTest2", 400, 100)
assert _dump_ttx(instance) == expected
@pytest.mark.parametrize(
"overlap, wght",
[
(instancer.OverlapMode.KEEP_AND_DONT_SET_FLAGS, 400),
(instancer.OverlapMode.REMOVE, 400),
(instancer.OverlapMode.REMOVE, 700),
],
)
def test_overlap(self, varfont3, wght, overlap):
pytest.importorskip("pathops")
location = {"wght": wght}
instance = instancer.instantiateVariableFont(
varfont3, location, overlap=overlap
)
expected = _get_expected_instance_ttx(
"PartialInstancerTest3", wght, overlap=overlap
)
assert _dump_ttx(instance) == expected

View File

@ -7,5 +7,6 @@ scipy==1.5.2; platform_python_implementation != "PyPy"
munkres==1.1.2; platform_python_implementation == "PyPy"
zopfli==0.1.6
fs==2.4.11
skia-pathops==0.5.0; platform_python_implementation != "PyPy"
# this is only required to run Tests/cu2qu/{ufo,cli}_test.py
ufoLib2==0.6.2

View File

@ -122,6 +122,10 @@ extras_require = {
"type1": [
"xattr; sys_platform == 'darwin'",
],
# for fontTools.ttLib.removeOverlaps, to remove overlaps in TTF fonts
"pathops": [
"skia-pathops >= 0.5.0",
],
}
# use a special 'all' key as shorthand to includes all the extra dependencies
extras_require["all"] = sum(extras_require.values(), [])

View File

@ -6,6 +6,11 @@ skip_missing_interpreters=true
[testenv]
setenv =
cy: FONTTOOLS_WITH_CYTHON=1
# use 'download = true' to have tox install the latest pip inside the virtualenv.
# We need this to be able to install skia-pathops on Linux, which uses a
# relatively recent 'manylinux2014' platform tag.
# https://github.com/tox-dev/tox/issues/791#issuecomment-518713438
download = true
deps =
cov: coverage>=4.3
pytest