Merge pull request #2323 from fonttools/fix-instancer-valuerecord
instancer: Fix AttributeError when ValueRecord has XAdvDevice but no XAdvance
This commit is contained in:
commit
cf57ee0bbd
@ -993,7 +993,7 @@ def merge(merger, self, lst):
|
||||
varidx = (dev.StartSize << 16) + dev.EndSize
|
||||
delta = otRound(instancer[varidx])
|
||||
|
||||
setattr(self, name, getattr(self, name) + delta)
|
||||
setattr(self, name, getattr(self, name, 0) + delta)
|
||||
|
||||
|
||||
#
|
||||
|
463
Tests/varLib/instancer/data/PartialInstancerTest4-VF.ttx
Normal file
463
Tests/varLib/instancer/data/PartialInstancerTest4-VF.ttx
Normal file
@ -0,0 +1,463 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.24">
|
||||
|
||||
<GlyphOrder>
|
||||
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||
<GlyphID id="0" name=".notdef"/>
|
||||
<GlyphID id="1" name="T"/>
|
||||
<GlyphID id="2" name="o"/>
|
||||
<GlyphID id="3" name="space"/>
|
||||
</GlyphOrder>
|
||||
|
||||
<head>
|
||||
<!-- Most of this table will be recalculated by the compiler -->
|
||||
<tableVersion value="1.0"/>
|
||||
<fontRevision value="1.0"/>
|
||||
<checkSumAdjustment value="0x95e7c646"/>
|
||||
<magicNumber value="0x5f0f3cf5"/>
|
||||
<flags value="00000000 00000011"/>
|
||||
<unitsPerEm value="1000"/>
|
||||
<created value="Tue May 25 09:10:37 2021"/>
|
||||
<modified value="Tue May 25 10:10:18 2021"/>
|
||||
<xMin value="32"/>
|
||||
<yMin value="-200"/>
|
||||
<xMax value="567"/>
|
||||
<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="32"/>
|
||||
<minRightSideBearing value="33"/>
|
||||
<xMaxExtent value="567"/>
|
||||
<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="2"/>
|
||||
</hhea>
|
||||
|
||||
<maxp>
|
||||
<!-- Most of this table will be recalculated by the compiler -->
|
||||
<tableVersion value="0x10000"/>
|
||||
<numGlyphs value="4"/>
|
||||
<maxPoints value="32"/>
|
||||
<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="575"/>
|
||||
<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="111"/>
|
||||
<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="2"/>
|
||||
</OS_2>
|
||||
|
||||
<hmtx>
|
||||
<mtx name=".notdef" width="500" lsb="50"/>
|
||||
<mtx name="T" width="600" lsb="32"/>
|
||||
<mtx name="o" width="600" lsb="58"/>
|
||||
<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="0x54" name="T"/><!-- LATIN CAPITAL LETTER T -->
|
||||
<map code="0x6f" name="o"/><!-- LATIN SMALL LETTER O -->
|
||||
</cmap_format_4>
|
||||
<cmap_format_4 platformID="3" platEncID="1" language="0">
|
||||
<map code="0x20" name="space"/><!-- SPACE -->
|
||||
<map code="0x54" name="T"/><!-- LATIN CAPITAL LETTER T -->
|
||||
<map code="0x6f" name="o"/><!-- LATIN SMALL LETTER O -->
|
||||
</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="T" xMin="32" yMin="0" xMax="567" yMax="710">
|
||||
<contour>
|
||||
<pt x="32" y="710" on="1"/>
|
||||
<pt x="567" y="710" on="1"/>
|
||||
<pt x="567" y="627" on="1"/>
|
||||
<pt x="32" y="627" on="1"/>
|
||||
</contour>
|
||||
<contour>
|
||||
<pt x="230" y="710" on="1"/>
|
||||
<pt x="370" y="710" on="1"/>
|
||||
<pt x="370" y="0" on="1"/>
|
||||
<pt x="230" y="0" on="1"/>
|
||||
</contour>
|
||||
<instructions/>
|
||||
</TTGlyph>
|
||||
|
||||
<TTGlyph name="o" xMin="58" yMin="-15" xMax="542" yMax="533">
|
||||
<contour>
|
||||
<pt x="300" y="-15" on="1"/>
|
||||
<pt x="233" y="-15" on="0"/>
|
||||
<pt x="123" y="59" on="0"/>
|
||||
<pt x="58" y="184" on="0"/>
|
||||
<pt x="58" y="259" on="1"/>
|
||||
<pt x="58" y="335" on="0"/>
|
||||
<pt x="123" y="459" on="0"/>
|
||||
<pt x="233" y="533" on="0"/>
|
||||
<pt x="300" y="533" on="1"/>
|
||||
<pt x="367" y="533" on="0"/>
|
||||
<pt x="477" y="459" on="0"/>
|
||||
<pt x="542" y="335" on="0"/>
|
||||
<pt x="542" y="259" on="1"/>
|
||||
<pt x="542" y="184" on="0"/>
|
||||
<pt x="477" y="59" on="0"/>
|
||||
<pt x="367" y="-15" on="0"/>
|
||||
</contour>
|
||||
<contour>
|
||||
<pt x="300" y="50" on="1"/>
|
||||
<pt x="343" y="50" on="0"/>
|
||||
<pt x="413" y="107" on="0"/>
|
||||
<pt x="455" y="202" on="0"/>
|
||||
<pt x="455" y="260" on="1"/>
|
||||
<pt x="455" y="318" on="0"/>
|
||||
<pt x="413" y="413" on="0"/>
|
||||
<pt x="343" y="470" on="0"/>
|
||||
<pt x="300" y="470" on="1"/>
|
||||
<pt x="257" y="470" on="0"/>
|
||||
<pt x="187" y="413" on="0"/>
|
||||
<pt x="145" y="318" on="0"/>
|
||||
<pt x="145" y="260" on="1"/>
|
||||
<pt x="145" y="202" on="0"/>
|
||||
<pt x="187" y="107" on="0"/>
|
||||
<pt x="257" y="50" on="0"/>
|
||||
</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="257" platformID="1" platEncID="0" langID="0x0" unicode="True">
|
||||
Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="258" platformID="1" platEncID="0" langID="0x0" unicode="True">
|
||||
Bold
|
||||
</namerecord>
|
||||
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
|
||||
New Font
|
||||
</namerecord>
|
||||
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
|
||||
Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
|
||||
1.000;NONE;NewFont-Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
|
||||
New Font Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
|
||||
Version 1.000
|
||||
</namerecord>
|
||||
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
|
||||
NewFont-Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
|
||||
Weight
|
||||
</namerecord>
|
||||
<namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
|
||||
Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
|
||||
Bold
|
||||
</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>
|
||||
|
||||
<GDEF>
|
||||
<Version value="0x00010003"/>
|
||||
<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=1 -->
|
||||
<NumShorts value="0"/>
|
||||
<!-- VarRegionCount=1 -->
|
||||
<VarRegionIndex index="0" value="0"/>
|
||||
<Item index="0" value="[-50]"/>
|
||||
</VarData>
|
||||
</VarStore>
|
||||
</GDEF>
|
||||
|
||||
<GPOS>
|
||||
<Version value="0x00010000"/>
|
||||
<ScriptList>
|
||||
<!-- ScriptCount=1 -->
|
||||
<ScriptRecord index="0">
|
||||
<ScriptTag value="DFLT"/>
|
||||
<Script>
|
||||
<DefaultLangSys>
|
||||
<ReqFeatureIndex value="65535"/>
|
||||
<!-- FeatureCount=1 -->
|
||||
<FeatureIndex index="0" value="0"/>
|
||||
</DefaultLangSys>
|
||||
<!-- LangSysCount=0 -->
|
||||
</Script>
|
||||
</ScriptRecord>
|
||||
</ScriptList>
|
||||
<FeatureList>
|
||||
<!-- FeatureCount=1 -->
|
||||
<FeatureRecord index="0">
|
||||
<FeatureTag value="kern"/>
|
||||
<Feature>
|
||||
<!-- LookupCount=1 -->
|
||||
<LookupListIndex index="0" value="0"/>
|
||||
</Feature>
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=1 -->
|
||||
<Lookup index="0">
|
||||
<LookupType value="2"/>
|
||||
<LookupFlag value="8"/><!-- ignoreMarks -->
|
||||
<!-- SubTableCount=1 -->
|
||||
<PairPos index="0" Format="1">
|
||||
<Coverage>
|
||||
<Glyph value="T"/>
|
||||
</Coverage>
|
||||
<ValueFormat1 value="64"/>
|
||||
<ValueFormat2 value="0"/>
|
||||
<!-- PairSetCount=1 -->
|
||||
<PairSet index="0">
|
||||
<!-- PairValueCount=1 -->
|
||||
<PairValueRecord index="0">
|
||||
<SecondGlyph value="o"/>
|
||||
<Value1>
|
||||
<XAdvDevice>
|
||||
<StartSize value="0"/>
|
||||
<EndSize value="0"/>
|
||||
<DeltaFormat value="32768"/>
|
||||
</XAdvDevice>
|
||||
</Value1>
|
||||
</PairValueRecord>
|
||||
</PairSet>
|
||||
</PairPos>
|
||||
</Lookup>
|
||||
</LookupList>
|
||||
</GPOS>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- Bold -->
|
||||
<NamedInstance flags="0x0" subfamilyNameID="258">
|
||||
<coord axis="wght" value="700.0"/>
|
||||
</NamedInstance>
|
||||
</fvar>
|
||||
|
||||
<gvar>
|
||||
<version value="1"/>
|
||||
<reserved value="0"/>
|
||||
<glyphVariations glyph="T">
|
||||
<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="-27"/>
|
||||
<delta pt="3" x="0" y="-27"/>
|
||||
<delta pt="4" x="-30" y="0"/>
|
||||
<delta pt="5" x="28" y="0"/>
|
||||
<delta pt="6" x="28" y="0"/>
|
||||
<delta pt="7" x="-30" y="0"/>
|
||||
<delta pt="8" x="0" y="0"/>
|
||||
<delta pt="9" x="0" y="0"/>
|
||||
<delta pt="10" x="0" y="0"/>
|
||||
<delta pt="11" x="0" y="0"/>
|
||||
</tuple>
|
||||
</glyphVariations>
|
||||
<glyphVariations glyph="o">
|
||||
<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"/>
|
||||
<delta pt="7" x="0" y="0"/>
|
||||
<delta pt="8" x="0" y="0"/>
|
||||
<delta pt="9" x="0" y="0"/>
|
||||
<delta pt="10" x="0" y="0"/>
|
||||
<delta pt="11" x="0" y="0"/>
|
||||
<delta pt="12" x="0" y="0"/>
|
||||
<delta pt="13" x="0" y="0"/>
|
||||
<delta pt="14" x="0" y="0"/>
|
||||
<delta pt="15" x="0" y="0"/>
|
||||
<delta pt="16" x="0" y="30"/>
|
||||
<delta pt="17" x="0" y="30"/>
|
||||
<delta pt="18" x="-15" y="15"/>
|
||||
<delta pt="19" x="-30" y="0"/>
|
||||
<delta pt="20" x="-30" y="0"/>
|
||||
<delta pt="21" x="-30" y="0"/>
|
||||
<delta pt="22" x="-15" y="-15"/>
|
||||
<delta pt="23" x="0" y="-30"/>
|
||||
<delta pt="24" x="0" y="-30"/>
|
||||
<delta pt="25" x="0" y="-30"/>
|
||||
<delta pt="26" x="15" y="-15"/>
|
||||
<delta pt="27" x="30" y="0"/>
|
||||
<delta pt="28" x="30" y="0"/>
|
||||
<delta pt="29" x="30" y="0"/>
|
||||
<delta pt="30" x="15" y="15"/>
|
||||
<delta pt="31" x="0" y="30"/>
|
||||
<delta pt="32" x="0" y="0"/>
|
||||
<delta pt="33" x="0" y="0"/>
|
||||
<delta pt="34" x="0" y="0"/>
|
||||
<delta pt="35" x="0" y="0"/>
|
||||
</tuple>
|
||||
</glyphVariations>
|
||||
</gvar>
|
||||
|
||||
</ttFont>
|
@ -936,6 +936,30 @@ class InstantiateOTLTest(object):
|
||||
assert not hasattr(valueRec1, "XAdvDevice")
|
||||
assert valueRec1.XAdvance == v2
|
||||
|
||||
def test_GPOS_ValueRecord_XAdvDevice_wtihout_XAdvance(self):
|
||||
# Test VF contains a PairPos adjustment in which the default instance
|
||||
# has no XAdvance but there are deltas in XAdvDevice (VariationIndex).
|
||||
vf = ttLib.TTFont()
|
||||
vf.importXML(os.path.join(TESTDATA, "PartialInstancerTest4-VF.ttx"))
|
||||
pairPos = vf["GPOS"].table.LookupList.Lookup[0].SubTable[0]
|
||||
assert pairPos.ValueFormat1 == 0x40
|
||||
valueRec1 = pairPos.PairSet[0].PairValueRecord[0].Value1
|
||||
assert not hasattr(valueRec1, "XAdvance")
|
||||
assert valueRec1.XAdvDevice.DeltaFormat == 0x8000
|
||||
outer = valueRec1.XAdvDevice.StartSize
|
||||
inner = valueRec1.XAdvDevice.EndSize
|
||||
assert vf["GDEF"].table.VarStore.VarData[outer].Item[inner] == [-50]
|
||||
|
||||
# check that MutatorMerger for ValueRecord doesn't raise AttributeError
|
||||
# when XAdvDevice is present but there's no corresponding XAdvance.
|
||||
instancer.instantiateOTL(vf, {"wght": 0.5})
|
||||
|
||||
pairPos = vf["GPOS"].table.LookupList.Lookup[0].SubTable[0]
|
||||
assert pairPos.ValueFormat1 == 0x4
|
||||
valueRec1 = pairPos.PairSet[0].PairValueRecord[0].Value1
|
||||
assert not hasattr(valueRec1, "XAdvDevice")
|
||||
assert valueRec1.XAdvance == -25
|
||||
|
||||
|
||||
class InstantiateAvarTest(object):
|
||||
@pytest.mark.parametrize("location", [{"wght": 0.0}, {"wdth": 0.0}])
|
||||
|
Loading…
x
Reference in New Issue
Block a user