Repository: fonttools/fonttools

Issue:
When parsing MVAR with lazy=True recordSize is wrong
Reproduction:
```
from fontTools import ttLib

import io
import sys

file_path = sys.argv[1]
fontdata = open(file_path, "rb").read()

font = ttLib.TTFont(io.BytesIO(fontdata), lazy=True)
mvar = font["MVAR"].table
print(mvar.ValueRecord.recordSize)
for rec in mvar.ValueRecord:
  print(rec.ValueTag, "->", rec.VarIdx)
```

Running this against the latest version of recursive gives:

16
hcrn -> 65538
sbxo -> 65536
stro -> 131072
undo -> 1
xhgt -> 0
Ê -> 732
@ -> 1073741824
 -> 0
 -> 16384

Record size should be 8.



Discussion:
`MVAR` is special in that it has a stupid design which encodes `ValueRecordSize`. To accommodate that, `MetricsValueRecord` is coded this way:
```
        ('MetricsValueRecord', [
                ('Tag', 'ValueTag', None, None, '4-byte font-wide measure identifier'),
                ('uint32', 'VarIdx', None, None, 'Combined outer-inner variation index'),
                ('uint8', 'MoreBytes', 'ValueRecordSize', -8, 'Extra bytes.  Set to empty array.'),
        ]),
```

Somehow `getRecordSize` is returning 16 on that. Maybe it doesn't see the `-8` bias? I didn't know we can even compute the recordSize for a struct like that.
Found it. Try:
```
diff --git a/Lib/fontTools/ttLib/tables/otBase.py b/Lib/fontTools/ttLib/tables/otBase.py
index 3c07f9e1..cc5423fd 100644
--- a/Lib/fontTools/ttLib/tables/otBase.py
+++ b/Lib/fontTools/ttLib/tables/otBase.py
@@ -571,7 +571,7 @@ class BaseTable(object):
                        countValue = 1
                        if conv.repeat:
                                if conv.repeat in reader:
-                                       countValue = reader[conv.repeat]
+                                       countValue = reader[conv.repeat] + conv.aux
                                else:
                                        return NotImplemented
                        totalSize += size * countValue
```

Resolving patch:
diff --git a/Lib/fontTools/ttLib/tables/otBase.py b/Lib/fontTools/ttLib/tables/otBase.py
--- a/Lib/fontTools/ttLib/tables/otBase.py
+++ b/Lib/fontTools/ttLib/tables/otBase.py
@@ -571,7 +571,7 @@ def getRecordSize(cls, reader):
 			countValue = 1
 			if conv.repeat:
 				if conv.repeat in reader:
-					countValue = reader[conv.repeat]
+					countValue = reader[conv.repeat] + conv.aux
 				else:
 					return NotImplemented
 			totalSize += size * countValue


Test patch:
diff --git a/Tests/ttLib/tables/M_V_A_R_test.py b/Tests/ttLib/tables/M_V_A_R_test.py
--- a/Tests/ttLib/tables/M_V_A_R_test.py
+++ b/Tests/ttLib/tables/M_V_A_R_test.py
@@ -8,8 +8,8 @@
 MVAR_DATA = deHexStr(
     '0001 0000 '  # 0:   version=1.0
     '0000 0008 '  # 4:   reserved=0, valueRecordSize=8
-    '0007 '       # 8:   valueRecordCount=7
-    '0044 '       # 10:  offsetToItemVariationStore=68
+    '0009 '       # 8:   valueRecordCount=9
+    '0054 '       # 10:  offsetToItemVariationStore=84
     '6861 7363 '  # 12:  ValueRecord.valueTag="hasc"
     '0000 '       # 16:  ValueRecord.deltaSetOuterIndex
     '0003 '       # 18:  ValueRecord.deltaSetInnerIndex
@@ -31,30 +31,36 @@
     '7370 796F '  # 60:  ValueRecord.valueTag="spyo"
     '0000 '       # 64:  ValueRecord.deltaSetOuterIndex
     '0002 '       # 66:  ValueRecord.deltaSetInnerIndex
-    '0001 '       # 68:  VarStore.format=1
-    '0000 000C '  # 70:  VarStore.offsetToVariationRegionList=12
-    '0001 '       # 74:  VarStore.itemVariationDataCount=1
-    '0000 0016 '  # 76:  VarStore.itemVariationDataOffsets[0]=22
-    '0001 '       # 80:  VarRegionList.axisCount=1
-    '0001 '       # 82:  VarRegionList.regionCount=1
-    '0000 '       # 84:  variationRegions[0].regionAxes[0].startCoord=0.0
-    '4000 '       # 86:  variationRegions[0].regionAxes[0].peakCoord=1.0
-    '4000 '       # 88:  variationRegions[0].regionAxes[0].endCoord=1.0
-    '0004 '       # 90:  VarData.ItemCount=4
-    '0001 '       # 92:  VarData.NumShorts=1
-    '0001 '       # 94:  VarData.VarRegionCount=1
-    '0000 '       # 96:  VarData.VarRegionIndex[0]=0
-    'FF38 '       # 98:  VarData.deltaSets[0]=-200
-    'FFCE '       # 100: VarData.deltaSets[0]=-50
-    '0064 '       # 102: VarData.deltaSets[0]=100
-    '00C8 '       # 104: VarData.deltaSets[0]=200
+    '7465 7374 '  # 68:  ValueRecord.valueTag="test"
+    '0000 '       # 72:  ValueRecord.deltaSetOuterIndex
+    '0002 '       # 74:  ValueRecord.deltaSetInnerIndex
+    '7465 7332 '  # 76:  ValueRecord.valueTag="tes2"
+    '0000 '       # 78:  ValueRecord.deltaSetOuterIndex
+    '0002 '       # 82:  ValueRecord.deltaSetInnerIndex
+    '0001 '       # 84:  VarStore.format=1
+    '0000 000C '  # 86:  VarStore.offsetToVariationRegionList=12
+    '0001 '       # 90:  VarStore.itemVariationDataCount=1
+    '0000 0016 '  # 92:  VarStore.itemVariationDataOffsets[0]=22
+    '0001 '       # 96:  VarRegionList.axisCount=1
+    '0001 '       # 98:  VarRegionList.regionCount=1
+    '0000 '       # 100:  variationRegions[0].regionAxes[0].startCoord=0.0
+    '4000 '       # 102:  variationRegions[0].regionAxes[0].peakCoord=1.0
+    '4000 '       # 104:  variationRegions[0].regionAxes[0].endCoord=1.0
+    '0004 '       # 106:  VarData.ItemCount=4
+    '0001 '       # 108:  VarData.NumShorts=1
+    '0001 '       # 110:  VarData.VarRegionCount=1
+    '0000 '       # 112:  VarData.VarRegionIndex[0]=0
+    'FF38 '       # 114:  VarData.deltaSets[0]=-200
+    'FFCE '       # 116: VarData.deltaSets[0]=-50
+    '0064 '       # 118: VarData.deltaSets[0]=100
+    '00C8 '       # 120: VarData.deltaSets[0]=200
 )
 
 MVAR_XML = [
     '<Version value="0x00010000"/>',
     '<Reserved value="0"/>',
     '<ValueRecordSize value="8"/>',
-    '<!-- ValueRecordCount=7 -->',
+    '<!-- ValueRecordCount=9 -->',
     '<VarStore Format="1">',
     '  <Format value="1"/>',
     '  <VarRegionList>',
@@ -108,6 +114,14 @@
     '  <ValueTag value="spyo"/>',
     '  <VarIdx value="2"/>',
     '</ValueRecord>',
+    '<ValueRecord index="7">',
+    '  <ValueTag value="test"/>',
+    '  <VarIdx value="2"/>',
+    '</ValueRecord>',
+    '<ValueRecord index="8">',
+    '  <ValueTag value="tes2"/>',
+    '  <VarIdx value="2"/>',
+    '</ValueRecord>',
 ]
 
 
@@ -123,6 +137,13 @@ def test_decompile_toXML(self):
         mvar.decompile(MVAR_DATA, font)
         self.assertEqual(getXML(mvar.toXML), MVAR_XML)
 
+
+    def test_decompile_toXML_lazy(self):
+        mvar = newTable('MVAR')
+        font = TTFont(lazy=True)
+        mvar.decompile(MVAR_DATA, font)
+        self.assertEqual(getXML(mvar.toXML), MVAR_XML)
+
     def test_compile_fromXML(self):
         mvar = newTable('MVAR')
         font = TTFont()