Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[COLR] Add PaintLocation and varcToCOLR #3262

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
120 changes: 120 additions & 0 deletions Lib/fontTools/colorLib/varcToCOLR.py
@@ -0,0 +1,120 @@
from fontTools.colorLib.builder import buildCOLR
from fontTools.ttLib.tables import otTables as ot
from fontTools.misc.fixedTools import floatToFixed as fl2fi


def varcToCOLR(font):
glyf = font["glyf"]

Check warning on line 7 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L7

Added line #L7 was not covered by tests

axisTags = glyf.axisTags

Check warning on line 9 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L9

Added line #L9 was not covered by tests
axisIndices = {tag: i for i, tag in enumerate(axisTags)}

paintForeground = {'Format': ot.PaintFormat.PaintSolid,

Check warning on line 12 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L12

Added line #L12 was not covered by tests
'PaletteIndex': 0xFFFF,
'Alpha': 1.0}

colorGlyphs = {}

Check warning on line 16 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L16

Added line #L16 was not covered by tests
for glyphName in glyf.keys():
glyph = glyf[glyphName]

Check warning on line 18 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L18

Added line #L18 was not covered by tests
if glyph.isVarComposite():

layers = []

Check warning on line 21 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L21

Added line #L21 was not covered by tests

for component in glyph.components:
if glyf[component.glyphName].isVarComposite():

paint = {'Format': ot.PaintFormat.PaintColrGlyph,

Check warning on line 26 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L26

Added line #L26 was not covered by tests
'Glyph': component.glyphName}
else:
paint = {'Format': ot.PaintFormat.PaintGlyph,

Check warning on line 29 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L29

Added line #L29 was not covered by tests
'Paint': paintForeground,
'Glyph': component.glyphName}

transform = component.transform

Check warning on line 33 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L33

Added line #L33 was not covered by tests

# Check for non-integer values

if (transform.translateX or transform.translateY or
transform.tCenterX or transform.tCenterY):
paint = {'Format': ot.PaintFormat.PaintTranslate,

Check warning on line 39 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L39

Added line #L39 was not covered by tests
'Paint': paint,
'dx': transform.translateX + transform.tCenterX,
'dy': transform.translateY + transform.tCenterY}

if transform.rotation:
paint = {'Format': ot.PaintFormat.PaintRotate,

Check warning on line 45 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L45

Added line #L45 was not covered by tests
'Paint': paint,
'angle': transform.rotation}

if transform.scaleX != 1.0 or transform.scaleY != 1.0:
if (abs(transform.scaleX) < 2.0 and abs(transform.scaleY) < 2.0):
paint = {'Format': ot.PaintFormat.PaintScale,

Check warning on line 51 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L51

Added line #L51 was not covered by tests
'Paint': paint,
'scaleX': transform.scaleX,
'scaleY': transform.scaleY}
else:
affine = ot.Affine2x3()
affine.xx = transform.scaleX
affine.xy = 0.0
affine.yx = 0.0
affine.yy = transform.scaleX
affine.dx = 0.0
affine.dy = 0.0
paint = {'Format': ot.PaintFormat.PaintTransform,

Check warning on line 63 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L56-L63

Added lines #L56 - L63 were not covered by tests
'Paint': paint,
'Transform': affine}

if transform.skewX or transform.skewY:
paint = {'Format': ot.PaintFormat.PaintSkew,

Check warning on line 68 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L68

Added line #L68 was not covered by tests
'Paint': paint,
'xSkewAngle': transform.skewX,
'ySkewAngle': -transform.skewY}

if transform.tCenterX or transform.tCenterY:
paint = {'Format': ot.PaintFormat.PaintTranslate,

Check warning on line 74 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L74

Added line #L74 was not covered by tests
'Paint': paint,
'dx': -transform.tCenterX,
'dy': -transform.tCenterY}

if component.location:
axisList = []
axisValues = []

Check warning on line 81 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L80-L81

Added lines #L80 - L81 were not covered by tests
for axisTag, value in component.location.items():
axisList.append(axisIndices[axisTag])
axisValues.append(value)

Check warning on line 84 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L83-L84

Added lines #L83 - L84 were not covered by tests

AxisList = ot.AxisList()
AxisList.Format = 1
AxisList.Axis = axisList

Check warning on line 88 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L86-L88

Added lines #L86 - L88 were not covered by tests

AxisValues = ot.AxisValues()
AxisValues.Value = axisValues

Check warning on line 91 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L90-L91

Added lines #L90 - L91 were not covered by tests

paint = {'Format': ot.PaintFormat.PaintLocation,

Check warning on line 93 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L93

Added line #L93 was not covered by tests
'Paint': paint,
'AxisList': AxisList,
'AxisValues': AxisValues}

layers.append(paint)

Check warning on line 98 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L98

Added line #L98 was not covered by tests

colorGlyphs[glyphName] = {'Format': ot.PaintFormat.PaintColrLayers,

Check warning on line 100 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L100

Added line #L100 was not covered by tests
'Layers': layers}

for glyphName in colorGlyphs:
glyf[glyphName].numberOfContours = 0

Check warning on line 104 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L104

Added line #L104 was not covered by tests

colr = buildCOLR(colorGlyphs,

Check warning on line 106 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L106

Added line #L106 was not covered by tests
version=1,
glyphMap=font.getReverseGlyphMap())
font["COLR"] = colr

Check warning on line 109 in Lib/fontTools/colorLib/varcToCOLR.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/colorLib/varcToCOLR.py#L109

Added line #L109 was not covered by tests


if __name__ == "__main__":
import sys
from fontTools.ttLib import TTFont

font = TTFont(sys.argv[1])

varcToCOLR(font)

font.save(sys.argv[2])
73 changes: 73 additions & 0 deletions Lib/fontTools/ttLib/tables/otData.py
Expand Up @@ -6157,6 +6157,79 @@
),
],
),
# AxisListFormat1
(
"AxisListFormat1",
[
("uint8", "Format", None, None, "Number of axis indices"),
("uint8", "AxisCount", None, None, "Number of axis indices"),
(
"uint8",
"Axis",
"AxisCount",
0,
"Array of axis indices",
),
],
),
# AxisListFormat2
(
"AxisListFormat2",
[
("uint8", "Format", None, None, "Number of axis indices"),
("uint8", "AxisCount", None, None, "Number of axis indices"),
(
"uint16",
"Axis",
"AxisCount",
0,
"Array of axis indices",
),
],
),
# AxisValues
(
"AxisValues",
[
("uint8", "AxisCount", None, None, "Number of axis indices"),
(
"F2Dot14",
"Value",
"AxisCount",
0,
"Array of axis values",
),
],
),
# PaintLocation
(
"PaintFormat33",
[
("uint8", "PaintFormat", None, None, "Format identifier-format = 33"),
(
"LOffset24To(Paint)",
"Paint",
None,
None,
"Offset (from beginning of PaintLocation table) to source Paint subtable.",
),
(
"LOffset24To(AxisList)",
"AxisList",
None,
None,
"",
),
(
"AxisValues",
"AxisValues",
None,
None,
"",
),
],
),

#
# avar
#
Expand Down
1 change: 1 addition & 0 deletions Lib/fontTools/ttLib/tables/otTables.py
Expand Up @@ -1562,6 +1562,7 @@ class PaintFormat(IntEnum):
PaintSkewAroundCenter = 30
PaintVarSkewAroundCenter = 31
PaintComposite = 32
PaintLocation = 33

def is_variable(self):
return self.name.startswith("PaintVar")
Expand Down