Repository: fonttools/fonttools

Issue:
[COLRv1] Drop DeltaSetIndexMap when not needed
In an experimental font generated with:
https://github.com/drott/color-fonts/tree/noDeltaSetIndexMap
fontTools creates and empty DeltaSetIndexMap. 

```
    <VarIndexMap Format="0">
      <!-- Omitted values default to 0xFFFF/0xFFFF (no variations) -->
      <Map index="0" outer="0" inner="0"/>
    </VarIndexMap>
```

I suggest to drop this when not needed for saving space. 

I am in the process of fixing this part in [FreeType in this issue (#1178)](https://gitlab.freedesktop.org/freetype/freetype/-/issues/1178).

PS: FF nightly seems to support those already.


Discussion:

Resolving patch:
diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py
--- a/Lib/fontTools/varLib/__init__.py
+++ b/Lib/fontTools/varLib/__init__.py
@@ -722,8 +722,11 @@ def _add_COLR(font, model, master_fonts, axisTags, colr_layer_reuse=True):
 	if store:
 		mapping = store.optimize()
 		colr.VarStore = store
+		# don't add DeltaSetIndexMap for identity mapping
+		colr.VarIndexMap = None
 		varIdxes = [mapping[v] for v in merger.varIdxes]
-		colr.VarIndexMap = builder.buildDeltaSetIndexMap(varIdxes)
+		if any(i != varIdxes[i] for i in range(len(varIdxes))):
+			colr.VarIndexMap = builder.buildDeltaSetIndexMap(varIdxes)
 
 
 def load_designspace(designspace):


Test patch:
diff --git a/Tests/varLib/varLib_test.py b/Tests/varLib/varLib_test.py
--- a/Tests/varLib/varLib_test.py
+++ b/Tests/varLib/varLib_test.py
@@ -1,7 +1,10 @@
+from fontTools.colorLib.builder import buildCOLR
 from fontTools.ttLib import TTFont, newTable
-from fontTools.varLib import build, load_designspace
+from fontTools.ttLib.tables import otTables as ot
+from fontTools.varLib import build, load_designspace, _add_COLR
 from fontTools.varLib.errors import VarLibValidationError
 import fontTools.varLib.errors as varLibErrors
+from fontTools.varLib.models import VariationModel
 from fontTools.varLib.mutator import instantiateVariableFont
 from fontTools.varLib import main as varLib_main, load_masters
 from fontTools.varLib import set_default_weight_width_slant
@@ -10,6 +13,7 @@
 )
 from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
 import difflib
+from copy import deepcopy
 from io import BytesIO
 import os
 import shutil
@@ -985,5 +989,38 @@ def test_all(self, ttFont):
         assert ttFont["post"].italicAngle == -12.0
 
 
+def test_variable_COLR_without_VarIndexMap():
+    # test we don't add a no-op VarIndexMap to variable COLR when not needed
+    # https://github.com/fonttools/fonttools/issues/2800
+
+    font1 = TTFont()
+    font1.setGlyphOrder([".notdef", "A"])
+    font1["COLR"] = buildCOLR({"A": (ot.PaintFormat.PaintSolid, 0, 1.0)})
+    # font2 == font1 except for PaintSolid.Alpha
+    font2 = deepcopy(font1)
+    font2["COLR"].table.BaseGlyphList.BaseGlyphPaintRecord[0].Paint.Alpha = 0.0
+    master_fonts = [font1, font2]
+
+    varfont = deepcopy(font1)
+    axis_order = ["XXXX"]
+    model = VariationModel([{}, {"XXXX": 1.0}], axis_order)
+
+    _add_COLR(varfont, model, master_fonts, axis_order)
+
+    colr = varfont["COLR"].table
+
+    assert len(colr.BaseGlyphList.BaseGlyphPaintRecord) == 1
+    baserec = colr.BaseGlyphList.BaseGlyphPaintRecord[0]
+    assert baserec.Paint.Format == ot.PaintFormat.PaintVarSolid
+    assert baserec.Paint.VarIndexBase == 0
+
+    assert colr.VarStore is not None
+    assert len(colr.VarStore.VarData) == 1
+    assert len(colr.VarStore.VarData[0].Item) == 1
+    assert colr.VarStore.VarData[0].Item[0] == [-16384]
+
+    assert colr.VarIndexMap is None
+
+
 if __name__ == "__main__":
     sys.exit(unittest.main())